-
Notifications
You must be signed in to change notification settings - Fork 7.9k
🐛 Fixed Bug #80908 PDO::lastInsertId() return wrong. #6810
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
Conversation
…igger than the maximum value of int64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure the approach of mimicking the signed version is totally correct, as I could imagine some overflow into negative numbers for very large 64 bit integers, can you add a test?
if (i64 == 0) { | ||
return ZSTR_CHAR('0'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also handle all numbers which are a single digit
{ | ||
char buffer[65]; | ||
char outbuf[65] = ""; | ||
register char *p; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
register char *p; | |
char *p; |
From my understanding this is pretty meaningless.
p = &buffer[sizeof(buffer)-1]; | ||
*p = '\0'; | ||
|
||
while ((uint64_t)i64 > (uint64_t)ZEND_LONG_MAX) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while ((uint64_t)i64 > (uint64_t)ZEND_LONG_MAX) { | |
while (i64 > (uint64_t)ZEND_LONG_MAX) { |
i64 is already an uint64_t
@Girgias Thanks for your code review. I will provider a test. The test steps:
// Let the table auto_increment id start from `10376293541461622799`. It's bigger than int64.
create table foo (`id` bigint(20) unsigned AUTO_INCREMENT, `name` varchar(5), primary key (`id`)) ENGINE = InnoDB AUTO_INCREMENT=10376293541461622799;
<?php
$dbh = new PDO('mysql:host=docker.for.mac.localhost:33060;dbname=test', 'root', 'secret');
$dbh->exec("insert into foo (`name`) values ('bar')");
echo $dbh->lastInsertId() . PHP_EOL;
// If we not fix the bug, this test will return a string '-8070450532247928817' In fact, MySQL Client C API function last_insert_id() is always return an unsigned int64 |
I don't think PDO should be responsible for implementing this functionality, so I've added some generic Zend APIs in 65a5c18. This PR should now just be a matter of switching from zend_i64_to_str to zend_u64_to_str. |
Fixed Bug #80908
MySQL api function
last_insert_id()
always return unsigned interger,but in
ext.pdo_mysql
we useint64
to receive theuint64
return value.When MySQL table
auto_increment id
bigger than the maximum value ofint64,
ext.pdo_mysql
will treat asint64
.