From 6d42e9f1e34680f1b8c671666436abb8c7c1bbe0 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Wed, 10 Feb 2021 01:35:50 -0700 Subject: [PATCH] PDO: add mysql-specific warning count function MySQL supplies the count of warnings along with the result set and provides a handy function to retrieve it. Without this, the only way to discover if there has been warnings in the last query is to run *another* query: "SHOW WARNINGS" OR "SELECT @@warning_count". This requires another round-trip across the network which makes warning discovery or reporting a drag on performance. Instead, we use the existing get_driver_methods function that others (postgres, sqlite) use to provide custom functionality outside the standard PDO interface. Thinking about the PDO interface, I looked into several other PDO drivers but couldn't find an analog for mysql_warning_count(). Thus I determined that this may well stay mysql-specific. Fixes php bug: #51499 (https://bugs.php.net/bug.php?id=51499) --- ext/pdo_mysql/mysql_driver.c | 32 ++++++++++++++++++- .../tests/pdo_mysql_get_warning_count.phpt | 22 +++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_mysql/tests/pdo_mysql_get_warning_count.phpt diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index c5dcc264adb1a..4c821a65d4e13 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -581,6 +581,36 @@ static zend_result pdo_mysql_check_liveness(pdo_dbh_t *dbh) } /* }}} */ +/* {{{ proto string PDO::mysqlGetWarningCount() + Returns the number of SQL warnings during the execution of the last statement */ +static PHP_METHOD(PDO, mysqlGetWarningCount) +{ + pdo_dbh_t *dbh; + pdo_mysql_db_handle *H; + + dbh = Z_PDO_DBH_P(ZEND_THIS); + PDO_CONSTRUCT_CHECK; + + H = (pdo_mysql_db_handle *)dbh->driver_data; + RETURN_LONG(mysql_warning_count(H->server)); +} +/* }}} */ + +static const zend_function_entry dbh_methods[] = { + PHP_ME(PDO, mysqlGetWarningCount, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; + +static const zend_function_entry *pdo_mysql_get_driver_methods(pdo_dbh_t *dbh, int kind) +{ + switch (kind) { + case PDO_DBH_DRIVER_METHOD_KIND_DBH: + return dbh_methods; + default: + return NULL; + } +} + /* {{{ pdo_mysql_request_shutdown */ static void pdo_mysql_request_shutdown(pdo_dbh_t *dbh) { @@ -625,7 +655,7 @@ static const struct pdo_dbh_methods mysql_methods = { pdo_mysql_fetch_error_func, pdo_mysql_get_attribute, pdo_mysql_check_liveness, - NULL, + pdo_mysql_get_driver_methods, pdo_mysql_request_shutdown, pdo_mysql_in_transaction, NULL /* get_gc */ diff --git a/ext/pdo_mysql/tests/pdo_mysql_get_warning_count.phpt b/ext/pdo_mysql/tests/pdo_mysql_get_warning_count.phpt new file mode 100644 index 0000000000000..4411532f5cf27 --- /dev/null +++ b/ext/pdo_mysql/tests/pdo_mysql_get_warning_count.phpt @@ -0,0 +1,22 @@ +--TEST-- +MySQL PDO->mysqlGetWarningCount() +--SKIPIF-- + +--FILE-- +query($q); + printf("Query %s produced %d warnings\n", $q, $db->mysqlGetWarningCount()); + }; + $assertWarnings($db, 'SELECT 1 = 1', 0); + $assertWarnings($db, 'SELECT 1 = "A"', 1); +?> +--EXPECT-- +Query SELECT 1 = 1 produced 0 warnings +Query SELECT 1 = "A" produced 1 warnings