From 7ab205b0097140cdbb4778b05d6f6a0522c05a78 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Wed, 25 Jun 2025 14:14:50 +0300 Subject: [PATCH] MDEV-34928 CREATE TABLE does not check valid engine for log tables Log tables cannot work with transactional InnoDB or Aria, that is checked by ALTER TABLE for ER_UNSUPORTED_LOG_ENGINE. But it was possible to circumvent this check with CREATE TABLE. The patch makes the check of supported engine common for ALTER TABLE and CREATE TABLE. --- mysql-test/main/log_tables.result | 31 +++++++++++++++++++++++++++++++ mysql-test/main/log_tables.test | 26 ++++++++++++++++++++++++++ sql/handler.h | 1 + sql/log.cc | 12 ++++++++++++ sql/sql_table.cc | 26 ++++++++++++-------------- 5 files changed, 82 insertions(+), 14 deletions(-) diff --git a/mysql-test/main/log_tables.result b/mysql-test/main/log_tables.result index e64b71d4ed7..dc3255e3700 100644 --- a/mysql-test/main/log_tables.result +++ b/mysql-test/main/log_tables.result @@ -1022,6 +1022,37 @@ select 'evil-doing', sleep(1.1) select 'after evil-doing', sleep(0.2) set global log_output=default; drop user u@localhost; +# End of 10.5 tests +# +# MDEV-34928 CREATE TABLE does not check valid engine for log tables +# +set global general_log='on'; +show create table mysql.general_log; +Table Create Table +general_log CREATE TABLE `general_log` ( + `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci COMMENT='General log' +create or replace table mysql.general_log (a int) engine=innodb; +ERROR HY000: Storage engine InnoDB cannot be used for log tables +create or replace table mysql.slow_log (a int) engine=innodb; +ERROR HY000: Storage engine InnoDB cannot be used for log tables +create temporary table t (c int) engine=innodb; +insert into t values (1); +set global log_output='table'; +set session autocommit=0; +update t set c=0; +truncate t; +select a; +ERROR 42S22: Unknown column 'a' in 'SELECT' +drop temporary table t; +set @@global.log_output= @old_log_output; +set @@global.general_log= @old_general_log; +# End of 10.6 tests SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; SET @@global.general_log= @old_general_log; diff --git a/mysql-test/main/log_tables.test b/mysql-test/main/log_tables.test index 46d7de2dd26..981097cf8d4 100644 --- a/mysql-test/main/log_tables.test +++ b/mysql-test/main/log_tables.test @@ -2,6 +2,7 @@ -- source include/not_embedded.inc --source include/have_csv.inc +--source include/have_innodb.inc SET SQL_MODE=""; SET @old_log_output= @@global.log_output; @@ -1060,6 +1061,31 @@ set global log_output=default; drop user u@localhost; --enable_cursor_protocol +--echo # End of 10.5 tests + +--echo # +--echo # MDEV-34928 CREATE TABLE does not check valid engine for log tables +--echo # +set global general_log='on'; +show create table mysql.general_log; +--error ER_UNSUPORTED_LOG_ENGINE +create or replace table mysql.general_log (a int) engine=innodb; +--error ER_UNSUPORTED_LOG_ENGINE +create or replace table mysql.slow_log (a int) engine=innodb; +create temporary table t (c int) engine=innodb; +insert into t values (1); +set global log_output='table'; +set session autocommit=0; +update t set c=0; +truncate t; +--error ER_BAD_FIELD_ERROR +select a; +drop temporary table t; +set @@global.log_output= @old_log_output; +set @@global.general_log= @old_general_log; + +--echo # End of 10.6 tests + SET @@global.log_output= @old_log_output; SET @@global.slow_query_log= @old_slow_query_log; SET @@global.general_log= @old_general_log; diff --git a/sql/handler.h b/sql/handler.h index e3ffd48f4f2..53c65866d27 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2315,6 +2315,7 @@ struct HA_CREATE_INFO: public Table_scope_and_contents_source_st, const Lex_table_charset_collation_attrs_st &default_cscl, const Lex_table_charset_collation_attrs_st &convert_cscl, const Charset_collation_context &ctx); + bool check_if_valid_log_table(); }; diff --git a/sql/log.cc b/sql/log.cc index a4268faafc3..fe6a7a56ac1 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -745,6 +745,18 @@ int check_if_log_table(const TABLE_LIST *table) } +bool HA_CREATE_INFO::check_if_valid_log_table() +{ + if (!(db_type->flags & HTON_SUPPORT_LOG_TABLES) || + (db_type == maria_hton && transactional != HA_CHOICE_NO)) + { + my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0), hton_name(db_type)->str); + return true; + } + return false; +} + + /** Check if a given table is opened log table diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2451209f0c1..4d271258f10 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4629,6 +4629,12 @@ int create_table_impl(THD *thd, goto err; } + TABLE_LIST table_list; + table_list.init_one_table(&db, &table_name, 0, TL_WRITE_ALLOW_WRITE); + int log_table= check_if_log_table(&table_list); + if (log_table && create_info->check_if_valid_log_table()) + goto err; + handlerton *db_type; if (!internal_tmp_table && ha_table_exists(thd, &db, &table_name, @@ -4645,12 +4651,13 @@ int create_table_impl(THD *thd, { (void) delete_statistics_for_table(thd, &db, &table_name); - TABLE_LIST table_list; - table_list.init_one_table(&db, &table_name, 0, TL_WRITE_ALLOW_WRITE); table_list.table= create_info->table; - if (check_if_log_table(&table_list, TRUE, "CREATE OR REPLACE")) + if (log_table && logger.is_log_table_enabled(log_table)) + { + my_error(ER_BAD_LOG_STATEMENT, MYF(0), "CREATE OR REPLACE"); goto err; + } /* Rollback the empty transaction started in mysql_create_table() @@ -10417,7 +10424,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, it is the case. TODO: this design is obsolete and will be removed. */ - int table_kind= check_if_log_table(table_list, FALSE, NullS); + int table_kind= check_if_log_table(table_list); const bool used_engine= create_info->used_fields & HA_CREATE_USED_ENGINE; if (table_kind) @@ -10432,17 +10439,8 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, /* Disable alter of log tables to unsupported engine */ if ((used_engine) && (!create_info->db_type || /* unknown engine */ - !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES))) - { - unsupported: - my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0), - hton_name(create_info->db_type)->str); + create_info->check_if_valid_log_table())) DBUG_RETURN(true); - } - - if (create_info->db_type == maria_hton && - create_info->transactional != HA_CHOICE_NO) - goto unsupported; #ifdef WITH_PARTITION_STORAGE_ENGINE if (alter_info->partition_flags & ALTER_PARTITION_INFO)