]> granicus.if.org Git - php/commitdiff
Handle mysqli errors in more cases
authorDharman <tekiela246@gmail.com>
Thu, 17 Sep 2020 22:45:17 +0000 (23:45 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 28 Oct 2020 10:33:50 +0000 (11:33 +0100)
Report errors autocommit, commit, rollback and mysqli_stmt_attr_set.

Additionally, copy the error from conn to stmt when preparing fails,
so these errors are also handled by mysqli_stmt_prepare.

Closes GH-6157.

ext/mysqli/mysqli_api.c
ext/mysqli/tests/mysqli_report.phpt
ext/mysqlnd/mysqlnd_ps.c

index e164e701b42d811d81eb49edf8bfc0d4d2007f3f..9a54171b3070c552055d49df5b97d2e5ec3e918c 100644 (file)
@@ -171,6 +171,7 @@ PHP_FUNCTION(mysqli_autocommit)
        MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 
        if (mysql_autocommit(mysql->mysql, (my_bool)automode)) {
+               MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -754,6 +755,7 @@ PHP_FUNCTION(mysqli_commit)
 #else
        if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
 #endif
+               MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -1989,6 +1991,7 @@ PHP_FUNCTION(mysqli_rollback)
 #else
        if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
 #endif
+               MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -2350,6 +2353,7 @@ PHP_FUNCTION(mysqli_stmt_attr_set)
 #else
        if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
 #endif
+               MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
                RETURN_FALSE;
        }
        RETURN_TRUE;
index 86fb45bc87c21d7babab9ed8e9c979bde90f4e78..33730976976ee9963bc88290d127fa95b1d0a45c 100644 (file)
@@ -49,6 +49,20 @@ require_once('skipifconnectfailure.inc');
         printf("[009] select_db should have failed\n");
     // mysqli_store_result() and mysqli_use_result() cannot be tested, because one would need to cause an error inside the C function to test it
 
+    mysqli_multi_query($link, "SELECT 1; FOO;");
+    mysqli_autocommit($link, true);
+    mysqli_commit($link);
+    mysqli_rollback($link);
+    $stmt = mysqli_stmt_init($link);
+    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
+    while(mysqli_more_results($link)) {
+        mysqli_next_result($link);
+        $res = mysqli_store_result($link);
+    }
+    mysqli_next_result($link);
+
+    $stmt = mysqli_prepare($link, "SELECT 1");
+    mysqli_stmt_attr_set($stmt, MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE);
 
     // Check that none of the above would have caused any error messages if MYSQL_REPORT_ERROR would
     // not have been set. If that would be the case, the test would be broken.
@@ -65,6 +79,21 @@ require_once('skipifconnectfailure.inc');
     mysqli_real_query($link, "FOO");
     mysqli_select_db($link, "Oh lord, let this be an unknown database name");
 
+    mysqli_multi_query($link, "SELECT 1; FOO;");
+    mysqli_autocommit($link, true);
+    mysqli_commit($link);
+    mysqli_rollback($link);
+    $stmt = mysqli_stmt_init($link);
+    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
+    while(mysqli_more_results($link)) {
+        mysqli_next_result($link);
+        $res = mysqli_store_result($link);
+    }
+    mysqli_next_result($link);
+
+    $stmt = mysqli_prepare($link, "SELECT 1");
+    mysqli_stmt_attr_set($stmt, MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE);
+
     /*
     Internal macro MYSQL_REPORT_STMT_ERROR
     */
@@ -294,6 +323,18 @@ Warning: mysqli_prepare(): (%d/%d): You have an error in your SQL syntax; check
 
 Warning: mysqli_real_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
 
+Warning: mysqli_autocommit(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
+
+Warning: mysqli_commit(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
+
+Warning: mysqli_rollback(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
+
+Warning: mysqli_stmt_prepare(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
+
+Warning: mysqli_store_result(): (%s/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
+
+Warning: mysqli_stmt_attr_set(): (%s/%d): Not implemented in %s on line %d
+
 Warning: mysqli_kill(): processid should have positive value in %s on line %d
 
 Warning: mysqli_stmt_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
index d4d34ee500efa3199c96469d6ab7124e78d0152b..010a7bbb4139fb5276c1f1215d04321b94c1a0af 100644 (file)
@@ -411,6 +411,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
 
                ret = conn->command->stmt_prepare(conn, query_string);
                if (FAIL == ret) {
+                       COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
                        goto fail;
                }
        }