diff --git a/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result b/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result index d86ca6f9c0032..67f6c0d47de71 100644 --- a/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result +++ b/mysql-test/suite/encryption/r/innodb_encrypt_temporary_tables.result @@ -24,3 +24,12 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted'; CAST(variable_value AS INT) > @old_decrypted 1 +set @old_encrypt_tables= @@innodb_encrypt_tables; +CREATE TEMPORARY TABLE t3 (c INT)ENCRYPTED=NO ENGINE=InnoDB; +Warnings: +Warning 1478 Ignoring encryption parameter during temporary table creation. +SET GLOBAL innodb_encrypt_tables='FORCE'; +TRUNCATE TABLE t3; +Warnings: +Warning 1478 Ignoring encryption parameter during temporary table creation. +SET GLOBAL innodb_encrypt_tables= @old_encrypt_tables; diff --git a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test index c48e5cf5c73b9..5e9c1fabfa1fe 100644 --- a/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test +++ b/mysql-test/suite/encryption/t/innodb_encrypt_temporary_tables.test @@ -28,3 +28,9 @@ WHERE variable_name = 'innodb_encryption_n_temp_blocks_encrypted'; SELECT CAST(variable_value AS INT) > @old_decrypted FROM information_schema.global_status WHERE variable_name = 'innodb_encryption_n_temp_blocks_decrypted'; + +set @old_encrypt_tables= @@innodb_encrypt_tables; +CREATE TEMPORARY TABLE t3 (c INT)ENCRYPTED=NO ENGINE=InnoDB; +SET GLOBAL innodb_encrypt_tables='FORCE'; +TRUNCATE TABLE t3; +SET GLOBAL innodb_encrypt_tables= @old_encrypt_tables; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 882ae68e5a5c9..9ff636aca2ad6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11292,7 +11292,13 @@ create_table_info_t::check_table_options() " ENCRYPTION_KEY_ID=1"); compile_time_assert(FIL_DEFAULT_ENCRYPTION_KEY == 1); } - if (srv_encrypt_tables != 2) { + /* m_trx is non-NULL because TRUNCATE that + passes its own transaction. TRUNCATE recreates + the table preserving the original ENCRYPTED=NO + attribute; bypass the innodb_encrypt_tables=FORCE + check here so the encryption state does not + silently change across a TRUNCATE. */ + if (m_trx || srv_encrypt_tables != 2) { break; } push_warning( @@ -13887,6 +13893,26 @@ int ha_innobase::truncate() if (ib_table->is_temporary()) { info.options|= HA_LEX_CREATE_TMP_TABLE; + + /* Validate the create options before dropping the existing + table, so that a validation failure leaves the original table + intact instead of dropping it and then failing in create(), + which would leave the handler without a table. */ + { + char norm_name[FN_REFLEN], remote_path[FN_REFLEN]; + create_table_info_t validate(m_user_thd, table, &info, norm_name, + remote_path, true, trx); + int err= validate.initialize(); + if (!err) + err= validate.prepare_create_table(ib_table->name.m_name, false); + if (err) + { + trx_rollback_for_mysql(trx); + trx->free(); + DBUG_RETURN(err); + } + } + btr_drop_temporary_table(*ib_table); m_prebuilt->table= nullptr; row_prebuilt_free(m_prebuilt); diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 79e188b8d2025..c6d3ffa8c3f64 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -710,7 +710,10 @@ class create_table_info_t /** Connection thread handle. */ THD* m_thd; - /** InnoDB transaction handle. */ + /** InnoDB transaction handle. Non-NULL only when + create is invoked from an truncation operation. + NULL for regular CREATE TABLE and ALTER TABLE, + which build their own transaction internally. */ trx_t* m_trx; /** Information on table columns and indexes. */