From a2a100af0627a187c5c78f3f4008692a3c8aad02 Mon Sep 17 00:00:00 2001 From: PranavKTiwari Date: Wed, 1 Jul 2026 17:51:17 +0530 Subject: [PATCH] MDEV-40167: GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes Problem: GLOBAL TEMPORARY tables were not subject to the same option/index restrictions as session TEMPORARY tables. Several InnoDB and server-layer checks tested only tmp_table(), so GLOBAL TEMPORARY tables could bypass validation for VECTOR/FULLTEXT indexes, DATA DIRECTORY, KEY_BLOCK_SIZE, and ROW_FORMAT=COMPRESSED. Cause: global_tmp_table() was added as a separate predicate from tmp_table(), but not all temp-table checks were updated to test both, so GLOBAL TEMPORARY tables fell through to "permanent table" logic in several places. Fix: Added global_tmp_table() alongside tmp_table() at each affected check: Reject VECTOR and FULLTEXT indexes on GLOBAL TEMPORARY tables. Reject/warn on DATA DIRECTORY, KEY_BLOCK_SIZE, and ROW_FORMAT=COMPRESSED for GLOBAL TEMPORARY tables, with accurate wording in the DATA DIRECTORY warning. Fixed zip_allowed and related ut_ad assertions to exclude GLOBAL TEMPORARY tables. Fixed m_use_file_per_table in set_tablespace_type() to exclude GLOBAL TEMPORARY tables (also fixes m_use_data_dir). GLOBAL TEMPORARY tables now validate the same as session TEMPORARY tables across these options. --- mysql-test/main/global_temporary_table.result | 13 ++++++ mysql-test/main/global_temporary_table.test | 17 ++++++++ .../binlog/r/global_temporary_table.result | 13 ++++++ .../suite/rpl/r/global_temporary_table.result | 13 ++++++ sql/sql_table.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 43 +++++++++++-------- 6 files changed, 81 insertions(+), 20 deletions(-) diff --git a/mysql-test/main/global_temporary_table.result b/mysql-test/main/global_temporary_table.result index 2fcbaccec1047..abd6e46f720bc 100644 --- a/mysql-test/main/global_temporary_table.result +++ b/mysql-test/main/global_temporary_table.result @@ -1322,6 +1322,8 @@ set autocommit=1; create global temporary table t (c int) engine=innodb on commit preserve rows; set session transaction isolation level serializable; flush tables t with read lock; +Warnings: +Warning 1809 Table `test`.`t` in system tablespace insert t values (1); update t set c=c+1; # Cleanup @@ -1351,3 +1353,14 @@ ERROR HY000: 'mysql.help_topic' is not of type 'BASE TABLE' drop table mysql.help_topic; rename table mysql.help_topic1 to mysql.help_topic; disconnect con1; +# MDEV-40167 - GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes +CREATE GLOBAL TEMPORARY TABLE gtt (id INT PRIMARY KEY, body TEXT, FULLTEXT (body)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; +ERROR HY000: Cannot create FULLTEXT index on temporary InnoDB table +CREATE GLOBAL TEMPORARY TABLE gtt_v (id INT PRIMARY KEY, v VECTOR (4) NOT NULL, VECTOR INDEX (v)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; +ERROR HY000: Cannot create VECTOR index on temporary InnoDB table +CREATE GLOBAL TEMPORARY TABLE gtt (id INT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ON COMMIT PRESERVE ROWS; +ERROR HY000: InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='MYSQLTEST_VARDIR/tmp' ON COMMIT PRESERVE ROWS; +ERROR HY000: Can't create table `test`.`g` (errno: 140 "Wrong create options") diff --git a/mysql-test/main/global_temporary_table.test b/mysql-test/main/global_temporary_table.test index 96d3aa6fe1ed2..e7577ac6287cb 100644 --- a/mysql-test/main/global_temporary_table.test +++ b/mysql-test/main/global_temporary_table.test @@ -1234,3 +1234,20 @@ drop table mysql.help_topic; rename table mysql.help_topic1 to mysql.help_topic; --disconnect con1 + +--echo # MDEV-40167 - GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes + +--error ER_NO_INDEX_ON_TEMPORARY +CREATE GLOBAL TEMPORARY TABLE gtt (id INT PRIMARY KEY, body TEXT, FULLTEXT (body)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; + +--error ER_NO_INDEX_ON_TEMPORARY +CREATE GLOBAL TEMPORARY TABLE gtt_v (id INT PRIMARY KEY, v VECTOR (4) NOT NULL, VECTOR INDEX (v)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; + +--error ER_UNSUPPORTED_COMPRESSED_TABLE +CREATE GLOBAL TEMPORARY TABLE gtt (id INT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ON COMMIT PRESERVE ROWS; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--error ER_CANT_CREATE_TABLE +eval CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp' ON COMMIT PRESERVE ROWS; diff --git a/mysql-test/suite/binlog/r/global_temporary_table.result b/mysql-test/suite/binlog/r/global_temporary_table.result index 5b50d474c5de6..310f5da50e49b 100644 --- a/mysql-test/suite/binlog/r/global_temporary_table.result +++ b/mysql-test/suite/binlog/r/global_temporary_table.result @@ -1325,6 +1325,8 @@ set autocommit=1; create global temporary table t (c int) engine=innodb on commit preserve rows; set session transaction isolation level serializable; flush tables t with read lock; +Warnings: +Warning 1809 Table `test`.`t` in system tablespace insert t values (1); update t set c=c+1; # Cleanup @@ -1354,6 +1356,17 @@ ERROR HY000: 'mysql.help_topic' is not of type 'BASE TABLE' drop table mysql.help_topic; rename table mysql.help_topic1 to mysql.help_topic; disconnect con1; +# MDEV-40167 - GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes +CREATE GLOBAL TEMPORARY TABLE gtt (id INT PRIMARY KEY, body TEXT, FULLTEXT (body)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; +ERROR HY000: Cannot create FULLTEXT index on temporary InnoDB table +CREATE GLOBAL TEMPORARY TABLE gtt_v (id INT PRIMARY KEY, v VECTOR (4) NOT NULL, VECTOR INDEX (v)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; +ERROR HY000: Cannot create VECTOR index on temporary InnoDB table +CREATE GLOBAL TEMPORARY TABLE gtt (id INT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ON COMMIT PRESERVE ROWS; +ERROR HY000: InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='MYSQLTEST_VARDIR/tmp' ON COMMIT PRESERVE ROWS; +ERROR HY000: Can't create table `test`.`g` (errno: 140 "Wrong create options") include/show_binlog_events.inc Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Gtid # # GTID #-#-# diff --git a/mysql-test/suite/rpl/r/global_temporary_table.result b/mysql-test/suite/rpl/r/global_temporary_table.result index 084c1be619dd9..ef64fa3588077 100644 --- a/mysql-test/suite/rpl/r/global_temporary_table.result +++ b/mysql-test/suite/rpl/r/global_temporary_table.result @@ -1325,6 +1325,8 @@ set autocommit=1; create global temporary table t (c int) engine=innodb on commit preserve rows; set session transaction isolation level serializable; flush tables t with read lock; +Warnings: +Warning 1809 Table `test`.`t` in system tablespace insert t values (1); update t set c=c+1; # Cleanup @@ -1354,6 +1356,17 @@ ERROR HY000: 'mysql.help_topic' is not of type 'BASE TABLE' drop table mysql.help_topic; rename table mysql.help_topic1 to mysql.help_topic; disconnect con1; +# MDEV-40167 - GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes +CREATE GLOBAL TEMPORARY TABLE gtt (id INT PRIMARY KEY, body TEXT, FULLTEXT (body)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; +ERROR HY000: Cannot create FULLTEXT index on temporary InnoDB table +CREATE GLOBAL TEMPORARY TABLE gtt_v (id INT PRIMARY KEY, v VECTOR (4) NOT NULL, VECTOR INDEX (v)) +ENGINE=InnoDB ON COMMIT PRESERVE ROWS; +ERROR HY000: Cannot create VECTOR index on temporary InnoDB table +CREATE GLOBAL TEMPORARY TABLE gtt (id INT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ON COMMIT PRESERVE ROWS; +ERROR HY000: InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='MYSQLTEST_VARDIR/tmp' ON COMMIT PRESERVE ROWS; +ERROR HY000: Can't create table `test`.`g` (errno: 140 "Wrong create options") connection slave; connection master; set @old_timeout= @@global.lock_wait_timeout; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 255281ed90e28..92411133bd049 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3778,7 +3778,7 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info, my_error(ER_INDEX_CANNOT_HAVE_NULL, MYF(0), "VECTOR"); DBUG_RETURN(TRUE); } - if (create_info->tmp_table()) + if (create_info->tmp_table() || create_info->global_tmp_table()) { my_error(ER_NO_INDEX_ON_TEMPORARY, MYF(0), "VECTOR", file->table_type()); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8b21f28cd2265..900479dc6beaf 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11055,15 +11055,17 @@ create_table_info_t::create_option_data_directory_is_valid() is_valid = false; } - /* Do not use DATA DIRECTORY with TEMPORARY TABLE. */ - if (m_create_info->tmp_table()) { - push_warning( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: DATA DIRECTORY cannot be used" - " for TEMPORARY tables."); - is_valid = false; - } + /* Do not use DATA DIRECTORY with TEMPORARY TABLE or + GLOBAL TEMPORARY TABLE. */ + if (m_create_info->tmp_table() || m_create_info->global_tmp_table()) { + push_warning_printf( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: DATA DIRECTORY cannot be used for %s tables.", + m_create_info->global_tmp_table() + ? "GLOBAL TEMPORARY" : "TEMPORARY"); + is_valid = false; + } /* We check for a DATA DIRECTORY mixed with TABLESPACE in create_option_tablespace_is_valid(), no need to here. */ @@ -11086,6 +11088,7 @@ create_table_info_t::create_options_are_invalid() const char* ret = NULL; enum row_type row_format = m_create_info->row_type; const bool is_temp = m_create_info->tmp_table(); + const bool is_global_temp = m_create_info->global_tmp_table(); ut_ad(m_thd != NULL); @@ -11096,7 +11099,7 @@ create_table_info_t::create_options_are_invalid() /* Check if a non-zero KEY_BLOCK_SIZE was specified. */ if (has_key_block_size) { - if (is_temp || innodb_read_only_compressed) { + if (is_temp || is_global_temp || innodb_read_only_compressed) { my_error(ER_UNSUPPORTED_COMPRESSED_TABLE, MYF(0)); return("KEY_BLOCK_SIZE"); } @@ -11152,7 +11155,7 @@ create_table_info_t::create_options_are_invalid() other incompatibilities. */ switch (row_format) { case ROW_TYPE_COMPRESSED: - if (is_temp || innodb_read_only_compressed) { + if (is_temp || is_global_temp || innodb_read_only_compressed) { my_error(ER_UNSUPPORTED_COMPRESSED_TABLE, MYF(0)); return("ROW_FORMAT"); } @@ -11510,7 +11513,8 @@ bool create_table_info_t::innobase_table_flags() rec_format_t innodb_row_format = get_row_format(m_default_row_format); const bool is_temp = m_create_info->tmp_table(); - bool zip_allowed = !is_temp; + const bool is_global_temp = m_create_info->global_tmp_table(); + bool zip_allowed = !is_temp && !is_global_temp; const ulint zip_ssize_max = ut_min(static_cast(UNIV_PAGE_SSIZE_MAX), @@ -11531,7 +11535,7 @@ bool create_table_info_t::innobase_table_flags() /* We don't support FTS indexes in temporary tables. */ - if (is_temp) { + if (is_temp || is_global_temp) { my_error(ER_NO_INDEX_ON_TEMPORARY, MYF(0), "FULLTEXT", "InnoDB"); DBUG_RETURN(false); @@ -11581,7 +11585,7 @@ bool create_table_info_t::innobase_table_flags() } /* Make sure compressed row format is allowed. */ - if (is_temp) { + if (is_temp || is_global_temp) { push_warning( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -11653,7 +11657,7 @@ bool create_table_info_t::innobase_table_flags() innodb_row_format = REC_FORMAT_COMPACT; break; case ROW_TYPE_COMPRESSED: - if (is_temp) { + if (is_temp || is_global_temp) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -11698,8 +11702,8 @@ bool create_table_info_t::innobase_table_flags() zip_allowed = false; } - ut_ad(!is_temp || !zip_allowed); - ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED); + ut_ad(!(is_temp || is_global_temp) || !zip_allowed); + ut_ad(!(is_temp || is_global_temp) || innodb_row_format != REC_FORMAT_COMPRESSED); /* Set the table flags */ if (!zip_allowed) { @@ -11929,10 +11933,11 @@ create_table_info_t::set_tablespace_type( /* Ignore the current innodb-file-per-table setting if we are creating a temporary table. */ m_use_file_per_table = m_allow_file_per_table - && !m_create_info->tmp_table(); + && !m_create_info->tmp_table() + && !m_create_info->global_tmp_table(); /* DATA DIRECTORY must have m_use_file_per_table but cannot be - used with TEMPORARY tables. */ + used with TEMPORARY tables and global temporary tables. */ m_use_data_dir = m_use_file_per_table && m_create_info->data_file_name