From 283d47c7b080c80574f47b00b4ec85b418b25d22 Mon Sep 17 00:00:00 2001 From: shannon data ai Date: Wed, 10 Jul 2024 16:10:01 +0800 Subject: [PATCH] feat(shannon): Native Vector Embeddings Support --- client/mysql.cc | 7 +- client/mysqldump.cc | 1 + client/mysqltest.cc | 28 + include/field_types.h | 5 +- include/mysql.h.pp | 5 +- .../services/bits/stored_program_bits.h | 1 + libbinlogevents/include/rows_event.h | 4 +- libbinlogevents/src/binary_log_funcs.cpp | 2 + libbinlogevents/src/rows_event.cpp | 21 + libmysql/libmysql.cc | 10 +- mysql-test/r/archive.result | 9 + mysql-test/r/blackhole.result | 7 + mysql-test/r/csv.result | 9 + .../r/information_schema_parameters.result | 2 +- .../r/information_schema_routines.result | 2 +- mysql-test/r/myisam.result | 9 + mysql-test/std_data/rpl_vector_binlog.000001 | Bin 0 -> 1466 bytes .../suite/funcs_1/r/is_columns_ci.result | 2 +- .../suite/funcs_1/r/is_columns_cs.result | 2 +- mysql-test/suite/funcs_1/r/is_routines.result | 2 +- .../suite/funcs_1/r/is_routines_ci.result | 2 +- .../r/i_s_schema_definition_debug.result | 24 +- .../t/i_s_schema_definition_debug.test | 6 + mysql-test/suite/ndbcluster/vector.result | 6 + mysql-test/suite/ndbcluster/vector.test | 5 + mysql-test/suite/rpl/r/rpl_vector.result | 238 +++++++++ mysql-test/suite/rpl/t/rpl_vector.test.bak | 486 ++++++++++++++++++ mysql-test/t/archive.test | 8 + mysql-test/t/blackhole.test | 8 + mysql-test/t/csv.test | 9 + mysql-test/t/dd_schema_definition_debug.test | 6 + mysql-test/t/myisam.test | 8 + plugin/x/src/mysql_function_names.cc | 4 + plugin/x/src/sql_data_result.cc | 2 +- plugin/x/src/streaming_command_delegate.cc | 1 + share/messages_to_clients.txt | 15 + sql-common/bind_params.cc | 1 + sql-common/client.cc | 2 + sql/create_field.cc | 16 + sql/dd/dd_table.cc | 3 + sql/dd/dd_version.h | 5 + sql/dd/impl/bootstrap/bootstrap_ctx.h | 1 - sql/dd/impl/system_views/columns.cc | 2 + sql/dd/impl/system_views/parameters.cc | 4 + sql/dd/impl/system_views/routines.cc | 4 + sql/dd/impl/tables/columns.cc | 2 +- sql/dd/impl/tables/parameters.cc | 2 +- sql/dd/impl/tables/routines.cc | 2 +- sql/dd/impl/types/index_impl.cc | 2 + sql/dd/types/column.h | 3 +- sql/dd_table_share.cc | 3 + sql/field.cc | 392 +++++++++++--- sql/field.h | 65 ++- sql/field_conv.cc | 9 +- sql/histograms/histogram.cc | 1 + sql/item.cc | 52 +- sql/item.h | 12 + sql/item_cmpfunc.cc | 17 +- sql/item_create.cc | 5 + sql/item_func.cc | 87 +++- sql/item_func.h | 30 +- sql/item_json_func.cc | 3 + sql/item_json_func.h | 16 + sql/item_strfunc.cc | 149 +++++- sql/item_strfunc.h | 31 ++ sql/item_sum.cc | 22 +- sql/item_timefunc.cc | 31 +- sql/item_timefunc.h | 12 + sql/item_xmlfunc.cc | 4 + sql/lex.h | 1 + sql/log_event.cc | 79 ++- sql/log_event.h | 12 +- sql/pack_rows.cc | 1 + sql/parse_tree_column_attrs.h | 15 + sql/partitioning/partition_handler.cc | 1 + sql/protocol_classic.cc | 1 + sql/rpl_utility.cc | 33 +- sql/rpl_utility.h | 27 +- .../mysql_query_attributes_imp.cc | 3 +- .../mysql_stored_program_imp.cc | 3 + sql/sql_insert.cc | 1 + sql/sql_optimizer.cc | 5 +- sql/sql_partition.cc | 14 + sql/sql_prepare.cc | 4 +- sql/sql_show.cc | 13 +- sql/sql_show.h | 3 +- sql/sql_table.cc | 13 + sql/sql_yacc.yy | 8 +- sql/vector_conversion.h | 144 ++++++ storage/innobase/fts/fts0fts.cc | 1 + storage/innobase/handler/ha_innodb.cc | 2 + storage/innobase/include/rem0cmp.ic | 1 + storage/innobase/rem/rem0cmp.cc | 1 + storage/myisam/ha_myisam.cc | 1 + storage/ndb/plugin/ha_ndbcluster.cc | 11 +- storage/ndb/plugin/ha_ndbcluster_cond.cc | 3 +- storage/temptable/include/temptable/handler.h | 1 + .../xplugin/xpl/mysql_function_names_t.cc.in | 5 + 98 files changed, 2186 insertions(+), 167 deletions(-) create mode 100644 mysql-test/std_data/rpl_vector_binlog.000001 create mode 100644 mysql-test/suite/ndbcluster/vector.result create mode 100644 mysql-test/suite/ndbcluster/vector.test create mode 100644 mysql-test/suite/rpl/r/rpl_vector.result create mode 100644 mysql-test/suite/rpl/t/rpl_vector.test.bak create mode 100644 sql/vector_conversion.h diff --git a/client/mysql.cc b/client/mysql.cc index fa6eded8f..1e83b1ea7 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1145,6 +1145,11 @@ static COMMANDS commands[] = { {"TO_DAYS", 0, nullptr, false, ""}, {"TOUCHES", 0, nullptr, false, ""}, {"TRIM", 0, nullptr, false, ""}, + {"TO_VECTOR", 0, nullptr, false, ""}, + {"STRING_TO_VECTOR", 0, nullptr, false, ""}, + {"FROM_VECTOR", 0, nullptr, false, ""}, + {"VECTOR_TO_STRING", 0, nullptr, false, ""}, + {"VECTOR_DIM", 0, nullptr, false, ""}, {"UCASE", 0, nullptr, false, ""}, {"UNCOMPRESS", 0, nullptr, false, ""}, {"UNCOMPRESSED_LENGTH", 0, nullptr, false, ""}, @@ -3736,7 +3741,7 @@ static bool is_binary_field(MYSQL_FIELD *field) { field->type == MYSQL_TYPE_TINY_BLOB || field->type == MYSQL_TYPE_VAR_STRING || field->type == MYSQL_TYPE_STRING || field->type == MYSQL_TYPE_VARCHAR || - field->type == MYSQL_TYPE_GEOMETRY)) + field->type == MYSQL_TYPE_VECTOR || field->type == MYSQL_TYPE_GEOMETRY)) return true; return false; } diff --git a/client/mysqldump.cc b/client/mysqldump.cc index 0bf85a1c0..5f1c0933c 100644 --- a/client/mysqldump.cc +++ b/client/mysqldump.cc @@ -3938,6 +3938,7 @@ static void dump_table(char *table, char *db) { field->type == MYSQL_TYPE_VAR_STRING || field->type == MYSQL_TYPE_VARCHAR || field->type == MYSQL_TYPE_BLOB || + field->type == MYSQL_TYPE_VECTOR || field->type == MYSQL_TYPE_LONG_BLOB || field->type == MYSQL_TYPE_MEDIUM_BLOB || field->type == MYSQL_TYPE_TINY_BLOB || diff --git a/client/mysqltest.cc b/client/mysqltest.cc index ec9798aef..8e7292c9d 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -8244,6 +8244,30 @@ static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD *field, } #endif + const size_t temp_val_max_width = (1 << 14); + char temp_val[temp_val_max_width]; + DYNAMIC_STRING ds_temp = {.str = nullptr, .length = 0, .max_length = 0}; + if (field->type == MYSQL_TYPE_VECTOR && !is_null) { + /* Do a binary to hex conversion for vector type */ + size_t orig_len = len; + len = 2 + orig_len * 2; + char *destination = temp_val; + if (len > temp_val_max_width) { + init_dynamic_string(&ds_temp, "", len + 1); + destination = ds_temp.str; + } + const char *ptr = val; + const char *end = ptr + orig_len; + val = destination; + int written = sprintf(destination, "0x"); + destination += written; + for (; ptr < end; ptr++, destination += written) { + written = sprintf( + destination, "%02X", + *(static_cast(static_cast(ptr)))); + } + } + if (!display_result_vertically) { if (col_idx) dynstr_append_mem(ds, "\t", 1); replace_dynstr_append_mem(ds, val, len); @@ -8253,6 +8277,10 @@ static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD *field, replace_dynstr_append_mem(ds, val, len); dynstr_append_mem(ds, "\n", 1); } + + if (ds_temp.str != nullptr) { + dynstr_free(&ds_temp); + } } /* diff --git a/include/field_types.h b/include/field_types.h index ead42b508..653a674db 100644 --- a/include/field_types.h +++ b/include/field_types.h @@ -76,8 +76,9 @@ enum enum_field_types { MYSQL_TYPE_DATETIME2, /**< Internal to MySQL. Not used in protocol */ MYSQL_TYPE_TIME2, /**< Internal to MySQL. Not used in protocol */ MYSQL_TYPE_TYPED_ARRAY, /**< Used for replication only */ - MYSQL_TYPE_DB_TRX_ID = 242, /**Internal to MySQL. Not used in protocol */ - MYSQL_TYPE_INVALID = 243, + MYSQL_TYPE_DB_TRX_ID = 241, /**Internal to MySQL. Not used in protocol */ + MYSQL_TYPE_INVALID = 242, + MYSQL_TYPE_VECTOR = 243, MYSQL_TYPE_BOOL = 244, /**< Currently just a placeholder */ MYSQL_TYPE_JSON = 245, MYSQL_TYPE_NEWDECIMAL = 246, diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 920e32361..4bb8ac13b 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -23,8 +23,9 @@ MYSQL_TYPE_DATETIME2, MYSQL_TYPE_TIME2, MYSQL_TYPE_TYPED_ARRAY, - MYSQL_TYPE_DB_TRX_ID =242, - MYSQL_TYPE_INVALID = 243, + MYSQL_TYPE_DB_TRX_ID =241, + MYSQL_TYPE_INVALID = 242, + MYSQL_TYPE_VECTOR = 243, MYSQL_TYPE_BOOL = 244, MYSQL_TYPE_JSON = 245, MYSQL_TYPE_NEWDECIMAL = 246, diff --git a/include/mysql/components/services/bits/stored_program_bits.h b/include/mysql/components/services/bits/stored_program_bits.h index c63329fba..a33a9ad49 100644 --- a/include/mysql/components/services/bits/stored_program_bits.h +++ b/include/mysql/components/services/bits/stored_program_bits.h @@ -58,5 +58,6 @@ #define MYSQL_SP_ARG_TYPE_VAR_STRING (1ULL << 31) #define MYSQL_SP_ARG_TYPE_STRING (1ULL << 32) #define MYSQL_SP_ARG_TYPE_GEOMETRY (1ULL << 33) +#define MYSQL_SP_ARG_TYPE_VECTOR (1ULL << 34) #endif diff --git a/libbinlogevents/include/rows_event.h b/libbinlogevents/include/rows_event.h index ac2cfad1b..09d341c9c 100644 --- a/libbinlogevents/include/rows_event.h +++ b/libbinlogevents/include/rows_event.h @@ -566,8 +566,9 @@ class Table_map_event : public Binary_log_event { columns, optimized to minimize space when many columns have the same charset. */ - COLUMN_VISIBILITY /* Flag to indicate column visibility + COLUMN_VISIBILITY, /* Flag to indicate column visibility attribute. */ + VECTOR_DIMENSIONALITY /* Vector column dimensionality */ }; /** @@ -604,6 +605,7 @@ class Table_map_event : public Binary_log_event { std::vector m_enum_str_value; std::vector m_set_str_value; std::vector m_geometry_type; + std::vector m_vector_dimensionality; /* The uint_pair means . Prefix length is 0 if whole column value is used. diff --git a/libbinlogevents/src/binary_log_funcs.cpp b/libbinlogevents/src/binary_log_funcs.cpp index 8b03f15c1..b9538105d 100644 --- a/libbinlogevents/src/binary_log_funcs.cpp +++ b/libbinlogevents/src/binary_log_funcs.cpp @@ -188,6 +188,7 @@ unsigned int max_display_length_for_field(enum_field_types sql_type, */ return uint_max(metadata * 8); + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: @@ -346,6 +347,7 @@ uint32_t calc_field_size(unsigned char col, const unsigned char *master_data, case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: { /* diff --git a/libbinlogevents/src/rows_event.cpp b/libbinlogevents/src/rows_event.cpp index 4b222d387..b2cecf514 100644 --- a/libbinlogevents/src/rows_event.cpp +++ b/libbinlogevents/src/rows_event.cpp @@ -252,6 +252,24 @@ static void parse_geometry_type(std::vector &vec, } } +/** + Parses VECTOR_DIMENSIONALITY field. + @param[out] vec stores vector columns's dimensionality extracted from + field. + @param[in] reader_obj the Event_reader object containing the serialized + field. + @param[in] length length of the field + */ +static void parse_vector_dimensionality(std::vector &vec, + Event_reader &reader_obj, + unsigned int length) { + const char *field = reader_obj.ptr(); + while (reader_obj.ptr() < field + length) { + vec.push_back(reader_obj.net_field_length_ll()); + if (reader_obj.has_error()) return; + } +} + /** Parses SIMPLE_PRIMARY_KEY field. @@ -372,6 +390,9 @@ Table_map_event::Optional_metadata_fields::Optional_metadata_fields( case COLUMN_VISIBILITY: parse_column_visibility(&m_column_visibility, reader_obj, len); break; + case VECTOR_DIMENSIONALITY: + parse_vector_dimensionality(m_vector_dimensionality, reader_obj, len); + break; default: BAPI_ASSERT(0); } diff --git a/libmysql/libmysql.cc b/libmysql/libmysql.cc index 7849f22c6..397ec99db 100644 --- a/libmysql/libmysql.cc +++ b/libmysql/libmysql.cc @@ -2795,6 +2795,7 @@ static void fetch_string_with_conversion(MYSQL_BIND *param, char *value, case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: default: { @@ -3404,10 +3405,10 @@ static bool is_binary_compatible(enum enum_field_types type1, range2[] = {MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, MYSQL_TYPE_NULL}, range3[] = {MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_NULL}, range4[] = { - MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB, - MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB, - MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY, - MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL}; + MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB, + MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB, + MYSQL_TYPE_VECTOR, MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, + MYSQL_TYPE_GEOMETRY, MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL}; static const enum enum_field_types *range_list[] = {range1, range2, range3, range4}, **range_list_end = @@ -3508,6 +3509,7 @@ static bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_BIT: assert(param->buffer_length != 0); param->fetch_result = fetch_result_bin; diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 4135c55f0..fdd083c23 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -12975,5 +12975,14 @@ id x 5 6 DROP VIEW v; DROP TABLE archive_table, innodb_table; +CREATE TABLE ta (pk INT, embedding VECTOR(4)) ENGINE=ARCHIVE; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +SELECT FROM_VECTOR(embedding) FROM ta; +FROM_VECTOR(embedding) +[1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +[4.00000e+00,5.00000e+00,6.00000e+00,7.00000e+00] +DROP TABLE ta; Warnings: Warning 1287 '@@binlog_format' is deprecated and will be removed in a future release. diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result index e190bc3be..b1674af4b 100644 --- a/mysql-test/r/blackhole.result +++ b/mysql-test/r/blackhole.result @@ -28,3 +28,10 @@ score SELECT 1 FROM t WHERE MATCH (a) AGAINST ('abc'); 1 DROP TABLE t; +CREATE TABLE ta (pk INT, embedding VECTOR(4), PRIMARY KEY (pk)) ENGINE=BLACKHOLE; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +SELECT FROM_VECTOR(embedding) FROM ta; +FROM_VECTOR(embedding) +DROP TABLE ta; diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result index 1d1505cd0..c50e2d4dc 100644 --- a/mysql-test/r/csv.result +++ b/mysql-test/r/csv.result @@ -5496,3 +5496,12 @@ SELECT * FROM t; j {"a": 1, "b": 2} DROP TABLE t; +CREATE TABLE ta (pk INT NOT NULL, embedding VECTOR(4) NOT NULL) ENGINE=csv; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +SELECT FROM_VECTOR(embedding) FROM ta; +FROM_VECTOR(embedding) +[1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +[4.00000e+00,5.00000e+00,6.00000e+00,7.00000e+00] +DROP TABLE ta; diff --git a/mysql-test/r/information_schema_parameters.result b/mysql-test/r/information_schema_parameters.result index f1b7232a9..45adee5de 100644 --- a/mysql-test/r/information_schema_parameters.result +++ b/mysql-test/r/information_schema_parameters.result @@ -2,7 +2,7 @@ USE INFORMATION_SCHEMA; SHOW CREATE TABLE INFORMATION_SCHEMA.PARAMETERS; View Create View character_set_client collation_connection -PARAMETERS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `PARAMETERS` AS select `cat`.`name` AS `SPECIFIC_CATALOG`,`sch`.`name` AS `SPECIFIC_SCHEMA`,`rtn`.`name` AS `SPECIFIC_NAME`,if((`rtn`.`type` = 'FUNCTION'),(`prm`.`ordinal_position` - 1),`prm`.`ordinal_position`) AS `ORDINAL_POSITION`,if(((`rtn`.`type` = 'FUNCTION') and (`prm`.`ordinal_position` = 1)),NULL,`prm`.`mode`) AS `PARAMETER_MODE`,if(((`rtn`.`type` = 'FUNCTION') and (`prm`.`ordinal_position` = 1)),NULL,`prm`.`name`) AS `PARAMETER_NAME`,substring_index(substring_index(`prm`.`data_type_utf8`,'(',1),' ',1) AS `DATA_TYPE`,internal_dd_char_length(`prm`.`data_type`,`prm`.`char_length`,`col`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`prm`.`data_type`,`prm`.`char_length`,`col`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`prm`.`numeric_precision` AS `NUMERIC_PRECISION`,if((`prm`.`numeric_precision` is null),NULL,ifnull(`prm`.`numeric_scale`,0)) AS `NUMERIC_SCALE`,`prm`.`datetime_precision` AS `DATETIME_PRECISION`,(case `prm`.`data_type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `prm`.`data_type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) else NULL end) AS `COLLATION_NAME`,`prm`.`data_type_utf8` AS `DTD_IDENTIFIER`,`rtn`.`type` AS `ROUTINE_TYPE` from (((((`mysql`.`parameters` `prm` join `mysql`.`routines` `rtn` on((`prm`.`routine_id` = `rtn`.`id`))) join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `col` on((`prm`.`collation_id` = `col`.`id`))) join `mysql`.`character_sets` `cs` on((`col`.`character_set_id` = `cs`.`id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci +PARAMETERS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `PARAMETERS` AS select `cat`.`name` AS `SPECIFIC_CATALOG`,`sch`.`name` AS `SPECIFIC_SCHEMA`,`rtn`.`name` AS `SPECIFIC_NAME`,if((`rtn`.`type` = 'FUNCTION'),(`prm`.`ordinal_position` - 1),`prm`.`ordinal_position`) AS `ORDINAL_POSITION`,if(((`rtn`.`type` = 'FUNCTION') and (`prm`.`ordinal_position` = 1)),NULL,`prm`.`mode`) AS `PARAMETER_MODE`,if(((`rtn`.`type` = 'FUNCTION') and (`prm`.`ordinal_position` = 1)),NULL,`prm`.`name`) AS `PARAMETER_NAME`,substring_index(substring_index(`prm`.`data_type_utf8`,'(',1),' ',1) AS `DATA_TYPE`,internal_dd_char_length(`prm`.`data_type`,`prm`.`char_length`,`col`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`prm`.`data_type`,`prm`.`char_length`,`col`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`prm`.`numeric_precision` AS `NUMERIC_PRECISION`,if((`prm`.`numeric_precision` is null),NULL,ifnull(`prm`.`numeric_scale`,0)) AS `NUMERIC_SCALE`,`prm`.`datetime_precision` AS `DATETIME_PRECISION`,(case `prm`.`data_type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `prm`.`data_type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`col`.`name`) else NULL end) AS `COLLATION_NAME`,`prm`.`data_type_utf8` AS `DTD_IDENTIFIER`,`rtn`.`type` AS `ROUTINE_TYPE` from (((((`mysql`.`parameters` `prm` join `mysql`.`routines` `rtn` on((`prm`.`routine_id` = `rtn`.`id`))) join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `col` on((`prm`.`collation_id` = `col`.`id`))) join `mysql`.`character_sets` `cs` on((`col`.`character_set_id` = `cs`.`id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci SELECT * FROM information_schema.columns WHERE table_schema = 'information_schema' AND table_name = 'PARAMETERS' diff --git a/mysql-test/r/information_schema_routines.result b/mysql-test/r/information_schema_routines.result index 58183bd01..e4a0dfcc8 100644 --- a/mysql-test/r/information_schema_routines.result +++ b/mysql-test/r/information_schema_routines.result @@ -2,7 +2,7 @@ USE INFORMATION_SCHEMA; SHOW CREATE TABLE INFORMATION_SCHEMA.ROUTINES; View Create View character_set_client collation_connection -ROUTINES CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,`cat`.`name` AS `ROUTINE_CATALOG`,`sch`.`name` AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` = 'PROCEDURE'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` = 'PROCEDURE'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,if((`rtn`.`external_language` = 'SQL'),'SQL','EXTERNAL') AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci +ROUTINES CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,`cat`.`name` AS `ROUTINE_CATALOG`,`sch`.`name` AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` = 'PROCEDURE'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` = 'PROCEDURE'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,if((`rtn`.`external_language` = 'SQL'),'SQL','EXTERNAL') AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci SELECT * FROM information_schema.columns WHERE table_schema = 'information_schema' AND table_name = 'ROUTINES' diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 6900582d6..a0ba7c275 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2782,3 +2782,12 @@ count(*) 0 DROP TABLE t1; SET sql_mode = default; +CREATE TABLE ta (pk INT, embedding VECTOR(4), PRIMARY KEY (pk)) ENGINE=MyISAM; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +SELECT FROM_VECTOR(embedding) FROM ta; +FROM_VECTOR(embedding) +[1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +[4.00000e+00,5.00000e+00,6.00000e+00,7.00000e+00] +DROP TABLE ta; diff --git a/mysql-test/std_data/rpl_vector_binlog.000001 b/mysql-test/std_data/rpl_vector_binlog.000001 new file mode 100644 index 0000000000000000000000000000000000000000..34bb36fe82e7606f18e916461fedc97200f633cb GIT binary patch literal 1466 zcmbVLT}TvB6h3zx7hBx?*+3Ag2?KW*HMjMlAlMmgD)DDySqu@g-E~%^u+XU&p|&C; z*wm6BO`->(lEMsv?7ezuH+=EIkP76h={gx?l_Zcf#sPw%$;-3cYeNm?$1bf z&x7=wR=@zDAN33>0}*ytRaaG4c50E6U1<3ip)gKxKpr`Z_y9yfEakrd0{+_Vc8>>& zYryWpBooKQuY@V1)LT(+qQ+4TnLmAdr18s~wvD!%P?xx!wYrq6vyY2DkKGlZgtc9u zZ4yer#WVy;@4tChWSbf8U@$e}yhp(V+B}AO2p4&v5F1l$zu)xx?ab%ynDB;2P-WK5^Wz0E5NpWqe!QMg$!uZdEchKF4# zDtv(oKTxJ+C>VDdLMI>h`p?206dnZ&cN&G)1yv=aN+G4TQI&MBFe`Nw9O}&$eJ=(SWOn)6cURp)1XYQBfkBYB8cslrkuohWQIMx_KfZ4Mz$A1A3(jwLX literal 0 HcmV?d00001 diff --git a/mysql-test/suite/funcs_1/r/is_columns_ci.result b/mysql-test/suite/funcs_1/r/is_columns_ci.result index 66edf41b1..75a9fbeba 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_ci.result +++ b/mysql-test/suite/funcs_1/r/is_columns_ci.result @@ -52,7 +52,7 @@ GENERATION_EXPRESSION longtext NO NULL SRS_ID int unsigned YES NULL SHOW CREATE TABLE information_schema.COLUMNS; View Create View character_set_client collation_connection -COLUMNS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`COLUMNS` AS select (`cat`.`name` collate utf8mb3_tolower_ci) AS `TABLE_CATALOG`,(`sch`.`name` collate utf8mb3_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8mb3_tolower_ci) AS `TABLE_NAME`,(`col`.`name` collate utf8mb3_tolower_ci) AS `COLUMN_NAME`,`col`.`ordinal_position` AS `ORDINAL_POSITION`,`col`.`default_value_utf8` AS `COLUMN_DEFAULT`,if((`col`.`is_nullable` = 1),'YES','NO') AS `IS_NULLABLE`,substring_index(substring_index(`col`.`column_type_utf8`,'(',1),' ',1) AS `DATA_TYPE`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,if((`col`.`numeric_precision` = 0),NULL,`col`.`numeric_precision`) AS `NUMERIC_PRECISION`,if(((`col`.`numeric_scale` = 0) and (`col`.`numeric_precision` = 0)),NULL,`col`.`numeric_scale`) AS `NUMERIC_SCALE`,`col`.`datetime_precision` AS `DATETIME_PRECISION`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) else NULL end) AS `COLLATION_NAME`,`col`.`column_type_utf8` AS `COLUMN_TYPE`,`col`.`column_key` AS `COLUMN_KEY`,internal_get_dd_column_extra((`col`.`generation_expression_utf8` is null),`col`.`is_virtual`,`col`.`is_auto_increment`,`col`.`update_option`,if(length(`col`.`default_option`),true,false),`col`.`options`,`col`.`hidden`,`tbl`.`type`) AS `EXTRA`,get_dd_column_privileges(`sch`.`name`,`tbl`.`name`,`col`.`name`) AS `PRIVILEGES`,ifnull(`col`.`comment`,'') AS `COLUMN_COMMENT`,ifnull(`col`.`generation_expression_utf8`,'') AS `GENERATION_EXPRESSION`,`col`.`srs_id` AS `SRS_ID` from (((((`mysql`.`columns` `col` join `mysql`.`tables` `tbl` on((`col`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll` on((`col`.`collation_id` = `coll`.`id`))) join `mysql`.`character_sets` `cs` on((`coll`.`character_set_id` = `cs`.`id`))) where ((0 <> internal_get_view_warning_or_error(`sch`.`name`,`tbl`.`name`,`tbl`.`type`,`tbl`.`options`)) and (0 <> can_access_column(`sch`.`name`,`tbl`.`name`,`col`.`name`)) and (0 <> is_visible_dd_object(`tbl`.`hidden`,(`col`.`hidden` not in ('Visible','User')),`col`.`options`))) utf8mb3 utf8mb3_general_ci +COLUMNS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`COLUMNS` AS select (`cat`.`name` collate utf8mb3_tolower_ci) AS `TABLE_CATALOG`,(`sch`.`name` collate utf8mb3_tolower_ci) AS `TABLE_SCHEMA`,(`tbl`.`name` collate utf8mb3_tolower_ci) AS `TABLE_NAME`,(`col`.`name` collate utf8mb3_tolower_ci) AS `COLUMN_NAME`,`col`.`ordinal_position` AS `ORDINAL_POSITION`,`col`.`default_value_utf8` AS `COLUMN_DEFAULT`,if((`col`.`is_nullable` = 1),'YES','NO') AS `IS_NULLABLE`,substring_index(substring_index(`col`.`column_type_utf8`,'(',1),' ',1) AS `DATA_TYPE`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,if((`col`.`numeric_precision` = 0),NULL,`col`.`numeric_precision`) AS `NUMERIC_PRECISION`,if(((`col`.`numeric_scale` = 0) and (`col`.`numeric_precision` = 0)),NULL,`col`.`numeric_scale`) AS `NUMERIC_SCALE`,`col`.`datetime_precision` AS `DATETIME_PRECISION`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) else NULL end) AS `COLLATION_NAME`,`col`.`column_type_utf8` AS `COLUMN_TYPE`,`col`.`column_key` AS `COLUMN_KEY`,internal_get_dd_column_extra((`col`.`generation_expression_utf8` is null),`col`.`is_virtual`,`col`.`is_auto_increment`,`col`.`update_option`,if(length(`col`.`default_option`),true,false),`col`.`options`,`col`.`hidden`,`tbl`.`type`) AS `EXTRA`,get_dd_column_privileges(`sch`.`name`,`tbl`.`name`,`col`.`name`) AS `PRIVILEGES`,ifnull(`col`.`comment`,'') AS `COLUMN_COMMENT`,ifnull(`col`.`generation_expression_utf8`,'') AS `GENERATION_EXPRESSION`,`col`.`srs_id` AS `SRS_ID` from (((((`mysql`.`columns` `col` join `mysql`.`tables` `tbl` on((`col`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll` on((`col`.`collation_id` = `coll`.`id`))) join `mysql`.`character_sets` `cs` on((`coll`.`character_set_id` = `cs`.`id`))) where ((0 <> internal_get_view_warning_or_error(`sch`.`name`,`tbl`.`name`,`tbl`.`type`,`tbl`.`options`)) and (0 <> can_access_column(`sch`.`name`,`tbl`.`name`,`col`.`name`)) and (0 <> is_visible_dd_object(`tbl`.`hidden`,(`col`.`hidden` not in ('Visible','User')),`col`.`options`))) utf8mb3 utf8mb3_general_ci SHOW COLUMNS FROM information_schema.COLUMNS; Field Type Null Key Default Extra TABLE_CATALOG varchar(64) YES NULL diff --git a/mysql-test/suite/funcs_1/r/is_columns_cs.result b/mysql-test/suite/funcs_1/r/is_columns_cs.result index f3fe8f9e3..2fb6b7be8 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_cs.result +++ b/mysql-test/suite/funcs_1/r/is_columns_cs.result @@ -52,7 +52,7 @@ GENERATION_EXPRESSION longtext NO NULL SRS_ID int unsigned YES NULL SHOW CREATE TABLE information_schema.COLUMNS; View Create View character_set_client collation_connection -COLUMNS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`COLUMNS` AS select `cat`.`name` AS `TABLE_CATALOG`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,(`col`.`name` collate utf8mb3_tolower_ci) AS `COLUMN_NAME`,`col`.`ordinal_position` AS `ORDINAL_POSITION`,`col`.`default_value_utf8` AS `COLUMN_DEFAULT`,if((`col`.`is_nullable` = 1),'YES','NO') AS `IS_NULLABLE`,substring_index(substring_index(`col`.`column_type_utf8`,'(',1),' ',1) AS `DATA_TYPE`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,if((`col`.`numeric_precision` = 0),NULL,`col`.`numeric_precision`) AS `NUMERIC_PRECISION`,if(((`col`.`numeric_scale` = 0) and (`col`.`numeric_precision` = 0)),NULL,`col`.`numeric_scale`) AS `NUMERIC_SCALE`,`col`.`datetime_precision` AS `DATETIME_PRECISION`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) else NULL end) AS `COLLATION_NAME`,`col`.`column_type_utf8` AS `COLUMN_TYPE`,`col`.`column_key` AS `COLUMN_KEY`,internal_get_dd_column_extra((`col`.`generation_expression_utf8` is null),`col`.`is_virtual`,`col`.`is_auto_increment`,`col`.`update_option`,if(length(`col`.`default_option`),true,false),`col`.`options`,`col`.`hidden`,`tbl`.`type`) AS `EXTRA`,get_dd_column_privileges(`sch`.`name`,`tbl`.`name`,`col`.`name`) AS `PRIVILEGES`,ifnull(`col`.`comment`,'') AS `COLUMN_COMMENT`,ifnull(`col`.`generation_expression_utf8`,'') AS `GENERATION_EXPRESSION`,`col`.`srs_id` AS `SRS_ID` from (((((`mysql`.`columns` `col` join `mysql`.`tables` `tbl` on((`col`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll` on((`col`.`collation_id` = `coll`.`id`))) join `mysql`.`character_sets` `cs` on((`coll`.`character_set_id` = `cs`.`id`))) where ((0 <> internal_get_view_warning_or_error(`sch`.`name`,`tbl`.`name`,`tbl`.`type`,`tbl`.`options`)) and (0 <> can_access_column(`sch`.`name`,`tbl`.`name`,`col`.`name`)) and (0 <> is_visible_dd_object(`tbl`.`hidden`,(`col`.`hidden` not in ('Visible','User')),`col`.`options`))) utf8mb3 utf8mb3_general_ci +COLUMNS CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`COLUMNS` AS select `cat`.`name` AS `TABLE_CATALOG`,`sch`.`name` AS `TABLE_SCHEMA`,`tbl`.`name` AS `TABLE_NAME`,(`col`.`name` collate utf8mb3_tolower_ci) AS `COLUMN_NAME`,`col`.`ordinal_position` AS `ORDINAL_POSITION`,`col`.`default_value_utf8` AS `COLUMN_DEFAULT`,if((`col`.`is_nullable` = 1),'YES','NO') AS `IS_NULLABLE`,substring_index(substring_index(`col`.`column_type_utf8`,'(',1),' ',1) AS `DATA_TYPE`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`col`.`type`,`col`.`char_length`,`coll`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,if((`col`.`numeric_precision` = 0),NULL,`col`.`numeric_precision`) AS `NUMERIC_PRECISION`,if(((`col`.`numeric_scale` = 0) and (`col`.`numeric_precision` = 0)),NULL,`col`.`numeric_scale`) AS `NUMERIC_SCALE`,`col`.`datetime_precision` AS `DATETIME_PRECISION`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`cs`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `col`.`type` when 'MYSQL_TYPE_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) when 'MYSQL_TYPE_SET' then if((`cs`.`name` = 'binary'),NULL,`coll`.`name`) else NULL end) AS `COLLATION_NAME`,`col`.`column_type_utf8` AS `COLUMN_TYPE`,`col`.`column_key` AS `COLUMN_KEY`,internal_get_dd_column_extra((`col`.`generation_expression_utf8` is null),`col`.`is_virtual`,`col`.`is_auto_increment`,`col`.`update_option`,if(length(`col`.`default_option`),true,false),`col`.`options`,`col`.`hidden`,`tbl`.`type`) AS `EXTRA`,get_dd_column_privileges(`sch`.`name`,`tbl`.`name`,`col`.`name`) AS `PRIVILEGES`,ifnull(`col`.`comment`,'') AS `COLUMN_COMMENT`,ifnull(`col`.`generation_expression_utf8`,'') AS `GENERATION_EXPRESSION`,`col`.`srs_id` AS `SRS_ID` from (((((`mysql`.`columns` `col` join `mysql`.`tables` `tbl` on((`col`.`table_id` = `tbl`.`id`))) join `mysql`.`schemata` `sch` on((`tbl`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll` on((`col`.`collation_id` = `coll`.`id`))) join `mysql`.`character_sets` `cs` on((`coll`.`character_set_id` = `cs`.`id`))) where ((0 <> internal_get_view_warning_or_error(`sch`.`name`,`tbl`.`name`,`tbl`.`type`,`tbl`.`options`)) and (0 <> can_access_column(`sch`.`name`,`tbl`.`name`,`col`.`name`)) and (0 <> is_visible_dd_object(`tbl`.`hidden`,(`col`.`hidden` not in ('Visible','User')),`col`.`options`))) utf8mb3 utf8mb3_general_ci SHOW COLUMNS FROM information_schema.COLUMNS; Field Type Null Key Default Extra TABLE_CATALOG varchar(64) NO NULL diff --git a/mysql-test/suite/funcs_1/r/is_routines.result b/mysql-test/suite/funcs_1/r/is_routines.result index ea12bc030..c1d7b30e8 100644 --- a/mysql-test/suite/funcs_1/r/is_routines.result +++ b/mysql-test/suite/funcs_1/r/is_routines.result @@ -61,7 +61,7 @@ COLLATION_CONNECTION varchar(64) NO NULL DATABASE_COLLATION varchar(64) NO NULL SHOW CREATE TABLE information_schema.ROUTINES; View Create View character_set_client collation_connection -ROUTINES CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,`cat`.`name` AS `ROUTINE_CATALOG`,`sch`.`name` AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` = 'PROCEDURE'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` = 'PROCEDURE'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,if((`rtn`.`external_language` = 'SQL'),'SQL','EXTERNAL') AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci +ROUTINES CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,`cat`.`name` AS `ROUTINE_CATALOG`,`sch`.`name` AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` = 'PROCEDURE'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` = 'PROCEDURE'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,if((`rtn`.`external_language` = 'SQL'),'SQL','EXTERNAL') AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci SHOW COLUMNS FROM information_schema.ROUTINES; Field Type Null Key Default Extra SPECIFIC_NAME varchar(64) NO NULL diff --git a/mysql-test/suite/funcs_1/r/is_routines_ci.result b/mysql-test/suite/funcs_1/r/is_routines_ci.result index a056ee423..c67cd8363 100644 --- a/mysql-test/suite/funcs_1/r/is_routines_ci.result +++ b/mysql-test/suite/funcs_1/r/is_routines_ci.result @@ -61,7 +61,7 @@ COLLATION_CONNECTION varchar(64) NO NULL DATABASE_COLLATION varchar(64) NO NULL SHOW CREATE TABLE information_schema.ROUTINES; View Create View character_set_client collation_connection -ROUTINES CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,(`cat`.`name` collate utf8mb3_tolower_ci) AS `ROUTINE_CATALOG`,(`sch`.`name` collate utf8mb3_tolower_ci) AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` = 'PROCEDURE'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` = 'PROCEDURE'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,if((`rtn`.`external_language` = 'SQL'),'SQL','EXTERNAL') AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci +ROUTINES CREATE ALGORITHM=UNDEFINED DEFINER=`mysql.infoschema`@`localhost` SQL SECURITY DEFINER VIEW `information_schema`.`ROUTINES` AS select `rtn`.`name` AS `SPECIFIC_NAME`,(`cat`.`name` collate utf8mb3_tolower_ci) AS `ROUTINE_CATALOG`,(`sch`.`name` collate utf8mb3_tolower_ci) AS `ROUTINE_SCHEMA`,`rtn`.`name` AS `ROUTINE_NAME`,`rtn`.`type` AS `ROUTINE_TYPE`,if((`rtn`.`type` = 'PROCEDURE'),'',substring_index(substring_index(`rtn`.`result_data_type_utf8`,'(',1),' ',1)) AS `DATA_TYPE`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,0) AS `CHARACTER_MAXIMUM_LENGTH`,internal_dd_char_length(`rtn`.`result_data_type`,`rtn`.`result_char_length`,`coll_result`.`name`,1) AS `CHARACTER_OCTET_LENGTH`,`rtn`.`result_numeric_precision` AS `NUMERIC_PRECISION`,`rtn`.`result_numeric_scale` AS `NUMERIC_SCALE`,`rtn`.`result_datetime_precision` AS `DATETIME_PRECISION`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`cs_result`.`name`) else NULL end) AS `CHARACTER_SET_NAME`,(case `rtn`.`result_data_type` when 'MYSQL_TYPE_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VAR_STRING' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VARCHAR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_TINY_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_MEDIUM_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_VECTOR' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_LONG_BLOB' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_ENUM' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) when 'MYSQL_TYPE_SET' then if((`cs_result`.`name` = 'binary'),NULL,`coll_result`.`name`) else NULL end) AS `COLLATION_NAME`,if((`rtn`.`type` = 'PROCEDURE'),NULL,`rtn`.`result_data_type_utf8`) AS `DTD_IDENTIFIER`,if((`rtn`.`external_language` = 'SQL'),'SQL','EXTERNAL') AS `ROUTINE_BODY`,if(can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,true),`rtn`.`definition_utf8`,NULL) AS `ROUTINE_DEFINITION`,NULL AS `EXTERNAL_NAME`,`rtn`.`external_language` AS `EXTERNAL_LANGUAGE`,'SQL' AS `PARAMETER_STYLE`,if((`rtn`.`is_deterministic` = 0),'NO','YES') AS `IS_DETERMINISTIC`,`rtn`.`sql_data_access` AS `SQL_DATA_ACCESS`,NULL AS `SQL_PATH`,`rtn`.`security_type` AS `SECURITY_TYPE`,`rtn`.`created` AS `CREATED`,`rtn`.`last_altered` AS `LAST_ALTERED`,`rtn`.`sql_mode` AS `SQL_MODE`,`rtn`.`comment` AS `ROUTINE_COMMENT`,`rtn`.`definer` AS `DEFINER`,`cs_client`.`name` AS `CHARACTER_SET_CLIENT`,`coll_conn`.`name` AS `COLLATION_CONNECTION`,`coll_db`.`name` AS `DATABASE_COLLATION` from ((((((((`mysql`.`routines` `rtn` join `mysql`.`schemata` `sch` on((`rtn`.`schema_id` = `sch`.`id`))) join `mysql`.`catalogs` `cat` on((`cat`.`id` = `sch`.`catalog_id`))) join `mysql`.`collations` `coll_client` on((`coll_client`.`id` = `rtn`.`client_collation_id`))) join `mysql`.`character_sets` `cs_client` on((`cs_client`.`id` = `coll_client`.`character_set_id`))) join `mysql`.`collations` `coll_conn` on((`coll_conn`.`id` = `rtn`.`connection_collation_id`))) join `mysql`.`collations` `coll_db` on((`coll_db`.`id` = `rtn`.`schema_collation_id`))) left join `mysql`.`collations` `coll_result` on((`coll_result`.`id` = `rtn`.`result_collation_id`))) left join `mysql`.`character_sets` `cs_result` on((`cs_result`.`id` = `coll_result`.`character_set_id`))) where (0 <> can_access_routine(`sch`.`name`,`rtn`.`name`,`rtn`.`type`,`rtn`.`definer`,false)) utf8mb3 utf8mb3_general_ci SHOW COLUMNS FROM information_schema.ROUTINES; Field Type Null Key Default Extra SPECIFIC_NAME varchar(64) NO NULL diff --git a/mysql-test/suite/information_schema/r/i_s_schema_definition_debug.result b/mysql-test/suite/information_schema/r/i_s_schema_definition_debug.result index b3199f3da..771e1967d 100644 --- a/mysql-test/suite/information_schema/r/i_s_schema_definition_debug.result +++ b/mysql-test/suite/information_schema/r/i_s_schema_definition_debug.result @@ -215,8 +215,8 @@ CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW information_schema IF (col.numeric_precision = 0, NULL, col.numeric_precision) AS NUMERIC_PRECISION, IF (col.numeric_scale = 0 && col.numeric_precision = 0, NULL, col.numeric_scale) AS NUMERIC_SCALE, col.datetime_precision AS DATETIME_PRECISION, - CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, - CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, coll.name)) ELSE NULL END AS COLLATION_NAME, + CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, + CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, coll.name)) ELSE NULL END AS COLLATION_NAME, col.column_type_utf8 AS COLUMN_TYPE, col.column_key AS COLUMN_KEY, INTERNAL_GET_DD_COLUMN_EXTRA(ISNULL(col.generation_expression_utf8), col.is_virtual, col.is_auto_increment, col.update_option, IF(LENGTH(col.default_option), TRUE, FALSE), col.options, col.hidden, tbl.type) AS EXTRA, @@ -248,8 +248,8 @@ INSERT INTO I_S_check_table(t) VALUES ("CREATE OR REPLACE DEFINER=`mysql.infosch IF (col.numeric_precision = 0, NULL, col.numeric_precision) AS NUMERIC_PRECISION, IF (col.numeric_scale = 0 && col.numeric_precision = 0, NULL, col.numeric_scale) AS NUMERIC_SCALE, col.datetime_precision AS DATETIME_PRECISION, - CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, - CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, coll.name)) ELSE NULL END AS COLLATION_NAME, + CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, + CASE col.type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, coll.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, coll.name)) ELSE NULL END AS COLLATION_NAME, col.column_type_utf8 AS COLUMN_TYPE, col.column_key AS COLUMN_KEY, INTERNAL_GET_DD_COLUMN_EXTRA(ISNULL(col.generation_expression_utf8), col.is_virtual, col.is_auto_increment, col.update_option, IF(LENGTH(col.default_option), TRUE, FALSE), col.options, col.hidden, tbl.type) AS EXTRA, @@ -666,8 +666,8 @@ CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW information_schema prm.numeric_precision AS NUMERIC_PRECISION, IF(ISNULL(prm.numeric_precision), NULL, IFNULL(prm.numeric_scale, 0)) AS NUMERIC_SCALE, prm.datetime_precision AS DATETIME_PRECISION, - CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, - CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, col.name)) ELSE NULL END AS COLLATION_NAME, + CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, + CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, col.name)) ELSE NULL END AS COLLATION_NAME, prm.data_type_utf8 AS DTD_IDENTIFIER, rtn.type AS ROUTINE_TYPE FROM mysql.parameters prm JOIN mysql.routines rtn ON prm.routine_id=rtn.id @@ -690,8 +690,8 @@ INSERT INTO I_S_check_table(t) VALUES ("CREATE OR REPLACE DEFINER=`mysql.infosch prm.numeric_precision AS NUMERIC_PRECISION, IF(ISNULL(prm.numeric_precision), NULL, IFNULL(prm.numeric_scale, 0)) AS NUMERIC_SCALE, prm.datetime_precision AS DATETIME_PRECISION, - CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, - CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, col.name)) ELSE NULL END AS COLLATION_NAME, + CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name)) ELSE NULL END AS CHARACTER_SET_NAME, + CASE prm.data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, col.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, col.name)) ELSE NULL END AS COLLATION_NAME, prm.data_type_utf8 AS DTD_IDENTIFIER, rtn.type AS ROUTINE_TYPE FROM mysql.parameters prm JOIN mysql.routines rtn ON prm.routine_id=rtn.id @@ -843,8 +843,8 @@ CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW information_schema rtn.result_numeric_precision AS NUMERIC_PRECISION, rtn.result_numeric_scale AS NUMERIC_SCALE, rtn.result_datetime_precision AS DATETIME_PRECISION, - CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) ELSE NULL END AS CHARACTER_SET_NAME, - CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) ELSE NULL END AS COLLATION_NAME, + CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) ELSE NULL END AS CHARACTER_SET_NAME, + CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) ELSE NULL END AS COLLATION_NAME, IF(rtn.type = 'PROCEDURE', NULL, rtn.result_data_type_utf8) AS DTD_IDENTIFIER, IF(rtn.external_language = 'SQL', 'SQL', 'EXTERNAL') AS ROUTINE_BODY, IF (CAN_ACCESS_ROUTINE(sch.name, rtn.name, rtn.type, rtn.definer, TRUE), rtn.definition_utf8, NULL) AS ROUTINE_DEFINITION, @@ -886,8 +886,8 @@ INSERT INTO I_S_check_table(t) VALUES ("CREATE OR REPLACE DEFINER=`mysql.infosch rtn.result_numeric_precision AS NUMERIC_PRECISION, rtn.result_numeric_scale AS NUMERIC_SCALE, rtn.result_datetime_precision AS DATETIME_PRECISION, - CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) ELSE NULL END AS CHARACTER_SET_NAME, - CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) ELSE NULL END AS COLLATION_NAME, + CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, cs_result.name)) ELSE NULL END AS CHARACTER_SET_NAME, + CASE rtn.result_data_type WHEN 'MYSQL_TYPE_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VAR_STRING' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VARCHAR' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_TINY_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) WHEN 'MYSQL_TYPE_SET' THEN (IF (cs_result.name='binary',NULL, coll_result.name)) ELSE NULL END AS COLLATION_NAME, IF(rtn.type = 'PROCEDURE', NULL, rtn.result_data_type_utf8) AS DTD_IDENTIFIER, IF(rtn.external_language = 'SQL', 'SQL', 'EXTERNAL') AS ROUTINE_BODY, IF (CAN_ACCESS_ROUTINE(sch.name, rtn.name, rtn.type, rtn.definer, TRUE), rtn.definition_utf8, NULL) AS ROUTINE_DEFINITION, diff --git a/mysql-test/suite/information_schema/t/i_s_schema_definition_debug.test b/mysql-test/suite/information_schema/t/i_s_schema_definition_debug.test index f3028f7e2..beefe0c70 100644 --- a/mysql-test/suite/information_schema/t/i_s_schema_definition_debug.test +++ b/mysql-test/suite/information_schema/t/i_s_schema_definition_debug.test @@ -314,6 +314,12 @@ INSERT INTO I_S_published_schema INSERT INTO I_S_published_schema VALUES ('80033', '80033', 1, '72835eb0d7b55036758ea2e959dbaef990f8e27cb3daf7d9bcb216e7a896bd42'); +INSERT INTO I_S_published_schema + VALUES ('80033', '80033', 0, + 'fce2482b7736ab8689aef1d66bd20615dd8b869ef2295c60f90627f662d891a9'); +INSERT INTO I_S_published_schema + VALUES ('80033', '80033', 1, + '891156b623ed2e309b26109f8dcfbd4084ac6f094639b3249087a4597431667c'); LET $checksum_version = `SELECT IF(ISNULL(mysqld_version), "0", i_s_version) FROM I_S_published_schema i RIGHT OUTER JOIN whole_schema w diff --git a/mysql-test/suite/ndbcluster/vector.result b/mysql-test/suite/ndbcluster/vector.result new file mode 100644 index 000000000..97009627a --- /dev/null +++ b/mysql-test/suite/ndbcluster/vector.result @@ -0,0 +1,6 @@ +create table t1 (pk int primary key, v vector) engine ndb; +ERROR 42000: Table 't1' uses an extension that doesn't exist in this MySQL version +show warnings; +Level Code Message +Warning 1112 VECTOR type is not supported by NDB in this MySQL version +Error 1112 Table 't1' uses an extension that doesn't exist in this MySQL version \ No newline at end of file diff --git a/mysql-test/suite/ndbcluster/vector.test b/mysql-test/suite/ndbcluster/vector.test new file mode 100644 index 000000000..4ac2e87d3 --- /dev/null +++ b/mysql-test/suite/ndbcluster/vector.test @@ -0,0 +1,5 @@ +source include/have_ndb.inc; + +--error ER_UNSUPPORTED_EXTENSION +create table t1 (pk int primary key, v vector) engine ndb; +show warnings; \ No newline at end of file diff --git a/mysql-test/suite/rpl/r/rpl_vector.result b/mysql-test/suite/rpl/r/rpl_vector.result new file mode 100644 index 000000000..f1b4b8d09 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_vector.result @@ -0,0 +1,238 @@ +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the connection metadata repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START REPLICA; see the 'START REPLICA Syntax' in the MySQL Manual for more information. +[connection master] +********************************************************** +***** Basic replication functionality with VECTOR ******* +********************************************************** +***** Table Create Section **** +CREATE TABLE t1 (c1 int not null auto_increment, +data LONGBLOB, v1 VECTOR(4), PRIMARY KEY(c1)) ENGINE=#; + +**** Data Insert Section t1 ***** + +INSERT INTO t1 VALUES (NULL, NULL, TO_VECTOR("[1,2,3,4]")); +INSERT INTO t1 VALUES (NULL, repeat('a',1*1024), TO_VECTOR("[1.1,2.1,3.1,4.1]")); +INSERT INTO t1 VALUES (NULL, repeat('b',16*1024), TO_VECTOR("[1.2,2.2,3.2,4.2]")); + +**** Data Insert Validation Source Section t1 **** + +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 1; +LENGTH(data) FROM_VECTOR(v1) +NULL [1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 2; +LENGTH(data) FROM_VECTOR(v1) +1024 [1.10000e+00,2.10000e+00,3.10000e+00,4.10000e+00] +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 3; +LENGTH(data) FROM_VECTOR(v1) +16384 [1.20000e+00,2.20000e+00,3.20000e+00,4.20000e+00] +include/include/sync_slave_sql_with_master.inc +include/diff_tables.inc [master:t1,slave:t1] +**** Data Update Section t1 **** + +[connection master] +UPDATE t1 set data=repeat('a',18*1024), v1=TO_VECTOR("[0,0,0,0]") where c1 = 1; +UPDATE t1 set data=repeat('c',17*1024), v1=TO_VECTOR("[7.1,7.2,7.3,7.4]") where c1 = 2; + +**** Data Update Validation Source Section t1 **** + +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 1; +LENGTH(data) FROM_VECTOR(v1) +18432 [0.00000e+00,0.00000e+00,0.00000e+00,0.00000e+00] +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 2; +LENGTH(data) FROM_VECTOR(v1) +17408 [7.10000e+00,7.20000e+00,7.30000e+00,7.40000e+00] +include/include/sync_slave_sql_with_master.inc +include/diff_tables.inc [master:t1,slave:t1] +[connection master] + +**** End Test Section t1 **** + +DROP TABLE t1; +***** Table with max width columns (16383) ***** +[connection master] +FLUSH LOGS; +include/save_binlog_position.inc +include/include/sync_slave_sql_with_master.inc +include/diff_tables.inc [master:a,slave:a] +[connection master] +include/include/sync_slave_sql_with_master.inc +include/diff_tables.inc [master:a,slave:a] +[connection master] +include/assert_grep.inc [Check the vector columns are available] +include/assert_grep.inc [Check the vector columns are available] +# +# BUG#36267410 +# R1. Test that UPDATE statement with column assignment fails, if size is large +# R2. Test that UPDATE statement with column assignment does not cause any binlog corruption (memcpy-ability between VECTOR types not possible) +# +FROM_VECTOR(a2) FROM_VECTOR(a3) +[1.00000e+00,2.00000e+00] [1.00000e+00] +ERROR 22001: Data too long for column 'a3' at row 1 +FROM_VECTOR(a2) FROM_VECTOR(a3) +[1.00000e+00] [1.00000e+00] +include/include/sync_slave_sql_with_master.inc +include/diff_tables.inc [master:a,slave:a] +[connection master] +********************************************************** +***** Tables with differing types (VECTOR <-> BLOB) ***** +********************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +[connection master] +pk FROM_VECTOR(v1) +1 [1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +2 [5.00000e+00,6.00000e+00,7.00000e+00,8.00000e+00] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +********************************************************** +***** Tables with differing types (VECTOR <-> TEXT) ***** +********************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +[connection master] +pk FROM_VECTOR(v1) +1 [1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +2 [5.00000e+00,6.00000e+00,7.00000e+00,8.00000e+00] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +********************************************************** +***** Tables with differing types (TEXT <-> VECTOR) ***** +********************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +[connection master] +pk v1 +1 [1,2,3,4] +2 [5,6,7,8] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +********************************************************** +***** Tables with differing types (BLOB <-> VECTOR) ***** +********************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +[connection master] +pk v1 +1 [1,2,3,4] +2 [5,6,7,8] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +************************************************************* +***** Tables with differing types (VARCHAR <-> VECTOR) ***** +************************************************************* +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +[connection master] +pk v1 +1 [1,2,3,4] +2 [5,6,7,8] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +********************************************************** +***** Tables with differing types (VECTOR <-> VARCHAR) ** +********************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +[connection master] +pk FROM_VECTOR(v1) +1 [1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +2 [5.00000e+00,6.00000e+00,7.00000e+00,8.00000e+00] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +************************************************************************** +***** Tables with differing sized columns (VECTOR(4) <-> VECTOR(2)) ***** +************************************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +Table Create Table +b CREATE TABLE `b` ( + `pk` int NOT NULL AUTO_INCREMENT, + `v1` vector(4) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +Table Create Table +b CREATE TABLE `b` ( + `pk` int NOT NULL AUTO_INCREMENT, + `v1` vector(2) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +[connection master] +Table Create Table +b CREATE TABLE `b` ( + `pk` int NOT NULL AUTO_INCREMENT, + `v1` vector(4) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +pk FROM_VECTOR(v1) +1 [1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +2 [5.00000e+00,6.00000e+00,7.00000e+00,8.00000e+00] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +****************************************************************************************** +***** Tables with differing sized columns (VECTOR(4) <-> VECTOR(2)) - ALL_NON_LOSSY ***** +****************************************************************************************** +[connection master] +include/include/sync_slave_sql_with_master.inc +[connection slave] +Table Create Table +b CREATE TABLE `b` ( + `pk` int NOT NULL AUTO_INCREMENT, + `v1` vector(4) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +Table Create Table +b CREATE TABLE `b` ( + `pk` int NOT NULL AUTO_INCREMENT, + `v1` vector(2) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +[connection master] +Table Create Table +b CREATE TABLE `b` ( + `pk` int NOT NULL AUTO_INCREMENT, + `v1` vector(4) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +pk FROM_VECTOR(v1) +1 [1.00000e+00,2.00000e+00,3.00000e+00,4.00000e+00] +2 [5.00000e+00,6.00000e+00,7.00000e+00,8.00000e+00] +[connection slave] +include/wait_for_slave_sql_error.inc [errno=13146] +[connection master] +[connection slave] +include/rpl_reset.inc +include/assert_grep.inc [Check the vector columns are available] +include/assert_grep.inc [Check the vector columns are available] +include/assert_grep.inc [Check the vector columns are available] +include/assert_grep.inc [Check the vector columns are available] +include/rpl_end.inc \ No newline at end of file diff --git a/mysql-test/suite/rpl/t/rpl_vector.test.bak b/mysql-test/suite/rpl/t/rpl_vector.test.bak new file mode 100644 index 000000000..81fed13d4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_vector.test.bak @@ -0,0 +1,486 @@ +# ==== Purpose ==== +# +# Basic test for replication of the VECTOR datatype: replication should work, +# different definitions on source and replica should result in errors, and +# mysqlbinlog should print metadata and data properly. +# +# ==== Requirements ==== +# +# R1. Replication of VECTOR should work. +# +# R2. Replication of VECTOR should work when the size is 65532 bytes (max supported size). +# +# R3. Replication from a column that is VECTOR on the source and any other data +# type on the replica, should fail. +# +# R4. Replication from a column that is any other data type on the source and +# VECTOR on the replica, should fail. +# +# R5. Replication from VECTOR(N) to VECTOR(M) should fail when N!=M. +# +# R6. mysqlbinlog --print-table-metadata should output VECTOR(N) for VECTOR +# columns (where N is the correct dimensionality) +# +# R7. mysqlbinlog -v -v should decode VECTOR values to human-readable floats. +# +# ==== Implementation ==== +# +# - Setup replication, create a table with a VECTOR column, insert/update/delete, +# and verify that it works. +# +# - Replicate a vector of size X and verify that it works. +# +# - For each of the BLOB, TEXT, and VARCHAR types, create a table with a column +# of type on the source and alter the column to VECTOR on the replica. Also +# create a table with a VECTOR column on the source and alter it to the given +# type on the replica. Insert a value in each table and verify that replication +# fails. +# +# - Create a table with a column of type VECTOR(4) on source, alter it to +# VECTOR(2) on the replica, and verify that it fails. +# +# - Run mysqlbinlog --print-table-metadata and verify that the output is as +# expected. +# +# - Run mysqlbinlog -v -v and verify that the output is as expected. +# +# ==== References ==== +# +# WL#16081 - Native Vector Embeddings Support In HeatWave + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc +let $engine_type=InnoDB; + +--echo ********************************************************** +--echo ***** Basic replication functionality with VECTOR ******* +--echo ********************************************************** + +# Start test section +--echo ***** Table Create Section **** +--replace_result $engine_type # +eval CREATE TABLE t1 (c1 int not null auto_increment, +data LONGBLOB, v1 VECTOR(4), PRIMARY KEY(c1)) ENGINE=$engine_type; + +--echo +--echo **** Data Insert Section t1 ***** +--echo +INSERT INTO t1 VALUES (NULL, NULL, TO_VECTOR("[1,2,3,4]")); +INSERT INTO t1 VALUES (NULL, repeat('a',1*1024), TO_VECTOR("[1.1,2.1,3.1,4.1]")); +INSERT INTO t1 VALUES (NULL, repeat('b',16*1024), TO_VECTOR("[1.2,2.2,3.2,4.2]")); +--echo + +--echo **** Data Insert Validation Source Section t1 **** +--echo +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 1; +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 2; +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 3; +--source include/sync_slave_sql_with_master.inc +--let $diff_tables=master:t1,slave:t1 +--source include/diff_tables.inc + +--echo **** Data Update Section t1 **** +--echo +--source include/rpl_connection_master.inc +UPDATE t1 set data=repeat('a',18*1024), v1=TO_VECTOR("[0,0,0,0]") where c1 = 1; +UPDATE t1 set data=repeat('c',17*1024), v1=TO_VECTOR("[7.1,7.2,7.3,7.4]") where c1 = 2; +--echo + +--echo **** Data Update Validation Source Section t1 **** +--echo +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 1; +SELECT LENGTH(data), FROM_VECTOR(v1) FROM t1 WHERE c1 = 2; +--source include/sync_slave_sql_with_master.inc +--let $diff_tables=master:t1,slave:t1 +--source include/diff_tables.inc + +--source include/rpl_connection_master.inc +--echo +--echo **** End Test Section t1 **** +--echo + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_row_vector_source.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/rpl_row_vector_replica.sql + +diff_files $MYSQLTEST_VARDIR/tmp/rpl_row_vector_source.sql $MYSQLTEST_VARDIR/tmp/rpl_row_vector_replica.sql; +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_row_vector_source.sql +--remove_file $MYSQLTEST_VARDIR/tmp/rpl_row_vector_replica.sql + +DROP TABLE t1; + +--echo ***** Table with max width columns (16383) ***** + +--source include/rpl_connection_master.inc +FLUSH LOGS; +--source include/save_binlog_position.inc +--disable_query_log +CREATE TABLE a (pk INT, embedding VECTOR(16383), PRIMARY KEY (pk)); +INSERT INTO a VALUES (0, TO_VECTOR(CONCAT("[", REPEAT("1.0,", 16382), "1.0]"))); +INSERT INTO a VALUES (1, TO_VECTOR(CONCAT("[", REPEAT("2.0,", 16382), "2.0]"))); +INSERT INTO a VALUES (2, TO_VECTOR(CONCAT("[", REPEAT("3.0,", 16382), "3.0]"))); +UPDATE a SET embedding = TO_VECTOR("[1]") WHERE pk = 1; +DELETE FROM a WHERE pk = 0; +--disable_result_log +--sorted_result +SELECT pk, FROM_VECTOR(embedding) FROM a; +--source include/sync_slave_sql_with_master.inc +--let $diff_tables=master:a,slave:a +--source include/diff_tables.inc + +--source include/rpl_connection_master.inc +UPDATE a SET embedding = TO_VECTOR("[0.0]"); + +--source include/sync_slave_sql_with_master.inc +--let $diff_tables=master:a,slave:a +--source include/diff_tables.inc + +--enable_result_log +--source include/rpl_connection_master.inc + +--exec $MYSQL_BINLOG -v -v $binlog_fullpath > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector2.output + +--let $assert_text=Check the vector columns are available +--let $assert_file=$MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector2.output +--let $assert_select=Corrupted replication event was detected +--let $assert_count=0 +--source include/assert_grep.inc + +--let $assert_text=Check the vector columns are available +--let $assert_file=$MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector2.output +--let $assert_select=VECTOR\(16383\) +--let $assert_count=11 +--source include/assert_grep.inc + +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector2.output + +DROP TABLE a; + +--echo # +--echo # BUG#36267410 +--echo # R1. Test that UPDATE statement with column assignment fails, if size is large +--echo # R2. Test that UPDATE statement with column assignment does not cause any binlog corruption (memcpy-ability between VECTOR types not possible) +--echo # + +CREATE TABLE a (a1 INT, a2 VECTOR(2), a3 VECTOR(1), a4 VARCHAR(1), PRIMARY KEY(a1)); +INSERT INTO a VALUES (1, TO_VECTOR("[1,2]"), TO_VECTOR("[1]"), "a"); +--sorted_result +SELECT FROM_VECTOR(a2), FROM_VECTOR(a3) FROM a; +--error ER_DATA_TOO_LONG +UPDATE a SET a3 = a2; +UPDATE a SET a2 = a3; +--sorted_result +SELECT FROM_VECTOR(a2), FROM_VECTOR(a3) FROM a; + +--source include/sync_slave_sql_with_master.inc +--let $diff_tables=master:a,slave:a +--source include/diff_tables.inc + +--source include/rpl_connection_master.inc +DROP TABLE a; + +--echo ********************************************************** +--echo ***** Tables with differing types (VECTOR <-> BLOB) ***** +--echo ********************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 VECTOR(16), + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +ALTER TABLE b MODIFY COLUMN v1 BLOB; + +--source include/rpl_connection_master.inc +INSERT INTO b(v1) VALUES (TO_VECTOR("[1,2,3,4]")), (TO_VECTOR("[5,6,7,8]")); +--sorted_result +SELECT pk, FROM_VECTOR(v1) FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'vector.16.' to type 'blob'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo ********************************************************** +--echo ***** Tables with differing types (VECTOR <-> TEXT) ***** +--echo ********************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 VECTOR(16), + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +ALTER TABLE b MODIFY COLUMN v1 TEXT; + +--source include/rpl_connection_master.inc +INSERT INTO b(v1) VALUES (TO_VECTOR("[1,2,3,4]")), (TO_VECTOR("[5,6,7,8]")); +--sorted_result +SELECT pk, FROM_VECTOR(v1) FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'vector.16.' to type 'text'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo ********************************************************** +--echo ***** Tables with differing types (TEXT <-> VECTOR) ***** +--echo ********************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 TEXT, + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +ALTER TABLE b MODIFY COLUMN v1 VECTOR(16); + +--source include/rpl_connection_master.inc +INSERT INTO b(v1) VALUES ("[1,2,3,4]"), ("[5,6,7,8]"); +--sorted_result +SELECT pk, v1 FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'blob' to type 'vector.16.'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo ********************************************************** +--echo ***** Tables with differing types (BLOB <-> VECTOR) ***** +--echo ********************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 BLOB, + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +ALTER TABLE b MODIFY COLUMN v1 VECTOR(16); + +--source include/rpl_connection_master.inc +INSERT INTO b(v1) VALUES ("[1,2,3,4]"), ("[5,6,7,8]"); +--sorted_result +SELECT pk, v1 FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'blob' to type 'vector.16.'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo ************************************************************* +--echo ***** Tables with differing types (VARCHAR <-> VECTOR) ***** +--echo ************************************************************* + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 VARCHAR(30), + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +ALTER TABLE b MODIFY COLUMN v1 VECTOR(16); + +--source include/rpl_connection_master.inc +INSERT INTO b(v1) VALUES ("[1,2,3,4]"), ("[5,6,7,8]"); +--sorted_result +SELECT pk, v1 FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'varchar.120.bytes..' to type 'vector.16.'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + + +--echo ********************************************************** +--echo ***** Tables with differing types (VECTOR <-> VARCHAR) ** +--echo ********************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 VECTOR(16), + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +ALTER TABLE b MODIFY COLUMN v1 VARCHAR(128); + +--source include/rpl_connection_master.inc +INSERT INTO b(v1) VALUES (TO_VECTOR("[1,2,3,4]")), (TO_VECTOR("[5,6,7,8]")); +--sorted_result +SELECT pk, FROM_VECTOR(v1) FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'vector.16.' to type 'varchar.512.bytes. utf8mb4.'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo ************************************************************************** +--echo ***** Tables with differing sized columns (VECTOR(4) <-> VECTOR(2)) ***** +--echo ************************************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 VECTOR(4), + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc +show create table b; + +SET @saved_replica_type_conversions = @@GLOBAL.replica_type_conversions; +SET GLOBAL replica_type_conversions='ALL_LOSSY'; + +ALTER TABLE b MODIFY COLUMN v1 VECTOR(2); +show create table b; + +--source include/rpl_connection_master.inc +show create table b; +INSERT INTO b(v1) VALUES (TO_VECTOR("[1,2,3,4]")), (TO_VECTOR("[5,6,7,8]")); +--sorted_result +SELECT pk, FROM_VECTOR(v1) FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'vector.4.' to type 'vector.2.'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--echo ****************************************************************************************** +--echo ***** Tables with differing sized columns (VECTOR(4) <-> VECTOR(2)) - ALL_NON_LOSSY ***** +--echo ****************************************************************************************** + +--source include/rpl_connection_master.inc +CREATE TABLE b ( + pk int not null auto_increment, + v1 VECTOR(4), + PRIMARY KEY(pk)); + +--source include/sync_slave_sql_with_master.inc +--source include/rpl_connection_slave.inc + +SET GLOBAL replica_type_conversions='ALL_NON_LOSSY'; + +show create table b; + +ALTER TABLE b MODIFY COLUMN v1 VECTOR(2); +show create table b; + +--source include/rpl_connection_master.inc +show create table b; +INSERT INTO b(v1) VALUES (TO_VECTOR("[1,2,3,4]")), (TO_VECTOR("[5,6,7,8]")); +--sorted_result +SELECT pk, FROM_VECTOR(v1) FROM b; + +--source include/rpl_connection_slave.inc +CALL mtr.add_suppression(".Column 1 of table 'test.B' cannot be converted from type 'vector.4.' to type 'vector.2.'"); +CALL mtr.add_suppression(".The replica coordinator and worker threads are stopped."); +--let $slave_sql_errno= convert_error(ER_SERVER_REPLICA_CONVERSION_FAILED); +--source include/wait_for_slave_sql_error.inc + +--source include/rpl_connection_master.inc +DROP TABLE b; +--source include/rpl_connection_slave.inc +DROP TABLE b; + +SET GLOBAL replica_type_conversions = @saved_replica_type_conversions; + +--let $rpl_only_running_threads= 1 +--source include/rpl_reset.inc + +--exec $MYSQL_BINLOG -v -v $MYSQL_TEST_DIR/std_data/rpl_vector_binlog.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output + +--let $assert_text=Check the vector columns are available +--let $assert_file=$MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output +--let $assert_select=1\.00000e\+00,2\.00000e\+00,3\.00000e\+00,4\.00000e\+00 +--let $assert_count=1 +--source include/assert_grep.inc + +--let $assert_text=Check the vector columns are available +--let $assert_file=$MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output +--let $assert_select=1\.10000e\+00,2\.10000e\+00,3\.10000e\+00,4\.10000e\+00 +--let $assert_count=1 +--source include/assert_grep.inc + +--let $assert_text=Check the vector columns are available +--let $assert_file=$MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output +--let $assert_select=1\.20000e\+00,2\.20000e\+00,3\.20000e\+00,4\.20000e\+00 +--let $assert_count=1 +--source include/assert_grep.inc + +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output + +--exec $MYSQL_BINLOG --print-table-metadata $MYSQL_TEST_DIR/std_data/rpl_vector_binlog.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output +--let $assert_text=Check the vector columns are available +--let $assert_file=$MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output +--let $assert_select=VECTOR\(4\) +--let $assert_count=4 +--source include/assert_grep.inc + +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_rpl_vector.output + +--source include/rpl_end.inc \ No newline at end of file diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 0fec294d5..93ea9a5b4 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1828,4 +1828,12 @@ SELECT * FROM innodb_table ORDER BY id; DROP VIEW v; DROP TABLE archive_table, innodb_table; +CREATE TABLE ta (pk INT, embedding VECTOR(4)) ENGINE=ARCHIVE; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +--sorted_result +SELECT FROM_VECTOR(embedding) FROM ta; +DROP TABLE ta; + --source include/restore_default_binlog_format.inc diff --git a/mysql-test/t/blackhole.test b/mysql-test/t/blackhole.test index 7d7035910..f35476cb2 100644 --- a/mysql-test/t/blackhole.test +++ b/mysql-test/t/blackhole.test @@ -41,3 +41,11 @@ SELECT MATCH (a) AGAINST ('abc') AS score FROM t; # But this index scan failed. Should succeed now. SELECT 1 FROM t WHERE MATCH (a) AGAINST ('abc'); DROP TABLE t; + +CREATE TABLE ta (pk INT, embedding VECTOR(4), PRIMARY KEY (pk)) ENGINE=BLACKHOLE; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +--sorted_result +SELECT FROM_VECTOR(embedding) FROM ta; +DROP TABLE ta; \ No newline at end of file diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 8a50fbd12..53e50d9b3 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1889,3 +1889,12 @@ CREATE TABLE t(j JSON NOT NULL) ENGINE = CSV; INSERT INTO t VALUES ('{"a": 1, "b": 2}'); SELECT * FROM t; DROP TABLE t; + + +CREATE TABLE ta (pk INT NOT NULL, embedding VECTOR(4) NOT NULL) ENGINE=csv; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +--sorted_result +SELECT FROM_VECTOR(embedding) FROM ta; +DROP TABLE ta; \ No newline at end of file diff --git a/mysql-test/t/dd_schema_definition_debug.test b/mysql-test/t/dd_schema_definition_debug.test index fcef6edeb..eb986992c 100644 --- a/mysql-test/t/dd_schema_definition_debug.test +++ b/mysql-test/t/dd_schema_definition_debug.test @@ -361,6 +361,12 @@ INSERT INTO dd_published_schema INSERT INTO dd_published_schema VALUES('80023', 1, '6e3311099b985c198bb3acbc88495825847dac79588dea4f0be2e4219ad7c52b'); +INSERT INTO dd_published_schema + VALUES('80023', 0, + '86dd5133e2341df99d857ecc95b14015eb959d923a14daf05b750c608173bb28'); +INSERT INTO dd_published_schema + VALUES('80023', 1, + 'ef7f041211ae273122471bec470459f852c72d53d00832b8ab4c51697acf9872'); --sorted_result SELECT IFNULL(CONCAT('The schema checksum corresponds to DD version ', version, '.'), diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index c4bd794ee..e955e2f21 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1832,3 +1832,11 @@ DELETE FROM t1 WHERE col1= '5cm' AND col1_dummy= '5cm'; SELECT count(*) FROM t1 WHERE col1= '5cm'; DROP TABLE t1; SET sql_mode = default; + +CREATE TABLE ta (pk INT, embedding VECTOR(4), PRIMARY KEY (pk)) ENGINE=MyISAM; +INSERT INTO ta VALUES +(0, TO_VECTOR("[1,2,3,4]")), +(1, TO_VECTOR("[4,5,6,7]")); +--sorted_result +SELECT FROM_VECTOR(embedding) FROM ta; +DROP TABLE ta; \ No newline at end of file diff --git a/plugin/x/src/mysql_function_names.cc b/plugin/x/src/mysql_function_names.cc index c3ea31876..1f5181085 100644 --- a/plugin/x/src/mysql_function_names.cc +++ b/plugin/x/src/mysql_function_names.cc @@ -178,6 +178,7 @@ const char *const native_mysql_functions[] = { "STATEMENT_DIGEST", "STATEMENT_DIGEST_TEXT", "STRCMP", + "STRING_TO_VECTOR", "STR_TO_DATE", "ST_AREA", "ST_ASBINARY", @@ -278,6 +279,7 @@ const char *const native_mysql_functions[] = { "TO_BASE64", "TO_DAYS", "TO_SECONDS", + "TO_VECTOR", "UCASE", "UNCOMPRESS", "UNCOMPRESSED_LENGTH", @@ -289,6 +291,8 @@ const char *const native_mysql_functions[] = { "UUID_SHORT", "UUID_TO_BIN", "VALIDATE_PASSWORD_STRENGTH", + "VECTOR_DIM", + "VECTOR_TO_STRING", "VERSION", "WAIT_FOR_EXECUTED_GTID_SET", "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS", diff --git a/plugin/x/src/sql_data_result.cc b/plugin/x/src/sql_data_result.cc index 700e4f29f..828c1e861 100644 --- a/plugin/x/src/sql_data_result.cc +++ b/plugin/x/src/sql_data_result.cc @@ -66,7 +66,7 @@ void Sql_data_result::get_next_field(bool *value) { void Sql_data_result::get_next_field(std::string *value) { validate_field_index({MYSQL_TYPE_VARCHAR, MYSQL_TYPE_STRING, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_BLOB, - MYSQL_TYPE_LONG_BLOB}); + MYSQL_TYPE_VECTOR, MYSQL_TYPE_LONG_BLOB}); Field_value *field_value = get_value(); diff --git a/plugin/x/src/streaming_command_delegate.cc b/plugin/x/src/streaming_command_delegate.cc index a6a9732f6..5f9ed12c4 100644 --- a/plugin/x/src/streaming_command_delegate.cc +++ b/plugin/x/src/streaming_command_delegate.cc @@ -222,6 +222,7 @@ int Streaming_command_delegate::field_metadata(struct st_send_field *field, case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: diff --git a/share/messages_to_clients.txt b/share/messages_to_clients.txt index 3f576cee7..f87dfc167 100644 --- a/share/messages_to_clients.txt +++ b/share/messages_to_clients.txt @@ -10047,6 +10047,21 @@ ER_INNODB_IMPORT_DROP_COL_METADATA_MISMATCH ER_INNODB_IMPORT_ENUM_NULL_TERMINATOR_MISSING eng "Enum/Set element name missing null terminator for column '%s'" +ER_NON_SCALAR_USED_AS_KEY + eng "Non-scalar (e.g., vector) column '%.64s' cannot be used as key." + +ER_INCOMPATIBLE_TYPE_AGG + eng "Columns aggregated with incompatible types: '%.64s', '%.64s'." + +ER_DATA_INCOMPATIBLE_WITH_VECTOR + eng "Value of type '%.16s, size: %zu' cannot be converted to 'vector' type." + +ER_EXCEEDS_VECTOR_MAX_DIMENSIONS + eng "Data size (%zu Bytes, %u dimensions) exceeds VECTOR max (%zu Bytes, %u dimensions) for column: '%.64s'" + +ER_TO_VECTOR_CONVERSION + eng "Data cannot be converted to a valid vector: '%.*s'" + # # End of 8.1 error messages (server-to-client). # Do NOT add messages intended for the error log above! diff --git a/sql-common/bind_params.cc b/sql-common/bind_params.cc index dbd3a62b6..d327f9507 100644 --- a/sql-common/bind_params.cc +++ b/sql-common/bind_params.cc @@ -465,6 +465,7 @@ bool fix_param_bind(MYSQL_BIND *param, uint idx) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: diff --git a/sql-common/client.cc b/sql-common/client.cc index 9b678134a..d84c4fc3a 100644 --- a/sql-common/client.cc +++ b/sql-common/client.cc @@ -9715,6 +9715,8 @@ const char *fieldtype2str(enum enum_field_types type) { return "BIT"; case MYSQL_TYPE_BLOB: return "BLOB"; + case MYSQL_TYPE_VECTOR: + return "VECTOR"; case MYSQL_TYPE_BOOL: return "BOOLEAN"; case MYSQL_TYPE_DATE: diff --git a/sql/create_field.cc b/sql/create_field.cc index 5e82b0f7e..de45d9e87 100644 --- a/sql/create_field.cc +++ b/sql/create_field.cc @@ -390,6 +390,18 @@ bool Create_field::init( break; case MYSQL_TYPE_STRING: break; + case MYSQL_TYPE_VECTOR: { + auto max_dimension_bytes = + Field_vector::dimension_bytes(Field_vector::max_dimensions); + if (m_max_display_width_in_codepoints > max_dimension_bytes) { + my_error(ER_EXCEEDS_VECTOR_MAX_DIMENSIONS, MYF(0), + m_max_display_width_in_codepoints, + m_max_display_width_in_codepoints / Field_vector::precision, + max_dimension_bytes, Field_vector::max_dimensions, fld_name); + break; + } + [[fallthrough]]; + } case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -780,6 +792,10 @@ size_t Create_field::key_length() const { } return pack_length() + (max_display_width_in_bytes() & 7 ? 1 : 0); } + /* LCOV_EXCL_START */ + case MYSQL_TYPE_VECTOR: + assert(false); // Key on VECTOR type column is not supported. + /* LCOV_EXCL_STOP */ default: { return pack_length(is_array); } diff --git a/sql/dd/dd_table.cc b/sql/dd/dd_table.cc index 19f292c6f..2512a51e8 100644 --- a/sql/dd/dd_table.cc +++ b/sql/dd/dd_table.cc @@ -204,6 +204,9 @@ dd::enum_column_types get_new_field_type(enum_field_types type) { case MYSQL_TYPE_LONG_BLOB: return dd::enum_column_types::LONG_BLOB; + case MYSQL_TYPE_VECTOR: + return dd::enum_column_types::VECTOR; + case MYSQL_TYPE_BLOB: return dd::enum_column_types::BLOB; diff --git a/sql/dd/dd_version.h b/sql/dd/dd_version.h index f4e7d4207..d4f11f1e1 100644 --- a/sql/dd/dd_version.h +++ b/sql/dd/dd_version.h @@ -203,6 +203,11 @@ ---------------------------------------------------------------------------- Changes from version 80023: - No changes, this version number is not active yet. + + 90000: + ---------------------------------------------------------------------------- + Changes: + - WL#16081: Native Vector Embeddings Support In MySQL And HeatWave */ namespace dd { diff --git a/sql/dd/impl/bootstrap/bootstrap_ctx.h b/sql/dd/impl/bootstrap/bootstrap_ctx.h index 19902ffcd..a00004905 100644 --- a/sql/dd/impl/bootstrap/bootstrap_ctx.h +++ b/sql/dd/impl/bootstrap/bootstrap_ctx.h @@ -63,7 +63,6 @@ static constexpr uint DD_VERSION_80017 = 80017; static constexpr uint DD_VERSION_80021 = 80021; static constexpr uint DD_VERSION_80022 = 80022; static constexpr uint DD_VERSION_80023 = 80023; - /* Set of supported DD version labels. A supported DD version is a version from which we can upgrade. In the case of downgrade, this is not relevant, diff --git a/sql/dd/impl/system_views/columns.cc b/sql/dd/impl/system_views/columns.cc index b01548302..76727876a 100644 --- a/sql/dd/impl/system_views/columns.cc +++ b/sql/dd/impl/system_views/columns.cc @@ -80,6 +80,7 @@ Columns::Columns() { " WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN (IF (cs.name='binary',NULL, " "cs.name))" " WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, cs.name))" + " WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, cs.name))" " WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, cs.name))" " WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, cs.name))" " WHEN 'MYSQL_TYPE_SET' THEN (IF (cs.name='binary',NULL, cs.name))" @@ -97,6 +98,7 @@ Columns::Columns() { " WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN " " (IF (cs.name='binary',NULL, coll.name))" " WHEN 'MYSQL_TYPE_BLOB' THEN (IF (cs.name='binary',NULL, coll.name))" + " WHEN 'MYSQL_TYPE_VECTOR' THEN (IF (cs.name='binary',NULL, coll.name))" " WHEN 'MYSQL_TYPE_LONG_BLOB' THEN (IF (cs.name='binary',NULL, " "coll.name))" " WHEN 'MYSQL_TYPE_ENUM' THEN (IF (cs.name='binary',NULL, coll.name))" diff --git a/sql/dd/impl/system_views/parameters.cc b/sql/dd/impl/system_views/parameters.cc index 783ed855e..8768371e2 100644 --- a/sql/dd/impl/system_views/parameters.cc +++ b/sql/dd/impl/system_views/parameters.cc @@ -77,6 +77,8 @@ Parameters::Parameters() { " (IF (cs.name='binary',NULL, cs.name))" " WHEN 'MYSQL_TYPE_BLOB' THEN " " (IF (cs.name='binary',NULL, cs.name))" + " WHEN 'MYSQL_TYPE_VECTOR' THEN " + " (IF (cs.name='binary',NULL, cs.name))" " WHEN 'MYSQL_TYPE_LONG_BLOB' THEN " " (IF (cs.name='binary',NULL, cs.name))" " WHEN 'MYSQL_TYPE_ENUM' THEN " @@ -94,6 +96,8 @@ Parameters::Parameters() { " (IF (cs.name='binary',NULL, col.name))" " WHEN 'MYSQL_TYPE_TINY_BLOB' THEN " " (IF (cs.name='binary',NULL, col.name))" + " WHEN 'MYSQL_TYPE_VECTOR' THEN " + " (IF (cs.name='binary',NULL, col.name))" " WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN " " (IF (cs.name='binary',NULL, col.name))" " WHEN 'MYSQL_TYPE_BLOB' THEN " diff --git a/sql/dd/impl/system_views/routines.cc b/sql/dd/impl/system_views/routines.cc index 6c5202d49..6d7364f02 100644 --- a/sql/dd/impl/system_views/routines.cc +++ b/sql/dd/impl/system_views/routines.cc @@ -72,6 +72,8 @@ Routines::Routines() { " (IF (cs_result.name='binary',NULL, cs_result.name))" " WHEN 'MYSQL_TYPE_BLOB' THEN " " (IF (cs_result.name='binary',NULL, cs_result.name))" + " WHEN 'MYSQL_TYPE_VECTOR' THEN " + " (IF (cs_result.name='binary',NULL, cs_result.name))" " WHEN 'MYSQL_TYPE_LONG_BLOB' THEN " " (IF (cs_result.name='binary',NULL, cs_result.name))" " WHEN 'MYSQL_TYPE_ENUM' THEN " @@ -90,6 +92,8 @@ Routines::Routines() { " (IF (cs_result.name='binary',NULL, coll_result.name))" " WHEN 'MYSQL_TYPE_TINY_BLOB' THEN " " (IF (cs_result.name='binary',NULL, coll_result.name))" + " WHEN 'MYSQL_TYPE_VECTOR' THEN " + " (IF (cs_result.name='binary',NULL, coll_result.name))" " WHEN 'MYSQL_TYPE_MEDIUM_BLOB' THEN " " (IF (cs_result.name='binary',NULL, coll_result.name))" " WHEN 'MYSQL_TYPE_BLOB' THEN " diff --git a/sql/dd/impl/tables/columns.cc b/sql/dd/impl/tables/columns.cc index e24359f53..cedbfd9e6 100644 --- a/sql/dd/impl/tables/columns.cc +++ b/sql/dd/impl/tables/columns.cc @@ -76,7 +76,7 @@ Columns::Columns() { "'MYSQL_TYPE_LONG_BLOB',\n" " 'MYSQL_TYPE_BLOB', 'MYSQL_TYPE_VAR_STRING',\n" " 'MYSQL_TYPE_STRING', 'MYSQL_TYPE_GEOMETRY',\n" - " 'MYSQL_TYPE_JSON'\n" + " 'MYSQL_TYPE_JSON', 'MYSQL_TYPE_VECTOR' \n" " ) NOT NULL"); m_target_def.add_field(FIELD_IS_NULLABLE, "FIELD_IS_NULLABLE", "is_nullable BOOL NOT NULL"); diff --git a/sql/dd/impl/tables/parameters.cc b/sql/dd/impl/tables/parameters.cc index b76e7a264..8b337bbe9 100644 --- a/sql/dd/impl/tables/parameters.cc +++ b/sql/dd/impl/tables/parameters.cc @@ -78,7 +78,7 @@ Parameters::Parameters() { " 'MYSQL_TYPE_LONG_BLOB', 'MYSQL_TYPE_BLOB',\n" " 'MYSQL_TYPE_VAR_STRING',\n" " 'MYSQL_TYPE_STRING', 'MYSQL_TYPE_GEOMETRY',\n" - " 'MYSQL_TYPE_JSON'\n" + " 'MYSQL_TYPE_JSON', 'MYSQL_TYPE_VECTOR'\n" " ) NOT NULL"); m_target_def.add_field(FIELD_DATA_TYPE_UTF8, "FIELD_DATA_TYPE_UTF8", "data_type_utf8 MEDIUMTEXT NOT NULL"); diff --git a/sql/dd/impl/tables/routines.cc b/sql/dd/impl/tables/routines.cc index 1a6c996d3..4c70cf6a9 100644 --- a/sql/dd/impl/tables/routines.cc +++ b/sql/dd/impl/tables/routines.cc @@ -80,7 +80,7 @@ Routines::Routines() { " 'MYSQL_TYPE_LONG_BLOB', 'MYSQL_TYPE_BLOB',\n" " 'MYSQL_TYPE_VAR_STRING',\n" " 'MYSQL_TYPE_STRING', 'MYSQL_TYPE_GEOMETRY',\n" - " 'MYSQL_TYPE_JSON'\n" + " 'MYSQL_TYPE_JSON', 'MYSQL_TYPE_VECTOR'\n" " ) DEFAULT NULL"); m_target_def.add_field(FIELD_RESULT_DATA_TYPE_UTF8, "FIELD_RESULT_DATA_TYPE_UTF8", diff --git a/sql/dd/impl/types/index_impl.cc b/sql/dd/impl/types/index_impl.cc index 045130033..a8c297dd1 100644 --- a/sql/dd/impl/types/index_impl.cc +++ b/sql/dd/impl/types/index_impl.cc @@ -362,6 +362,8 @@ bool Index_impl::is_candidate_key() const { if (idx_elem_obj->column().type() == enum_column_types::GEOMETRY) return false; + if (idx_elem_obj->column().type() == enum_column_types::VECTOR) + return false; /* Probably we should adjust is_prefix() to take these two scenarios into account. But this also means that we probably need avoid diff --git a/sql/dd/types/column.h b/sql/dd/types/column.h index dbd50e33e..8ddad6349 100644 --- a/sql/dd/types/column.h +++ b/sql/dd/types/column.h @@ -80,7 +80,8 @@ enum class enum_column_types { VAR_STRING, STRING, GEOMETRY, - JSON + JSON, + VECTOR }; class Column : virtual public Entity_object { diff --git a/sql/dd_table_share.cc b/sql/dd_table_share.cc index f11920778..5b733e61d 100644 --- a/sql/dd_table_share.cc +++ b/sql/dd_table_share.cc @@ -179,6 +179,9 @@ enum_field_types dd_get_old_field_type(dd::enum_column_types type) { case dd::enum_column_types::LONG_BLOB: return MYSQL_TYPE_LONG_BLOB; + case dd::enum_column_types::VECTOR: + return MYSQL_TYPE_VECTOR; + case dd::enum_column_types::BLOB: return MYSQL_TYPE_BLOB; diff --git a/sql/field.cc b/sql/field.cc index 577c43d66..46d510eb5 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -88,9 +88,11 @@ #include "sql/time_zone_common.h" #include "sql/transaction_info.h" #include "sql/tztime.h" // Time_zone +#include "sql/vector_conversion.h" // get_dimensions #include "string_with_len.h" #include "template_utils.h" // pointer_cast #include "typelib.h" + namespace dd { class Spatial_reference_system; } // namespace dd @@ -123,8 +125,9 @@ uchar Field::dummy_null_buffer = ' '; and index of field in this array. */ #define FIELDTYPE_TEAR_FROM (MYSQL_TYPE_BIT + 1) -#define FIELDTYPE_TEAR_TO (243 - 1) +#define FIELDTYPE_TEAR_TO (MYSQL_TYPE_INVALID - 1) #define FIELDTYPE_NUM (FIELDTYPE_TEAR_FROM + (255 - FIELDTYPE_TEAR_TO)) +static_assert(FIELDTYPE_NUM == 31, "FIELDTYPE_NUM expected as 31"); namespace { /** @@ -268,8 +271,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_NEWDECIMAL, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_DECIMAL, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -299,8 +306,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_TINY, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_TINY MYSQL_TYPE_TINY, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -330,8 +341,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_SHORT, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_SHORT, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -361,8 +376,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_LONG, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_LONG, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -392,8 +411,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_FLOAT, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_DOUBLE, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_DOUBLE, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_FLOAT, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -423,8 +446,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_DOUBLE, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_DOUBLE, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_DOUBLE, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_DOUBLE, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -454,8 +481,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_BIT, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_BIT, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_VECTOR, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_BOOL, MYSQL_TYPE_JSON, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -485,8 +516,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -516,8 +551,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_LONGLONG, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_LONGLONG, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -547,8 +586,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INT24, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_INT24, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -578,8 +621,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -609,8 +656,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -640,8 +691,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -671,8 +726,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_YEAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_SHORT, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -702,8 +761,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_DATETIME, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -733,8 +796,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -764,8 +831,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_LONGLONG, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_BIT, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_BIT, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_LONGLONG, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -778,6 +849,41 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_BLOB, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR}, + /* MYSQL_TYPE_VECTOR -> */ + {// MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_SHORT MYSQL_TYPE_LONG + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP + MYSQL_TYPE_VECTOR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_DATE MYSQL_TYPE_TIME + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_VECTOR, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_SET MYSQL_TYPE_TINY_BLOB + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_MEDIUM_BLOB MYSQL_TYPE_LONG_BLOB + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BLOB MYSQL_TYPE_VAR_STRING + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_STRING MYSQL_TYPE_GEOMETRY + MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID}, /* MYSQL_TYPE_INVALID -> */ {// MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, @@ -795,8 +901,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_INVALID, MYSQL_TYPE_INVALID, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -826,8 +936,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_SHORT, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONGLONG, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_LONGLONG, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_BOOL, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -857,8 +971,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_JSON, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -888,8 +1006,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_NEWDECIMAL, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_NEWDECIMAL, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -919,8 +1041,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -950,8 +1076,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -981,8 +1111,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_TINY_BLOB, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_LONG_BLOB, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1012,8 +1146,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_MEDIUM_BLOB, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1043,8 +1181,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_LONG_BLOB, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1074,8 +1216,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_BLOB, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_BLOB, MYSQL_TYPE_LONG_BLOB, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1105,8 +1251,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1136,8 +1286,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_STRING, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_STRING, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_STRING, MYSQL_TYPE_STRING, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1167,8 +1321,12 @@ static enum_field_types field_types_merge_rules[FIELDTYPE_NUM][FIELDTYPE_NUM] = MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - MYSQL_TYPE_VARCHAR, MYSQL_TYPE_INVALID, + // MYSQL_TYPE_BIT + MYSQL_TYPE_VARCHAR, + // MYSQL_TYPE_VECTOR + MYSQL_TYPE_INVALID, + // MYSQL_TYPE_INVALID + MYSQL_TYPE_INVALID, // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, // MYSQL_TYPE_NEWDECIMAL MYSQL_TYPE_ENUM @@ -1261,8 +1419,12 @@ static Item_result field_types_result_type[FIELDTYPE_NUM] = { STRING_RESULT, INT_RESULT, // MYSQL_TYPE_NEWDATE MYSQL_TYPE_VARCHAR STRING_RESULT, STRING_RESULT, - // MYSQL_TYPE_BIT MYSQL_TYPE_INVALID - INT_RESULT, INVALID_RESULT, + // MYSQL_TYPE_BIT + INT_RESULT, + // MYSQL_TYPE_VECTOR + STRING_RESULT, + // MYSQL_TYPE_INVALID + INVALID_RESULT, // Unused entries: <17>-<242> // MYSQL_TYPE_BOOL MYSQL_TYPE_JSON INT_RESULT, STRING_RESULT, @@ -7088,6 +7250,99 @@ type_conversion_status Field_blob::store(const char *from, size_t length, return store_internal(from, length, cs); } +type_conversion_status Field_vector::store(double) { + my_error(ER_DATA_INCOMPATIBLE_WITH_VECTOR, MYF(0), "numeric", sizeof(double)); + return TYPE_ERR_BAD_VALUE; +} + +type_conversion_status Field_vector::store(longlong, bool) { + my_error(ER_DATA_INCOMPATIBLE_WITH_VECTOR, MYF(0), "numeric", + sizeof(longlong)); + return TYPE_ERR_BAD_VALUE; +} + +type_conversion_status Field_vector::store_decimal(const my_decimal *) { + my_error(ER_DATA_INCOMPATIBLE_WITH_VECTOR, MYF(0), "numeric", + sizeof(my_decimal)); + return TYPE_ERR_BAD_VALUE; +} + +type_conversion_status Field_vector::store(const char *from, size_t length, + const CHARSET_INFO *cs) { + uint32 dimensions = get_dimensions(length, Field_vector::precision); + if (dimensions == UINT32_MAX || cs != &my_charset_bin) { + my_error(ER_DATA_INCOMPATIBLE_WITH_VECTOR, MYF(0), "string", length); + return TYPE_ERR_BAD_VALUE; + } + + if (dimensions > get_max_dimensions()) { + set_warning(Sql_condition::SL_WARNING, ER_DATA_TOO_LONG, 1); + return TYPE_WARN_TRUNCATED; + } + + /* Check for NAN or INF value in the vector. */ + for (uint32 i = 0; i < dimensions; i++) { + float to_store = 0; + memcpy(&to_store, from + sizeof(float) * i, sizeof(float)); + if (std::isnan(to_store) || std::isinf(to_store)) { + my_error(ER_DATA_INCOMPATIBLE_WITH_VECTOR, MYF(0), "NAN or INF", length); + return TYPE_ERR_BAD_VALUE; + } + } + +#ifdef WORDS_BIGENDIAN + if (value.alloc(length)) { + reset(); + return TYPE_ERR_OOM; + } + for (uint32 i = 0; i < dimensions; i++) { + float to_store = 0; + memcpy(&to_store, from + sizeof(float) * i, sizeof(float)); + float4store(value.ptr() + i * sizeof(float), to_store); + } + from = value.ptr(); +#endif + + return Field_blob::store(from, length, cs); +} + +String *Field_vector::val_str(String *, String *val_ptr) const { + ASSERT_COLUMN_MARKED_FOR_READ; + + const char *blob = pointer_cast(get_blob_data()); + if (blob == nullptr) { + val_ptr->set("", 0, charset()); // A bit safer than ->length(0) + } else { + uint32 length = get_length(ptr); +#ifdef WORDS_BIGENDIAN + val_ptr->alloc(length); + uint32 dimensions = get_dimensions(length, Field_vector::precision); + float *to_store = (float *)(val_ptr->ptr()); + for (uint32 i = 0; i < dimensions; i++) { + to_store[i] = float4get((const uchar *)(blob + i * sizeof(float))); + } + val_ptr->length(length); +#else + val_ptr->set(blob, length, charset()); +#endif + } + return val_ptr; +} + +uint Field_vector::is_equal(const Create_field *new_field) const { + if (new_field->sql_type != MYSQL_TYPE_VECTOR || + new_field->max_display_width_in_codepoints() != field_length || + new_field->charset != field_charset) { + return IS_EQUAL_NO; + } + return IS_EQUAL_YES; +} + +void Field_vector::make_send_field(Send_field *field) const { + Field::make_send_field(field); + field->type = MYSQL_TYPE_VECTOR; +} + type_conversion_status Field_blob::store(double nr) { const CHARSET_INFO *cs = charset(); value.set_real(nr, DECIMAL_NOT_SPECIFIED, cs); @@ -9256,10 +9511,9 @@ size_t calc_pack_length(enum_field_types type, size_t length) { return 2 + portable_sizeof_char_ptr; case MYSQL_TYPE_MEDIUM_BLOB: return 3 + portable_sizeof_char_ptr; + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_LONG_BLOB: - return 4 + portable_sizeof_char_ptr; case MYSQL_TYPE_GEOMETRY: - return 4 + portable_sizeof_char_ptr; case MYSQL_TYPE_JSON: return 4 + portable_sizeof_char_ptr; case MYSQL_TYPE_SET: @@ -9289,6 +9543,7 @@ size_t calc_pack_length(dd::enum_column_types type, size_t char_length, case dd::enum_column_types::MEDIUM_BLOB: case dd::enum_column_types::LONG_BLOB: case dd::enum_column_types::BLOB: + case dd::enum_column_types::VECTOR: case dd::enum_column_types::GEOMETRY: case dd::enum_column_types::VAR_STRING: case dd::enum_column_types::STRING: @@ -9411,6 +9666,13 @@ Field *make_field(MEM_ROOT *mem_root, TABLE_SHARE *share, uchar *ptr, return new (mem_root) Field_varstring( ptr, field_length, HA_VARCHAR_PACKLENGTH(field_length), null_pos, null_bit, auto_flags, field_name, share, field_charset); + case MYSQL_TYPE_VECTOR: { + const uint pack_length = + calc_pack_length(field_type, field_length) - portable_sizeof_char_ptr; + return new (mem_root) + Field_vector(ptr, field_length, null_pos, null_bit, auto_flags, + field_name, share, pack_length, field_charset); + } case MYSQL_TYPE_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_TINY_BLOB: diff --git a/sql/field.h b/sql/field.h index 75b0ce8eb..24176fb48 100644 --- a/sql/field.h +++ b/sql/field.h @@ -63,7 +63,8 @@ #include "sql/sql_const.h" #include "sql/sql_error.h" // Sql_condition #include "sql/table.h" -#include "sql_string.h" // String +#include "sql/vector_conversion.h" // get_dimensions +#include "sql_string.h" // String #include "template_utils.h" class Create_field; @@ -157,7 +158,7 @@ Field (abstract) | | +--Field_geom | | +--Field_json | | +--Field_typed_array -| | +| | +--Field_vector | +--Field_null | +--Field_enum | +--Field_set @@ -3706,7 +3707,7 @@ class Field_blob : public Field_longstr { */ uint32 pack_length_no_ptr() const { return (uint32)(packlength); } uint row_pack_length() const final { return pack_length_no_ptr(); } - uint32 max_data_length() const final { + uint32 max_data_length() const override { return (uint32)(((ulonglong)1 << (packlength * 8)) - 1); } size_t get_field_buffer_size() { return value.alloced_length(); } @@ -3881,6 +3882,64 @@ class Field_blob : public Field_longstr { int do_save_field_metadata(uchar *first_byte) const override; }; +class Field_vector : public Field_blob { + public: + static const uint32 max_dimensions = 16383; + static const uint32 precision = sizeof(float); + static uint32 dimension_bytes(uint32 dimensions) { + return precision * dimensions; + } + uint32 get_max_dimensions() const { + return get_dimensions(field_length, precision); + } + + Field_vector(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, + uchar null_bit_arg, uchar auto_flags_arg, + const char *field_name_arg, TABLE_SHARE *share, + uint blob_pack_length, const CHARSET_INFO *cs) + : Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, auto_flags_arg, + field_name_arg, share, blob_pack_length, cs) { + set_field_length(len_arg); + assert(packlength == 4); + } + + Field_vector(uint32 len_arg, bool is_nullable_arg, const char *field_name_arg, + const CHARSET_INFO *cs) + : Field_blob(len_arg, is_nullable_arg, field_name_arg, cs, false) { + set_field_length(len_arg); + assert(packlength == 4); + } + + Field_vector(const Field_vector &field) : Field_blob(field) { + assert(packlength == 4); + } + + void sql_type(String &res) const override { + const CHARSET_INFO *cs = res.charset(); + size_t length = + cs->cset->snprintf(cs, res.ptr(), res.alloced_length(), "%s(%u)", + "vector", get_max_dimensions()); + res.length(length); + } + Field_vector *clone(MEM_ROOT *mem_root) const override { + assert(type() == MYSQL_TYPE_VECTOR); + return new (mem_root) Field_vector(*this); + } + uint32 max_data_length() const override { return field_length; } + uint32 char_length() const override { return field_length; } + enum_field_types type() const final { return MYSQL_TYPE_VECTOR; } + enum_field_types real_type() const final { return MYSQL_TYPE_VECTOR; } + void make_send_field(Send_field *field) const override; + using Field_blob::store; + type_conversion_status store(double nr) final; + type_conversion_status store(longlong nr, bool unsigned_val) final; + type_conversion_status store_decimal(const my_decimal *) final; + type_conversion_status store(const char *from, size_t length, + const CHARSET_INFO *cs) final; + uint is_equal(const Create_field *new_field) const override; + String *val_str(String *, String *) const override; +}; + class Field_geom final : public Field_blob { private: const std::optional m_srid; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 2f24dbd7a..3740d550b 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -601,6 +601,12 @@ Copy_field::Copy_func *Copy_field::get_copy_func() { !compatible_db_low_byte_first) { return do_copy_blob; } + if (m_from_field->real_type() == MYSQL_TYPE_VECTOR || + m_to_field->real_type() == MYSQL_TYPE_VECTOR) { + /* Use do_copy_blob if an involved field is VECTOR, since + * we need to check for explicit field length */ + return do_copy_blob; + } } else { if (m_to_field->real_type() == MYSQL_TYPE_BIT || m_from_field->real_type() == MYSQL_TYPE_BIT) @@ -716,7 +722,8 @@ bool fields_are_memcpyable(const Field *to, const Field *from) { } if (to_type == MYSQL_TYPE_JSON || to_real_type == MYSQL_TYPE_GEOMETRY || to_real_type == MYSQL_TYPE_VARCHAR || to_real_type == MYSQL_TYPE_ENUM || - to_real_type == MYSQL_TYPE_SET || to_real_type == MYSQL_TYPE_BIT) { + to_real_type == MYSQL_TYPE_SET || to_real_type == MYSQL_TYPE_BIT || + to_real_type == MYSQL_TYPE_VECTOR) { return false; } if (from->is_array()) { diff --git a/sql/histograms/histogram.cc b/sql/histograms/histogram.cc index 4325eff89..eaffd1f22 100644 --- a/sql/histograms/histogram.cc +++ b/sql/histograms/histogram.cc @@ -172,6 +172,7 @@ static Value_map_type field_type_to_value_map_type( case MYSQL_TYPE_JSON: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_NULL: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_INVALID: default: return Value_map_type::INVALID; diff --git a/sql/item.cc b/sql/item.cc index 59ef5523b..d403e1cb0 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -564,6 +564,13 @@ type_conversion_status Item::save_str_value_in_field(Field *field, return field->store(result->ptr(), result->length(), collation.collation); } +/** + Returns a string for a mysql field type. + @param type the type of the field. +*/ + +const char *fieldtype2str(enum enum_field_types type); + /** Aggregates data types from array of items into current item @@ -609,7 +616,14 @@ bool Item::aggregate_type(const char *name, Item **items, uint count) { // Do not aggregate items with NULL type if (items[itemno]->data_type() == MYSQL_TYPE_NULL) continue; assert(items[itemno]->result_type() != ROW_RESULT); - new_type = Field::field_type_merge(new_type, real_data_type(items[itemno])); + auto left_type = new_type; + auto right_type = real_data_type(items[itemno]); + new_type = Field::field_type_merge(left_type, right_type); + if (new_type == MYSQL_TYPE_INVALID) { + my_error(ER_INCOMPATIBLE_TYPE_AGG, MYF(0), fieldtype2str(left_type), + fieldtype2str(right_type)); + return true; + } mixed_signs |= (new_unsigned != items[itemno]->unsigned_flag); new_length = max(new_length, items[itemno]->max_length); } @@ -718,6 +732,7 @@ bool Item::aggregate_type(const char *name, Item **items, uint count) { set_data_type_json(); break; + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_TINY_BLOB: @@ -1240,6 +1255,21 @@ bool Item_field::check_function_as_value_generator(uchar *checker_args) { return false; } + if (field->real_type() == MYSQL_TYPE_VECTOR) { + /* Vector typed column cannot be used in generated column expression */ + if (func_args->source == VGS_DEFAULT_EXPRESSION) { + my_error(ER_INCORRECT_TYPE, MYF(0), field->field_name, + "DEFAULT EXPRESSION"); /* LCOV_EXCL_LINE */ + } else if (func_args->source == VGS_CHECK_CONSTRAINT) { + my_error(ER_INCORRECT_TYPE, MYF(0), field->field_name, + "CHECK CONSTRAINT"); + } else { + my_error(ER_INCORRECT_TYPE, MYF(0), field->field_name, + "GENERATED COLUMN"); + } + return true; + } + const int fld_idx = func_args->col_index; assert(fld_idx > -1); @@ -1814,7 +1844,8 @@ bool Item::is_blob_field() const { assert(fixed); const enum_field_types type = data_type(); - return (type == MYSQL_TYPE_BLOB || type == MYSQL_TYPE_GEOMETRY || + return (type == MYSQL_TYPE_BLOB || type == MYSQL_TYPE_VECTOR || + type == MYSQL_TYPE_GEOMETRY || // Char length, not the byte one, should be taken into account max_length / collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB); @@ -3861,6 +3892,10 @@ bool Item_param::propagate_type(THD *, const Type_properties &type) { case MYSQL_TYPE_JSON: set_data_type_json(); break; + case MYSQL_TYPE_VECTOR: + set_data_type_vector( + Field_vector::dimension_bytes(Field_vector::max_dimensions)); + break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -6590,6 +6625,10 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length, field = make_string_field(table, root); // if (field) field->set_pseudo(is_pseudo); return field; + case MYSQL_TYPE_VECTOR: + field = new (*THR_MALLOC) Field_vector( + max_length, m_nullable, item_name.ptr(), collation.collation); + break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -7424,6 +7463,7 @@ bool Item::send(Protocol *protocol, String *buffer) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: @@ -7529,6 +7569,7 @@ bool Item::evaluate(THD *thd, String *buffer) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: @@ -7846,6 +7887,9 @@ bool Item::aggregate_string_properties(enum_field_types type, const char *name, decimals = DECIMAL_NOT_SPECIFIED; fix_char_length(char_width); break; + case MYSQL_TYPE_VECTOR: + set_data_type_vector(char_width); + break; default: assert(false); @@ -9120,6 +9164,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **reference) { are internally stored are BLOB only. Same applies to geometry type. */ if ((def_field->type() == MYSQL_TYPE_BLOB || + def_field->type() == MYSQL_TYPE_VECTOR || def_field->type() == MYSQL_TYPE_GEOMETRY)) { try { thd->lex->insert_values_map(field_arg, def_field); @@ -9179,7 +9224,7 @@ void Item_insert_value::bind_fields() { m_rowbuffer_saved = field->table->insert_values; Item_field *field_arg = down_cast(arg->real_item()); - if ((field->type() == MYSQL_TYPE_BLOB || + if ((field->type() == MYSQL_TYPE_BLOB || field->type() == MYSQL_TYPE_VECTOR || field->type() == MYSQL_TYPE_GEOMETRY)) { current_thd->lex->insert_values_map(field_arg, field); } @@ -10500,6 +10545,7 @@ uint32 Item_aggregate_type::display_length(Item *item) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: case MYSQL_TYPE_GEOMETRY: diff --git a/sql/item.h b/sql/item.h index 9494ce0ab..bce28df28 100644 --- a/sql/item.h +++ b/sql/item.h @@ -996,6 +996,7 @@ class Item : public Parse_tree_node { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: case MYSQL_TYPE_ENUM: @@ -1067,6 +1068,7 @@ class Item : public Parse_tree_node { case MYSQL_TYPE_NULL: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: return MYSQL_TYPE_VARCHAR; @@ -1678,6 +1680,16 @@ class Item : public Parse_tree_node { max_length = MAX_DATETIME_WIDTH + fsp + (fsp > 0 ? 1 : 0); } + /** + Set the data type of the Item to be VECTOR. + */ + void set_data_type_vector(uint32 max_l) { + set_data_type(MYSQL_TYPE_VECTOR); + collation.set(&my_charset_bin, DERIVATION_IMPLICIT); + decimals = DECIMAL_NOT_SPECIFIED; + max_length = max_l; + } + /** Set the data type of the Item to be GEOMETRY. */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5a36491de..bdac6202a 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -655,9 +655,15 @@ bool Item_bool_func2::resolve_type(THD *thd) { the GEOMETRY byte string rather than doing a geometric equality comparison. */ const Functype func_type = functype(); + uint nvector_args = num_vector_args(); + if (func_type == EQ_FUNC && nvector_args != 0 && nvector_args != arg_count) { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } + if ((func_type == LT_FUNC || func_type == LE_FUNC || func_type == GE_FUNC || func_type == GT_FUNC || func_type == FT_FUNC) && - reject_geometry_args(arg_count, args, this)) + (reject_geometry_args() || reject_vector_args())) return true; // Make a special case of compare with fields to get nicer DATE comparisons @@ -697,7 +703,7 @@ bool Item_func_like::resolve_type(THD *thd) { } } - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args() || reject_vector_args()) return true; // LIKE is always carried out as a string operation args[0]->cmp_context = STRING_RESULT; @@ -2441,6 +2447,11 @@ longlong Item_func_eq::val_int() { bool Item_func_equal::resolve_type(THD *thd) { if (Item_bool_func2::resolve_type(thd)) return true; + uint nvector_args = num_vector_args(); + if (nvector_args != 0 && nvector_args != arg_count) { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } set_nullable(false); null_value = false; return false; @@ -2952,7 +2963,7 @@ bool Item_func_between::resolve_type(THD *thd) { See comments for the code block doing similar checks in Item_bool_func2::resolve_type(). */ - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args() || reject_vector_args()) return true; /* JSON values will be compared as strings, and not with the JSON diff --git a/sql/item_create.cc b/sql/item_create.cc index 65a574c19..657dbddbc 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -1673,6 +1673,11 @@ static const std::pair func_array[] = { {"TO_BASE64", SQL_FN(Item_func_to_base64, 1)}, {"TO_DAYS", SQL_FN(Item_func_to_days, 1)}, {"TO_SECONDS", SQL_FN(Item_func_to_seconds, 1)}, + {"TO_VECTOR", SQL_FN(Item_func_to_vector, 1)}, + {"STRING_TO_VECTOR", SQL_FN(Item_func_to_vector, 1)}, + {"FROM_VECTOR", SQL_FN(Item_func_from_vector, 1)}, + {"VECTOR_TO_STRING", SQL_FN(Item_func_from_vector, 1)}, + {"VECTOR_DIM", SQL_FN(Item_func_vector_dim, 1)}, {"UCASE", SQL_FN(Item_func_upper, 1)}, {"UNCOMPRESS", SQL_FN(Item_func_uncompress, 1)}, {"UNCOMPRESSED_LENGTH", SQL_FN(Item_func_uncompressed_length, 1)}, diff --git a/sql/item_func.cc b/sql/item_func.cc index 5e6087aeb..f48caeb83 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -146,7 +146,8 @@ #include "sql/strfunc.h" // find_type #include "sql/system_variables.h" #include "sql/thd_raii.h" -#include "sql/val_int_compare.h" // Integer_value +#include "sql/val_int_compare.h" // Integer_value +#include "sql/vector_conversion.h" // get_dimensions #include "sql_string.h" #include "string_with_len.h" #include "template_utils.h" @@ -1563,11 +1564,33 @@ void Item_func_num1::fix_num_length_and_dec() { max_length = args[0]->max_length; } +uint Item_func::num_vector_args() { + uint num_vectors = 0; + for (uint i = 0; i < arg_count; i++) { + /* VECTOR type fields should not participate as function arguments. */ + if (args[i]->data_type() == MYSQL_TYPE_VECTOR) { + num_vectors++; + } + } + return num_vectors; +} + +/* + Reject unsupported VECTOR type arguments. + */ +bool Item_func::reject_vector_args() { + if (num_vector_args() > 0) { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } + return false; +} + /* Reject geometry arguments, should be called in resolve_type() for SQL functions/operators where geometries are not suitable as operands. */ -bool reject_geometry_args(uint arg_count, Item **args, Item_result_field *me) { +bool Item_func::reject_geometry_args() { /* We want to make sure the operands are not GEOMETRY strings because it's meaningless for them to participate in arithmetic and/or numerical @@ -1583,7 +1606,7 @@ bool reject_geometry_args(uint arg_count, Item **args, Item_result_field *me) { for (uint i = 0; i < arg_count; i++) { if (args[i]->result_type() != ROW_RESULT && args[i]->data_type() == MYSQL_TYPE_GEOMETRY) { - my_error(ER_WRONG_ARGUMENTS, MYF(0), me->func_name()); + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); return true; } } @@ -1637,8 +1660,11 @@ bool Item_func_numhybrid::resolve_type(THD *thd) { if (args[1]->propagate_type(thd, Type_properties(*args[0]))) return true; } } - if (resolve_type_inner(thd)) return true; - return reject_geometry_args(arg_count, args, this); + + if (resolve_type_inner(thd) || reject_geometry_args() || + reject_vector_args()) return true; + + return false; } bool Item_func_numhybrid::resolve_type_inner(THD *) { @@ -1855,7 +1881,7 @@ void Item_typecast_signed::print(const THD *thd, String *str, } bool Item_typecast_signed::resolve_type(THD *thd) { - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args() || reject_vector_args()) return true; return args[0]->propagate_type(thd, MYSQL_TYPE_LONGLONG, false, true); } @@ -1913,7 +1939,7 @@ void Item_typecast_unsigned::print(const THD *thd, String *str, } bool Item_typecast_unsigned::resolve_type(THD *thd) { - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args() || reject_vector_args()) return true; return args[0]->propagate_type(thd, MYSQL_TYPE_LONGLONG, false, true); } @@ -2782,7 +2808,8 @@ bool Item_dec_func::resolve_type(THD *thd) { decimals = DECIMAL_NOT_SPECIFIED; max_length = float_length(decimals); set_nullable(true); - return reject_geometry_args(arg_count, args, this); + if (reject_geometry_args() || reject_vector_args()) return true; + return false; } /** Gateway to natural LOG function. */ @@ -2962,7 +2989,8 @@ bool Item_func_bit::resolve_type(THD *thd) { set_data_type_longlong(); unsigned_flag = true; } - return reject_geometry_args(arg_count, args, this); + if (reject_vector_args()) return true; + return reject_geometry_args(); } longlong Item_func_bit::val_int() { @@ -3266,7 +3294,7 @@ bool Item_func_int_val::resolve_type_inner(THD *) { DBUG_PRINT("info", ("name %s", func_name())); assert(args[0]->data_type() != MYSQL_TYPE_INVALID); - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args() || reject_vector_args()) return true; switch (args[0]->result_type()) { case STRING_RESULT: @@ -3399,7 +3427,7 @@ bool Item_func_round::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_NEWDECIMAL)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args() || reject_vector_args()) return true; switch (args[0]->result_type()) { case INT_RESULT: @@ -3628,7 +3656,8 @@ void Item_func_rand::seed_random(Item *arg) { bool Item_func_rand::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DOUBLE)) return true; if (Item_real_func::resolve_type(thd)) return true; - return reject_geometry_args(arg_count, args, this); + if (reject_geometry_args() || reject_vector_args()) return true; + return false; } bool Item_func_rand::fix_fields(THD *thd, Item **ref) { @@ -3697,7 +3726,8 @@ double Item_func_rand::val_real() { bool Item_func_sign::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true; if (Item_int_func::resolve_type(thd)) return true; - return reject_geometry_args(arg_count, args, this); + if (reject_geometry_args() || reject_vector_args()) return true; + return false; } longlong Item_func_sign::val_int() { @@ -3711,7 +3741,8 @@ bool Item_func_units::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true; decimals = DECIMAL_NOT_SPECIFIED; max_length = float_length(decimals); - return reject_geometry_args(arg_count, args, this); + if (reject_geometry_args() || reject_vector_args()) return true; + return false; } double Item_func_units::val_real() { @@ -3728,7 +3759,8 @@ bool Item_func_min_max::resolve_type(THD *thd) { return false; if (resolve_type_inner(thd)) return true; - return reject_geometry_args(arg_count, args, this); + if (reject_geometry_args() || reject_vector_args()) return true; + return false; } /* @@ -4139,6 +4171,21 @@ longlong Item_func_length::val_int() { return (longlong)res->length(); } +longlong Item_func_vector_dim::val_int() { + assert(fixed); + String *res = args[0]->val_str(&value); + null_value = false; + if (res == nullptr || res->ptr() == nullptr) { + return error_int(); /* purecov: inspected */ + } + uint32 dimensions = get_dimensions(res->length(), Field_vector::precision); + if (dimensions == UINT32_MAX) { + my_error(ER_TO_VECTOR_CONVERSION, MYF(0), res->length(), res->ptr()); + return error_int(); /* purecov: inspected */ + } + return (longlong)dimensions; +} + longlong Item_func_char_length::val_int() { assert(fixed == 1); String *res = args[0]->val_str(&value); @@ -6894,6 +6941,10 @@ bool Item_func_get_user_var::propagate_type(THD *, case MYSQL_TYPE_TIME2: set_data_type_string(15, type.m_collation); break; + case MYSQL_TYPE_VECTOR: + set_data_type_vector( + Field_vector::dimension_bytes(Field_vector::max_dimensions)); + break; default: assert(false); } @@ -9816,6 +9867,12 @@ longlong Item_func_internal_dd_char_length::val_int() { // Check data types for getting info const enum_field_types field_type = dd_get_old_field_type(col_type); + + if (field_type == MYSQL_TYPE_VECTOR) { + /* For vector types, we can return the field_length as is. */ + return field_length; + } + const bool blob_flag = is_blob(field_type); if (!blob_flag && field_type != MYSQL_TYPE_ENUM && field_type != MYSQL_TYPE_SET && diff --git a/sql/item_func.h b/sql/item_func.h index 51fa23627..95369ca49 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -80,8 +80,6 @@ class List; /* Function items used by mysql */ -extern bool reject_geometry_args(uint arg_count, Item **args, - Item_result_field *me); void unsupported_json_comparison(size_t arg_count, Item **args, const char *msg); @@ -137,6 +135,9 @@ class Item_func : public Item_result_field { return (argument_count() > 0) ? args : nullptr; } + bool reject_vector_args(); + uint num_vector_args(); + bool reject_geometry_args(); protected: /* These decide of types of arguments which are prepared-statement @@ -1077,6 +1078,7 @@ class Item_typecast_decimal final : public Item_func { my_decimal *val_decimal(my_decimal *) override; enum Item_result result_type() const override { return DECIMAL_RESULT; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (args[0]->propagate_type(thd, MYSQL_TYPE_NEWDECIMAL, false, true)) return true; return false; @@ -1116,6 +1118,7 @@ class Item_typecast_real final : public Item_func { my_decimal *val_decimal(my_decimal *decimal_value) override; enum Item_result result_type() const override { return REAL_RESULT; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; return args[0]->propagate_type(thd, MYSQL_TYPE_DOUBLE, false, true); } const char *func_name() const override { return "cast_as_real"; } @@ -1750,6 +1753,29 @@ class Item_func_length : public Item_int_func { Item *pq_clone(THD *thd, Query_block *select) override; }; +class Item_func_vector_dim : public Item_int_func { + String value; + + public: + Item_func_vector_dim(const POS &pos, Item *a) : Item_int_func(pos, a) {} + longlong val_int() override; + const char *func_name() const override { return "vector_dim"; } + bool resolve_type(THD *thd) override { + if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_VECTOR)) { + return true; + } + bool valid_type = (args[0]->data_type() == MYSQL_TYPE_VECTOR) || + (args[0]->result_type() == STRING_RESULT && + args[0]->collation.collation == &my_charset_bin); + if (!valid_type) { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } + max_length = 10; + return false; + } +}; + class Item_func_bit_length final : public Item_func_length { public: Item_func_bit_length(const POS &pos, Item *a) : Item_func_length(pos, a) {} diff --git a/sql/item_json_func.cc b/sql/item_json_func.cc index 562cd649b..5aa29acd6 100644 --- a/sql/item_json_func.cc +++ b/sql/item_json_func.cc @@ -1185,6 +1185,7 @@ static constexpr uint32 typelit_max_length = bool Item_func_json_type::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; + if (reject_vector_args()) return true; set_nullable(true); m_value.set_charset(&my_charset_utf8mb4_bin); set_data_type_string(typelit_max_length, &my_charset_utf8mb4_bin); @@ -1914,6 +1915,7 @@ bool Item_func_json_extract::eq(const Item *item, bool binary_cmp) const { bool Item_func_modify_json_in_path::resolve_type(THD *thd) { if (Item_json_func::resolve_type(thd)) return true; + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; if (param_type_is_default(thd, 1, -1, 2, MYSQL_TYPE_VARCHAR)) return true; if (param_type_is_default(thd, 2, -1, 2, MYSQL_TYPE_JSON)) return true; @@ -3747,6 +3749,7 @@ void Item_func_array_cast::add_json_info(Json_object *obj) { } bool Item_func_array_cast::resolve_type(THD *) { + if (reject_vector_args()) return true; set_nullable(true); return false; } diff --git a/sql/item_json_func.h b/sql/item_json_func.h index 30313829d..f47643246 100644 --- a/sql/item_json_func.h +++ b/sql/item_json_func.h @@ -184,6 +184,7 @@ class Item_json_func : public Item_func { } bool resolve_type(THD *) override { + if (reject_vector_args()) return true; set_nullable(true); return false; } @@ -322,6 +323,7 @@ class Item_func_json_valid final : public Item_int_func { longlong val_int() override; bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; set_nullable(true); return false; @@ -372,6 +374,7 @@ class Item_func_json_schema_validation_report final : public Item_json_func { bool val_json(Json_wrapper *wr) override; bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; set_nullable(true); return false; @@ -409,6 +412,7 @@ class Item_func_json_contains final : public Item_int_func { longlong val_int() override; bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; if (param_type_is_default(thd, 1, 3)) return true; set_nullable(true); @@ -447,6 +451,7 @@ class Item_func_json_contains_path final : public Item_int_func { longlong val_int() override; bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; if (param_type_is_default(thd, 1, -1)) return true; set_nullable(true); @@ -488,6 +493,7 @@ class Item_typecast_json final : public Item_json_func { : Item_json_func(thd, pos, a) {} bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (Item_json_func::resolve_type(thd)) return true; return args[0]->propagate_type(thd, MYSQL_TYPE_JSON, false, true); } @@ -509,6 +515,7 @@ class Item_func_json_length final : public Item_int_func { Item_func_json_length(const POS &pos, Item *doc) : Item_int_func(pos, doc) {} bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; if (param_type_is_default(thd, 1, 2)) return true; set_nullable(true); @@ -532,6 +539,7 @@ class Item_func_json_depth final : public Item_int_func { const char *func_name() const override { return "json_depth"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; set_nullable(true); return false; @@ -557,6 +565,7 @@ class Item_func_json_keys : public Item_json_func { const char *func_name() const override { return "json_keys"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (Item_json_func::resolve_type(thd)) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; if (param_type_is_default(thd, 1, 2)) return true; @@ -582,6 +591,7 @@ class Item_func_json_extract final : public Item_json_func { const char *func_name() const override { return "json_extract"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (Item_json_func::resolve_type(thd)) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_JSON)) return true; if (param_type_is_default(thd, 1, -1)) return true; @@ -880,6 +890,7 @@ class Item_func_json_quote : public Item_str_func { const char *func_name() const override { return "json_quote"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1)) return true; set_nullable(true); @@ -914,6 +925,7 @@ class Item_func_json_unquote : public Item_str_func { enum Functype functype() const override { return JSON_UNQUOTE_FUNC; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1)) return true; set_nullable(true); set_data_type_string(args[0]->max_char_length(), &my_charset_utf8mb4_bin); @@ -933,6 +945,7 @@ class Item_func_json_pretty final : public Item_str_func { const char *func_name() const override { return "json_pretty"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_JSON)) return true; set_data_type_string(MAX_BLOB_WIDTH, &my_charset_utf8mb4_bin); return false; @@ -951,6 +964,7 @@ class Item_func_json_storage_size final : public Item_int_func { const char *func_name() const override { return "json_storage_size"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_JSON)) return true; if (Item_int_func::resolve_type(thd)) return true; set_nullable(true); @@ -970,6 +984,7 @@ class Item_func_json_storage_free final : public Item_int_func { const char *func_name() const override { return "json_storage_free"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_JSON)) return true; return false; } @@ -1072,6 +1087,7 @@ class Item_func_member_of : public Item_bool_func { const char *func_name() const override { return "member of"; } enum Functype functype() const override { return MEMBER_OF_FUNC; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 2, MYSQL_TYPE_JSON)) return true; args[0]->mark_json_as_scalar(); return false; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 2c55e1119..403fda1d4 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -120,8 +120,9 @@ #include "sql/strfunc.h" #include "sql/system_variables.h" #include "sql/table.h" -#include "sql/val_int_compare.h" // Integer_value -#include "sql_string.h" // needs_conversion +#include "sql/val_int_compare.h" // Integer_value +#include "sql/vector_conversion.h" // from_string_to_vector +#include "sql_string.h" // needs_conversion #include "string_with_len.h" #include "strxmov.h" #include "template_utils.h" @@ -704,7 +705,7 @@ String *Item_func_aes_decrypt::val_str(String *str) { } bool Item_func_aes_decrypt::resolve_type(THD *thd) { - if (Item_str_func::resolve_type(thd)) return true; + if (Item_str_func::resolve_type(thd) || reject_vector_args()) return true; set_data_type_string(args[0]->max_char_length()); set_nullable(true); return false; @@ -728,7 +729,9 @@ bool Item_func_random_bytes::do_itemize(Parse_context *pc, Item **res) { const ulonglong Item_func_random_bytes::MAX_RANDOM_BYTES_BUFFER = 1024ULL; bool Item_func_random_bytes::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG)) return true; + if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG) || + reject_vector_args()) return true; + set_data_type_string(MAX_RANDOM_BYTES_BUFFER, &my_charset_bin); return false; } @@ -800,7 +803,7 @@ String *Item_func_to_base64::val_str_ascii(String *str) { } bool Item_func_from_base64::resolve_type(THD *thd) { - if (Item_str_func::resolve_type(thd)) return true; + if (Item_str_func::resolve_type(thd) || reject_vector_args()) return true; if (args[0]->max_length > (uint)base64_decode_max_arg_length()) { set_data_type_string(ulonglong(base64_decode_max_arg_length())); } else { @@ -1005,7 +1008,7 @@ bool parse(THD *thd, Item *statement_expr, String *statement_string) { } // namespace bool Item_func_statement_digest::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, 1)) return true; + if (param_type_is_default(thd, 0, 1) || reject_vector_args()) return true; set_data_type_string(DIGEST_HASH_TO_STRING_LENGTH, default_charset()); m_token_buffer = static_cast(thd->alloc(get_max_digest_length())); if (m_token_buffer == nullptr) return true; @@ -1050,7 +1053,7 @@ String *Item_func_statement_digest::val_str_ascii(String *buf) { } bool Item_func_statement_digest_text::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, 1)) return true; + if (param_type_is_default(thd, 0, 1) || reject_vector_args()) return true; set_data_type_string(MAX_BLOB_WIDTH, args[0]->collation); m_token_buffer = static_cast(thd->alloc(get_max_digest_length())); if (m_token_buffer == nullptr) return true; @@ -1111,7 +1114,7 @@ String *Item_func_concat::val_str(String *str) { } bool Item_func_concat::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, -1)) return true; + if (param_type_is_default(thd, 0, -1) || reject_vector_args()) return true; ulonglong char_length = 0; @@ -1168,7 +1171,7 @@ String *Item_func_concat_ws::val_str(String *str) { } bool Item_func_concat_ws::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, -1)) return true; + if (param_type_is_default(thd, 0, -1) || reject_vector_args()) return true; ulonglong char_length; @@ -1225,7 +1228,7 @@ String *Item_func_reverse::val_str(String *str) { } bool Item_func_reverse::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, 1)) return true; + if (param_type_is_default(thd, 0, 1) || reject_vector_args()) return true; if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; assert(collation.collation != nullptr); set_data_type_string(args[0]->max_char_length()); @@ -1299,7 +1302,7 @@ String *Item_func_replace::val_str(String *str) { } bool Item_func_replace::resolve_type(THD *thd) { - if (param_type_is_default(thd, 0, 3)) return true; + if (param_type_is_default(thd, 0, 3) || reject_vector_args()) return true; // We let the first argument (only) determine the character set of the result. // REPLACE(str, from_str, to_str) @@ -1375,6 +1378,7 @@ bool Item_func_insert::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1)) return true; if (param_type_is_default(thd, 1, 3, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 3, 4)) return true; + if (reject_vector_args()) return true; // Character set of result is based on first argument if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; @@ -1422,6 +1426,7 @@ String *Item_str_conv::val_str(String *str) { bool Item_func_lower::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1)) return true; if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; + if (reject_vector_args()) return true; assert(collation.collation != nullptr); multiply = collation.collation->casedn_multiply; @@ -1433,6 +1438,7 @@ bool Item_func_lower::resolve_type(THD *thd) { bool Item_func_upper::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1)) return true; if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; + if (reject_vector_args()) return true; assert(collation.collation != nullptr); multiply = collation.collation->caseup_multiply; @@ -1492,6 +1498,8 @@ bool Item_func_left::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; + if (reject_vector_args()) return true; + assert(collation.collation != nullptr); left_right_max_length(thd); return false; @@ -1579,6 +1587,7 @@ String *Item_func_substr::val_str(String *str) { bool Item_func_substr::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1)) return true; if (param_type_is_default(thd, 1, 3, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; uint32 max_char_length = args[0]->max_char_length(); @@ -1619,6 +1628,7 @@ bool Item_func_substr::resolve_type(THD *thd) { bool Item_func_substr_index::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 2)) return true; if (param_type_is_default(thd, 2, 3, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; // We let the first argument (only) determine the character set of the result. // SUBSTRING_INDEX(str, delim, count) if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; @@ -1838,6 +1848,7 @@ String *Item_func_trim::val_str(String *str) { bool Item_func_trim::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1)) return true; + if (reject_vector_args()) return true; // The parser swaps arguments, so args[0] is FROM str. // We let the first argument (only) determine the character set of the // result. @@ -2030,6 +2041,7 @@ bool Item_func_current_user::do_itemize(Parse_context *pc, Item **res) { bool Item_func_soundex::resolve_type(THD *thd) { if (Item_str_func::resolve_type(thd)) return true; + if (reject_vector_args()) return true; uint32 char_length = args[0]->max_char_length(); if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; assert(collation.collation != nullptr); @@ -2193,6 +2205,7 @@ bool Item_func_format::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_NEWDECIMAL)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 2, 3)) return true; + if (reject_vector_args()) return true; decimals = FORMAT_MAX_DECIMALS; const uint32 char_length = args[0]->max_char_length(); @@ -2204,7 +2217,7 @@ bool Item_func_format::resolve_type(THD *thd) { locale = args[2]->basic_const_item() ? get_locale(args[2]) : nullptr; else locale = &my_locale_en_US; /* Two arguments */ - return reject_geometry_args(arg_count, args, this); + return reject_geometry_args(); } /** @@ -2320,6 +2333,7 @@ void Item_func_format::print(const THD *thd, String *str, bool Item_func_elt::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 1, -1)) return true; + if (reject_vector_args()) return true; uint32 char_length = 0; decimals = 0; @@ -2399,6 +2413,7 @@ void Item_func_make_set::split_sum_func(THD *thd, Ref_item_array ref_item_array, bool Item_func_make_set::resolve_type(THD *thd) { if (item->propagate_type(thd, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 0, -1)) return true; + if (reject_vector_args()) return true; uint32 char_length = arg_count - 1; /* Separators */ if (agg_arg_charsets_for_string_result(collation, args, arg_count)) @@ -2530,6 +2545,7 @@ inline String *alloc_buffer(String *res, String *str, String *tmp_value, bool Item_func_repeat::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; assert(collation.collation != nullptr); @@ -2613,6 +2629,7 @@ String *Item_func_repeat::val_str(String *str) { bool Item_func_space::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); if (args[0]->const_item() && args[0]->may_eval_const_item(thd)) { @@ -2673,6 +2690,7 @@ String *Item_func_space::val_str(String *str) { bool Item_func_rpad::resolve_type(THD *thd) { if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 0, -1)) return true; + if (reject_vector_args()) return true; // Character set of result is based on first argument. if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; @@ -2771,6 +2789,7 @@ String *Item_func_rpad::val_str(String *str) { bool Item_func_lpad::resolve_type(THD *thd) { if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 0, -1)) return true; + if (reject_vector_args()) return true; // Character set of result is based on first argument. if (agg_arg_charsets_for_string_result(collation, args, 1)) return true; @@ -2798,6 +2817,7 @@ bool Item_func_lpad::resolve_type(THD *thd) { bool Item_func_uuid_to_bin::resolve_type(THD *thd) { if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; if (Item_str_func::resolve_type(thd)) return true; + if (reject_vector_args()) return true; set_data_type_string(uint32(binary_log::Uuid::BYTE_LENGTH), &my_charset_bin); set_nullable(true); return false; @@ -2840,6 +2860,7 @@ String *Item_func_uuid_to_bin::val_str(String *str) { bool Item_func_bin_to_uuid::resolve_type(THD *thd) { if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; if (Item_str_func::resolve_type(thd)) return true; + if (reject_vector_args()) return true; set_data_type_string(uint32(binary_log::Uuid::TEXT_LENGTH), default_charset()); set_nullable(true); @@ -2976,9 +2997,10 @@ String *Item_func_lpad::val_str(String *str) { bool Item_func_conv::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; set_data_type_string(CONV_MAX_LENGTH, default_charset()); set_nullable(true); - return reject_geometry_args(arg_count, args, this); + return reject_geometry_args(); } String *Item_func_conv::val_str(String *str) { @@ -3080,6 +3102,7 @@ String *Item_func_set_collation::val_str(String *str) { } bool Item_func_set_collation::resolve_type(THD *thd) { + if (reject_vector_args()) return true; CHARSET_INFO *set_collation; String tmp; assert(args[1]->basic_const_item()); @@ -3195,6 +3218,7 @@ void Item_func_weight_string::print(const THD *thd, String *str, bool Item_func_weight_string::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1)) return true; + if (reject_vector_args()) return true; const CHARSET_INFO *cs = args[0]->collation.collation; collation.set(&my_charset_bin, args[0]->collation.derivation); flags = my_strxfrm_flag_normalize(flags); @@ -3380,6 +3404,7 @@ String *Item_func_hex::val_str_ascii(String *str) { bool Item_func_unhex::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1)) return true; + if (reject_vector_args()) return true; // The length of the result is half the length of the input string, rounded // up. Perform the calculation with 64-bit precision to not overflow the // intermediate result if args[0]->max_length == UINT_MAX. @@ -3604,6 +3629,11 @@ bool Item_charset_conversion::resolve_type(THD *thd) { return true; } + if (m_cast_cs != &my_charset_bin) { + // For a cast target other than binary, reject it for VECTOR arguments. + if (reject_vector_args()) return true; + } + if (args[0]->data_type() == MYSQL_TYPE_INVALID) { if (args[0]->propagate_type(thd, Type_properties(MYSQL_TYPE_VARCHAR, m_cast_cs))) @@ -3788,6 +3818,7 @@ String *Item_func_export_set::val_str(String *str) { } bool Item_func_export_set::resolve_type(THD *thd) { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 1, 4)) return true; if (param_type_is_default(thd, 4, 5, MYSQL_TYPE_LONGLONG)) return true; @@ -3807,6 +3838,7 @@ bool Item_func_export_set::resolve_type(THD *thd) { } bool Item_func_quote::resolve_type(THD *thd) { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1)) return true; /* Since QUOTE may add escapes to potentially all the characters in its @@ -4103,6 +4135,96 @@ String *Item_func_compress::val_str(String *str) { return &buffer; } +bool Item_func_to_vector::resolve_type(THD *thd) { + if (Item_str_func::resolve_type(thd)) { + return true; + } + if (args[0]->result_type() != STRING_RESULT || + args[0]->data_type() == MYSQL_TYPE_JSON) { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } + if (reject_geometry_args()) return true; + set_data_type_vector(static_cast( + Field_vector::dimension_bytes(Field_vector::max_dimensions))); + return false; +} + +String *Item_func_to_vector::val_str(String *str) { + assert(fixed); + null_value = false; + String *res = args[0]->val_str(str); + if (res == nullptr || res->ptr() == nullptr) { + return error_str(); + } + + uint32 output_dims = Field_vector::max_dimensions; + auto dimension_bytes = Field_vector::dimension_bytes(output_dims); + if (buffer.mem_realloc(dimension_bytes)) return error_str(); + + bool err = from_string_to_vector(res->ptr(), res->length(), buffer.ptr(), + &output_dims); + if (err) { + if (output_dims == Field_vector::max_dimensions) { + res->replace(32, 5, "... \0", 5); + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), res->ptr(), func_name()); + } else { + my_error(ER_TO_VECTOR_CONVERSION, MYF(0), res->length(), res->ptr()); + } + return error_str(); + } + + buffer.length(Field_vector::dimension_bytes(output_dims)); + return &buffer; +} + +bool Item_func_from_vector::resolve_type(THD *thd) { + if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_VECTOR)) { + return true; + } + bool valid_type = (args[0]->data_type() == MYSQL_TYPE_VECTOR) || + (args[0]->result_type() == STRING_RESULT && + args[0]->collation.collation == &my_charset_bin); + if (!valid_type) { + my_error(ER_WRONG_ARGUMENTS, MYF(0), func_name()); + return true; + } + set_data_type_string(Item_func_from_vector::max_output_bytes); + return false; +} + +String *Item_func_from_vector::val_str(String *str) { + assert(fixed); + null_value = false; + String *res = args[0]->val_str(str); + if (res == nullptr || res->ptr() == nullptr) { + return error_str(); + } + + uint32 input_dims = get_dimensions(res->length(), Field_vector::precision); + if (input_dims == UINT32_MAX) { + my_error(ER_TO_VECTOR_CONVERSION, MYF(0), res->length(), res->ptr()); + return error_str(); + } + uint32 out_length = input_dims * Item_func_from_vector::per_value_chars; + if (input_dims == 0 || out_length > Item_func_from_vector::max_output_bytes) { + res->replace(32, 5, "... \0", 5); + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), res->ptr(), func_name()); + return error_str(); + } + if (buffer.mem_realloc(out_length)) return error_str(); + if (from_vector_to_string(res->ptr(), input_dims, buffer.ptr(), + &out_length)) { + /* LCOV_EXCL_START */ + my_error(ER_DATA_OUT_OF_RANGE, MYF(0), res->ptr(), func_name()); + return error_str(); + /* LCOV_EXCL_STOP */ + } + + buffer.length(out_length); + return &buffer; +} + String *Item_func_uncompress::val_str(String *str) { assert(fixed == 1); String *res = args[0]->val_str(str); @@ -4191,6 +4313,7 @@ static void set_clock_seq_str() { } bool Item_func_uuid::resolve_type(THD *) { + if (reject_vector_args()) return true; collation.set(system_charset_info, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); set_data_type_string(uint32(UUID_LENGTH)); return false; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index cd6042172..590cc6efb 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -821,6 +821,7 @@ class Item_func_char final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; set_data_type_string(arg_count * 4U); return false; } @@ -918,6 +919,7 @@ class Item_func_is_uuid final : public Item_bool_func { longlong val_int() override; const char *func_name() const override { return "is_uuid"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; bool res = super::resolve_type(thd); set_nullable(true); return res; @@ -977,6 +979,7 @@ class Item_func_like_range : public Item_str_func { bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, 1)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; set_data_type_string(uint32{MAX_BLOB_WIDTH}, args[0]->collation); return false; } @@ -1102,6 +1105,7 @@ class Item_load_file final : public Item_str_func { } bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, 1)) return true; + if (reject_vector_args()) return true; collation.set(&my_charset_bin, DERIVATION_COERCIBLE); set_data_type_blob(MYSQL_TYPE_LONG_BLOB, MAX_BLOB_WIDTH); set_nullable(true); @@ -1281,6 +1285,7 @@ class Item_func_uncompressed_length final : public Item_int_func { const char *func_name() const override { return "uncompressed_length"; } bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, 1)) return true; + if (reject_vector_args()) return true; max_length = 10; return false; } @@ -1299,12 +1304,38 @@ class Item_func_compress final : public Item_str_func { Item *pq_clone(THD *thd, Query_block *select) override; }; +class Item_func_to_vector final : public Item_str_func { + String buffer; + + public: + Item_func_to_vector(const POS &pos, Item *a) : Item_str_func(pos, a) {} + bool resolve_type(THD *thd) override; + const char *func_name() const override { return "to_vector"; } + String *val_str(String *str) override; +}; + +class Item_func_from_vector final : public Item_str_func { + static const uint32 per_value_chars = 16; + static const uint32 max_output_bytes = + (Field_vector::max_dimensions * Item_func_from_vector::per_value_chars); + String buffer; + + public: + Item_func_from_vector(const POS &pos, Item *a) : Item_str_func(pos, a) { + collation.set(&my_charset_utf8mb4_0900_bin); + } + bool resolve_type(THD *thd) override; + const char *func_name() const override { return "from_vector"; } + String *val_str(String *str) override; +}; + class Item_func_uncompress final : public Item_str_func { String buffer; public: Item_func_uncompress(const POS &pos, Item *a) : Item_str_func(pos, a) {} bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (Item_str_func::resolve_type(thd)) return true; set_nullable(true); set_data_type_string(uint32{MAX_BLOB_WIDTH}); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 2a551992c..fbe4129a4 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -494,8 +494,13 @@ bool Item_sum::resolve_type(THD *thd) { // None except these 4 types are allowed for geometry arguments. if (!(t == COUNT_FUNC || t == COUNT_DISTINCT_FUNC || t == SUM_BIT_FUNC || - t == GEOMETRY_AGGREGATE_FUNC)) - return reject_geometry_args(arg_count, args, this); + t == GEOMETRY_AGGREGATE_FUNC)) { + if (reject_geometry_args()) return true; + } + + if (t != COUNT_FUNC && t != COUNT_DISTINCT_FUNC) { + if (reject_vector_args()) return true; + } return false; } @@ -1469,6 +1474,8 @@ bool Item_sum_bit::fix_fields(THD *thd, Item **ref) { } bool Item_sum_bit::resolve_type(THD *thd) { + if (reject_vector_args()) return true; + // Assume varbinary; if integer is provided then re-prepare. if (args[0]->data_type() == MYSQL_TYPE_INVALID) { if (args[0]->propagate_type( @@ -1521,7 +1528,7 @@ bool Item_sum_bit::resolve_type(THD *thd) { decimals = 0; unsigned_flag = true; - return reject_geometry_args(arg_count, args, this); + return reject_geometry_args(); } void Item_sum_bit::remove_bits(const String *s1, ulonglong b1) { @@ -1883,7 +1890,8 @@ void Item_sum_sum::no_rows_in_result() { clear(); } bool Item_sum_sum::resolve_type(THD *thd) { DBUG_TRACE; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true; - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_vector_args()) return true; + if (reject_geometry_args()) return true; set_nullable(true); null_value = true; @@ -2652,7 +2660,8 @@ bool Item_sum_variance::resolve_type(THD *thd) { set_data_type_double(); hybrid_type = REAL_RESULT; - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_vector_args()) return true; + if (reject_geometry_args()) return true; DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals)); return false; } @@ -5144,6 +5153,7 @@ bool Item_first_last_value::resolve_type(THD *thd) { set_nullable(true); // if empty frame, notwithstanding nullability of arg null_value = true; if (param_type_is_default(thd, 0, 1)) return true; + if (reject_vector_args()) return true; set_data_type_from_item(args[0]); m_hybrid_type = args[0]->result_type(); @@ -5293,6 +5303,7 @@ String *Item_first_last_value::val_str(String *str) { bool Item_nth_value::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1)) return true; + if (reject_vector_args()) return true; if (args[1]->propagate_type(thd, MYSQL_TYPE_LONGLONG, true)) return true; set_nullable(true); @@ -5521,6 +5532,7 @@ bool Item_lead_lag::resolve_type(THD *thd) { arg_count--; } + if (reject_vector_args()) return true; if (param_type_uses_non_param(thd)) return true; if (aggregate_type(func_name(), args, arg_count)) return true; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a899090ab..a586d2855 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1039,6 +1039,7 @@ bool Item_func_at_time_zone::check_type() const { } bool Item_func_period_add::resolve_type(THD *thd) { + if (reject_vector_args()) return true; return param_type_is_default(thd, 0, -1, MYSQL_TYPE_LONGLONG); } @@ -1057,6 +1058,7 @@ longlong Item_func_period_add::val_int() { } bool Item_func_period_diff::resolve_type(THD *thd) { + if (reject_vector_args()) return true; return param_type_is_default(thd, 0, -1, MYSQL_TYPE_LONGLONG); } @@ -1077,6 +1079,7 @@ longlong Item_func_period_diff::val_int() { bool Item_func_to_days::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // The maximum string length returned by TO_DAYS is 7, as its range is // [0000-01-01, 9999-12-31] -> [0, 3652424]. Set the maximum length to one // higher, to account for the sign, even though the function never returns @@ -1120,6 +1123,7 @@ longlong Item_func_to_seconds::val_int_endpoint(bool, bool *) { bool Item_func_to_seconds::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; set_nullable(true); return false; } @@ -1220,6 +1224,7 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) { bool Item_func_dayofyear::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Returns a value in the range [1, 366], so max three digits. Add one to the // character length for the sign. fix_char_length(4); @@ -1238,6 +1243,7 @@ longlong Item_func_dayofyear::val_int() { bool Item_func_dayofmonth::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Returns a value in the range [0, 31], so max two digits. Add one to the // character length for the sign. fix_char_length(3); @@ -1254,6 +1260,7 @@ longlong Item_func_dayofmonth::val_int() { bool Item_func_month::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Returns a value in the range [1, 12], so max two digits. Add one to the // character length for the sign. fix_char_length(3); @@ -1270,6 +1277,7 @@ longlong Item_func_month::val_int() { bool Item_func_monthname::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; const CHARSET_INFO *cs = thd->variables.collation_connection; const uint32 repertoire = my_charset_repertoire(cs); locale = thd->variables.lc_time_names; @@ -1296,6 +1304,7 @@ String *Item_func_monthname::val_str(String *str) { bool Item_func_quarter::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Always one digit [1, 4]. Add one character for the sign. fix_char_length(2); assert(decimal_precision() == 1); @@ -1316,6 +1325,7 @@ longlong Item_func_quarter::val_int() { bool Item_func_hour::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Can have up to three digits (TIME_MAX_HOUR == 838). Add one for the sign. fix_char_length(4); assert(decimal_precision() == 3); @@ -1331,6 +1341,7 @@ longlong Item_func_hour::val_int() { bool Item_func_minute::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Can have up to two digits [0, 59]. Add one for the sign. fix_char_length(3); assert(decimal_precision() == 2); @@ -1346,6 +1357,7 @@ longlong Item_func_minute::val_int() { bool Item_func_second::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Can have up to two digits [0, 59]. Add one for the sign. fix_char_length(3); assert(decimal_precision() == 2); @@ -1382,6 +1394,7 @@ bool Item_func_week::do_itemize(Parse_context *pc, Item **res) { bool Item_func_week::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; // Can have up to two digits [0, 53] (0 when using WEEK_YEAR, otherwise [1, // 53]). Add one for the sign. fix_char_length(3); @@ -1432,6 +1445,7 @@ longlong Item_func_week::val_int() { bool Item_func_yearweek::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; // Returns six digits (YYYYWW). Add one character for the sign. fix_char_length(7); assert(decimal_precision() == 6); @@ -1451,6 +1465,7 @@ longlong Item_func_yearweek::val_int() { bool Item_func_weekday::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; // Always one digit (either [0, 6] or [1, 7], depending on whether it's called // as WEEKDAY or DAYOFWEEK). Add one character for the sign. fix_char_length(2); @@ -1471,6 +1486,7 @@ longlong Item_func_weekday::val_int() { bool Item_func_dayname::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; const CHARSET_INFO *cs = thd->variables.collation_connection; const uint32 repertoire = my_charset_repertoire(cs); locale = thd->variables.lc_time_names; @@ -1496,6 +1512,7 @@ String *Item_func_dayname::val_str(String *str) { bool Item_func_year::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; set_data_type_year(); set_nullable(true); return false; @@ -1508,7 +1525,8 @@ longlong Item_func_year::val_int() { } bool Item_typecast_year::resolve_type(THD *thd) { - if (reject_geometry_args(arg_count, args, this)) return true; + if (reject_geometry_args()) return true; + if (reject_vector_args()) return true; if (args[0]->propagate_type(thd, MYSQL_TYPE_YEAR, false, true)) return true; assert(decimal_precision() == 4); set_nullable(true); @@ -1701,6 +1719,7 @@ longlong Item_func_unix_timestamp::val_int_endpoint(bool, bool *) { bool Item_func_time_to_sec::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_TIME)) return true; + if (reject_vector_args()) return true; fix_char_length(10); set_nullable(true); return false; @@ -2180,6 +2199,8 @@ bool Item_func_sec_to_time::get_time(MYSQL_TIME *ltime) { bool Item_func_date_format::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; if (param_type_is_default(thd, 1, 2)) return true; + if (reject_vector_args()) return true; + /* Must use this_item() in case it's a local SP variable (for ->max_length and ->str_value) @@ -2337,6 +2358,7 @@ String *Item_func_date_format::val_str(String *str) { bool Item_func_from_unixtime::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_NEWDECIMAL)) return true; + if (reject_vector_args()) return true; set_data_type_datetime(min(args[0]->decimals, uint8{DATETIME_MAX_DECIMALS})); set_nullable(true); thd->time_zone_used = true; @@ -2399,6 +2421,7 @@ bool Item_func_from_unixtime::get_date(MYSQL_TIME *ltime, bool Item_func_convert_tz::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; if (param_type_is_default(thd, 1, -1)) return true; + if (reject_vector_args()) return true; set_data_type_datetime(args[0]->datetime_precision()); set_nullable(true); return false; @@ -2449,6 +2472,8 @@ void Item_func_convert_tz::cleanup() { } bool Item_date_add_interval::resolve_type(THD *thd) { + if (reject_geometry_args()) return true; + if (reject_vector_args()) return true; set_nullable(true); /* @@ -2696,6 +2721,7 @@ void Item_extract::print(const THD *thd, String *str, bool Item_extract::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; set_nullable(true); // If wrong date switch (int_type) { case INTERVAL_YEAR: @@ -3016,6 +3042,7 @@ bool Item_func_add_time::resolve_type(THD *thd) { m_datetime ? MYSQL_TYPE_DATETIME : MYSQL_TYPE_TIME)) return true; if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_TIME)) return true; + if (reject_vector_args()) return true; /* The field type for the result of an Item_func_add_time function is defined @@ -3289,6 +3316,7 @@ longlong Item_func_microsecond::val_int() { bool Item_func_microsecond::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; set_nullable(true); return false; } @@ -3549,6 +3577,7 @@ void Item_func_str_to_date::fix_from_format(const char *format, size_t length) { bool Item_func_str_to_date::resolve_type(THD *thd) { if (param_type_is_default(thd, 0, 2)) return true; + if (reject_vector_args()) return true; set_nullable(true); cached_timestamp_type = MYSQL_TIMESTAMP_DATETIME; set_data_type_datetime(DATETIME_MAX_DECIMALS); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 1823f6d11..a44e99635 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -454,6 +454,7 @@ class Item_func_unix_timestamp final : public Item_timeval_func { bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; + if (reject_vector_args()) return true; collation.set_numeric(); const uint8 dec = arg_count == 0 ? 0 : args[0]->datetime_precision(); if (dec > 0) { @@ -1284,6 +1285,7 @@ class Item_func_from_days final : public Item_date_func { } bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG)) return true; + if (reject_vector_args()) return true; return Item_date_func::resolve_type(thd); } Item *pq_clone(THD *thd, Query_block *select) override; @@ -1357,6 +1359,7 @@ class Item_func_sec_to_time final : public Item_time_func { : Item_time_func(pos, item) {} bool resolve_type(THD *thd) override { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_NEWDECIMAL)) return true; + if (reject_vector_args()) return true; set_data_type_time( std::min(args[0]->decimals, uint8{DATETIME_MAX_DECIMALS})); set_nullable(true); @@ -1484,6 +1487,7 @@ class Item_typecast_date final : public Item_date_func { bool resolve_type(THD *thd) override { if (args[0]->propagate_type(thd, MYSQL_TYPE_DATE, false, true)) return true; + if (reject_vector_args()) return true; return Item_date_func::resolve_type(thd); } void print(const THD *thd, String *str, @@ -1525,6 +1529,7 @@ class Item_typecast_time final : public Item_time_func { bool get_time(MYSQL_TIME *ltime) override; const char *cast_type() const { return "time"; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (args[0]->propagate_type(thd, MYSQL_TYPE_DATETIME, false, true)) return true; set_data_type_time(detect_precision_from_arg ? args[0]->time_precision() @@ -1564,6 +1569,7 @@ class Item_typecast_datetime final : public Item_datetime_func { const char *cast_type() const { return "datetime"; } bool is_explicit_cast() const { return m_explicit_cast; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (args[0]->propagate_type(thd, MYSQL_TYPE_DATETIME, false, true)) return true; set_data_type_datetime( @@ -1586,6 +1592,7 @@ class Item_func_makedate final : public Item_date_func { bool get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzy_date) override; enum Functype functype() const override { return MAKEDATE_FUNC; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_LONGLONG)) return true; return Item_date_func::resolve_type(thd); } @@ -1634,6 +1641,7 @@ class Item_func_timediff final : public Item_time_func { const char *func_name() const override { return "timediff"; } enum Functype functype() const override { return TIMEDIFF_FUNC; } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; /* This function can operate on two TIME, or on two DATETIME (no mix). We infer the type from the other argument. If both arguments are '?', we @@ -1658,6 +1666,7 @@ class Item_func_maketime final : public Item_time_func { set_nullable(true); } bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 2, MYSQL_TYPE_LONGLONG)) return true; if (param_type_is_default(thd, 2, 3, MYSQL_TYPE_NEWDECIMAL)) return true; set_data_type_time( @@ -1696,6 +1705,7 @@ class Item_func_timestamp_diff final : public Item_int_func { interval_type intervaltype() const { return int_type; } longlong val_int() override; bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DATETIME)) return true; set_nullable(true); return false; @@ -1723,6 +1733,7 @@ class Item_func_get_format final : public Item_str_ascii_func { const char *func_name() const override { return "get_format"; } enum Functype functype() const override { return GET_FORMAT_FUNC; } bool resolve_type(THD *) override { + if (reject_vector_args()) return true; set_nullable(true); set_data_type_string(17, default_charset()); return false; @@ -1759,6 +1770,7 @@ class Item_func_last_day final : public Item_date_func { enum Functype functype() const override { return LAST_DAY_FUNC; } bool get_date(MYSQL_TIME *res, my_time_flags_t fuzzy_date) override; bool resolve_type(THD *thd) override { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DATETIME)) return true; return Item_date_func::resolve_type(thd); } diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index ba7332baa..2ce19ec69 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -184,6 +184,7 @@ class Item_nodeset_func : public Item_str_func { } enum Item_result result_type() const override { return STRING_RESULT; } bool resolve_type(THD *) override { + if (reject_vector_args()) return true; set_data_type_string(uint32{MAX_BLOB_WIDTH}); // To avoid premature evaluation, mark all nodeset functions as non-const. used_tables_cache = RAND_TABLE_BIT; @@ -419,6 +420,7 @@ class Item_func_xpath_position : public Item_int_func { explicit Item_func_xpath_position(Item *a) : Item_int_func(a) {} const char *func_name() const override { return "xpath_position"; } bool resolve_type(THD *) override { + if (reject_vector_args()) return true; set_data_type_string(10U); return false; } @@ -436,6 +438,7 @@ class Item_func_xpath_count : public Item_int_func { explicit Item_func_xpath_count(Item *a) : Item_int_func(a) {} const char *func_name() const override { return "xpath_count"; } bool resolve_type(THD *) override { + if (reject_vector_args()) return true; set_data_type_string(10U); return false; } @@ -2281,6 +2284,7 @@ static int my_xpath_parse(MY_XPATH *xpath, const char *str, } bool Item_xml_str_func::resolve_type(THD *thd) { + if (reject_vector_args()) return true; if (param_type_is_default(thd, 0, -1)) return true; if (agg_arg_charsets_for_comparison(collation, args, arg_count)) return true; diff --git a/sql/lex.h b/sql/lex.h index 10307d57a..277c274e0 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -796,6 +796,7 @@ static const SYMBOL symbols[] = { {SYM("VARCHARACTER", VARCHAR_SYM)}, {SYM("VARIABLES", VARIABLES)}, {SYM("VARYING", VARYING)}, + {SYM("VECTOR", VECTOR_SYM)}, {SYM("WAIT", WAIT_SYM)}, {SYM("WARNINGS", WARNINGS)}, {SYM("WEEK", WEEK_SYM)}, diff --git a/sql/log_event.cc b/sql/log_event.cc index dbfc29241..224250c20 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -82,6 +82,7 @@ #include "sql/system_variables.h" #include "sql/tc_log.h" #include "sql/xa/sql_cmd_xa.h" // Sql_cmd_xa_* +#include "sql/vector_conversion.h" #include "sql_const.h" #include "sql_string.h" #include "strmake.h" @@ -1749,6 +1750,7 @@ static const char *print_json_diff(IO_CACHE *out, const uchar *data, @param[in] col_name Column name @param[in] is_partial True if this is a JSON column that will be read in partial format, false otherwise. + @param[in] vector_dimensionality Dimensionality of vector column @retval 0 on error @retval number of bytes scanned from ptr for non-NULL fields, or @@ -1758,7 +1760,8 @@ static const char *print_json_diff(IO_CACHE *out, const uchar *data, static size_t log_event_print_value(IO_CACHE *file, const uchar *ptr, uint type, uint meta, char *typestr, size_t typestr_length, char *col_name, - bool is_partial) { + bool is_partial, + unsigned int vector_dimensionality) { uint32 length = 0; if (type == MYSQL_TYPE_STRING) { @@ -2004,6 +2007,25 @@ static size_t log_event_print_value(IO_CACHE *file, const uchar *ptr, uint type, my_b_write_bit(file, ptr, (meta & 0xFF) * 8); return meta & 0xFF; + case MYSQL_TYPE_VECTOR: { + snprintf(typestr, typestr_length, "VECTOR(%u)", vector_dimensionality); + if (ptr == nullptr) { + return my_b_printf(file, "NULL"); + } + length = uint4korr(ptr); + ptr += 4; + uint dims = get_dimensions(length, sizeof(float)); + my_b_printf(file, "["); + const uint tmp_length = 40; + char tmp[tmp_length]; + for (uint i = 0; i < dims; i++) { + char delimiter = (i == dims - 1) ? ']' : ','; + snprintf(tmp, tmp_length, "%.5e", float4get(ptr + i * sizeof(float))); + my_b_printf(file, "%s%c", tmp, delimiter); + } + return length + 4; + } + case MYSQL_TYPE_BLOB: switch (meta) { case 1: @@ -2138,6 +2160,8 @@ size_t Rows_log_event::print_verbose_one_row( my_b_printf(file, "%s", prefix); + auto vector_dimensionality_it = td->get_vector_dimensionality_begin(); + for (size_t i = 0; i < td->size(); i++) { /* Note: need to read partial bit before reading cols_bitmap, since @@ -2166,11 +2190,18 @@ size_t Rows_log_event::print_verbose_one_row( return 0; } } + + unsigned int vector_dimensionality = 0; + if (td->type(i) == MYSQL_TYPE_VECTOR && + vector_dimensionality_it != td->get_vector_dimensionality_end()) { + vector_dimensionality = *vector_dimensionality_it++; + } + char col_name[256]; sprintf(col_name, "@%lu", (unsigned long)i + 1); const size_t size = log_event_print_value( file, is_null ? nullptr : value, td->type(i), td->field_metadata(i), - typestr, sizeof(typestr), col_name, is_partial); + typestr, sizeof(typestr), col_name, is_partial, vector_dimensionality); if (!size) return 0; if (!is_null) value += size; @@ -10825,9 +10856,17 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) { inside Relay_log_info::clear_tables_to_lock() by calling the table_def destructor explicitly. */ + uint vector_column_count = + table_def::vector_column_count(m_coltype, m_colcnt); + std::vector vector_dimensionality; + if (vector_column_count > 0) { + const Optional_metadata_fields fields(m_optional_metadata, + m_optional_metadata_len); + vector_dimensionality = fields.m_vector_dimensionality; + } new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt, m_field_metadata, m_field_metadata_size, - m_null_bits, m_flags); + m_null_bits, m_flags, vector_dimensionality); table_list->m_tabledef_valid = true; table_list->m_conv_table = nullptr; @@ -11017,6 +11056,7 @@ static inline bool is_character_type(uint type) { case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: return true; default: return false; @@ -11059,7 +11099,7 @@ void Table_map_log_event::init_metadata_fields() { if (init_signedness_field() || init_charset_field(&is_character_field, DEFAULT_CHARSET, COLUMN_CHARSET) || - init_geometry_type_field()) { + init_geometry_type_field() || init_vector_dimensionality_field()) { m_metadata_buf.length(0); return; } @@ -11277,6 +11317,20 @@ bool Table_map_log_event::init_geometry_type_field() { return false; } +bool Table_map_log_event::init_vector_dimensionality_field() { + StringBuffer<256> buf; + for (auto *field : *m_column_view) { + if (field->real_type() == MYSQL_TYPE_VECTOR) { + store_compressed_length( + buf, down_cast(field)->get_max_dimensions()); + } + } + + if (buf.length() > 0) + return write_tlv_field(m_metadata_buf, VECTOR_DIMENSIONALITY, buf); + return false; +} + bool Table_map_log_event::init_primary_key_field() { DBUG_EXECUTE_IF("simulate_init_primary_key_field_error", return true;); @@ -11410,7 +11464,8 @@ void Table_map_log_event::print(FILE *, */ static void get_type_name(uint type, unsigned char **meta_ptr, const CHARSET_INFO *cs, char *typestr, - uint typestr_length, unsigned int geometry_type) { + uint typestr_length, unsigned int geometry_type, + unsigned int vector_dimensionality) { switch (type) { case MYSQL_TYPE_LONG: snprintf(typestr, typestr_length, "%s", "INT"); @@ -11484,6 +11539,11 @@ static void get_type_name(uint type, unsigned char **meta_ptr, snprintf(typestr, typestr_length, "SET"); (*meta_ptr) += 2; break; + case MYSQL_TYPE_VECTOR: { + snprintf(typestr, typestr_length, "VECTOR(%u)", vector_dimensionality); + (*meta_ptr)++; + break; + } case MYSQL_TYPE_BLOB: { const bool is_text = (cs && cs->number != my_charset_bin.number); const char *names[5][2] = {{"INVALID_BLOB(%d)", "INVALID_TEXT(%d)"}, @@ -11650,6 +11710,7 @@ void Table_map_log_event::print_columns( uint geometry_type = 0; std::vector::const_iterator column_visibility_it = fields.m_column_visibility.begin(); + auto vector_dimensionality_it = fields.m_vector_dimensionality.begin(); my_b_printf(file, "# Columns("); @@ -11685,11 +11746,17 @@ void Table_map_log_event::print_columns( : 0; } + unsigned int vector_dimensionality = 0; + if (real_type == MYSQL_TYPE_VECTOR && + vector_dimensionality_it != fields.m_vector_dimensionality.end()) { + vector_dimensionality = *vector_dimensionality_it++; + } + // print column type const uint TYPE_NAME_LEN = 100; char type_name[TYPE_NAME_LEN]; get_type_name(real_type, &field_metadata_ptr, cs, type_name, TYPE_NAME_LEN, - geometry_type); + geometry_type, vector_dimensionality); if (type_name[0] == '\0') { my_b_printf(file, "INVALID_TYPE(%d)", real_type); diff --git a/sql/log_event.h b/sql/log_event.h index cb47b855e..628871bd8 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2337,8 +2337,17 @@ class Table_map_log_event : public binary_log::Table_map_event, #ifndef MYSQL_SERVER table_def *create_table_def() { assert(m_colcnt > 0); + uint vector_column_count = + table_def::vector_column_count(m_coltype, m_colcnt); + std::vector vector_dimensionality; + if (vector_column_count > 0) { + const Optional_metadata_fields fields(m_optional_metadata, + m_optional_metadata_len); + vector_dimensionality = fields.m_vector_dimensionality; + } return new table_def(m_coltype, m_colcnt, m_field_metadata, - m_field_metadata_size, m_null_bits, m_flags); + m_field_metadata_size, m_null_bits, m_flags, + vector_dimensionality); } static bool rewrite_db_in_buffer(char **buf, ulong *event_len, const Format_description_event &fde); @@ -2475,6 +2484,7 @@ class Table_map_log_event : public binary_log::Table_map_event, bool init_geometry_type_field(); bool init_primary_key_field(); bool init_column_visibility_field(); + bool init_vector_dimensionality_field(); #endif #ifndef MYSQL_SERVER diff --git a/sql/pack_rows.cc b/sql/pack_rows.cc index 095a43e17..7ff76b0d2 100644 --- a/sql/pack_rows.cc +++ b/sql/pack_rows.cc @@ -169,6 +169,7 @@ static size_t CalculateColumnStorageSize(const Column &column) { break; case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: diff --git a/sql/parse_tree_column_attrs.h b/sql/parse_tree_column_attrs.h index 41fdca126..ba40d3ef5 100644 --- a/sql/parse_tree_column_attrs.h +++ b/sql/parse_tree_column_attrs.h @@ -689,6 +689,21 @@ class PT_char_type : public PT_type { const CHARSET_INFO *get_charset() const override { return charset; } }; +class PT_vector_type : public PT_type { + char vector_length_buffer[33]{}; + + public: + PT_vector_type(const POS &pos, const char *length) + : PT_type(pos, MYSQL_TYPE_VECTOR) { + const char *length_arg = length == nullptr ? "2048" : length; + uint vector_length = atoi(length_arg) * sizeof(float); + sprintf(vector_length_buffer, "%u", vector_length); + } + + const char *get_length() const override { return vector_length_buffer; } + const CHARSET_INFO *get_charset() const override { return &my_charset_bin; } +}; + enum class Blob_type { TINY = MYSQL_TYPE_TINY_BLOB, MEDIUM = MYSQL_TYPE_MEDIUM_BLOB, diff --git a/sql/partitioning/partition_handler.cc b/sql/partitioning/partition_handler.cc index aac1d1a68..c450c68c7 100644 --- a/sql/partitioning/partition_handler.cc +++ b/sql/partitioning/partition_handler.cc @@ -888,6 +888,7 @@ uint32 Partition_helper::ph_calculate_key_hash_value(Field **field_array) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_INVALID: diff --git a/sql/protocol_classic.cc b/sql/protocol_classic.cc index 930a541f8..ce854b4db 100644 --- a/sql/protocol_classic.cc +++ b/sql/protocol_classic.cc @@ -3430,6 +3430,7 @@ bool Protocol_classic::store_string(const char *from, size_t length, field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL || field_types[field_pos] == MYSQL_TYPE_NEWDATE || field_types[field_pos] == MYSQL_TYPE_JSON || + field_types[field_pos] == MYSQL_TYPE_VECTOR || (field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_GEOMETRY)); field_pos++; diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 0ab392587..aa8f500cc 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -228,6 +228,7 @@ inline bool time_cross_check(enum_field_types type1, enum_field_types type2) { @param[in] is_array Whether the source field is a typed array @param[in] rli Relay log info (for error reporting) @param[in] mflags Flags from the table map event + @param[in] vector_dimensionality Dimensionality of vector column @param[out] order_var Order between source field and target field @return @c true if conversion is possible according to the current @@ -237,6 +238,7 @@ inline bool time_cross_check(enum_field_types type1, enum_field_types type2) { static bool can_convert_field_to(Field *field, enum_field_types source_type, uint metadata, bool is_array, Relay_log_info *rli, uint16 mflags, + unsigned int vector_dimensionality, int *order_var) { DBUG_TRACE; #ifndef NDEBUG @@ -270,6 +272,12 @@ static bool can_convert_field_to(Field *field, enum_field_types source_type, return true; } + if (field->real_type() == MYSQL_TYPE_VECTOR && + down_cast(field)->get_max_dimensions() != + vector_dimensionality) { + return false; + } + DBUG_PRINT("debug", ("Base types are identical, doing field size comparison")); if (field->compatible_field_size(metadata, rli, mflags, order_var)) @@ -418,6 +426,7 @@ static bool can_convert_field_to(Field *field, enum_field_types source_type, } break; + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: case MYSQL_TYPE_TIMESTAMP: @@ -538,13 +547,23 @@ bool table_def::compatible_with(THD *thd, Relay_log_info *rli, TABLE *table, min(fields->filtered_size(), filtered_size(replica_has_gipk)); TABLE *tmp_table = nullptr; + auto vector_dimensionality_it = m_vector_dimensionality.begin(); + for (auto it = fields->begin(); it.filtered_pos() < cols_to_check; ++it) { Field *const field = *it; size_t col = it.translated_pos(); size_t absolute_col_pos = it.absolute_pos(); int order; + + unsigned int vector_dimensionality = 0; + if (type(col) == MYSQL_TYPE_VECTOR && + vector_dimensionality_it != m_vector_dimensionality.end()) { + vector_dimensionality = *vector_dimensionality_it++; + } + if (can_convert_field_to(field, type(col), field_metadata(col), - is_array(col), rli, m_flags, &order)) { + is_array(col), rli, m_flags, vector_dimensionality, + &order)) { DBUG_PRINT("debug", ("Checking column %lu -" " field '%s' can be converted - order: %d", static_cast(col), @@ -586,8 +605,8 @@ bool table_def::compatible_with(THD *thd, Relay_log_info *rli, TABLE *table, enum loglevel report_level = INFORMATION_LEVEL; String source_type(source_buf, sizeof(source_buf), &my_charset_latin1); String target_type(target_buf, sizeof(target_buf), &my_charset_latin1); - show_sql_type(type(col), is_array(col), field_metadata(col), - &source_type); + show_sql_type(type(col), is_array(col), field_metadata(col), &source_type, + nullptr, vector_dimensionality); field->sql_type(target_type); if (!ignored_error_code(ER_SERVER_REPLICA_CONVERSION_FAILED)) { report_level = ERROR_LEVEL; @@ -880,6 +899,7 @@ std::pair> read_field_metadata( switch (binlog_type) { case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_DOUBLE: @@ -935,7 +955,8 @@ std::pair> read_field_metadata( PSI_memory_key key_memory_table_def_memory; table_def::table_def(unsigned char *types, ulong size, uchar *field_metadata, - int metadata_size, uchar *null_bitmap, uint16 flags) + int metadata_size, uchar *null_bitmap, uint16 flags, + const std::vector &vector_dimensionality) : m_size(size), m_type(nullptr), m_field_metadata_size(metadata_size), @@ -946,7 +967,8 @@ table_def::table_def(unsigned char *types, ulong size, uchar *field_metadata, m_json_column_count(-1), m_is_array(nullptr), m_is_gipk_set(false), - m_is_gipk_on_table(false) { + m_is_gipk_on_table(false), + m_vector_dimensionality(vector_dimensionality) { m_memory = (uchar *)my_multi_malloc( key_memory_table_def_memory, MYF(MY_WME), &m_type, size, &m_field_metadata, size * sizeof(uint), &m_is_array, size * sizeof(bool), @@ -1232,6 +1254,7 @@ uint Hash_slave_rows::make_hash_key(TABLE *table, MY_BITMAP *cols) { */ switch (f->type()) { case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index a7c135e9c..9d138f633 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -31,6 +31,7 @@ #include #include #include +#include #include "field_types.h" // enum_field_types #include "my_dbug.h" @@ -263,9 +264,11 @@ class table_def { @param metadata_size Size of the field_metadata array @param null_bitmap The bitmap of fields that can be null @param flags Table flags + @param vector_dimensionality Vector dimensionality array */ table_def(unsigned char *types, ulong size, uchar *field_metadata, - int metadata_size, uchar *null_bitmap, uint16 flags); + int metadata_size, uchar *null_bitmap, uint16 flags, + const std::vector &vector_dimensionality); ~table_def(); @@ -307,6 +310,17 @@ class table_def { return m_json_column_count; } + /// Return the number of VECTOR columns + static uint vector_column_count(const unsigned char *types, ulong size) { + uint count = 0; + for (ulong i = 0; i < size; i++) { + if (static_cast(types[i]) == MYSQL_TYPE_VECTOR) { + count++; + } + } + return count; + } + /* Return a representation of the type data for one field. @@ -399,6 +413,16 @@ class table_def { */ uint32 calc_field_size(uint col, const uchar *master_data) const; + std::vector::const_iterator get_vector_dimensionality_begin() + const { + return m_vector_dimensionality.begin(); + } + + std::vector::const_iterator get_vector_dimensionality_end() + const { + return m_vector_dimensionality.end(); + } + #ifdef MYSQL_SERVER /** Decide if the table definition is compatible with a table. @@ -501,6 +525,7 @@ class table_def { bool *m_is_array; bool m_is_gipk_set; bool m_is_gipk_on_table; + std::vector m_vector_dimensionality; }; #ifdef MYSQL_SERVER diff --git a/sql/server_component/mysql_query_attributes_imp.cc b/sql/server_component/mysql_query_attributes_imp.cc index a498d6ac9..ba0694116 100644 --- a/sql/server_component/mysql_query_attributes_imp.cc +++ b/sql/server_component/mysql_query_attributes_imp.cc @@ -350,7 +350,8 @@ static String *query_parameter_val_str(const PS_PARAM *param, case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: { + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: { str = new String[1]; uint dummy_errors; if (str->copy(reinterpret_cast(param->value), param->length, diff --git a/sql/server_component/mysql_stored_program_imp.cc b/sql/server_component/mysql_stored_program_imp.cc index 97a4790f0..9fca4c37a 100644 --- a/sql/server_component/mysql_stored_program_imp.cc +++ b/sql/server_component/mysql_stored_program_imp.cc @@ -231,6 +231,9 @@ static int get_field_metadata_internal(Create_field &field, bool input, case MYSQL_TYPE_GEOMETRY: *reinterpret_cast(value) = MYSQL_SP_ARG_TYPE_GEOMETRY; break; + case MYSQL_TYPE_VECTOR: + *reinterpret_cast(value) = MYSQL_SP_ARG_TYPE_VECTOR; + break; default: return MYSQL_FAILURE; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d8ca76038..1de9c7e8e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -403,6 +403,7 @@ static bool mysql_prepare_blob_values(THD *thd, Field *lhs_field = field->field; if (lhs_field->type() == MYSQL_TYPE_BLOB || + lhs_field->type() == MYSQL_TYPE_VECTOR || lhs_field->type() == MYSQL_TYPE_GEOMETRY) blob_update_field_set.insert_unique(down_cast(lhs_field)); } diff --git a/sql/sql_optimizer.cc b/sql/sql_optimizer.cc index 9f9f50459..9cf880ec6 100644 --- a/sql/sql_optimizer.cc +++ b/sql/sql_optimizer.cc @@ -6720,6 +6720,7 @@ bool uses_index_fields_only(Item *item, TABLE *tbl, uint keyno, */ return item_field->field->part_of_key.is_set(keyno) && item_field->field->type() != MYSQL_TYPE_GEOMETRY && + item_field->field->type() != MYSQL_TYPE_VECTOR && item_field->field->type() != MYSQL_TYPE_BLOB; } case Item::REF_ITEM: @@ -11574,8 +11575,8 @@ static uint32 get_key_length_tmp_table(Item *item) { // references KEY_PART_INFO::init_from_field() const enum_field_types type = item->data_type(); - if (type == MYSQL_TYPE_BLOB || type == MYSQL_TYPE_VARCHAR || - type == MYSQL_TYPE_GEOMETRY) + if (type == MYSQL_TYPE_BLOB || type == MYSQL_TYPE_VECTOR || + type == MYSQL_TYPE_VARCHAR || type == MYSQL_TYPE_GEOMETRY) len += HA_KEY_BLOB_LENGTH; return len; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 09c0f4dca..4bf28b09c 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -510,6 +510,13 @@ static bool set_up_field_array(TABLE *table, bool is_sub_part) { performance reasons. */ + if (field->real_type() == MYSQL_TYPE_VECTOR) { + /* vector column as partition key is not supported */ + my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0), + field->field_name); + result = true; + } + if (field->is_flag_set(BLOB_FLAG)) { my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0)); result = true; @@ -1949,6 +1956,13 @@ static int check_part_field(enum_field_types sql_type, const char *field_name, my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0)); return true; } + if (sql_type == MYSQL_TYPE_VECTOR) { + /* vector column as partition key is not supported */ + /* LCOV_EXCL_START */ + my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0), field_name); + return true; + /* LCOV_EXCL_STOP */ + } switch (sql_type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 33e43420f..5b99d96e9 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -506,7 +506,8 @@ static void set_parameter_type(Item_param *param, enum enum_field_types type, case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: { + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: { param->set_collation_source(&my_charset_bin); break; } @@ -2944,6 +2945,7 @@ bool Prepared_statement::check_parameter_types() { case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_LONG_BLOB: if (item->data_type_actual() == MYSQL_TYPE_LONGLONG || item->data_type_actual() == MYSQL_TYPE_NEWDECIMAL || diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f87b63639..a1aebd9e9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4616,6 +4616,7 @@ static TABLE *create_schema_table(THD *thd, Table_ref *table_list) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: if (!(item = new Item_blob(fields_info->field_name, fields_info->field_length))) { return nullptr; @@ -5585,11 +5586,13 @@ static void get_cs_converted_string_value(THD *thd, String *input_str, @param str String to print to @param field_cs field's charset. When given [var]char length is printed in characters, otherwise - in bytes + @param vector_dimensionality The dimensionality of a vector field */ void show_sql_type(enum_field_types type, bool is_array, uint metadata, - String *str, const CHARSET_INFO *field_cs) { + String *str, const CHARSET_INFO *field_cs, + unsigned int vector_dimensionality) { DBUG_TRACE; DBUG_PRINT("enter", ("type: %d, metadata: 0x%x", type, metadata)); @@ -5721,6 +5724,14 @@ void show_sql_type(enum_field_types type, bool is_array, uint metadata, str->set_ascii(STRING_WITH_LEN("longtext")); break; + case MYSQL_TYPE_VECTOR: { + const CHARSET_INFO *cs = str->charset(); + size_t length = cs->cset->snprintf(cs, str->ptr(), str->alloced_length(), + "vector(%u)", vector_dimensionality); + str->length(length); + break; + } + case MYSQL_TYPE_BLOB: /* Field::real_type() lies regarding the actual type of a BLOB, so diff --git a/sql/sql_show.h b/sql/sql_show.h index dd7a365aa..6624ba8b9 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -144,7 +144,8 @@ int get_quote_char_for_identifier(const THD *thd, const char *name, size_t length); void show_sql_type(enum_field_types type, bool is_array, uint metadata, - String *str, const CHARSET_INFO *field_cs = nullptr); + String *str, const CHARSET_INFO *field_cs = nullptr, + unsigned int vector_dimensionality = 0); bool do_fill_information_schema_table(THD *thd, Table_ref *table_list, Item *condition); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8d3cb5f95..da270446b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4085,6 +4085,7 @@ bool prepare_pack_create_field(THD *thd, Create_field *sql_field, } [[fallthrough]]; case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -5005,6 +5006,12 @@ static bool prepare_key_column(THD *thd, HA_CREATE_INFO *create_info, return true; } + // VECTOR columns cannot be used as keys + if (sql_field->sql_type == MYSQL_TYPE_VECTOR) { + my_error(ER_NON_SCALAR_USED_AS_KEY, MYF(0), column->get_field_name()); + return true; + } + if (sql_field->auto_flags & Field::NEXT_NUMBER) { if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY)) (*auto_increment)--; // Field is used @@ -7597,6 +7604,10 @@ bool Item_field::replace_field_processor(uchar *arg) { if (create_field) { field = new (targ->thd()->mem_root) Create_field_wrapper(create_field); switch (create_field->sql_type) { + case MYSQL_TYPE_VECTOR: + my_error(ER_INCORRECT_TYPE, MYF(0), create_field->field_name, + "GENERATED COLUMN"); + return true; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -8159,6 +8170,7 @@ bool mysql_prepare_create_table( switch (sql_field->sql_type) { case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -18957,6 +18969,7 @@ bool mysql_checksum_table(THD *thd, Table_ref *tables, */ switch (f->type()) { case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e59a6c688..3c83be26e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -531,7 +531,7 @@ void warn_on_deprecated_user_defined_collation( 2. We should not introduce new shift/reduce conflicts any more. */ -%expect 63 +%expect 64 /* MAINTAINER: @@ -1410,6 +1410,7 @@ void warn_on_deprecated_user_defined_collation( %token PARSE_TREE_SYM 1205 /* MYSQL */ +%token VECTOR_SYM 1215 /* Precedence rules used to resolve the ambiguity when using keywords as idents in the case e.g.: @@ -7170,6 +7171,10 @@ type: { $$= NEW_PTN PT_char_type(@$, Char_type::VARCHAR, $2, &my_charset_bin); } + | VECTOR_SYM opt_field_length + { + $$= NEW_PTN PT_vector_type(@$, $2); + } | YEAR_SYM opt_field_length field_options { if ($2) @@ -15793,6 +15798,7 @@ ident_keywords_unambiguous: | XML_SYM | YEAR_SYM | ZONE_SYM + | VECTOR_SYM ; /* diff --git a/sql/vector_conversion.h b/sql/vector_conversion.h new file mode 100644 index 000000000..221660677 --- /dev/null +++ b/sql/vector_conversion.h @@ -0,0 +1,144 @@ +/* Copyright (c) 2024, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef VECTOR_CONV_INCLUDED +#define VECTOR_CONV_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sql_string.h" + +static inline bool from_string_to_vector(const char *input, uint32_t input_len, + char *const output, + uint32_t *max_output_dims) { + if (input == nullptr || input[0] != '[' || input_len == 0 || + input[input_len - 1] != ']') { + *max_output_dims = 0; + return true; + } + + // Check for memory region overlap + size_t output_len = sizeof(float) * (*max_output_dims); + String temp_output(output, output_len, nullptr); + if (output + output_len >= input && input + input_len >= output) { + temp_output = String(output_len); + } + + const char *const input_end = input + input_len - 1; + input = input + 1; + uint32_t dim = 0; + char *end = nullptr; + bool with_success = false; + errno = 0; + for (float fnum = strtof(input, &end); input != end; + fnum = strtof(input, &end)) { + input = end; + if (errno == ERANGE || dim >= *max_output_dims || std::isnan(fnum) || + std::isinf(fnum)) { + errno = 0; + break; + } + memcpy(temp_output.ptr() + dim * sizeof(float), &fnum, sizeof(float)); + + if (*input == ',') { + input = input + 1; + dim++; + } else if (*input == ']' && input == input_end) { + with_success = true; + dim++; + break; + } else { + break; + } + } + + if (temp_output.ptr() != output) { + memcpy(output, temp_output.ptr(), dim * sizeof(float)); + } + + *max_output_dims = dim; + return !with_success; +} + +static inline bool from_vector_to_string(const char *const input, + uint32_t input_dims, + char *const output, + uint32_t *max_output_len) { + const uint32_t end_cushion = 12; + if (input == nullptr || *max_output_len < end_cushion) { + return true; + } + + // Check for memory region overlap + size_t input_len = input_dims * sizeof(float); + String temp_output(output, *max_output_len, nullptr); + if (output + *max_output_len >= input && input + input_len >= output) { + temp_output = String(*max_output_len); + } + + char *write_ptr = temp_output.ptr(); + uint32_t total_length = 1; + write_ptr[0] = '['; + write_ptr += 1; + for (uint32_t i = 0; i < input_dims; i++) { + int remaining_bytes = *max_output_len - total_length; + int nchars = 0; + if (*max_output_len <= total_length + end_cushion) { + nchars = snprintf(write_ptr, remaining_bytes, "..."); + i = input_dims; + } else { + char delimiter = (i == input_dims - 1) ? ']' : ','; + float input_value = 0; + memcpy(&input_value, input + i * sizeof(float), sizeof(float)); + nchars = snprintf(write_ptr, remaining_bytes, "%.5e%c", input_value, + delimiter); + if (nchars < 0 || nchars >= remaining_bytes) { + return true; /* LCOV_EXCL_LINE */ + } + } + write_ptr += nchars; + total_length += nchars; + } + + if (temp_output.ptr() != output) { + memcpy(output, temp_output.ptr(), total_length); + } + + *max_output_len = total_length; + return false; +} + +static inline uint32_t get_dimensions(const uint32_t length, + const uint32_t precision) { + if (length == 0 || (length % precision > 0)) { + return UINT32_MAX; + } + return length / precision; +} + +#endif /* VECTOR_CONV_INCLUDED */ \ No newline at end of file diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index b520a7c0c..05adc448a 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -272,6 +272,7 @@ static inline CHARSET_INFO *fts_get_charset(ulint prtype) { case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: break; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 45777eb0d..ac169761d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -7992,6 +7992,7 @@ ulint get_innobase_type_from_mysql_type(ulint *unsigned_flag, const void *f) { case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_JSON: // JSON fields are stored as BLOBs return (DATA_BLOB); case MYSQL_TYPE_NULL: @@ -8129,6 +8130,7 @@ ulint get_innobase_type_from_mysql_dd_type(ulint *unsigned_flag, case dd::enum_column_types::MEDIUM_BLOB: case dd::enum_column_types::BLOB: case dd::enum_column_types::LONG_BLOB: + case dd::enum_column_types::VECTOR: *charset_no = field_charset->number; if (field_charset != &my_charset_bin) *binary_type = 0; return (DATA_BLOB); diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic index 0f75edf75..0d6fdd9ed 100644 --- a/storage/innobase/include/rem0cmp.ic +++ b/storage/innobase/include/rem0cmp.ic @@ -138,6 +138,7 @@ static inline bool cmp_dfield_dfield_eq_prefix(const dfield_t *dfield1, case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: break; diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc index ed8f67f56..707c7c00f 100644 --- a/storage/innobase/rem/rem0cmp.cc +++ b/storage/innobase/rem/rem0cmp.cc @@ -83,6 +83,7 @@ static inline int innobase_mysql_cmp(ulint prtype, const byte *a, case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: break; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index b72e9493f..3a87c0d74 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -311,6 +311,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, keydef[i].seg[j].null_pos = 0; } if (field->type() == MYSQL_TYPE_BLOB || + field->type() == MYSQL_TYPE_VECTOR || field->type() == MYSQL_TYPE_GEOMETRY) { keydef[i].seg[j].flag |= HA_BLOB_PART; /* save number of bytes used to pack length */ diff --git a/storage/ndb/plugin/ha_ndbcluster.cc b/storage/ndb/plugin/ha_ndbcluster.cc index c0f125cd1..8a921d6af 100644 --- a/storage/ndb/plugin/ha_ndbcluster.cc +++ b/storage/ndb/plugin/ha_ndbcluster.cc @@ -1351,6 +1351,7 @@ static bool field_type_forces_var_part(enum_field_types type) { return true; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_JSON: @@ -1696,7 +1697,7 @@ static bool type_supports_default_value(enum_field_types mysql_type) { (mysql_type != MYSQL_TYPE_BLOB && mysql_type != MYSQL_TYPE_TINY_BLOB && mysql_type != MYSQL_TYPE_MEDIUM_BLOB && mysql_type != MYSQL_TYPE_LONG_BLOB && mysql_type != MYSQL_TYPE_JSON && - mysql_type != MYSQL_TYPE_GEOMETRY); + mysql_type != MYSQL_TYPE_GEOMETRY && mysql_type != MYSQL_TYPE_VECTOR); return ret; } @@ -8455,6 +8456,12 @@ static int create_ndb_column(THD *thd, NDBCOL &col, Field *field, col.setLength(no_of_bits); break; } + case MYSQL_TYPE_VECTOR: + push_warning_printf( + thd, Sql_condition::SL_WARNING, ER_UNSUPPORTED_EXTENSION, + "VECTOR type is not supported by NDB in this MySQL version"); + return HA_ERR_UNSUPPORTED; + case MYSQL_TYPE_NULL: goto mysql_type_unsupported; mysql_type_unsupported: @@ -9892,6 +9899,7 @@ int ha_ndbcluster::create(const char *path [[maybe_unused]], switch (field->real_type()) { case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_JSON: { @@ -10277,6 +10285,7 @@ int ha_ndbcluster::create_index_in_NDB(THD *thd, const char *name, key_store_length += HA_KEY_NULL_LENGTH; } if (field->type() == MYSQL_TYPE_BLOB || + field->type() == MYSQL_TYPE_VECTOR || field->real_type() == MYSQL_TYPE_VARCHAR || field->type() == MYSQL_TYPE_GEOMETRY) { key_store_length += HA_KEY_BLOB_LENGTH; diff --git a/storage/ndb/plugin/ha_ndbcluster_cond.cc b/storage/ndb/plugin/ha_ndbcluster_cond.cc index ebebfb8d0..c9e1b6d0a 100644 --- a/storage/ndb/plugin/ha_ndbcluster_cond.cc +++ b/storage/ndb/plugin/ha_ndbcluster_cond.cc @@ -955,7 +955,8 @@ static void ndb_serialize_cond(const Item *item, void *arg) { type != MYSQL_TYPE_TINY_BLOB && type != MYSQL_TYPE_MEDIUM_BLOB && type != MYSQL_TYPE_LONG_BLOB && type != MYSQL_TYPE_BLOB && - type != MYSQL_TYPE_JSON && type != MYSQL_TYPE_GEOMETRY) { + type != MYSQL_TYPE_JSON && type != MYSQL_TYPE_GEOMETRY && + type != MYSQL_TYPE_VECTOR) { // Found a Field_item of a supported type assert(item->used_tables() != 0); diff --git a/storage/temptable/include/temptable/handler.h b/storage/temptable/include/temptable/handler.h index d4361fb26..429a93aa4 100644 --- a/storage/temptable/include/temptable/handler.h +++ b/storage/temptable/include/temptable/handler.h @@ -568,6 +568,7 @@ inline void Handler::opened_table_validate() { inline bool Handler::is_field_type_fixed_size(const Field &mysql_field) const { switch (mysql_field.type()) { case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VECTOR: case MYSQL_TYPE_GEOMETRY: case MYSQL_TYPE_JSON: case MYSQL_TYPE_LONG_BLOB: diff --git a/unittest/gunit/xplugin/xpl/mysql_function_names_t.cc.in b/unittest/gunit/xplugin/xpl/mysql_function_names_t.cc.in index 498f1da3b..c3e5efb25 100644 --- a/unittest/gunit/xplugin/xpl/mysql_function_names_t.cc.in +++ b/unittest/gunit/xplugin/xpl/mysql_function_names_t.cc.in @@ -574,6 +574,11 @@ Param_mysql_functions documentation_mysql_functions_param[] = { {"TO_BASE64", PASS}, {"TO_DAYS", PASS}, {"TO_SECONDS", PASS}, + {"TO_VECTOR", PASS}, + {"STRING_TO_VECTOR", PASS}, + {"FROM_VECTOR", PASS}, + {"VECTOR_TO_STRING", PASS}, + {"VECTOR_DIM", PASS}, {"TRIM", PASS}, {"TRUNCATE", PASS}, {"UCASE", PASS},