MySQL 9: Add support for VECTOR type (#15431)

This commit is contained in:
Kamil Tekiela 2024-08-20 17:34:52 +02:00 committed by GitHub
parent c9ea4d76af
commit a1ab846231
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 62 additions and 8 deletions

View file

@ -400,6 +400,11 @@ const MYSQLI_TYPE_INTERVAL = UNKNOWN;
* @cvalue FIELD_TYPE_GEOMETRY
*/
const MYSQLI_TYPE_GEOMETRY = UNKNOWN;
/**
* @var int
* @cvalue FIELD_TYPE_VECTOR
*/
const MYSQLI_TYPE_VECTOR = UNKNOWN;
#ifdef FIELD_TYPE_JSON
/**
* @var int

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 6a64c5833a4c83d0bd0e63f34d27d2e696c78b66 */
* Stub hash: ff768a152d4ee91b184999d351ce39a7d0bfef46 */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING)
ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0)
@ -1118,6 +1118,7 @@ static void register_mysqli_symbols(int module_number)
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_CHAR", FIELD_TYPE_CHAR, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_INTERVAL", FIELD_TYPE_INTERVAL, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_GEOMETRY", FIELD_TYPE_GEOMETRY, CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_VECTOR", FIELD_TYPE_VECTOR, CONST_PERSISTENT);
#if defined(FIELD_TYPE_JSON)
REGISTER_LONG_CONSTANT("MYSQLI_TYPE_JSON", FIELD_TYPE_JSON, CONST_PERSISTENT);
#endif

View file

@ -1,5 +1,5 @@
--TEST--
Bug GH-15432 (Heap corruption when querying a vector)
Bug GH-15432 (Heap corruption when querying a vector/PHP crashes when processing a MySQL DB query with a new Vector format introduced in MySQL 9.0)
--EXTENSIONS--
mysqli
--SKIPIF--
@ -16,9 +16,49 @@ if ($link->server_version < 90000 || $link->server_version >= 10_00_00) {
--FILE--
<?php
require 'connect.inc';
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket);
var_dump($link->query('SELECT STRING_TO_VECTOR("[1.05, -17.8, 32]")'));
$expected = '00000040000040400000a040';
mysqli_query($link, "DROP TABLE IF EXISTS test");
mysqli_query($link, "CREATE TABLE test(vectorfield VECTOR)");
mysqli_query($link, 'INSERT INTO test VALUES (TO_VECTOR("[2, 3, 5]"))');
// Textual protocol
$result = mysqli_query($link, "SELECT vectorfield FROM test")->fetch_column();
$value = bin2hex($result);
if($value !== $expected) {
printf("[001] Expecting %s/%s, got %s/%s\n",
gettype($expected), $expected,
gettype($value), $value);
}
// Binary protocol
$result = $link->execute_query("SELECT vectorfield FROM test")->fetch_column();
$value = bin2hex($result);
if($value !== $expected) {
printf("[002] Expecting %s/%s, got %s/%s\n",
gettype($expected), $expected,
gettype($value), $value);
}
// Testing inverse to make sure the value hasn't been changed
$expected = '[2.00000e+00,3.00000e+00,5.00000e+00]';
$result = $link->execute_query("SELECT VECTOR_TO_STRING(0x". $value .")")->fetch_column();
if($result !== $expected) {
printf("[002] Expecting %s/%s, got %s/%s\n",
gettype($expected), $expected,
gettype($result), $result);
}
echo "OK";
?>
--EXPECTF--
Warning: mysqli::query(): Unknown type 242 sent by the server. Please send a report to the developers in %s on line %d
bool(false)
--CLEAN--
<?php
require_once 'clean_table.inc';
?>
--EXPECT--
OK

View file

@ -66,6 +66,8 @@ $expected_constants = array(
"MYSQLI_TYPE_NEWDATE" => true,
"MYSQLI_TYPE_ENUM" => true,
"MYSQLI_TYPE_SET" => true,
"MYSQLI_TYPE_VECTOR" => true,
"MYSQLI_TYPE_JSON" => true,
"MYSQLI_TYPE_TINY_BLOB" => true,
"MYSQLI_TYPE_MEDIUM_BLOB" => true,
"MYSQLI_TYPE_LONG_BLOB" => true,
@ -143,8 +145,6 @@ $expected_constants["MYSQLI_DATA_TRUNCATED"] = true;
$expected_constants["MYSQLI_OPT_CAN_HANDLE_EXPIRED_PASSWORDS"] = true;
$expected_constants["MYSQLI_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS"] = true;
$expected_constants["MYSQLI_TYPE_JSON"] = true;
$unexpected_constants = array();
foreach ($constants as $consts) {

View file

@ -280,6 +280,7 @@ typedef enum mysqlnd_field_types
MYSQL_TYPE_NEWDATE = 14,
MYSQL_TYPE_VARCHAR = 15,
MYSQL_TYPE_BIT = 16,
MYSQL_TYPE_VECTOR=242,
MYSQL_TYPE_JSON=245,
MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
@ -322,6 +323,7 @@ typedef enum mysqlnd_server_option
#define FIELD_TYPE_NEWDATE MYSQL_TYPE_NEWDATE
#define FIELD_TYPE_ENUM MYSQL_TYPE_ENUM
#define FIELD_TYPE_SET MYSQL_TYPE_SET
#define FIELD_TYPE_VECTOR MYSQL_TYPE_VECTOR
#define FIELD_TYPE_JSON MYSQL_TYPE_JSON
#define FIELD_TYPE_TINY_BLOB MYSQL_TYPE_TINY_BLOB
#define FIELD_TYPE_MEDIUM_BLOB MYSQL_TYPE_MEDIUM_BLOB

View file

@ -414,6 +414,10 @@ void _mysqlnd_init_ps_fetch_subsystem(void)
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].php_type= IS_STRING;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VECTOR].func = ps_fetch_string;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VECTOR].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_VECTOR].php_type = IS_STRING;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].func = ps_fetch_string;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].php_type = IS_STRING;

View file

@ -1468,6 +1468,7 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_ROW_BUFFER * row_buffer, zval * fi
case MYSQL_TYPE_MEDIUM_BLOB:statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_LONG_BLOB: statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_BLOB: statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_VECTOR: statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_VAR_STRING: statistic = STAT_BINARY_TYPE_FETCHED_STRING; break;
case MYSQL_TYPE_STRING: statistic = STAT_BINARY_TYPE_FETCHED_STRING; break;
case MYSQL_TYPE_GEOMETRY: statistic = STAT_BINARY_TYPE_FETCHED_GEOMETRY; break;
@ -1553,6 +1554,7 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_ROW_BUFFER * row_buffer, zval * fiel
case MYSQL_TYPE_MEDIUM_BLOB:statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_LONG_BLOB: statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_BLOB: statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_VECTOR: statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
case MYSQL_TYPE_VAR_STRING: statistic = STAT_TEXT_TYPE_FETCHED_STRING; break;
case MYSQL_TYPE_STRING: statistic = STAT_TEXT_TYPE_FETCHED_STRING; break;
case MYSQL_TYPE_GEOMETRY: statistic = STAT_TEXT_TYPE_FETCHED_GEOMETRY; break;