johannes                Mon Oct 27 17:20:27 2008 UTC

  Added files:                 
    /php-src/ext/mysqli/tests   mysqli_insert_id_variation.phpt 

  Modified files:              
    /php-src/ext/mysqlnd        mysqlnd.c mysqlnd_loaddata.c mysqlnd_ps.c 
  Log:
  Fix #46285 (lastInsertId() returns "0" when a deferenced PDOStatement is
  executed)
  
  
http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd.c?r1=1.29&r2=1.30&diff_format=u
Index: php-src/ext/mysqlnd/mysqlnd.c
diff -u php-src/ext/mysqlnd/mysqlnd.c:1.29 php-src/ext/mysqlnd/mysqlnd.c:1.30
--- php-src/ext/mysqlnd/mysqlnd.c:1.29  Wed Oct  1 19:46:58 2008
+++ php-src/ext/mysqlnd/mysqlnd.c       Mon Oct 27 17:20:25 2008
@@ -18,7 +18,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: mysqlnd.c,v 1.29 2008/10/01 19:46:58 johannes Exp $ */
+/* $Id: mysqlnd.c,v 1.30 2008/10/27 17:20:25 johannes Exp $ */
 #include "php.h"
 #include "mysqlnd.h"
 #include "mysqlnd_wireprotocol.h"
@@ -268,7 +268,8 @@
 /* {{{ mysqlnd_simple_command_handle_response */
 enum_func_status
 mysqlnd_simple_command_handle_response(MYSQLND *conn, enum 
php_mysql_packet_type ok_packet,
-                                                                          
zend_bool silent, enum php_mysqlnd_server_command command
+                                                                          
zend_bool silent, enum php_mysqlnd_server_command command,
+                                                                          
zend_bool ignore_upsert_status
                                                                           
TSRMLS_DC)
 {
        enum_func_status ret;
@@ -309,10 +310,12 @@
                                                                        
ok_response.message, ok_response.message_len,
                                                                        
conn->persistent);
 
-                                       conn->upsert_status.warning_count = 
ok_response.warning_count;
-                                       conn->upsert_status.server_status = 
ok_response.server_status;
-                                       conn->upsert_status.affected_rows = 
ok_response.affected_rows;
-                                       conn->upsert_status.last_insert_id = 
ok_response.last_insert_id;
+                                       if (!ignore_upsert_status) {
+                                               
conn->upsert_status.warning_count = ok_response.warning_count;
+                                               
conn->upsert_status.server_status = ok_response.server_status;
+                                               
conn->upsert_status.affected_rows = ok_response.affected_rows;
+                                               
conn->upsert_status.last_insert_id = ok_response.last_insert_id;
+                                       }
                                }
                        }
                        PACKET_FREE_ALLOCA(ok_response);
@@ -367,7 +370,8 @@
 enum_func_status
 mysqlnd_simple_command(MYSQLND *conn, enum php_mysqlnd_server_command command,
                                           const char * const arg, size_t 
arg_len,
-                                          enum php_mysql_packet_type 
ok_packet, zend_bool silent TSRMLS_DC)
+                                          enum php_mysql_packet_type 
ok_packet, zend_bool silent, 
+                                          zend_bool ignore_upsert_status 
TSRMLS_DC)
 {
        enum_func_status ret = PASS;
        php_mysql_packet_command cmd_packet;
@@ -390,7 +394,9 @@
        }
 
        /* clean UPSERT info */
-       memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
+       if (!ignore_upsert_status) {
+               memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
+       }
        SET_ERROR_AFF_ROWS(conn);
        SET_EMPTY_ERROR(conn->error_info);
 
@@ -409,7 +415,7 @@
                DBG_ERR("Server is gone");
                ret = FAIL;
        } else if (ok_packet != PROT_LAST) {
-               ret = mysqlnd_simple_command_handle_response(conn, ok_packet, 
silent, command TSRMLS_CC);
+               ret = mysqlnd_simple_command_handle_response(conn, ok_packet, 
silent, command, ignore_upsert_status TSRMLS_CC);
        }
 
        /*
@@ -435,7 +441,7 @@
 
        int2store(buffer, (uint) option);
        ret = mysqlnd_simple_command(conn, COM_SET_OPTION, buffer, 
sizeof(buffer),
-                                                                
PROT_EOF_PACKET, FALSE TSRMLS_CC);
+                                                                
PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
        DBG_RETURN(ret);
 }
 /* }}} */
@@ -850,7 +856,7 @@
 
        if (PASS != mysqlnd_simple_command(conn, COM_QUERY, query, query_len,
                                                                           
PROT_LAST /* we will handle the OK packet*/,
-                                                                          
FALSE TSRMLS_CC)) {
+                                                                          
FALSE, FALSE TSRMLS_CC)) {
                DBG_RETURN(FAIL);
        }
        CONN_SET_STATE(conn, CONN_QUERY_SENT);
@@ -897,7 +903,7 @@
 
        if (PASS != mysqlnd_simple_command(conn, COM_FIELD_LIST, buff, p - buff,
                                                                           
PROT_LAST /* we will handle the OK packet*/,
-                                                                          
FALSE TSRMLS_CC)) {
+                                                                          
FALSE, TRUE TSRMLS_CC)) {
                DBG_RETURN(NULL);
        }
        /*
@@ -1018,7 +1024,7 @@
 {
        DBG_ENTER("mysqlnd_conn::dump_debug_info");
        DBG_INF_FMT("conn=%llu", conn->thread_id);
-       DBG_RETURN(mysqlnd_simple_command(conn, COM_DEBUG, NULL, 0, 
PROT_EOF_PACKET, FALSE TSRMLS_CC));
+       DBG_RETURN(mysqlnd_simple_command(conn, COM_DEBUG, NULL, 0, 
PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC));
 }
 /* }}} */
 
@@ -1034,7 +1040,7 @@
        DBG_ENTER("mysqlnd_conn::select_db");
        DBG_INF_FMT("conn=%llu db=%s", conn->thread_id, db);
 
-       ret = mysqlnd_simple_command(conn, COM_INIT_DB, db, db_len, 
PROT_OK_PACKET, FALSE TSRMLS_CC);
+       ret = mysqlnd_simple_command(conn, COM_INIT_DB, db, db_len, 
PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
        /*
          The server sends 0 but libmysql doesn't read it and has established
          a protocol of giving back -1. Thus we have to follow it :(
@@ -1055,7 +1061,7 @@
        DBG_ENTER("mysqlnd_conn::ping");
        DBG_INF_FMT("conn=%llu", conn->thread_id);
 
-       ret = mysqlnd_simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, 
TRUE TSRMLS_CC);
+       ret = mysqlnd_simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, 
TRUE, TRUE TSRMLS_CC);
        /*
          The server sends 0 but libmysql doesn't read it and has established
          a protocol of giving back -1. Thus we have to follow it :(
@@ -1078,7 +1084,7 @@
        DBG_ENTER("mysqlnd_conn::stat");
        DBG_INF_FMT("conn=%llu", conn->thread_id);
 
-       ret = mysqlnd_simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, 
FALSE TSRMLS_CC);
+       ret = mysqlnd_simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, 
FALSE, TRUE TSRMLS_CC);
        if (FAIL == ret) {
                DBG_RETURN(FAIL);
        }
@@ -1112,14 +1118,14 @@
 
        /* If we kill ourselves don't expect OK packet, PROT_LAST will skip it 
*/
        if (pid != conn->thread_id) {
-               ret = mysqlnd_simple_command(conn, COM_PROCESS_KILL, buff, 4, 
PROT_OK_PACKET, FALSE TSRMLS_CC);
+               ret = mysqlnd_simple_command(conn, COM_PROCESS_KILL, buff, 4, 
PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
                /*
                  The server sends 0 but libmysql doesn't read it and has 
established
                  a protocol of giving back -1. Thus we have to follow it :(
                */
                SET_ERROR_AFF_ROWS(conn);
        } else if (PASS == (ret = mysqlnd_simple_command(conn, 
COM_PROCESS_KILL, buff,
-                                                                               
                         4, PROT_LAST, FALSE TSRMLS_CC))) {
+                                                                               
                         4, PROT_LAST, FALSE, TRUE TSRMLS_CC))) {
                CONN_SET_STATE(conn, CONN_QUIT_SENT);
        }
        DBG_RETURN(ret);
@@ -1172,7 +1178,7 @@
 
        int1store(bits, options);
 
-       DBG_RETURN(mysqlnd_simple_command(conn, COM_REFRESH, (char *)bits, 1, 
PROT_OK_PACKET, FALSE TSRMLS_CC));
+       DBG_RETURN(mysqlnd_simple_command(conn, COM_REFRESH, (char *)bits, 1, 
PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC));
 }
 /* }}} */
 
@@ -1187,7 +1193,7 @@
 
        int1store(bits, level);
 
-       DBG_RETURN(mysqlnd_simple_command(conn, COM_SHUTDOWN, (char *)bits, 1, 
PROT_OK_PACKET, FALSE TSRMLS_CC));
+       DBG_RETURN(mysqlnd_simple_command(conn, COM_SHUTDOWN, (char *)bits, 1, 
PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC));
 }
 /* }}} */
 
@@ -1206,7 +1212,7 @@
                case CONN_READY:
                        DBG_INF("Connection clean, sending COM_QUIT");
                        ret =  mysqlnd_simple_command(conn, COM_QUIT, NULL, 0, 
PROT_LAST,
-                                                                               
  TRUE TSRMLS_CC);
+                                                                               
  TRUE, TRUE TSRMLS_CC);
                        /* Do nothing */
                        break;
                case CONN_SENDING_LOAD_DATA:
@@ -1633,7 +1639,7 @@
 
        if (PASS != mysqlnd_simple_command(conn, COM_CHANGE_USER, buffer, p - 
buffer,
                                                                           
PROT_LAST /* we will handle the OK packet*/,
-                                                                          
FALSE TSRMLS_CC)) {
+                                                                          
FALSE, TRUE TSRMLS_CC)) {
                DBG_RETURN(FAIL);
        }
 
http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd_loaddata.c?r1=1.6&r2=1.7&diff_format=u
Index: php-src/ext/mysqlnd/mysqlnd_loaddata.c
diff -u php-src/ext/mysqlnd/mysqlnd_loaddata.c:1.6 
php-src/ext/mysqlnd/mysqlnd_loaddata.c:1.7
--- php-src/ext/mysqlnd/mysqlnd_loaddata.c:1.6  Wed Apr 16 12:53:18 2008
+++ php-src/ext/mysqlnd/mysqlnd_loaddata.c      Mon Oct 27 17:20:25 2008
@@ -27,7 +27,8 @@
 
 enum_func_status mysqlnd_simple_command_handle_response(MYSQLND *conn,
                                                                                
enum php_mysql_packet_type ok_packet,
-                                                                               
zend_bool silent, enum php_mysqlnd_server_command command
+                                                                               
zend_bool silent, enum php_mysqlnd_server_command command,
+                                                                               
zend_bool ignore_upsert_status
                                                                                
TSRMLS_DC);
 
 
@@ -241,7 +242,7 @@
 
 infile_error:
        /* get response from server and update upsert values */
-       if (FAIL == mysqlnd_simple_command_handle_response(conn, 
PROT_OK_PACKET, FALSE, COM_QUERY TSRMLS_CC)) {
+       if (FAIL == mysqlnd_simple_command_handle_response(conn, 
PROT_OK_PACKET, FALSE, COM_QUERY, FALSE TSRMLS_CC)) {
                result = FAIL;
                goto infile_error;
        }
http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd_ps.c?r1=1.21&r2=1.22&diff_format=u
Index: php-src/ext/mysqlnd/mysqlnd_ps.c
diff -u php-src/ext/mysqlnd/mysqlnd_ps.c:1.21 
php-src/ext/mysqlnd/mysqlnd_ps.c:1.22
--- php-src/ext/mysqlnd/mysqlnd_ps.c:1.21       Sun Oct 19 12:22:49 2008
+++ php-src/ext/mysqlnd/mysqlnd_ps.c    Mon Oct 27 17:20:25 2008
@@ -18,7 +18,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: mysqlnd_ps.c,v 1.21 2008/10/19 12:22:49 johannes Exp $ */
+/* $Id: mysqlnd_ps.c,v 1.22 2008/10/27 17:20:25 johannes Exp $ */
 #include "php.h"
 #include "mysqlnd.h"
 #include "mysqlnd_wireprotocol.h"
@@ -39,7 +39,8 @@
 enum_func_status mysqlnd_simple_command(MYSQLND *conn, enum 
php_mysqlnd_server_command command,
                                                                                
const char * const arg, size_t arg_len,
                                                                                
enum php_mysql_packet_type ok_packet,
-                                                                               
zend_bool silent TSRMLS_DC);
+                                                                               
zend_bool silent, zend_bool ignore_upsert_status
+                                                                               
TSRMLS_DC);
 
 /* Exported by mysqlnd_ps_codec.c */
 zend_uchar* mysqlnd_stmt_execute_generate_request(MYSQLND_STMT *stmt, size_t 
*request_len,
@@ -420,7 +421,7 @@
        }
 
        if (FAIL == mysqlnd_simple_command(stmt_to_prepare->conn, 
COM_STMT_PREPARE, query,
-                                                                          
query_len, PROT_LAST, FALSE TSRMLS_CC) ||
+                                                                          
query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) ||
                FAIL == mysqlnd_stmt_read_prepare_response(stmt_to_prepare 
TSRMLS_CC)) {
                goto fail;
        }
@@ -682,7 +683,7 @@
 
        ret = mysqlnd_simple_command(stmt->conn, COM_STMT_EXECUTE, (char 
*)request, request_len,
                                                                 PROT_LAST /* 
we will handle the response packet*/,
-                                                                FALSE 
TSRMLS_CC);
+                                                                FALSE, FALSE 
TSRMLS_CC);
 
        if (free_request) {
                mnd_efree(request);
@@ -990,7 +991,7 @@
 
        if (FAIL == mysqlnd_simple_command(stmt->conn, COM_STMT_FETCH, (char 
*)buf, sizeof(buf),
                                                                           
PROT_LAST /* we will handle the response packet*/,
-                                                                          
FALSE TSRMLS_CC)) {
+                                                                          
FALSE, TRUE TSRMLS_CC)) {
                stmt->error_info = stmt->conn->error_info;
                DBG_RETURN(FAIL);
        }
@@ -1182,7 +1183,7 @@
                if (CONN_GET_STATE(conn) == CONN_READY &&
                        FAIL == (ret = mysqlnd_simple_command(conn, 
COM_STMT_RESET, (char *)cmd_buf,
                                                                                
                  sizeof(cmd_buf), PROT_OK_PACKET,
-                                                                               
                  FALSE TSRMLS_CC))) {
+                                                                               
                  FALSE, TRUE TSRMLS_CC))) {
                        stmt->error_info = conn->error_info;
                }
                stmt->upsert_status = conn->upsert_status;
@@ -1254,7 +1255,7 @@
 
                /* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/
                ret = mysqlnd_simple_command(conn, cmd, (char *)cmd_buf, 
packet_len,
-                                                                        
PROT_LAST , FALSE TSRMLS_CC);
+                                                                        
PROT_LAST , FALSE, TRUE TSRMLS_CC);
                mnd_efree(cmd_buf);
                if (FAIL == ret) {
                        stmt->error_info = conn->error_info;
@@ -2023,7 +2024,7 @@
                if (CONN_GET_STATE(conn) == CONN_READY &&
                        FAIL == mysqlnd_simple_command(conn, COM_STMT_CLOSE, 
(char *)cmd_buf, sizeof(cmd_buf),
                                                                                
   PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/,
-                                                                               
   FALSE TSRMLS_CC)) {
+                                                                               
   FALSE, TRUE TSRMLS_CC)) {
                        stmt->error_info = conn->error_info;
                        DBG_RETURN(FAIL);
                }

http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_insert_id_variation.phpt?view=markup&rev=1.1
Index: php-src/ext/mysqli/tests/mysqli_insert_id_variation.phpt
+++ php-src/ext/mysqli/tests/mysqli_insert_id_variation.phpt
--TEST--
Checking last_insert_id after different operations
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifconnectfailure.inc');
?>
--FILE--
<?php
include "connect.inc";

if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
    printf("[001] Cannot connect to the server using host=%s, user=%s, 
passwd=***, dbname=%s, port=%s, socket=%s\n",
                        $host, $user, $db, $port, $socket);

$link->query("DROP TABLE IF EXISTS test_insert_id_var");
$link->query("CREATE TABLE test_insert_id_var (id INT auto_increment, PRIMARY 
KEY (id))");
$link->query("INSERT INTO test_insert_id_var VALUES (null)");
$i = $link->insert_id;

if (!$i) {
    printf("[001] Got no valid insert id: %s", var_export($i, true));
    die();
}


$link->options(MYSQLI_OPT_LOCAL_INFILE, false);
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[002] mysqli_option changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}

/*
$link->dump_debug_info();
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[003] mysqli_debug_info changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}
*/

$link->stat();
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[004] mysqli_stat changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}

/*$link->kill($link->thread_id);
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[005] mysqli_kill changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}*/

$link->ping();
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[006] mysqli_ping changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}

/*
mysqlnd resets the IDE to 0
libmysql doesn't

$link->change_user ($user, $passwd, $db);
if (0 != $link->insert_id || 0 != mysqli_insert_id($link)) {
    printf("[007] mysqli_change_user changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}
*/

$stmt = $link->prepare("SELECT 1");
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[008a] mysqli_prepare changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}
echo mysqli_error($link);
if (0 != $stmt->insert_id || 0 != mysqli_stmt_insert_id($stmt)) {
    printf("[008b] mysqli_stmt doesn't initialise insert_id: %s", 
var_export($stmt->insert_id, true));
    die();
}

unset($stmt);
if ($i != $link->insert_id || $i != mysqli_insert_id($link)) {
    printf("[009] stmt free changes insert_id: %s", 
var_export($link->insert_id, true));
    die();
}

$link->query("DROP TABLE IF EXISTS test_insert_id_var");

echo "DONE";
--EXPECTF--
DONE


-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to