From 45b9b0861c4d38706ddf77405dd0cd957fddb082 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 | 11 +++++ mysql-test/main/global_temporary_table.test | 16 +++++++ sql/sql_table.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 46 ++++++++++--------- 4 files changed, 53 insertions(+), 22 deletions(-) diff --git a/mysql-test/main/global_temporary_table.result b/mysql-test/main/global_temporary_table.result index 2fcbaccec1047..bbed03a2f6293 100644 --- a/mysql-test/main/global_temporary_table.result +++ b/mysql-test/main/global_temporary_table.result @@ -1351,3 +1351,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='/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..92206fcb107e0 100644 --- a/mysql-test/main/global_temporary_table.test +++ b/mysql-test/main/global_temporary_table.test @@ -1234,3 +1234,19 @@ 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; + +--error ER_CANT_CREATE_TABLE +CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='/tmp' ON COMMIT PRESERVE ROWS; 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..f0481c0f57f1b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11055,15 +11055,16 @@ 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 +11087,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 +11098,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 +11154,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 +11512,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 +11534,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 +11584,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 +11656,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 +11701,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) { @@ -11926,13 +11929,14 @@ create_table_info_t::set_tablespace_type( m_innodb_file_per_table || table_being_altered_is_file_per_table; - /* Ignore the current innodb-file-per-table setting if we are - creating a temporary table. */ + /* Ignore the current innodb-file-per-table setting if we are + creating a temporary table (local or global). */ 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