mysqli_last_insert_id.phpt 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. --TEST--
  2. API vs. SQL LAST_INSERT_ID()
  3. --SKIPIF--
  4. <?php
  5. require_once('skipif.inc');
  6. require_once('skipifconnectfailure.inc');
  7. ?>
  8. --FILE--
  9. <?php
  10. /*
  11. CAUTION: the insert_id() API call is not supposed to return
  12. the same value as a call to the LAST_INSERT_ID() SQL function.
  13. It is not necessarily a bug if API and SQL function return different
  14. values. Check the MySQL C API reference manual for details.
  15. */
  16. require_once("connect.inc");
  17. function get_sql_id($link) {
  18. if (!($res = $link->query("SELECT LAST_INSERT_ID() AS _id"))) {
  19. printf("[003] [%d] %s\n", $link->errno, $link->error);
  20. return NULL;
  21. }
  22. $row = $res->fetch_assoc();
  23. $res->close();
  24. return $row['_id'];
  25. }
  26. if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
  27. printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
  28. $host, $user, $db, $port, $socket);
  29. if (!$link->query("DROP TABLE IF EXISTS test") ||
  30. !$link->query("CREATE TABLE test (id INT auto_increment, label varchar(10) not null, PRIMARY KEY (id)) ENGINE=MyISAM") ||
  31. !$link->query("INSERT INTO test (id, label) VALUES (null, 'a')")) {
  32. printf("[002] [%d] %s\n", $link->errno, $link->error);
  33. }
  34. $api_id = $link->insert_id;
  35. $sql_id = get_sql_id($link);
  36. printf("API: %d, SQL: %d\n", $api_id, $sql_id);
  37. if ($api_id < 1)
  38. printf("[004] Expecting id > 0 got %d, [%d] %s\n", $api_id, $link->errno, $link->error) ;
  39. if ($api_id != $sql_id)
  40. printf("[005] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
  41. // Not an INSERT, API value must become 0
  42. if (!($res = $link->query("SELECT 1 FROM DUAL")))
  43. printf("[006] [%d] %s\n", $link->errno, $link->error);
  44. else
  45. $res->close();
  46. $api_id = $link->insert_id;
  47. $new_sql_id = get_sql_id($link);
  48. if (0 !== $api_id) {
  49. printf("[007] API id should have been reset to 0 because previous query was SELECT, got API %d, SQL %d\n",
  50. $api_id, $new_sql_id);
  51. }
  52. if ($new_sql_id != $sql_id) {
  53. printf("[008] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
  54. }
  55. // Insert fails, LAST_INSERT_ID shall not change, API shall return 0
  56. if ($link->query("INSERT INTO test (id, label) VALUES (null, null)")) {
  57. printf("[009] The INSERT did not fail as planned, [%d] %s\n", $link->errno, $link->error);
  58. }
  59. $api_id = $link->insert_id;
  60. $new_sql_id = get_sql_id($link);
  61. if (0 !== $api_id) {
  62. printf("[010] API id should have been reset to 0 because previous query was SELECT, got API %d, SQL %d\n",
  63. $api_id, $new_sql_id);
  64. }
  65. if ($new_sql_id != $sql_id) {
  66. printf("[011] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
  67. }
  68. // Sequence counter pattern...
  69. if (!$link->query("UPDATE test SET id=LAST_INSERT_ID(id+1)"))
  70. printf("[012] [%d] %s\n", $link->errno, $link->error);
  71. $api_id = $link->insert_id;
  72. $new_sql_id = get_sql_id($link);
  73. if ($api_id < 1)
  74. printf("[013] Expecting id > 0 got %d, [%d] %s\n", $api_id, $link->errno, $link->error) ;
  75. if ($api_id != $new_sql_id)
  76. printf("[014] SQL id %d should be equal to API id %d\n", $new_sql_id, $api_id);
  77. if ($sql_id == $new_sql_id)
  78. printf("[015] SQL id %d should have had changed, got %d\n", $sql_id, $new_sql_id);
  79. $sql_id = $new_sql_id;
  80. // Not an INSERT (after UPDATE), API value must become 0
  81. if (!$link->query("SET @myvar=1"))
  82. printf("[016] [%d] %s\n", $link->errno, $link->error);
  83. $api_id = $link->insert_id;
  84. $new_sql_id = get_sql_id($link);
  85. if (0 !== $api_id) {
  86. printf("[017] API id should have been reset to 0 because previous query was SET, got API %d, SQL %d\n",
  87. $api_id, $new_sql_id);
  88. }
  89. if ($new_sql_id != $sql_id) {
  90. printf("[018] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
  91. }
  92. if (!$link->query("INSERT INTO test(id, label) VALUES (LAST_INSERT_ID(id + 1), 'b')"))
  93. printf("[019] [%d] %s\n", $link->errno, $link->error);
  94. $api_id = $link->insert_id;
  95. $sql_id = get_sql_id($link);
  96. if ($api_id != $sql_id)
  97. printf("[020] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
  98. if (!$link->query("INSERT INTO test(label) VALUES ('c')"))
  99. printf("[021] [%d] %s\n", $link->errno, $link->error);
  100. $api_id = $link->insert_id;
  101. $sql_id = get_sql_id($link);
  102. if ($api_id != $sql_id)
  103. printf("[022] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
  104. if (!($res = $link->query("SELECT id, label FROM test ORDER BY id ASC")))
  105. printf("[023] [%d] %s\n", $link->errno, $link->error);
  106. printf("Dumping table contents before INSERT...SELECT experiments...\n");
  107. while ($row = $res->fetch_assoc()) {
  108. printf("id = %d, label = '%s'\n", $row['id'], $row['label']);
  109. }
  110. $res->close();
  111. if (!$link->query("INSERT INTO test(label) SELECT CONCAT(label, id) FROM test ORDER BY id ASC"))
  112. printf("[024] [%d] %s\n", $link->errno, $link->error);
  113. $api_id = $link->insert_id;
  114. $sql_id = get_sql_id($link);
  115. if ($api_id != $sql_id)
  116. printf("[025] SQL id %d should be equal to API id %d\n", $sql_id, $api_id);
  117. if ($link->query("INSERT INTO test(id, label) SELECT id, CONCAT(label, id) FROM test ORDER BY id ASC"))
  118. printf("[026] INSERT should have failed because of duplicate PK value, [%d] %s\n", $link->errno, $link->error);
  119. $api_id = $link->insert_id;
  120. $new_sql_id = get_sql_id($link);
  121. if (0 !== $api_id) {
  122. printf("[027] API id should have been reset to 0 because previous query failed, got API %d, SQL %d\n",
  123. $api_id, $new_sql_id);
  124. }
  125. if ($new_sql_id != $sql_id) {
  126. printf("[028] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
  127. }
  128. /* API insert id will be 101 because of UPDATE, SQL unchanged */
  129. if (!$link->query(sprintf("INSERT INTO test(id, label) VALUES (%d, 'z') ON DUPLICATE KEY UPDATE id = 101", $sql_id) ))
  130. printf("[029] [%d] %s\n", $link->errno, $link->error);
  131. $api_id = $link->insert_id;
  132. $new_sql_id = get_sql_id($link);
  133. if ($api_id != 101)
  134. printf("[030] API id should be %d got %d\n", $sql_id, $api_id);
  135. if ($new_sql_id != $sql_id) {
  136. printf("[031] The servers LAST_INSERT_ID() changed unexpectedly from %d to %d\n", $sql_id, $new_sql_id);
  137. }
  138. if (!($res = $link->query("SELECT id, label FROM test ORDER BY id ASC")))
  139. printf("[032] [%d] %s\n", $link->errno, $link->error);
  140. printf("Dumping table contents after INSERT...SELECT...\n");
  141. while ($row = $res->fetch_assoc()) {
  142. printf("id = %d, label = '%s'\n", $row['id'], $row['label']);
  143. }
  144. $res->close();
  145. print "done!";
  146. ?>
  147. --CLEAN--
  148. <?php
  149. require_once("clean_table.inc");
  150. ?>
  151. --EXPECTF--
  152. API: %d, SQL: %d
  153. Dumping table contents before INSERT...SELECT experiments...
  154. id = %d, label = 'b'
  155. id = %d, label = 'a'
  156. id = %d, label = 'c'
  157. Dumping table contents after INSERT...SELECT...
  158. id = %d, label = 'b'
  159. id = %d, label = 'a'
  160. id = %d, label = 'c'
  161. id = %d, label = 'a%d'
  162. id = %d, label = 'c%d'
  163. id = 101, label = 'b%d'
  164. done!