Skip to content

Feature: Output correct error message from pdo_firebird #12669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

SakiTakamachi
Copy link
Member

@SakiTakamachi SakiTakamachi commented Nov 14, 2023

The current implementation does not retrieve sqlstatus from the DB, and any errors will be treated as General errors.

So I changed it to get the SQL state and error messages from the vendor driver.

I also used the same naming conventions as other PDO drivers for function names, etc.

Other changes require error handling, so I'd be happy if I could merge them from this PR.

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch 13 times, most recently from 9c2cc79 to 12fc53b Compare November 17, 2023 02:10
@SakiTakamachi SakiTakamachi changed the title [WIP] Feature: Output correct error message from pdo_firebird Feature: Output correct error message from pdo_firebird Nov 17, 2023
@SakiTakamachi SakiTakamachi marked this pull request as ready for review November 17, 2023 10:24
@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch from 12fc53b to 7bfb5e6 Compare November 17, 2023 12:05
@SakiTakamachi
Copy link
Member Author

@Girgias

Sorry for the change in order, but first, I would like to ask you to review this PR.

@SakiTakamachi
Copy link
Member Author

I found some unnecessary parts, so I'll edit them.

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch 3 times, most recently from 5d5b183 to c252527 Compare November 17, 2023 23:36
@SakiTakamachi
Copy link
Member Author

done

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me and only have some suggestions

buf[read_len - 1] = '\0';
}

einfo->errmsg = pestrdup(buf, dbh->is_persistent);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this duplicate 512 bytes every time?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Judging from the implementation of pestrdup, it looks fine.

ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)

However, considering the balance with other changes, it seemed better to use pestrndup, so I changed it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has nothing to do with this change, but I'm a little concerned that it haven't given +1 here.

memcpy(p, s, length);

Copy link
Member Author

@SakiTakamachi SakiTakamachi Nov 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's the opposite. +1 to potentially lost the terminating null

Here, _estrdup is getting the length, so there seems to be no problem. Excuse me, I understand.

Comment on lines 62 to 66
typedef struct {
int sqlcode;
char *errmsg;
} pdo_firebird_error_info;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add the length component so that we don't need to recompute known lengths when converting this to zend_string ?

Suggested change
typedef struct {
int sqlcode;
char *errmsg;
} pdo_firebird_error_info;
typedef struct {
int sqlcode;
char *errmsg;
size_t errmsg_length;
} pdo_firebird_error_info;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea. Changed pdo_firebird_fetch_error_func to use add_next_index_stringl.

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch from c252527 to 9a435f3 Compare November 18, 2023 06:58
@SakiTakamachi
Copy link
Member Author

@Girgias
Thank you, the corrections you pointed out have been completed.

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch from 9a435f3 to 2ca4077 Compare November 18, 2023 10:09
Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for being slow, but possibly some more improvements (but they could also be left for later)

}
#endif
} else if (msg) {
einfo->errmsg_length = strlen(msg);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that the msg argument is always constant at the call site. Precomputing the length at call site and passing it as an argument should allow the compiler to precompute it instead of needing a runtime strlen() in the function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to require length in argument

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you meant writing the numbers directly in the code without using strlen at all? I may have misunderstood something.

Comment on lines 509 to 514
if (state) {
strcpy(*error_code, state);
} else {
strcpy(*error_code, "HY000");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here, we can precompute the length of the strings and potentially use memcpy() instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to require length in argument, and to explicitly pass HY000 where NULL was passed to state

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch from 2ca4077 to 9ae039c Compare November 19, 2023 08:53
@SakiTakamachi
Copy link
Member Author

SakiTakamachi commented Nov 19, 2023

@Girgias
Thank you, I fixed these.

My changes may be inappropriate to save runtime overhead.

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch from 9ae039c to 4810a72 Compare November 19, 2023 10:04
@SakiTakamachi
Copy link
Member Author

I fixed, I think I've eliminated runtime overhead as much as possible.

if (state && state_len && state_len < sizeof(pdo_error_type)) {
memcpy(*error_code, state, state_len + 1);
} else {
memcpy(*error_code, "HY000", 6);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be better AFAIK

Suggested change
memcpy(*error_code, "HY000", 6);
memcpy(*error_code, "HY000", sizeof("HY000");

@@ -848,7 +904,7 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
if (bval) {
/* turning on auto_commit with an open transaction is illegal, because
we won't know what to do with it */
H->last_app_error = "Cannot enable auto-commit while a transaction is already open";
firebird_error_with_info(dbh, "HY000", 5, "Cannot enable auto-commit while a transaction is already open", 61);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using sizeof of strlen is better, the compiler will fill in the integer constant by itself

@@ -325,7 +322,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, zval *result, ISC_QU

if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error
|| i >= sizeof(bl_info)) {
H->last_app_error = "Couldn't determine BLOB size";
firebird_error_stmt_with_info(stmt, "HY000", 5, "Couldn't determine BLOB size", 28);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@SakiTakamachi SakiTakamachi force-pushed the feature/pdo_firebird_error_code_and_message branch from 4810a72 to 700f92a Compare November 20, 2023 02:19
@SakiTakamachi
Copy link
Member Author

SakiTakamachi commented Nov 20, 2023

Thank you, I didn't even consider the behavior of the compiler.
I tried changing it, does this work as expected? Or is there a better way to write it?


I'm looking into it while studying while looking at the assembly code.

@@ -848,7 +904,8 @@ static bool firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *
if (bval) {
/* turning on auto_commit with an open transaction is illegal, because
we won't know what to do with it */
H->last_app_error = "Cannot enable auto-commit while a transaction is already open";
const char *msg = "Cannot enable auto-commit while a transaction is already open";
firebird_error_with_info(dbh, "HY000", strlen("HY000"), msg, strlen(msg));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nielsdos just to sanity check, but this is sensible right? The compiler will replace at compile time the strlen call by the actual value

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it does

Copy link
Member Author

@SakiTakamachi SakiTakamachi Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you both! I was able to understand it a little. I'll learn some more.


What I wanted to say was a little different.

Although I understand the content, I am still not very good at reading the differences in assembly code, so I will learn to read assembly code better.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried various things. I understand that strlen("HY000") will be replaced, but strlen(msg) will not be replaced, is this correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because msg is a variable, where the content is only known at runtime.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thank you. Should msg be replaced as well? I feel the msg is a little too long for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't look at this specific case, but in this one the compiler should be smart enough :)

@Girgias Girgias merged commit 239379b into php:master Nov 20, 2023
@SakiTakamachi
Copy link
Member Author

Thank you!

@SakiTakamachi SakiTakamachi deleted the feature/pdo_firebird_error_code_and_message branch November 21, 2023 07:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants