Skip to content

Commit 10bb8cc

Browse files
committed
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.
1 parent fcf1416 commit 10bb8cc

4 files changed

Lines changed: 55 additions & 20 deletions

File tree

mysql-test/main/global_temporary_table.result

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,8 @@ set autocommit=1;
13221322
create global temporary table t (c int) engine=innodb on commit preserve rows;
13231323
set session transaction isolation level serializable;
13241324
flush tables t with read lock;
1325+
Warnings:
1326+
Warning 1809 Table `test`.`t` in system tablespace
13251327
insert t values (1);
13261328
update t set c=c+1;
13271329
# Cleanup
@@ -1351,3 +1353,14 @@ ERROR HY000: 'mysql.help_topic' is not of type 'BASE TABLE'
13511353
drop table mysql.help_topic;
13521354
rename table mysql.help_topic1 to mysql.help_topic;
13531355
disconnect con1;
1356+
# MDEV-40167 - GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes
1357+
CREATE GLOBAL TEMPORARY TABLE gtt (id INT PRIMARY KEY, body TEXT, FULLTEXT (body))
1358+
ENGINE=InnoDB ON COMMIT PRESERVE ROWS;
1359+
ERROR HY000: Cannot create FULLTEXT index on temporary InnoDB table
1360+
CREATE GLOBAL TEMPORARY TABLE gtt_v (id INT PRIMARY KEY, v VECTOR (4) NOT NULL, VECTOR INDEX (v))
1361+
ENGINE=InnoDB ON COMMIT PRESERVE ROWS;
1362+
ERROR HY000: Cannot create VECTOR index on temporary InnoDB table
1363+
CREATE GLOBAL TEMPORARY TABLE gtt (id INT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ON COMMIT PRESERVE ROWS;
1364+
ERROR HY000: InnoDB refuses to write tables with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE.
1365+
CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='MYSQLTEST_VARDIR/tmp' ON COMMIT PRESERVE ROWS;
1366+
ERROR HY000: Can't create table `test`.`g` (errno: 140 "Wrong create options")

mysql-test/main/global_temporary_table.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,3 +1234,20 @@ drop table mysql.help_topic;
12341234
rename table mysql.help_topic1 to mysql.help_topic;
12351235

12361236
--disconnect con1
1237+
1238+
--echo # MDEV-40167 - GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes
1239+
1240+
--error ER_NO_INDEX_ON_TEMPORARY
1241+
CREATE GLOBAL TEMPORARY TABLE gtt (id INT PRIMARY KEY, body TEXT, FULLTEXT (body))
1242+
ENGINE=InnoDB ON COMMIT PRESERVE ROWS;
1243+
1244+
--error ER_NO_INDEX_ON_TEMPORARY
1245+
CREATE GLOBAL TEMPORARY TABLE gtt_v (id INT PRIMARY KEY, v VECTOR (4) NOT NULL, VECTOR INDEX (v))
1246+
ENGINE=InnoDB ON COMMIT PRESERVE ROWS;
1247+
1248+
--error ER_UNSUPPORTED_COMPRESSED_TABLE
1249+
CREATE GLOBAL TEMPORARY TABLE gtt (id INT ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED ON COMMIT PRESERVE ROWS;
1250+
1251+
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
1252+
--error ER_CANT_CREATE_TABLE
1253+
eval CREATE GLOBAL TEMPORARY TABLE g (id INT PRIMARY KEY) ENGINE=InnoDB DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp' ON COMMIT PRESERVE ROWS;

sql/sql_table.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3778,7 +3778,7 @@ mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info,
37783778
my_error(ER_INDEX_CANNOT_HAVE_NULL, MYF(0), "VECTOR");
37793779
DBUG_RETURN(TRUE);
37803780
}
3781-
if (create_info->tmp_table())
3781+
if (create_info->tmp_table() || create_info->global_tmp_table())
37823782
{
37833783
my_error(ER_NO_INDEX_ON_TEMPORARY, MYF(0), "VECTOR",
37843784
file->table_type());

storage/innobase/handler/ha_innodb.cc

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11055,15 +11055,17 @@ create_table_info_t::create_option_data_directory_is_valid()
1105511055
is_valid = false;
1105611056
}
1105711057

11058-
/* Do not use DATA DIRECTORY with TEMPORARY TABLE. */
11059-
if (m_create_info->tmp_table()) {
11060-
push_warning(
11061-
m_thd, Sql_condition::WARN_LEVEL_WARN,
11062-
ER_ILLEGAL_HA_CREATE_OPTION,
11063-
"InnoDB: DATA DIRECTORY cannot be used"
11064-
" for TEMPORARY tables.");
11065-
is_valid = false;
11066-
}
11058+
/* Do not use DATA DIRECTORY with TEMPORARY TABLE or
11059+
GLOBAL TEMPORARY TABLE. */
11060+
if (m_create_info->tmp_table() || m_create_info->global_tmp_table()) {
11061+
push_warning_printf(
11062+
m_thd, Sql_condition::WARN_LEVEL_WARN,
11063+
ER_ILLEGAL_HA_CREATE_OPTION,
11064+
"InnoDB: DATA DIRECTORY cannot be used for %s tables.",
11065+
m_create_info->global_tmp_table()
11066+
? "GLOBAL TEMPORARY" : "TEMPORARY");
11067+
is_valid = false;
11068+
}
1106711069

1106811070
/* We check for a DATA DIRECTORY mixed with TABLESPACE in
1106911071
create_option_tablespace_is_valid(), no need to here. */
@@ -11086,6 +11088,7 @@ create_table_info_t::create_options_are_invalid()
1108611088
const char* ret = NULL;
1108711089
enum row_type row_format = m_create_info->row_type;
1108811090
const bool is_temp = m_create_info->tmp_table();
11091+
const bool is_global_temp = m_create_info->global_tmp_table();
1108911092

1109011093
ut_ad(m_thd != NULL);
1109111094

@@ -11096,7 +11099,7 @@ create_table_info_t::create_options_are_invalid()
1109611099

1109711100
/* Check if a non-zero KEY_BLOCK_SIZE was specified. */
1109811101
if (has_key_block_size) {
11099-
if (is_temp || innodb_read_only_compressed) {
11102+
if (is_temp || is_global_temp || innodb_read_only_compressed) {
1110011103
my_error(ER_UNSUPPORTED_COMPRESSED_TABLE, MYF(0));
1110111104
return("KEY_BLOCK_SIZE");
1110211105
}
@@ -11152,7 +11155,7 @@ create_table_info_t::create_options_are_invalid()
1115211155
other incompatibilities. */
1115311156
switch (row_format) {
1115411157
case ROW_TYPE_COMPRESSED:
11155-
if (is_temp || innodb_read_only_compressed) {
11158+
if (is_temp || is_global_temp || innodb_read_only_compressed) {
1115611159
my_error(ER_UNSUPPORTED_COMPRESSED_TABLE, MYF(0));
1115711160
return("ROW_FORMAT");
1115811161
}
@@ -11510,7 +11513,8 @@ bool create_table_info_t::innobase_table_flags()
1151011513
rec_format_t innodb_row_format =
1151111514
get_row_format(m_default_row_format);
1151211515
const bool is_temp = m_create_info->tmp_table();
11513-
bool zip_allowed = !is_temp;
11516+
const bool is_global_temp = m_create_info->global_tmp_table();
11517+
bool zip_allowed = !is_temp && !is_global_temp;
1151411518

1151511519
const ulint zip_ssize_max =
1151611520
ut_min(static_cast<ulint>(UNIV_PAGE_SSIZE_MAX),
@@ -11531,7 +11535,7 @@ bool create_table_info_t::innobase_table_flags()
1153111535

1153211536
/* We don't support FTS indexes in temporary
1153311537
tables. */
11534-
if (is_temp) {
11538+
if (is_temp || is_global_temp) {
1153511539
my_error(ER_NO_INDEX_ON_TEMPORARY, MYF(0),
1153611540
"FULLTEXT", "InnoDB");
1153711541
DBUG_RETURN(false);
@@ -11581,7 +11585,7 @@ bool create_table_info_t::innobase_table_flags()
1158111585
}
1158211586

1158311587
/* Make sure compressed row format is allowed. */
11584-
if (is_temp) {
11588+
if (is_temp || is_global_temp) {
1158511589
push_warning(
1158611590
m_thd, Sql_condition::WARN_LEVEL_WARN,
1158711591
ER_ILLEGAL_HA_CREATE_OPTION,
@@ -11653,7 +11657,7 @@ bool create_table_info_t::innobase_table_flags()
1165311657
innodb_row_format = REC_FORMAT_COMPACT;
1165411658
break;
1165511659
case ROW_TYPE_COMPRESSED:
11656-
if (is_temp) {
11660+
if (is_temp || is_global_temp) {
1165711661
push_warning_printf(
1165811662
m_thd, Sql_condition::WARN_LEVEL_WARN,
1165911663
ER_ILLEGAL_HA_CREATE_OPTION,
@@ -11698,8 +11702,8 @@ bool create_table_info_t::innobase_table_flags()
1169811702
zip_allowed = false;
1169911703
}
1170011704

11701-
ut_ad(!is_temp || !zip_allowed);
11702-
ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED);
11705+
ut_ad(!(is_temp || is_global_temp) || !zip_allowed);
11706+
ut_ad(!(is_temp || is_global_temp) || innodb_row_format != REC_FORMAT_COMPRESSED);
1170311707

1170411708
/* Set the table flags */
1170511709
if (!zip_allowed) {
@@ -11929,10 +11933,11 @@ create_table_info_t::set_tablespace_type(
1192911933
/* Ignore the current innodb-file-per-table setting if we are
1193011934
creating a temporary table. */
1193111935
m_use_file_per_table = m_allow_file_per_table
11932-
&& !m_create_info->tmp_table();
11936+
&& !m_create_info->tmp_table()
11937+
&& !m_create_info->global_tmp_table();
1193311938

1193411939
/* DATA DIRECTORY must have m_use_file_per_table but cannot be
11935-
used with TEMPORARY tables. */
11940+
used with TEMPORARY tables and global temporary tables. */
1193611941
m_use_data_dir =
1193711942
m_use_file_per_table
1193811943
&& m_create_info->data_file_name

0 commit comments

Comments
 (0)