From 12726be31374fdc7c1c3d42f4eb432fc3b9c83c2 Mon Sep 17 00:00:00 2001 From: "wangzihao.wzh" Date: Mon, 11 May 2026 15:46:11 +0800 Subject: [PATCH 1/4] Fix VECTOR column DATA_TYPE in INFORMATION_SCHEMA views VECTOR columns stored as '/*!99999 vector(N) */ varbinary(4N)' in DD caused INFORMATION_SCHEMA.COLUMNS/PARAMETERS/ROUTINES to return '/*!99999' as DATA_TYPE instead of 'varbinary'. Fix by adding SUBSTRING_INDEX(..., '*/ ', -1) to strip the versioned comment prefix. Add EXTRA_IS_VERSION minor upgrade mechanism to rebuild I_S views on existing installations without bumping upstream IS_DD_VERSION. Co-Authored-By: Claude Opus 4.6 --- mysql-test/r/all_persisted_variables.result | 8 +- .../r/information_schema_parameters.result | 2 +- .../r/information_schema_routines.result | 2 +- .../r/i_s_schema_definition_debug.result | 8 +- .../t/i_s_schema_definition_debug.test | 8 +- .../suite/rds/r/vidx_i_s_metadata.result | 86 ++++++++++++++++ mysql-test/suite/rds/t/vidx_i_s_metadata.test | 97 +++++++++++++++++++ mysql-test/suite/sys_vars/r/all_vars.result | 10 ++ mysql-test/t/all_persisted_variables.test | 2 +- sql/CMakeLists.txt | 1 + sql/dd/dd_minor_upgrade.cc | 83 ++++++++++++++++ sql/dd/dd_minor_upgrade.h | 64 ++++++++++++ sql/dd/impl/system_views/columns.cc | 9 +- sql/dd/impl/system_views/parameters.cc | 10 +- sql/dd/impl/system_views/routines.cc | 12 ++- sql/dd/impl/tables/dd_properties.cc | 3 +- sql/dd/info_schema/metadata.cc | 12 +++ 17 files changed, 397 insertions(+), 20 deletions(-) create mode 100644 mysql-test/suite/rds/r/vidx_i_s_metadata.result create mode 100644 mysql-test/suite/rds/t/vidx_i_s_metadata.test create mode 100644 sql/dd/dd_minor_upgrade.cc create mode 100644 sql/dd/dd_minor_upgrade.h diff --git a/mysql-test/r/all_persisted_variables.result b/mysql-test/r/all_persisted_variables.result index 15e373f3d79..fc69409bfec 100644 --- a/mysql-test/r/all_persisted_variables.result +++ b/mysql-test/r/all_persisted_variables.result @@ -40,7 +40,7 @@ include/assert.inc [Expect 500+ variables in the table. Due to open Bugs, we are # Test SET PERSIST -include/assert.inc [Expect 476 persisted variables in the table.] +include/assert.inc [Expect 481 persisted variables in the table.] ************************************************************ * 3. Restart server, it must preserve the persisted variable @@ -48,9 +48,9 @@ include/assert.inc [Expect 476 persisted variables in the table.] ************************************************************ # restart -include/assert.inc [Expect 476 persisted variables in persisted_variables table.] -include/assert.inc [Expect 476 persisted variables shown as PERSISTED in variables_info table.] -include/assert.inc [Expect 476 persisted variables with matching peristed and global values.] +include/assert.inc [Expect 481 persisted variables in persisted_variables table.] +include/assert.inc [Expect 481 persisted variables shown as PERSISTED in variables_info table.] +include/assert.inc [Expect 481 persisted variables with matching peristed and global values.] ************************************************************ * 4. Test RESET PERSIST IF EXISTS. Verify persisted variable diff --git a/mysql-test/r/information_schema_parameters.result b/mysql-test/r/information_schema_parameters.result index f1b7232a9ae..7ffc059be2b 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(substring_index(`prm`.`data_type_utf8`,'*/ ',-(1)),'(',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 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 58f573230e2..fad3559ca55 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`,'SQL' 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(substring_index(`rtn`.`result_data_type_utf8`,'*/ ',-(1)),'(',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`,'SQL' 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/suite/information_schema/r/i_s_schema_definition_debug.result b/mysql-test/suite/information_schema/r/i_s_schema_definition_debug.result index 09eb2924848..35ac283e4a2 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 @@ -660,7 +660,7 @@ CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW information_schema 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, + SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(prm.data_type_utf8, '*/ ', -1), '(', 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, @@ -684,7 +684,7 @@ INSERT INTO I_S_check_table(t) VALUES ("CREATE OR REPLACE DEFINER=`mysql.infosch 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, + SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(prm.data_type_utf8, '*/ ', -1), '(', 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, @@ -837,7 +837,7 @@ CREATE OR REPLACE DEFINER=`mysql.infoschema`@`localhost` VIEW information_schema 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, + IF(rtn.type = 'PROCEDURE', '', SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX( rtn.result_data_type_utf8, '*/ ', -1), '(', 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, @@ -880,7 +880,7 @@ INSERT INTO I_S_check_table(t) VALUES ("CREATE OR REPLACE DEFINER=`mysql.infosch 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, + IF(rtn.type = 'PROCEDURE', '', SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX( rtn.result_data_type_utf8, '*/ ', -1), '(', 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, 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 c2090783942..ffde71094a3 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 @@ -116,9 +116,9 @@ eval CREATE TABLE $I_S_view_names (name VARCHAR(64) PRIMARY KEY); --echo # Print the actual I_S version stored on disk. let $current_i_s_version = `SELECT SUBSTRING_INDEX( - SUBSTRING_INDEX(SUBSTRING(properties, - LOCATE('IS_VERSION', properties), 30), ';', 1) - , '=', -1) AS I_S_VERSION + SUBSTRING_INDEX( + CONCAT(';', properties), ';IS_VERSION=', -1) + , ';', 1) AS I_S_VERSION FROM mysql.dd_properties`; --echo Current I_S_VERSION=$current_i_s_version @@ -304,7 +304,7 @@ INSERT INTO I_S_published_schema '06bdff30a209ee9b41bf1b654048010e0ca67399ccca594600659816fb3ee036'); INSERT INTO I_S_published_schema VALUES ('80030', '80030', 0, - 'f2f9eac78a7fe69de079bd55831bb4451236c492a76f9195e43051db44e84510'); + '55420c6267947962b2198fad2aa9b4aa9cbac51c49a046a360bf76032fe0e992'); INSERT INTO I_S_published_schema VALUES ('80030', '80030', 1, '4399948df993b3a2084c4a6dd80d76e38b2ff874e68b7e33a16b907eeb090ff0'); diff --git a/mysql-test/suite/rds/r/vidx_i_s_metadata.result b/mysql-test/suite/rds/r/vidx_i_s_metadata.result new file mode 100644 index 00000000000..e40a5c328e2 --- /dev/null +++ b/mysql-test/suite/rds/r/vidx_i_s_metadata.result @@ -0,0 +1,86 @@ +SET GLOBAL vidx_disabled = OFF; +SET transaction_isolation = 'READ-COMMITTED'; +######################################################################## +# Setup +######################################################################## +CREATE DATABASE IF NOT EXISTS vidx_is_test; +USE vidx_is_test; +CREATE TABLE t_vec ( +id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +v VECTOR(64) +); +CREATE PROCEDURE p_vec_param(IN v1 VECTOR(64), IN v2 VECTOR(64)) +BEGIN +SELECT VEC_DISTANCE_EUCLIDEAN(v1, v2); +END$$ +CREATE FUNCTION f_vec_return(in_str TEXT) RETURNS VECTOR(64) +DETERMINISTIC +BEGIN +RETURN VEC_FROMTEXT(in_str); +END$$ +######################################################################## +# PART 1. INFORMATION_SCHEMA.COLUMNS - DATA_TYPE should be 'varbinary' +######################################################################## +SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE +FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_SCHEMA = 'vidx_is_test' AND TABLE_NAME = 't_vec' + AND COLUMN_NAME = 'v'; +TABLE_NAME t_vec +COLUMN_NAME v +DATA_TYPE varbinary +COLUMN_TYPE /*!99999 vector(64) */ varbinary(256) +######################################################################## +# PART 2. INFORMATION_SCHEMA.PARAMETERS - DATA_TYPE should be 'varbinary' +######################################################################## +# Procedure parameters +SELECT SPECIFIC_NAME, PARAMETER_NAME, DATA_TYPE, DTD_IDENTIFIER +FROM INFORMATION_SCHEMA.PARAMETERS +WHERE SPECIFIC_SCHEMA = 'vidx_is_test' AND SPECIFIC_NAME = 'p_vec_param' + ORDER BY ORDINAL_POSITION; +SPECIFIC_NAME p_vec_param +PARAMETER_NAME v1 +DATA_TYPE varbinary +DTD_IDENTIFIER /*!99999 vector(64) */ varbinary(256) +SPECIFIC_NAME p_vec_param +PARAMETER_NAME v2 +DATA_TYPE varbinary +DTD_IDENTIFIER /*!99999 vector(64) */ varbinary(256) +# Function return value + parameters +SELECT SPECIFIC_NAME, PARAMETER_NAME, DATA_TYPE, DTD_IDENTIFIER +FROM INFORMATION_SCHEMA.PARAMETERS +WHERE SPECIFIC_SCHEMA = 'vidx_is_test' AND SPECIFIC_NAME = 'f_vec_return' + ORDER BY ORDINAL_POSITION; +SPECIFIC_NAME f_vec_return +PARAMETER_NAME NULL +DATA_TYPE varbinary +DTD_IDENTIFIER /*!99999 vector(64) */ varbinary(256) +SPECIFIC_NAME f_vec_return +PARAMETER_NAME in_str +DATA_TYPE text +DTD_IDENTIFIER text +######################################################################## +# PART 3. INFORMATION_SCHEMA.ROUTINES - DATA_TYPE should be 'varbinary' +######################################################################## +# Function return type +SELECT ROUTINE_NAME, ROUTINE_TYPE, DATA_TYPE, DTD_IDENTIFIER +FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA = 'vidx_is_test' AND ROUTINE_NAME = 'f_vec_return'; +ROUTINE_NAME f_vec_return +ROUTINE_TYPE FUNCTION +DATA_TYPE varbinary +DTD_IDENTIFIER /*!99999 vector(64) */ varbinary(256) +# Procedure has empty DATA_TYPE (standard behavior) +SELECT ROUTINE_NAME, ROUTINE_TYPE, DATA_TYPE +FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA = 'vidx_is_test' AND ROUTINE_NAME = 'p_vec_param'; +ROUTINE_NAME p_vec_param +ROUTINE_TYPE PROCEDURE +DATA_TYPE +######################################################################## +# Cleanup +######################################################################## +DROP TABLE t_vec; +DROP PROCEDURE p_vec_param; +DROP FUNCTION f_vec_return; +DROP DATABASE vidx_is_test; +SET GLOBAL vidx_disabled = ON; diff --git a/mysql-test/suite/rds/t/vidx_i_s_metadata.test b/mysql-test/suite/rds/t/vidx_i_s_metadata.test new file mode 100644 index 00000000000..8788c5ec7fd --- /dev/null +++ b/mysql-test/suite/rds/t/vidx_i_s_metadata.test @@ -0,0 +1,97 @@ +############################################################## +# Test VECTOR type metadata in INFORMATION_SCHEMA +# +# Background: +# VECTOR columns are rewritten to versioned-comment form +# (/*!99999 vector(N) */ varbinary(4N)) in the data dictionary +# so that downstream applications unaware of the VECTOR type +# only see a plain varbinary column. +# +# Verifies DATA_TYPE is 'varbinary' (the underlying storage +# type) across COLUMNS, PARAMETERS, and ROUTINES views. +############################################################## +--source include/have_binlog_format_mixed_or_row.inc + +SET GLOBAL vidx_disabled = OFF; +SET transaction_isolation = 'READ-COMMITTED'; + +--echo ######################################################################## +--echo # Setup +--echo ######################################################################## + +CREATE DATABASE IF NOT EXISTS vidx_is_test; +USE vidx_is_test; + +CREATE TABLE t_vec ( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + v VECTOR(64) +); + +DELIMITER $$; + +CREATE PROCEDURE p_vec_param(IN v1 VECTOR(64), IN v2 VECTOR(64)) +BEGIN + SELECT VEC_DISTANCE_EUCLIDEAN(v1, v2); +END$$ + +CREATE FUNCTION f_vec_return(in_str TEXT) RETURNS VECTOR(64) + DETERMINISTIC +BEGIN + RETURN VEC_FROMTEXT(in_str); +END$$ + +DELIMITER ;$$ + +--vertical_results + +--echo ######################################################################## +--echo # PART 1. INFORMATION_SCHEMA.COLUMNS - DATA_TYPE should be 'varbinary' +--echo ######################################################################## + +SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, COLUMN_TYPE + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = 'vidx_is_test' AND TABLE_NAME = 't_vec' + AND COLUMN_NAME = 'v'; + +--echo ######################################################################## +--echo # PART 2. INFORMATION_SCHEMA.PARAMETERS - DATA_TYPE should be 'varbinary' +--echo ######################################################################## + +--echo # Procedure parameters +SELECT SPECIFIC_NAME, PARAMETER_NAME, DATA_TYPE, DTD_IDENTIFIER + FROM INFORMATION_SCHEMA.PARAMETERS + WHERE SPECIFIC_SCHEMA = 'vidx_is_test' AND SPECIFIC_NAME = 'p_vec_param' + ORDER BY ORDINAL_POSITION; + +--echo # Function return value + parameters +SELECT SPECIFIC_NAME, PARAMETER_NAME, DATA_TYPE, DTD_IDENTIFIER + FROM INFORMATION_SCHEMA.PARAMETERS + WHERE SPECIFIC_SCHEMA = 'vidx_is_test' AND SPECIFIC_NAME = 'f_vec_return' + ORDER BY ORDINAL_POSITION; + +--echo ######################################################################## +--echo # PART 3. INFORMATION_SCHEMA.ROUTINES - DATA_TYPE should be 'varbinary' +--echo ######################################################################## + +--echo # Function return type +SELECT ROUTINE_NAME, ROUTINE_TYPE, DATA_TYPE, DTD_IDENTIFIER + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA = 'vidx_is_test' AND ROUTINE_NAME = 'f_vec_return'; + +--echo # Procedure has empty DATA_TYPE (standard behavior) +SELECT ROUTINE_NAME, ROUTINE_TYPE, DATA_TYPE + FROM INFORMATION_SCHEMA.ROUTINES + WHERE ROUTINE_SCHEMA = 'vidx_is_test' AND ROUTINE_NAME = 'p_vec_param'; + +--horizontal_results + +--echo ######################################################################## +--echo # Cleanup +--echo ######################################################################## + +DROP TABLE t_vec; +DROP PROCEDURE p_vec_param; +DROP FUNCTION f_vec_return; +DROP DATABASE vidx_is_test; + +SET GLOBAL vidx_disabled = ON; diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 982bea5f865..37b347d57f0 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -240,6 +240,16 @@ terminology_use_previous tls_ciphersuites tls_ciphersuites use_secondary_engine +vidx_default_distance +vidx_default_distance +vidx_disabled +vidx_disabled +vidx_hnsw_cache_size +vidx_hnsw_cache_size +vidx_hnsw_default_m +vidx_hnsw_default_m +vidx_hnsw_ef_search +vidx_hnsw_ef_search xa_detach_on_prepare xa_detach_on_prepare drop table t1; diff --git a/mysql-test/t/all_persisted_variables.test b/mysql-test/t/all_persisted_variables.test index 3205f019c90..e735d12caf1 100644 --- a/mysql-test/t/all_persisted_variables.test +++ b/mysql-test/t/all_persisted_variables.test @@ -41,7 +41,7 @@ call mtr.add_suppression("\\[Warning\\] .*MY-\\d+.* Changing innodb_extend_and_i call mtr.add_suppression("Failed to initialize TLS for channel: mysql_main"); let $total_global_vars=`SELECT COUNT(*) FROM performance_schema.global_variables where variable_name NOT LIKE 'ndb_%' AND variable_name NOT LIKE 'debug_%'`; -let $total_persistent_vars=476; +let $total_persistent_vars=481; --echo *************************************************************** --echo * 0. Verify that variables present in performance_schema.global diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 4ebcb7775e2..af91b746be8 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -119,6 +119,7 @@ ADD_SUBDIRECTORY(protobuf) SET(DD_SOURCES dd/collection.cc dd/dd_event.cc + dd/dd_minor_upgrade.cc dd/dd_resource_group.cc dd/dd_routine.cc dd/dd_schema.cc diff --git a/sql/dd/dd_minor_upgrade.cc b/sql/dd/dd_minor_upgrade.cc new file mode 100644 index 00000000000..68c5caafc88 --- /dev/null +++ b/sql/dd/dd_minor_upgrade.cc @@ -0,0 +1,83 @@ +/***************************************************************************** + +Copyright (c) 2026, Alibaba and/or its affiliates. All Rights Reserved. + +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 + +*****************************************************************************/ + +#include "my_inttypes.h" +#include "sql/dd/impl/tables/dd_properties.h" +#include "sql/dd/string_type.h" +#include "sql/sql_class.h" + +#include "sql/dd/dd_minor_upgrade.h" + +namespace dd { +/** + Version for server I_S tables and System Views. + PLS increase it if update server I_S tables or System Views. + + + Historical I_S version number published: + + 1. Fixed VECTOR column DATA_TYPE in INFORMATION_SCHEMA views + --------------------------- + Strip versioned comment markers from VECTOR column DATA_TYPE in + INFORMATION_SCHEMA.COLUMNS + INFORMATION_SCHEMA.PARAMETERS + INFORMATION_SCHEMA.ROUTINES + to correctly show the underlying storage type. +*/ +static const uint EXTRA_IS_DD_VERSION = 1; + +static const String_type EXTRA_IS_DD_VERSION_STRING("EXTRA_IS_VERSION"); + +// Get the singleton instance +Minor_upgrade_ctx *Minor_upgrade_ctx::instance() { + static Minor_upgrade_ctx ctx; + return &ctx; +} + +// Get compiled extra I_S version +uint Minor_upgrade_ctx::get_target_extra_I_S_version() { + return EXTRA_IS_DD_VERSION; +} + +// Get persisted extra I_S version +uint Minor_upgrade_ctx::get_actual_extra_I_S_version(THD *thd) { + bool exists = false; + uint version = 0; + bool error MY_ATTRIBUTE((unused)) = tables::DD_properties::instance().get( + thd, EXTRA_IS_DD_VERSION_STRING.c_str(), &version, &exists); + if (error || !exists) + return UNKNOWN_EXTRA_VERSION; + else + return version; +} + +// Persist extra I_S version into dd_properties +uint Minor_upgrade_ctx::set_extra_I_S_version(THD *thd, uint version) { + return tables::DD_properties::instance().set( + thd, EXTRA_IS_DD_VERSION_STRING.c_str(), version); +} + +} // namespace dd diff --git a/sql/dd/dd_minor_upgrade.h b/sql/dd/dd_minor_upgrade.h new file mode 100644 index 00000000000..bf04d2b4765 --- /dev/null +++ b/sql/dd/dd_minor_upgrade.h @@ -0,0 +1,64 @@ +/***************************************************************************** + +Copyright (c) 2026, Alibaba and/or its affiliates. All Rights Reserved. + +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 SQL_DD_DD_MINOR_UPGRADE_H_INCLUDED +#define SQL_DD_DD_MINOR_UPGRADE_H_INCLUDED + +#include "my_inttypes.h" + +class THD; + +/** + Minor Upgrade is designed to upgrade I_S System Views without changing + the upstream IS_DD_VERSION. + + This strategy adds EXTRA_IS_VERSION into the DD_properties table. + Increase EXTRA_IS_DD_VERSION when modifying I_S system view definitions. + + DD restart will reconstruct I_S system views if the persisted version + does not match the compiled target version. +*/ +namespace dd { + +static const uint UNKNOWN_EXTRA_VERSION = -1; + +class Minor_upgrade_ctx { + public: + Minor_upgrade_ctx() {} + ~Minor_upgrade_ctx() {} + + static Minor_upgrade_ctx *instance(); + + static uint get_target_extra_I_S_version(); + + virtual uint get_actual_extra_I_S_version(THD *thd); + + uint set_extra_I_S_version(THD *thd, uint version); +}; + +} // namespace dd + +#endif diff --git a/sql/dd/impl/system_views/columns.cc b/sql/dd/impl/system_views/columns.cc index b707d8993a7..6f81114656a 100644 --- a/sql/dd/impl/system_views/columns.cc +++ b/sql/dd/impl/system_views/columns.cc @@ -52,7 +52,14 @@ Columns::Columns() { "col.default_value_utf8"); m_target_def.add_field(FIELD_IS_NULLABLE, "IS_NULLABLE", "IF (col.is_nullable = 1, 'YES','NO')"); - /* Ignore the comment especially for vector columns. */ + /* + VECTOR columns are stored as '99999 vector(N) varbinary(4N)' in + the data dictionary for backward compatibility with downstream applications + that do not support the VECTOR type. The versioned comment is invisible to + older MySQL versions, so they only see a plain varbinary column. + Strip the comment prefix (everything up to and including '* /') to expose + the underlying storage type (e.g. 'varbinary') as DATA_TYPE. + */ m_target_def.add_field(FIELD_DATA_TYPE, "DATA_TYPE", "SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col." "column_type_utf8, '*/ ', -1), '(', 1),' ', 1)"); diff --git a/sql/dd/impl/system_views/parameters.cc b/sql/dd/impl/system_views/parameters.cc index 2cdc7ef8bea..43462f4dcd7 100644 --- a/sql/dd/impl/system_views/parameters.cc +++ b/sql/dd/impl/system_views/parameters.cc @@ -48,9 +48,17 @@ Parameters::Parameters() { m_target_def.add_field(FIELD_PARAMETER_NAME, "PARAMETER_NAME", "IF (rtn.type = 'FUNCTION' AND prm.ordinal_position = " "1, NULL, prm.name)"); + /* + VECTOR routine parameters are stored with a versioned comment prefix + (e.g. '99999 vector(N) varbinary(4N)') in the data dictionary + for backward compatibility with downstream applications that do not + support the VECTOR type. Strip the comment prefix to expose the + underlying storage type (e.g. 'varbinary') as DATA_TYPE. + */ m_target_def.add_field( FIELD_DATA_TYPE, "DATA_TYPE", - "SUBSTRING_INDEX(SUBSTRING_INDEX(prm.data_type_utf8, '(', 1), ' ', 1)"); + "SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(" + "prm.data_type_utf8, '*/ ', -1), '(', 1), ' ', 1)"); m_target_def.add_field( FIELD_CHARACTER_MAXIMUM_LENGTH, "CHARACTER_MAXIMUM_LENGTH", "INTERNAL_DD_CHAR_LENGTH(prm.data_type, prm.char_length, col.name, 0)"); diff --git a/sql/dd/impl/system_views/routines.cc b/sql/dd/impl/system_views/routines.cc index e81939e510f..7d828cac256 100644 --- a/sql/dd/impl/system_views/routines.cc +++ b/sql/dd/impl/system_views/routines.cc @@ -41,10 +41,18 @@ Routines::Routines() { "sch.name" + m_target_def.fs_name_collation()); m_target_def.add_field(FIELD_ROUTINE_NAME, "ROUTINE_NAME", "rtn.name"); m_target_def.add_field(FIELD_ROUTINE_TYPE, "ROUTINE_TYPE", "rtn.type"); + /* + VECTOR function return types are stored with a versioned comment prefix + (e.g. '99999 vector(N) varbinary(4N)') in the data dictionary + for backward compatibility with downstream applications that do not + support the VECTOR type. Strip the comment prefix to expose the + underlying storage type (e.g. 'varbinary') as DATA_TYPE. + */ m_target_def.add_field(FIELD_DATA_TYPE, "DATA_TYPE", "IF(rtn.type = 'PROCEDURE', '', " - " SUBSTRING_INDEX(SUBSTRING_INDEX(" - " rtn.result_data_type_utf8, '(', 1), ' ', 1))"); + " SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(" + " rtn.result_data_type_utf8, '*/ ', -1)," + " '(', 1), ' ', 1))"); m_target_def.add_field(FIELD_CHARACTER_MAXIMUM_LENGTH, "CHARACTER_MAXIMUM_LENGTH", "INTERNAL_DD_CHAR_LENGTH(rtn.result_data_type," diff --git a/sql/dd/impl/tables/dd_properties.cc b/sql/dd/impl/tables/dd_properties.cc index 309d5bc52ff..12d428c02b8 100644 --- a/sql/dd/impl/tables/dd_properties.cc +++ b/sql/dd/impl/tables/dd_properties.cc @@ -123,7 +123,8 @@ DD_properties::DD_properties() : m_properties() { {"MYSQLD_VERSION_UPGRADED", Property_type::UNSIGNED_INT_32}, {"MYSQL_VERSION_STABILITY", Property_type::CHARACTER_STRING}, {"SERVER_DOWNGRADE_THRESHOLD", Property_type::UNSIGNED_INT_32}, - {"SERVER_UPGRADE_THRESHOLD", Property_type::UNSIGNED_INT_32}}; + {"SERVER_UPGRADE_THRESHOLD", Property_type::UNSIGNED_INT_32}, + {"EXTRA_IS_VERSION", Property_type::UNSIGNED_INT_32}}; } // Read all properties from disk and populate the cache. diff --git a/sql/dd/info_schema/metadata.cc b/sql/dd/info_schema/metadata.cc index 58f541916e4..e96598d1b72 100644 --- a/sql/dd/info_schema/metadata.cc +++ b/sql/dd/info_schema/metadata.cc @@ -51,6 +51,7 @@ #include "mysql/components/services/log_shared.h" #include "mysql/plugin.h" #include "sql/dd/cache/dictionary_client.h" // dd::cache::Dictionary_client +#include "sql/dd/dd_minor_upgrade.h" // dd::Minor_upgrade_ctx #include "sql/dd/dd_schema.h" // dd::Schema_MDL_locker #include "sql/dd/dd_table.h" // dd::get_sql_type_by_field_info #include "sql/dd/dd_utility.h" // check_if_server_ddse_readonly @@ -470,6 +471,12 @@ bool create_system_views(THD *thd, bool is_non_dd_based) { d->get_actual_I_S_version(thd)); error = d->set_I_S_version(thd, d->get_target_I_S_version()); dd::bootstrap::DD_bootstrap_ctx::instance().set_I_S_upgrade_done(); + + if (!error) { + dd::Minor_upgrade_ctx *upgrade_ctx = dd::Minor_upgrade_ctx::instance(); + error = upgrade_ctx->set_extra_I_S_version( + thd, upgrade_ctx->get_target_extra_I_S_version()); + } } // Restore the original character set. @@ -504,11 +511,16 @@ bool update_server_I_S_metadata(THD *thd) { // Stop if I_S version is same and no DD upgrade was done. uint actual_version = d->get_actual_I_S_version(thd); + // Extra I_S version check + dd::Minor_upgrade_ctx *upgrade_ctx = dd::Minor_upgrade_ctx::instance(); + uint extra_version = upgrade_ctx->get_actual_extra_I_S_version(thd); + // Testing to make sure we update plugins when version changes. DBUG_EXECUTE_IF("test_i_s_metadata_version", { actual_version = UNKNOWN_PLUGIN_VERSION; }); if (d->get_target_I_S_version() == actual_version && + upgrade_ctx->get_target_extra_I_S_version() == extra_version && !dd::bootstrap::DD_bootstrap_ctx::instance().dd_upgrade_done()) return false; From 687f38e5b5012e8ad090bccf9231e54beb6bf7b3 Mon Sep 17 00:00:00 2001 From: huaxiongsong <52561339+p1p1bear@users.noreply.github.com> Date: Tue, 12 May 2026 11:06:49 +0800 Subject: [PATCH 2/4] ci: trigger alisql-docker build on release publish (#148) On every published release whose tag starts with AliSQL-8.0.*, push the same tag to p1p1bear/alisql-docker so its existing build workflow can build and push the multi-arch Docker image to Docker Hub (songhuaxiong/alisql). Requires repo secret DOCKER_REPO_PAT (fine-grained PAT with Contents: read/write on p1p1bear/alisql-docker). --- .../workflows/trigger-alisql-docker-build.yml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/trigger-alisql-docker-build.yml diff --git a/.github/workflows/trigger-alisql-docker-build.yml b/.github/workflows/trigger-alisql-docker-build.yml new file mode 100644 index 00000000000..23fb7815fe1 --- /dev/null +++ b/.github/workflows/trigger-alisql-docker-build.yml @@ -0,0 +1,29 @@ +name: trigger-alisql-docker-build + +on: + release: + types: [published] + +jobs: + trigger: + runs-on: ubuntu-latest + if: startsWith(github.event.release.tag_name, 'AliSQL-8.0.') + steps: + - name: Push tag to alisql-docker + env: + PAT: ${{ secrets.DOCKER_REPO_PAT }} + TAG: ${{ github.event.release.tag_name }} + run: | + set -eux + git clone --depth 1 "https://x-access-token:${PAT}@github.com/p1p1bear/alisql-docker.git" work + cd work + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + if git ls-remote --tags origin "refs/tags/${TAG}" | grep -q "refs/tags/${TAG}$"; then + echo "Tag ${TAG} already exists on alisql-docker, skipping." + exit 0 + fi + + git tag "${TAG}" + git push origin "${TAG}" From d06deb558023800ec41f51e8f1e995714dc5ed7a Mon Sep 17 00:00:00 2001 From: huaxiongsong <52561339+p1p1bear@users.noreply.github.com> Date: Tue, 12 May 2026 11:57:39 +0800 Subject: [PATCH 3/4] ci: trigger alisql-docker build on 8.0/5.7 release publish (#149) --- .github/workflows/trigger-alisql-docker-build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/trigger-alisql-docker-build.yml b/.github/workflows/trigger-alisql-docker-build.yml index 23fb7815fe1..62ce01a3acb 100644 --- a/.github/workflows/trigger-alisql-docker-build.yml +++ b/.github/workflows/trigger-alisql-docker-build.yml @@ -7,7 +7,9 @@ on: jobs: trigger: runs-on: ubuntu-latest - if: startsWith(github.event.release.tag_name, 'AliSQL-8.0.') + if: | + startsWith(github.event.release.tag_name, 'AliSQL-8.0.') || + startsWith(github.event.release.tag_name, 'AliSQL-5.7.') steps: - name: Push tag to alisql-docker env: From dce1871224772a8c9c2b7e2830e268bed9f9f73a Mon Sep 17 00:00:00 2001 From: huaxiongsong <52561339+p1p1bear@users.noreply.github.com> Date: Tue, 12 May 2026 17:00:06 +0800 Subject: [PATCH 4/4] ci: add build-and-release workflow for tag-triggered tarball builds (#150) Build glibc 2.17 compatible AliSQL tarballs (x86_64 + aarch64) inside oraclelinux:7 on tag push, inject version from tag name into the version file, then create a GitHub Release with both tarballs attached. Triggered by tags matching AliSQL-8.0.* or AliSQL-5.7.*. --- .github/workflows/build-and-release.yml | 175 ++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 .github/workflows/build-and-release.yml diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 00000000000..27b6ee0a0b4 --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,175 @@ +name: build-and-release + +on: + push: + tags: + - 'AliSQL-8.0.*' + - 'AliSQL-5.7.*' + +permissions: + contents: write + +jobs: + parse: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.p.outputs.version }} + major: ${{ steps.p.outputs.major }} + minor: ${{ steps.p.outputs.minor }} + patch: ${{ steps.p.outputs.patch }} + extra: ${{ steps.p.outputs.extra }} + steps: + - id: p + run: | + set -eu + TAG="${GITHUB_REF_NAME}" + VERSION="${TAG#AliSQL-}" + MAJOR="${VERSION%%.*}" + REST="${VERSION#*.}" + MINOR="${REST%%.*}" + REST="${REST#*.}" + PATCH="${REST%%-*}" + EXTRA="${REST#*-}" + { + echo "version=$VERSION" + echo "major=$MAJOR" + echo "minor=$MINOR" + echo "patch=$PATCH" + echo "extra=$EXTRA" + } >> "$GITHUB_OUTPUT" + echo "Parsed: version=$VERSION major=$MAJOR minor=$MINOR patch=$PATCH extra=$EXTRA" + + build: + needs: parse + strategy: + fail-fast: false + matrix: + include: + - arch: x86_64 + runner: ubuntu-24.04 + cmake_arch: x86_64 + - arch: aarch64 + runner: ubuntu-24.04-arm + cmake_arch: aarch64 + runs-on: ${{ matrix.runner }} + timeout-minutes: 120 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Build inside oraclelinux:7 + env: + MAJOR: ${{ needs.parse.outputs.major }} + MINOR: ${{ needs.parse.outputs.minor }} + PATCH: ${{ needs.parse.outputs.patch }} + EXTRA: ${{ needs.parse.outputs.extra }} + CMAKE_ARCH: ${{ matrix.cmake_arch }} + run: | + set -eux + mkdir -p "${GITHUB_WORKSPACE}/out" + docker run --rm -i \ + -v "${GITHUB_WORKSPACE}:/AliSQL" \ + -v "${GITHUB_WORKSPACE}/out:/out" \ + -e MAJOR -e MINOR -e PATCH -e EXTRA -e CMAKE_ARCH \ + oraclelinux:7 \ + bash -ex <<'INNER' + + # ---- Toolchain repo (devtoolset-10) ---- + cat >/etc/yum.repos.d/ol7-scl.repo <<'REPO' + [ol7_software_collections] + name=Oracle Linux 7 Software Collections ($basearch) + baseurl=https://yum.oracle.com/repo/OracleLinux/OL7/SoftwareCollections/$basearch/ + gpgcheck=1 + enabled=1 + gpgkey=https://yum.oracle.com/RPM-GPG-KEY-oracle-ol7 + REPO + + yum clean all + yum makecache + yum install -y git wget \ + devtoolset-10-gcc devtoolset-10-gcc-c++ devtoolset-10-binutils \ + openssl openssl-devel ncurses-devel libaio-devel perl-IPC-Cmd bison + + # ---- CMake ---- + cd /opt + wget -q "https://github.com/Kitware/CMake/releases/download/v3.28.6/cmake-3.28.6-linux-${CMAKE_ARCH}.tar.gz" + tar -xzf "cmake-3.28.6-linux-${CMAKE_ARCH}.tar.gz" + export PATH="/opt/cmake-3.28.6-linux-${CMAKE_ARCH}/bin:$PATH" + cmake --version + + # ---- Inject version from tag ---- + # 8.0 branch uses MYSQL_VERSION; 5.7 branch uses VERSION; same internal format. + cd /AliSQL + VERSION_FILE="" + for f in MYSQL_VERSION VERSION; do + [ -f "$f" ] && VERSION_FILE="$f" && break + done + if [ -z "$VERSION_FILE" ]; then + echo "ERROR: neither MYSQL_VERSION nor VERSION found in source root" >&2 + exit 1 + fi + sed -i \ + -e "s/^MYSQL_VERSION_MAJOR=.*/MYSQL_VERSION_MAJOR=${MAJOR}/" \ + -e "s/^MYSQL_VERSION_MINOR=.*/MYSQL_VERSION_MINOR=${MINOR}/" \ + -e "s/^MYSQL_VERSION_PATCH=.*/MYSQL_VERSION_PATCH=${PATCH}/" \ + -e "s/^MYSQL_VERSION_EXTRA=.*/MYSQL_VERSION_EXTRA=${EXTRA}/" \ + "$VERSION_FILE" + echo "--- ${VERSION_FILE} after injection ---" + cat "$VERSION_FILE" + + # ---- Build & install ---- + source scl_source enable devtoolset-10 + sh build.sh -t release -d /opt/alisql + make install + + # ---- Package ---- + cd /opt + VER="${MAJOR}.${MINOR}.${PATCH}-${EXTRA}" + GLIBC="glibc$(ldd --version | awk 'NR==1{print $NF}')" + ARCH="$(uname -m)" + PKG="alisql-${VER}-linux-${GLIBC}-${ARCH}.tar.xz" + TOPDIR="${PKG%.tar.xz}" + XZ_OPT='-T0 -9' tar -cJf "/out/${PKG}" \ + --transform="s,^alisql,${TOPDIR}," \ + --exclude='alisql/mysql-test' \ + --exclude='alisql/run' \ + --exclude='alisql/var' \ + --exclude='alisql/LICENSE-test' \ + --exclude='alisql/LICENSE.router' \ + --exclude='alisql/README-test' \ + --exclude='alisql/README.router' \ + --exclude='alisql/mysqlrouter-log-rotate' \ + alisql/ + ls -lh "/out/${PKG}" + INNER + + - uses: actions/upload-artifact@v4 + with: + name: alisql-${{ matrix.arch }} + path: ${{ github.workspace }}/out/alisql-*.tar.xz + retention-days: 7 + + release: + needs: [parse, build] + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: true + + - name: List artifacts + run: ls -lh artifacts/ + + - name: Create release with tarballs + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + VERSION: ${{ needs.parse.outputs.version }} + run: | + gh release create "$TAG" \ + --repo "$GITHUB_REPOSITORY" \ + --title "$TAG" \ + --notes "Auto-built AliSQL ${VERSION} (oraclelinux:7, glibc 2.17). x86_64 and aarch64 binaries attached." \ + artifacts/*.tar.xz