From ba3c4c914722174c8ac307b90b92a7a2e583e1f1 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Thu, 25 Jul 2024 16:22:29 -0400 Subject: [PATCH 1/9] Add additional flags to the output returned from the getColumnMeta() method for the pdo_mysql driver. --- ext/mysqlnd/mysqlnd_enum_n_def.h | 23 ++++++++++++++++----- ext/pdo_mysql/mysql_statement.c | 34 ++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h index 27846f077a849..f2ff5616f9672 100644 --- a/ext/mysqlnd/mysqlnd_enum_n_def.h +++ b/ext/mysqlnd/mysqlnd_enum_n_def.h @@ -348,14 +348,27 @@ typedef enum mysqlnd_server_option #define SET_FLAG 2048 #define NO_DEFAULT_VALUE_FLAG 4096 #define ON_UPDATE_NOW_FLAG 8192 +#define NUM_FLAG 32768 + +/* The following flags are marked as internal in mysql_com.h */ #define PART_KEY_FLAG 16384 #define GROUP_FLAG 32768 -#define NUM_FLAG 32768 -#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) -#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) -#define IS_BLOB(n) ((n) & BLOB_FLAG) -#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL) +#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) +#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) +#define IS_UNIQUE_KEY(n) ((n) & UNIQUE_KEY_FLAG) +#define IS_MULTIPLE_KEY(n) ((n) & MULTIPLE_KEY_FLAG) +#define IS_BLOB(n) ((n) & BLOB_FLAG) +#define IS_UNSIGNED(n) ((n) & UNSIGNED_FLAG) +#define IS_ZEROFILL(n) ((n) & ZEROFILL_FLAG) +#define IS_BINARY(n) ((n) & BINARY_FLAG) +#define IS_ENUM(n) ((n) & ENUM_FLAG) +#define IS_AUTO_INCREMENT(n) ((n) & AUTO_INCREMENT_FLAG) +#define IS_TIMESTAMP(n) ((n) & TIMESTAMP_FLAG) +#define IS_SET(n) ((n) & SET_FLAG) +#define IS_NO_DEFAULT_VALUE(n) ((n) & NO_DEFAULT_VALUE_FLAG) +#define IS_ON_UPDATE_NOW(n) ((n) & ON_UPDATE_NOW_FLAG) +#define IS_NUM(n) ((n) & NUM_FLAG) /* diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index 9c28be41e9edf..edd31cd4c3412 100644 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -793,15 +793,45 @@ static int pdo_mysql_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *retu if (IS_PRI_KEY(F->flags)) { add_next_index_string(&flags, "primary_key"); } - if (F->flags & MULTIPLE_KEY_FLAG) { + if (IS_MULTIPLE_KEY(F->flags)) { add_next_index_string(&flags, "multiple_key"); } - if (F->flags & UNIQUE_KEY_FLAG) { + if (IS_UNIQUE_KEY(F->flags)) { add_next_index_string(&flags, "unique_key"); } if (IS_BLOB(F->flags)) { add_next_index_string(&flags, "blob"); } + if (IS_UNSIGNED(F->flags)) { + add_next_index_string(&flags, "unsigned"); + } + if (IS_ZEROFILL(F->flags)) { + add_next_index_string(&flags, "zerofill"); + } + if (IS_BINARY(F->flags)) { + add_next_index_string(&flags, "binary"); + } + if (IS_ENUM(F->flags)) { + add_next_index_string(&flags, "enum"); + } + if (IS_AUTO_INCREMENT(F->flags)) { + add_next_index_string(&flags, "auto_increment"); + } + if (IS_TIMESTAMP(F->flags)) { + add_next_index_string(&flags, "timestamp"); + } + if (IS_SET(F->flags)) { + add_next_index_string(&flags, "set"); + } + if (IS_NO_DEFAULT_VALUE(F->flags)) { + add_next_index_string(&flags, "no_default_value"); + } + if (IS_ON_UPDATE_NOW(F->flags)) { + add_next_index_string(&flags, "on_update_now"); + } + if (IS_NUM(F->flags)) { + add_next_index_string(&flags, "num"); + } str = type_to_name_native(F->type); if (str) { add_assoc_string(return_value, "native_type", str); From 19b7a9e5949076dd250f38b6baa888ba7abed53e Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Thu, 25 Jul 2024 16:23:08 -0400 Subject: [PATCH 2/9] Add 'native_flags' value to the output returned from the getColumnMeta() method for the pdo_mysql driver. --- ext/pdo_mysql/mysql_statement.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c index edd31cd4c3412..2ed3f9e79c437 100644 --- a/ext/pdo_mysql/mysql_statement.c +++ b/ext/pdo_mysql/mysql_statement.c @@ -857,6 +857,7 @@ static int pdo_mysql_stmt_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *retu add_assoc_long(return_value, "pdo_type", param_type); add_assoc_zval(return_value, "flags", &flags); + add_assoc_long(return_value, "native_flags", F->flags); add_assoc_string(return_value, "table", (char *) (F->table?F->table : "")); PDO_DBG_RETURN(SUCCESS); From 398200f90d85e15aea999fb6e3e746b6028cdaa3 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Fri, 26 Jul 2024 14:53:52 -0400 Subject: [PATCH 3/9] Update expected test output for pdo_mysql bug_33689. --- ext/pdo_mysql/tests/bug_33689.phpt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/pdo_mysql/tests/bug_33689.phpt b/ext/pdo_mysql/tests/bug_33689.phpt index 1041eb82c8fc1..4919f92376c7d 100644 --- a/ext/pdo_mysql/tests/bug_33689.phpt +++ b/ext/pdo_mysql/tests/bug_33689.phpt @@ -56,8 +56,11 @@ Array [flags] => Array ( [0] => not_null + [1] => no_default_value + [2] => num ) + [native_flags] => 36865 [table] => test_33689 [name] => bar [len] => 11 From 8bd06a7a58122057f5b96ebaba5dc4c11d083708 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Sun, 28 Jul 2024 22:40:46 -0400 Subject: [PATCH 4/9] Add test without output for new pdo_mysql flags. --- ext/pdo_mysql/tests/gh15093.phpt | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 ext/pdo_mysql/tests/gh15093.phpt diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt new file mode 100644 index 0000000000000..40a1bd9710311 --- /dev/null +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -0,0 +1,53 @@ +--TEST-- +GH-15093: Add support for all flags from mysql in the PDO MySql driver in the getColumnMeta function. +--EXTENSIONS-- +pdo_mysql +--SKIPIF-- + +--FILE-- +exec(" + CREATE TABLE gh_15093 ( + `id` INT NOT NULL AUTO_INCREMENT, + `uuid` BINARY(16) DEFAULT random_bytes(16), + `blob` BLOB, + `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `set` SET('one', 'two'), + `enum` ENUM('a', 'b', 'c'), + 'num' INT(11) UNSIGNED ZEROFILL DEFAULT 0, + PRIMARY KEY(`id`), + UNIQUE KEY `UUID` (`uuid`) + ) +"); + +$stmt = $db->prepare('SELECT `id`, `uuid`, `blob`, `ts`, `set`, `enum`, `num` FROM gh_15093'); +$stmt->execute(); + +$n = $stmt->columnCount(); +$meta = []; + +for ($i = 0; $i < $n; ++$i) { + $m = $stmt->getColumnMeta($i); + + // libmysql and mysqlnd will show the pdo_type entry at a different position in the hash + // and will report a different type, as mysqlnd returns native types. + unset($m['pdo_type']); + + $meta[$i] = $m; +} + +print_r($meta); +?> +--CLEAN-- +exec('DROP TABLE IF EXISTS gh_15093'); +?> +--EXPECTF-- From 7d3aba9497ce928bc48b58e2d3fbf71fb6844612 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Mon, 29 Jul 2024 08:46:01 -0400 Subject: [PATCH 5/9] Fix create table statement for new pdo_mysql test. --- ext/pdo_mysql/tests/gh15093.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt index 40a1bd9710311..0aa0ba6f3f49d 100644 --- a/ext/pdo_mysql/tests/gh15093.phpt +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -13,14 +13,14 @@ require_once __DIR__ . '/inc/mysql_pdo_test.inc'; $db = MySQLPDOTest::factory(); $db->exec(" - CREATE TABLE gh_15093 ( + CREATE TABLE `gh_15093` ( `id` INT NOT NULL AUTO_INCREMENT, - `uuid` BINARY(16) DEFAULT random_bytes(16), + `uuid` BINARY(16), `blob` BLOB, `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `set` SET('one', 'two'), `enum` ENUM('a', 'b', 'c'), - 'num' INT(11) UNSIGNED ZEROFILL DEFAULT 0, + `num` INT(11) UNSIGNED ZEROFILL DEFAULT 0, PRIMARY KEY(`id`), UNIQUE KEY `UUID` (`uuid`) ) From fb9a2acbf6e92def555a0b8c678f507229bb5905 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Mon, 29 Jul 2024 09:17:54 -0400 Subject: [PATCH 6/9] Add default value to uuid column in pdo_mysql test. --- ext/pdo_mysql/tests/gh15093.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt index 0aa0ba6f3f49d..2cc60a9d02b73 100644 --- a/ext/pdo_mysql/tests/gh15093.phpt +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -15,7 +15,7 @@ $db = MySQLPDOTest::factory(); $db->exec(" CREATE TABLE `gh_15093` ( `id` INT NOT NULL AUTO_INCREMENT, - `uuid` BINARY(16), + `uuid` BINARY(16) DEFAULT (uuid_to_bin(uuid())), `blob` BLOB, `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `set` SET('one', 'two'), From 0d19718b1fcf1525f3c7c7e528f2aef30e991ba6 Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Mon, 29 Jul 2024 11:09:26 -0400 Subject: [PATCH 7/9] Add expected output for pdo_mysql test. --- ext/pdo_mysql/tests/gh15093.phpt | 117 +++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt index 2cc60a9d02b73..070559344226c 100644 --- a/ext/pdo_mysql/tests/gh15093.phpt +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -51,3 +51,120 @@ $db = MySQLPDOTest::factory(); $db->exec('DROP TABLE IF EXISTS gh_15093'); ?> --EXPECTF-- +Array +( + [0] => Array + ( + [native_type] => LONG + [flags] => Array + ( + [0] => not_null + [1] => primary_key + [2] => auto_increment + [3] => num + ) + + [native_flags] => 49667 + [table] => gh_15093 + [name] => id + [len] => 11 + [precision] => 0 + ) + + [1] => Array + ( + [native_type] => STRING + [flags] => Array + ( + [0] => unique_key + [1] => binary + ) + + [native_flags] => 16516 + [table] => gh_15093 + [name] => uuid + [len] => 16 + [precision] => 0 + ) + + [2] => Array + ( + [native_type] => BLOB + [flags] => Array + ( + [0] => blob + [1] => binary + ) + + [native_flags] => 144 + [table] => gh_15093 + [name] => blob + [len] => 65535 + [precision] => 0 + ) + + [3] => Array + ( + [native_type] => TIMESTAMP + [flags] => Array + ( + [0] => binary + [1] => timestamp + [2] => on_update_now + ) + + [native_flags] => 9344 + [table] => gh_15093 + [name] => ts + [len] => 19 + [precision] => 0 + ) + + [4] => Array + ( + [native_type] => STRING + [flags] => Array + ( + [0] => set + ) + + [native_flags] => 2048 + [table] => gh_15093 + [name] => set + [len] => 28 + [precision] => 0 + ) + + [5] => Array + ( + [native_type] => STRING + [flags] => Array + ( + [0] => enum + ) + + [native_flags] => 256 + [table] => gh_15093 + [name] => enum + [len] => 4 + [precision] => 0 + ) + + [6] => Array + ( + [native_type] => LONG + [flags] => Array + ( + [0] => unsigned + [1] => zerofill + [2] => num + ) + + [native_flags] => 32864 + [table] => gh_15093 + [name] => num + [len] => 11 + [precision] => 0 + ) + +) From ba7c8d24aadf741c53a91b585ed9c2507576c45d Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Tue, 30 Jul 2024 13:24:44 -0400 Subject: [PATCH 8/9] Skip the new pdo_mysql flags test if we are not testing against the mysqlnd driver. --- ext/pdo_mysql/tests/gh15093.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt index 070559344226c..3a4988835b752 100644 --- a/ext/pdo_mysql/tests/gh15093.phpt +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -5,7 +5,7 @@ pdo_mysql --SKIPIF-- --FILE-- Date: Thu, 1 Aug 2024 08:10:53 -0400 Subject: [PATCH 9/9] Revert "Skip the new pdo_mysql flags test if we are not testing against the mysqlnd driver." This reverts commit ba7c8d24aadf741c53a91b585ed9c2507576c45d as it causes the test to fail. --- ext/pdo_mysql/tests/gh15093.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt index 3a4988835b752..070559344226c 100644 --- a/ext/pdo_mysql/tests/gh15093.phpt +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -5,7 +5,7 @@ pdo_mysql --SKIPIF-- --FILE--