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..2ed3f9e79c437 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); @@ -827,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); 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 diff --git a/ext/pdo_mysql/tests/gh15093.phpt b/ext/pdo_mysql/tests/gh15093.phpt new file mode 100644 index 0000000000000..070559344226c --- /dev/null +++ b/ext/pdo_mysql/tests/gh15093.phpt @@ -0,0 +1,170 @@ +--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 (uuid_to_bin(uuid())), + `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-- +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 + ) + +)