From 72de7721b9ebc80ab8cb8019d2ca955f666368df Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 3 Jul 2017 17:38:59 +0300 Subject: [PATCH] SQL: No implicit versioning when created from SELECT [closes #219] --- mysql-test/suite/versioning/r/create.result | 69 ++++++++++++++------ mysql-test/suite/versioning/r/sysvars.result | 4 +- mysql-test/suite/versioning/r/vtmd.result | 2 +- mysql-test/suite/versioning/t/create.test | 58 +++++++++++----- mysql-test/suite/versioning/t/sysvars.test | 2 +- mysql-test/suite/versioning/t/vtmd.test | 2 +- sql/handler.cc | 49 +++++--------- sql/sql_base.cc | 27 +++++--- 8 files changed, 130 insertions(+), 83 deletions(-) diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result index 2324adfaa73..e4341223ef5 100644 --- a/mysql-test/suite/versioning/r/create.result +++ b/mysql-test/suite/versioning/r/create.result @@ -301,21 +301,39 @@ tt1 CREATE TABLE `tt1` ( ) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING drop table tt1; create or replace table t1 (x int) with system versioning; -create or replace table t2 (y int); -create or replace table t3 select * from t1 for system_time all, t2; -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `x` int(11) DEFAULT NULL, - `y` int(11) DEFAULT NULL -) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 -create or replace table t2 ( +create or replace table t0( y int, st SYS_TRX_TYPE generated always as row start, en SYS_TRX_TYPE generated always as row end, period for system_time (st, en) ) with system versioning; -create or replace table t3 select * from t2; +create or replace table t2 as select * from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `x` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 +create or replace table t3 as select * from t0; +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `y` int(11) DEFAULT NULL +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 +insert into t1 values (1); +insert into t0 values (2); +create or replace table t2 with system versioning as select * from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `x` int(11) DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +select * from t2; +x +1 +create or replace table t3 with system versioning as select * from t0; show create table t3; Table Create Table t3 CREATE TABLE `t3` ( @@ -324,7 +342,23 @@ t3 CREATE TABLE `t3` ( `en` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, PERIOD FOR SYSTEM_TIME (`st`, `en`) ) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING -create or replace table t3 select x, y, t1.sys_trx_start, t2.en from t1, t2; +select * from t3 where y > 2; +y st en +delete from t0; +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int); +create or replace table t3 with system versioning select * from t1 for system_time all, t2; +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `x` int(11) DEFAULT NULL, + `sys_trx_start` SYS_TRX_TYPE GENERATED ALWAYS AS ROW START, + `sys_trx_end` SYS_TRX_TYPE GENERATED ALWAYS AS ROW END, + `y` int(11) DEFAULT NULL, + PERIOD FOR SYSTEM_TIME (`sys_trx_start`, `sys_trx_end`) +) ENGINE=INNODB_OR_MYISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +create or replace table t2 with system versioning as select * from t0; +create or replace table t3 with system versioning select x, y, t1.sys_trx_start, t2.en from t1, t2; ERROR HY000: Wrong parameters for `t3`: system fields selected from different tables insert into t2 values (1), (2); delete from t2 where y = 2; @@ -339,18 +373,11 @@ y 2 create or replace table t1 (a int) with system versioning engine INNODB_OR_MYISAM; create or replace table t2 as select a, sys_trx_start, sys_trx_end from t1 for system_time all; -create or replace table t2 engine INNODB_OR_MYISAM as select a, sys_trx_start, sys_trx_end from t1 for system_time all; +create or replace table t2 with system versioning engine INNODB_OR_MYISAM as select a, sys_trx_start, sys_trx_end from t1 for system_time all; ERROR HY000: `sys_trx_start` must be of type `SYS_TRX_TYPE` for versioned table `t2` create or replace table t1 (a int, id int) with system versioning engine INNODB_OR_MYISAM; create or replace table t2 (b int, id int); create or replace table t3 as select t2.b, t1.a, t1.sys_trx_start, t1.sys_trx_end from t2 inner join t1 on t2.id=t1.id; -drop table t1; -drop table t2; -drop table t3; -drop function non_default_engine; -drop procedure verify_vtq; -drop procedure innodb_verify_vtq; -drop function default_engine; -drop function sys_commit_ts; -drop function sys_datatype; +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/r/sysvars.result b/mysql-test/suite/versioning/r/sysvars.result index 172a10c78d7..56122432e6e 100644 --- a/mysql-test/suite/versioning/r/sysvars.result +++ b/mysql-test/suite/versioning/r/sysvars.result @@ -139,12 +139,12 @@ Table Create Table t CREATE TABLE `t` ( `x` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -insert into t values (1); +insert into t values (2); delete from t; select * from t; x select * from t for system_time all; x -1 +2 drop table t; set versioning_hide= IMPLICIT; diff --git a/mysql-test/suite/versioning/r/vtmd.result b/mysql-test/suite/versioning/r/vtmd.result index f2e7956bfa8..808f6e7d92d 100644 --- a/mysql-test/suite/versioning/r/vtmd.result +++ b/mysql-test/suite/versioning/r/vtmd.result @@ -28,7 +28,7 @@ create or replace procedure check_vtmd (in vtmd_name varchar(64)) begin set @tmp= concat(' create or replace temporary table - tmp_vtmd as + tmp_vtmd with system versioning as select * from ', vtmd_name, ' as vtmd for system_time all'); prepare stmt from @tmp; execute stmt; drop prepare stmt; diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test index 71b248c0003..032c75b64ef 100644 --- a/mysql-test/suite/versioning/t/create.test +++ b/mysql-test/suite/versioning/t/create.test @@ -243,24 +243,55 @@ drop table tt1; # CREATE TABLE ... SELECT create or replace table t1 (x int) with system versioning; -create or replace table t2 (y int); -create or replace table t3 select * from t1 for system_time all, t2; ---replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE -show create table t3; - --replace_result "bigint unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE -eval create or replace table t2 ( +eval create or replace table t0( y int, st $sys_datatype generated always as row start, en $sys_datatype generated always as row end, period for system_time (st, en) ) with system versioning; -create or replace table t3 select * from t2; + +## For non-versioned table: +### 1. system fields are not inherited (hidden and not hidden) +create or replace table t2 as select * from t1; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t2; + +create or replace table t3 as select * from t0; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM +show create table t3; + +### 2. hidden fields are inherited as hidden +### TODO: non-system hidden fields + +## For versioned table system fields are inherited as is. +insert into t1 values (1); +insert into t0 values (2); + +create or replace table t2 with system versioning as select * from t1; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t2; +# implicit system fields are hidden +select * from t2; + +create or replace table t3 with system versioning as select * from t0; +--replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE +show create table t3; +# explicit system fields are not hidden +select * from t3 where y > 2; + +delete from t0; + +## Combinations of versioned + non-versioned +create or replace table t1 (x int) with system versioning; +create or replace table t2 (y int); +create or replace table t3 with system versioning select * from t1 for system_time all, t2; --replace_result InnoDB INNODB_OR_MYISAM MyISAM INNODB_OR_MYISAM "bigint(20) unsigned" SYS_TRX_TYPE timestamp(6) SYS_TRX_TYPE show create table t3; +create or replace table t2 with system versioning as select * from t0; --error ER_VERS_WRONG_PARAMS -create or replace table t3 select x, y, t1.sys_trx_start, t2.en from t1, t2; +create or replace table t3 with system versioning select x, y, t1.sys_trx_start, t2.en from t1, t2; insert into t2 values (1), (2); delete from t2 where y = 2; @@ -276,7 +307,7 @@ eval create or replace table t1 (a int) with system versioning engine $non_defau create or replace table t2 as select a, sys_trx_start, sys_trx_end from t1 for system_time all; --replace_result innodb INNODB_OR_MYISAM myisam INNODB_OR_MYISAM "BIGINT(20) UNSIGNED" SYS_TRX_TYPE "TIMESTAMP(6)" SYS_TRX_TYPE --error ER_VERS_FIELD_WRONG_TYPE -eval create or replace table t2 engine $default_engine as select a, sys_trx_start, sys_trx_end from t1 for system_time all; +eval create or replace table t2 with system versioning engine $default_engine as select a, sys_trx_start, sys_trx_end from t1 for system_time all; --replace_result innodb INNODB_OR_MYISAM myisam INNODB_OR_MYISAM eval create or replace table t1 (a int, id int) with system versioning engine $non_default_engine; @@ -284,10 +315,5 @@ create or replace table t2 (b int, id int); create or replace table t3 as select t2.b, t1.a, t1.sys_trx_start, t1.sys_trx_end from t2 inner join t1 on t2.id=t1.id; -drop table t1; -drop table t2; -drop table t3; - -drop function non_default_engine; - --- source suite/versioning/common_finish.inc +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/t/sysvars.test b/mysql-test/suite/versioning/t/sysvars.test index 49ee14326f1..4516833d58d 100644 --- a/mysql-test/suite/versioning/t/sysvars.test +++ b/mysql-test/suite/versioning/t/sysvars.test @@ -101,7 +101,7 @@ create or replace table t ( with system versioning; show create table t; -insert into t values (1); +insert into t values (2); delete from t; select * from t; diff --git a/mysql-test/suite/versioning/t/vtmd.test b/mysql-test/suite/versioning/t/vtmd.test index 299d31ee036..01b68275737 100644 --- a/mysql-test/suite/versioning/t/vtmd.test +++ b/mysql-test/suite/versioning/t/vtmd.test @@ -36,7 +36,7 @@ create or replace procedure check_vtmd (in vtmd_name varchar(64)) begin set @tmp= concat(' create or replace temporary table - tmp_vtmd as + tmp_vtmd with system versioning as select * from ', vtmd_name, ' as vtmd for system_time all'); prepare stmt from @tmp; execute stmt; drop prepare stmt; diff --git a/sql/handler.cc b/sql/handler.cc index 3589c3aee19..0bf4f766dac 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -6675,31 +6675,31 @@ bool Vers_parse_info::check_and_fix_implicit( if (table->table && table->table->versioned()) vers_tables++; } - - // Possibly override default storage engine to match - // one used in source table. - if (!(create_info->used_fields & HA_CREATE_USED_ENGINE)) - { - List_iterator_fast it(alter_info->create_list); - while (Create_field *f= it++) - { - if (is_trx_start(*f) || is_trx_end(*f)) - { - create_info->db_type= f->field->orig_table->file->ht; - break; - } - } - } } // CREATE ... SELECT: if at least one table in SELECT is versioned, // then created table will be versioned. - if (thd->variables.vers_force || vers_tables > 0) + if (thd->variables.vers_force) { with_system_versioning= true; create_info->options|= HA_VERSIONED_TABLE; } + // Possibly override default storage engine to match one used in source table. + if (from_select && with_system_versioning && + !(create_info->used_fields & HA_CREATE_USED_ENGINE)) + { + List_iterator_fast it(alter_info->create_list); + while (Create_field *f= it++) + { + if (is_trx_start(*f) || is_trx_end(*f)) + { + create_info->db_type= f->field->orig_table->file->ht; + break; + } + } + } + if (!need_check()) return false; @@ -6764,22 +6764,7 @@ bool Vers_parse_info::check_and_fix_implicit( bool integer_fields= create_info->db_type->flags & HTON_NATIVE_SYS_VERSIONING; - if (vers_tables > 0) - { - if (!generated_as_row.start && !generated_as_row.end) - { - with_system_versioning= false; - create_info->options&= ~HA_VERSIONED_TABLE; - return false; - } - if (!generated_as_row.start || !generated_as_row.end) - { - my_error_as(ER_VERS_WRONG_PARAMS, ER_MISSING, MYF(0), table_name, - generated_as_row.start ? "AS ROW END" : "AS ROW START"); - return true; - } - } - else if (fix_implicit(thd, alter_info, integer_fields)) + if (fix_implicit(thd, alter_info, integer_fields)) return true; int plain_cols= 0; // column doesn't have WITH or WITHOUT SYSTEM VERSIONING diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8cdc835c0df..238fa3a0fa4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7596,16 +7596,25 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, tl->vers_conditions.type == FOR_SYSTEM_TIME_UNSPECIFIED ? slex->vers_conditions.type : tl->vers_conditions.type; - if ((sys_field && (thd->lex->sql_command == SQLCOM_CREATE_VIEW || - slex->nest_level > 0 || - (vers_hide == VERS_HIDE_FULL && thd->lex->sql_command != SQLCOM_CREATE_TABLE))) || - ((fl & HIDDEN_FLAG) && ( - !sys_field || - vers_hide == VERS_HIDE_IMPLICIT || - (vers_hide == VERS_HIDE_AUTO && ( - vers_type == FOR_SYSTEM_TIME_UNSPECIFIED || - vers_type == FOR_SYSTEM_TIME_AS_OF))))) + enum_sql_command sql_command= thd->lex->sql_command; + unsigned int create_options= thd->lex->create_info.options; + + if ( + sql_command == SQLCOM_CREATE_TABLE ? + sys_field && !(create_options & HA_VERSIONED_TABLE) : ( + sys_field ? + (sql_command == SQLCOM_CREATE_VIEW || + slex->nest_level > 0 || + vers_hide == VERS_HIDE_FULL || + ((fl & HIDDEN_FLAG) && ( + vers_hide == VERS_HIDE_IMPLICIT || + (vers_hide == VERS_HIDE_AUTO && ( + vers_type == FOR_SYSTEM_TIME_UNSPECIFIED || + vers_type == FOR_SYSTEM_TIME_AS_OF))))) : + (fl & HIDDEN_FLAG))) + { continue; + } } else if (item->type() == Item::REF_ITEM) {