From 585cb18ed1a38f9bb27c7542343d9ea197d313eb Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 13 Jan 2022 23:35:17 +0300 Subject: [PATCH] MDEV-27452 TIMESTAMP(0) system field is allowed for certain creation of system-versioned table First, we do not add VERS_UPDATE_UNVERSIONED_FLAG for system field and that fixes SHOW CREATE result. Second, we have to call check_sys_fields() for any CREATE TABLE and there correct type is checked for system fields. Third, we update system_time like as_row structures for ALTER TABLE and that makes check_sys_fields() happy for ALTER TABLE when we make system fields hidden. --- mysql-test/suite/versioning/r/create.result | 28 ++++++++++++++++++-- mysql-test/suite/versioning/t/create.test | 29 +++++++++++++++++++++ sql/handler.cc | 7 +++-- sql/sql_table.cc | 9 +++++-- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result index 8943ea1f1cd..f65db4e6ca0 100644 --- a/mysql-test/suite/versioning/r/create.result +++ b/mysql-test/suite/versioning/r/create.result @@ -619,8 +619,32 @@ Table Create Table t1 CREATE TABLE `t1` ( `x` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING, `y` int(11) DEFAULT NULL, - `row_start` timestamp(6) GENERATED ALWAYS AS ROW START WITHOUT SYSTEM VERSIONING, - `row_end` timestamp(6) GENERATED ALWAYS AS ROW END WITHOUT SYSTEM VERSIONING, + `row_start` timestamp(6) GENERATED ALWAYS AS ROW START, + `row_end` timestamp(6) GENERATED ALWAYS AS ROW END, PERIOD FOR SYSTEM_TIME (`row_start`, `row_end`) ) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING drop table t1; +# +# MDEV-27452 TIMESTAMP(0) system field is allowed for certain creation of system-versioned table +# +create or replace table t ( +a int, +s timestamp as row start, +e timestamp as row end, +period for system_time (s, e)) +with system versioning; +ERROR HY000: `s` must be of type TIMESTAMP(6) for system-versioned table `t` +create or replace table t ( +a int with system versioning, +s timestamp as row start, +e timestamp as row end, +period for system_time (s, e)); +ERROR HY000: `s` must be of type TIMESTAMP(6) for system-versioned table `t` +create or replace table t ( +a int with system versioning, +b int with system versioning, +s timestamp(6) as row start, +e timestamp(6) as row end, +period for system_time (s, e)); +insert into t () values (),(); +drop table t; diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test index b1f0055f5cc..2f894ae890b 100644 --- a/mysql-test/suite/versioning/t/create.test +++ b/mysql-test/suite/versioning/t/create.test @@ -468,3 +468,32 @@ create or replace table t1 ( show create table t1; drop table t1; + +--echo # +--echo # MDEV-27452 TIMESTAMP(0) system field is allowed for certain creation of system-versioned table +--echo # +--error ER_VERS_FIELD_WRONG_TYPE +create or replace table t ( + a int, + s timestamp as row start, + e timestamp as row end, + period for system_time (s, e)) +with system versioning; + +--error ER_VERS_FIELD_WRONG_TYPE +create or replace table t ( + a int with system versioning, + s timestamp as row start, + e timestamp as row end, + period for system_time (s, e)); + +create or replace table t ( + a int with system versioning, + b int with system versioning, + s timestamp(6) as row start, + e timestamp(6) as row end, + period for system_time (s, e)); +insert into t () values (),(); + +# cleanup +drop table t; diff --git a/sql/handler.cc b/sql/handler.cc index 871ba3c4149..1e5e4b18366 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7226,6 +7226,8 @@ bool Table_scope_and_contents_source_st::vers_fix_system_fields( List_iterator it(alter_info->create_list); while (Create_field *f= it++) { + if (f->vers_sys_field()) + continue; if ((f->versioning == Column_definition::VERSIONING_NOT_SET && !add_versioning) || f->versioning == Column_definition::WITHOUT_VERSIONING) { @@ -7247,9 +7249,10 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields( if (!(options & HA_VERSIONED_TABLE)) return false; + uint versioned_fields= 0; + if (!(alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING)) { - uint versioned_fields= 0; uint fieldnr= 0; List_iterator field_it(alter_info->create_list); while (Create_field *f= field_it++) @@ -7280,7 +7283,7 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields( } } - if (!(alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING)) + if (!(alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING) && !versioned_fields) return false; bool can_native= ha_check_storage_engine_flag(db_type, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 52948968c95..7e2609fcc57 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8230,9 +8230,14 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, def->invisible= INVISIBLE_SYSTEM; alter_info->flags|= ALTER_CHANGE_COLUMN; if (field->flags & VERS_ROW_START) - create_info->vers_info.as_row.start= def->field_name= Vers_parse_info::default_start; + create_info->vers_info.system_time.start= + create_info->vers_info.as_row.start= + def->field_name= Vers_parse_info::default_start; + else - create_info->vers_info.as_row.end= def->field_name= Vers_parse_info::default_end; + create_info->vers_info.system_time.end= + create_info->vers_info.as_row.end= + def->field_name= Vers_parse_info::default_end; new_create_list.push_back(def, thd->mem_root); dropped_sys_vers_fields|= field->flags; drop_it.remove();