diff --git a/mysql-test/suite/versioning/r/cte.result b/mysql-test/suite/versioning/r/cte.result index 20fe0c1a081..3043bcb4093 100644 --- a/mysql-test/suite/versioning/r/cte.result +++ b/mysql-test/suite/versioning/r/cte.result @@ -42,7 +42,26 @@ from emp for system_time as of timestamp @ts_1 as e, ancestors as a where e.mgr = a.emp_id ) -select * from ancestors for system_time as of current_timestamp; +select * from ancestors; +emp_id name mgr salary +1 bill NULL 1000 +20 john 1 500 +30 jane 1 750 +with recursive +ancestors +as +( +select e.emp_id, e.name, e.mgr, e.salary +from emp as e +where name = 'bill' + union +select e.emp_id, e.name, e.mgr, e.salary +from emp as e, +ancestors as a +where e.mgr = a.emp_id +) +select * from ancestors +for system_time as of timestamp @ts_1; emp_id name mgr salary 1 bill NULL 1000 30 jane 1 750 diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result index d2a909ebf44..d6323074857 100644 --- a/mysql-test/suite/versioning/r/derived.result +++ b/mysql-test/suite/versioning/r/derived.result @@ -133,25 +133,28 @@ create or replace table t1 (x int) with system versioning; create or replace table t2 (y int) with system versioning; insert into t1 values (1); set @t0= now(6); +delete from t1; insert into t1 values (2); -delete from t1 where x = 1; insert into t2 values (10); select * from (select *, t1.sys_trx_end, t1.sys_trx_end as endo from t1) as s0; ERROR HY000: Derived table is prohibited: multiple end system fields `t1.sys_trx_end`, `t1.sys_trx_end` in query! select * from (select *, t1.sys_trx_end, t2.sys_trx_start from t1, t2) as s0; ERROR HY000: Derived table is prohibited: system fields from multiple tables `t1`, `t2` in query! +# SYSTEM_TIME propagation from inner to outer select * from (select * from t1 for system_time as of timestamp @t0, t2) as s0; x y 1 10 with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * from s1; x y 1 10 +# leading table selection select * from (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) as s2; y x 10 1 with s3 as (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) select * from s3; y x 10 1 +# SYSTEM_TIME propagation from outer to inner select * from (select *, t1.sys_trx_start from t2 for system_time as of current_timestamp, t1) as s4 for system_time as of timestamp @t0; y x 10 1 @@ -161,21 +164,56 @@ y x with s6 as (select *, t1.sys_trx_start from t2 for system_time as of current_timestamp, t1) select * from s6 for system_time as of timestamp @t0; y x 10 1 +### VIEW instead of t1 set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'"); prepare q from @q; execute q; drop prepare q; +create view vt2 as select * from t1; +# SYSTEM_TIME propagation from view select * from vt1; x 1 +# SYSTEM_TIME propagation from inner to outer select * from (select * from vt1, t2) as s0; x y 1 10 +# leading table selection select * from (select *, vt1.sys_trx_end from t2, vt1) as s0; y x 10 1 -select * from (select *, vt1.sys_trx_start from t2 for system_time as of current_timestamp, vt1) as s0 for system_time as of timestamp @t0; -y x -10 1 -drop table t1, t2; -drop view vt1; +### SYSTEM_TIME clash +select * from (select * from t1 for system_time all) dt0 for system_time all; +ERROR HY000: SYSTEM_TIME is not allowed outside historical `dt0` +select * from vt1 for system_time all; +ERROR HY000: SYSTEM_TIME is not allowed outside historical `vt1` +with dt1 as (select * from t1 for system_time all) +select * from dt1 for system_time all; +ERROR HY000: SYSTEM_TIME is not allowed outside historical `dt1` +### UNION +set @t1= now(6); +delete from t2; +insert into t2 values (3); +# SYSTEM_TIME is not propagated +select x from t1 union +select y from t2; +x +2 +3 +select x from t1 for system_time as of @t0 union +select y from t2; +x +1 +3 +select x from t1 union +select y from t2 for system_time as of @t1; +x +2 +10 +select x from t1 for system_time as of @t0 union +select y from t2 for system_time as of @t1; +x +1 +10 +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/r/view.result b/mysql-test/suite/versioning/r/view.result index 8557121d786..03c8b08ce2f 100644 --- a/mysql-test/suite/versioning/r/view.result +++ b/mysql-test/suite/versioning/r/view.result @@ -12,12 +12,6 @@ set @vt2= concat("create or replace view vt2 as select *, sys_trx_end from t1 fo prepare stmt from @vt2; execute stmt; drop prepare stmt; -select * from vt1 for system_time all; -x -1 -select * from vt2 for system_time all; -x -2 select * from t1; x create or replace view vt1 as select * from t1; @@ -26,17 +20,7 @@ View Create View character_set_client collation_connection vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from `t1` FOR SYSTEM_TIME ALL where `t1`.`sys_trx_end` = MAX_RESULT latin1 latin1_swedish_ci drop view vt1; drop view vt2; -create view vt1 as select * from t1 for system_time all; -select * from vt1 for system_time all; -x -2 -1 -prepare stmt from 'select * from vt1 for system_time all'; -execute stmt; -x -2 -1 -drop prepare stmt; +create or replace view vt1 as select * from t1 for system_time all; select * from vt1; x 2 @@ -47,39 +31,24 @@ x 2 1 drop prepare stmt; +set @str= concat('create or replace view vt1 as +select * from t1 for system_time as of timestamp "', @t1, '"'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; select * from t1 for system_time as of timestamp @t1; x 1 -select * from vt1 for system_time as of timestamp @t1; +select * from vt1; x 1 -prepare stmt from 'select * from vt1 for system_time as of timestamp @t1'; -execute stmt; -x -1 -drop prepare stmt; -create or replace view vt1 as select * from t1; -select * from vt1 for system_time all; -x -prepare stmt from 'select * from vt1 for system_time all'; -execute stmt; -x -drop prepare stmt; insert into vt1 values (3); select * from t1; x 3 select * from vt1; x -3 -select * from t1 for system_time all; -x -2 1 -3 -select * from vt1 for system_time all; -x -3 create or replace table t1 (x int) with system versioning; insert into t1 values (1), (2); set @t1=now(6); @@ -91,7 +60,7 @@ set @tmp= concat("create or replace view vt1 as select * from t1 for system_time prepare stmt from @tmp; execute stmt; drop prepare stmt; -select * from vt1 for system_time all; +select * from vt1; x 1 2 diff --git a/mysql-test/suite/versioning/t/cte.test b/mysql-test/suite/versioning/t/cte.test index bc7caec9e71..488e7de5dfc 100644 --- a/mysql-test/suite/versioning/t/cte.test +++ b/mysql-test/suite/versioning/t/cte.test @@ -49,7 +49,23 @@ as ancestors as a where e.mgr = a.emp_id ) -select * from ancestors for system_time as of current_timestamp; +select * from ancestors; + +with recursive +ancestors +as +( + select e.emp_id, e.name, e.mgr, e.salary + from emp as e + where name = 'bill' + union + select e.emp_id, e.name, e.mgr, e.salary + from emp as e, + ancestors as a + where e.mgr = a.emp_id +) +select * from ancestors +for system_time as of timestamp @ts_1; /* Expected 3 rows */ with recursive diff --git a/mysql-test/suite/versioning/t/derived.test b/mysql-test/suite/versioning/t/derived.test index 9e3bd367064..1e86cb9f824 100644 --- a/mysql-test/suite/versioning/t/derived.test +++ b/mysql-test/suite/versioning/t/derived.test @@ -96,8 +96,8 @@ create or replace table t1 (x int) with system versioning; create or replace table t2 (y int) with system versioning; insert into t1 values (1); set @t0= now(6); +delete from t1; insert into t1 values (2); -delete from t1 where x = 1; insert into t2 values (10); --error ER_VERS_DERIVED_PROHIBITED @@ -105,29 +105,51 @@ select * from (select *, t1.sys_trx_end, t1.sys_trx_end as endo from t1) as s0; --error ER_VERS_DERIVED_PROHIBITED select * from (select *, t1.sys_trx_end, t2.sys_trx_start from t1, t2) as s0; -# system_time propagation from inner to outer +--echo # SYSTEM_TIME propagation from inner to outer select * from (select * from t1 for system_time as of timestamp @t0, t2) as s0; with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * from s1; -# leading table selection +--echo # leading table selection select * from (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) as s2; with s3 as (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) select * from s3; -# system_time propagation from outer to inner +--echo # SYSTEM_TIME propagation from outer to inner select * from (select *, t1.sys_trx_start from t2 for system_time as of current_timestamp, t1) as s4 for system_time as of timestamp @t0; with s5 as (select *, t1.sys_trx_start from t2 for system_time as of current_timestamp, t1) select * from s5 for system_time as of timestamp @t0; with s6 as (select *, t1.sys_trx_start from t2 for system_time as of current_timestamp, t1) select * from s6 for system_time as of timestamp @t0; -# VIEW instead of t1 +--echo ### VIEW instead of t1 set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'"); prepare q from @q; execute q; drop prepare q; +create view vt2 as select * from t1; -# system_time propagation from view +--echo # SYSTEM_TIME propagation from view select * from vt1; -# system_time propagation from inner to outer +--echo # SYSTEM_TIME propagation from inner to outer select * from (select * from vt1, t2) as s0; -# leading table selection +--echo # leading table selection select * from (select *, vt1.sys_trx_end from t2, vt1) as s0; -# system_time propagation from outer to inner -select * from (select *, vt1.sys_trx_start from t2 for system_time as of current_timestamp, vt1) as s0 for system_time as of timestamp @t0; -drop table t1, t2; -drop view vt1; +--echo ### SYSTEM_TIME clash +--error ER_VERS_SYSTEM_TIME_CLASH +select * from (select * from t1 for system_time all) dt0 for system_time all; +--error ER_VERS_SYSTEM_TIME_CLASH +select * from vt1 for system_time all; +--error ER_VERS_SYSTEM_TIME_CLASH +with dt1 as (select * from t1 for system_time all) +select * from dt1 for system_time all; + +--echo ### UNION +set @t1= now(6); +delete from t2; +insert into t2 values (3); +--echo # SYSTEM_TIME is not propagated +select x from t1 union +select y from t2; +select x from t1 for system_time as of @t0 union +select y from t2; +select x from t1 union +select y from t2 for system_time as of @t1; +select x from t1 for system_time as of @t0 union +select y from t2 for system_time as of @t1; + +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/t/view.test b/mysql-test/suite/versioning/t/view.test index 960adbf8b2f..a82949673f6 100644 --- a/mysql-test/suite/versioning/t/view.test +++ b/mysql-test/suite/versioning/t/view.test @@ -16,8 +16,6 @@ prepare stmt from @vt1; execute stmt; drop prepare stmt; set @vt2= concat("create or replace view vt2 as select *, sys_trx_end from t1 for system_time as of timestamp '", @t2, "'"); prepare stmt from @vt2; execute stmt; drop prepare stmt; -select * from vt1 for system_time all; -select * from vt2 for system_time all; select * from t1; create or replace view vt1 as select * from t1; @@ -27,26 +25,19 @@ show create view vt1; drop view vt1; drop view vt2; -create view vt1 as select * from t1 for system_time all; -select * from vt1 for system_time all; -prepare stmt from 'select * from vt1 for system_time all'; execute stmt; drop prepare stmt; - +create or replace view vt1 as select * from t1 for system_time all; select * from vt1; prepare stmt from 'select * from vt1'; execute stmt; drop prepare stmt; +set @str= concat('create or replace view vt1 as +select * from t1 for system_time as of timestamp "', @t1, '"'); +prepare stmt from @str; execute stmt; drop prepare stmt; select * from t1 for system_time as of timestamp @t1; -select * from vt1 for system_time as of timestamp @t1; -prepare stmt from 'select * from vt1 for system_time as of timestamp @t1'; execute stmt; drop prepare stmt; - -create or replace view vt1 as select * from t1; -select * from vt1 for system_time all; -prepare stmt from 'select * from vt1 for system_time all'; execute stmt; drop prepare stmt; +select * from vt1; insert into vt1 values (3); select * from t1; select * from vt1; -select * from t1 for system_time all; -select * from vt1 for system_time all; create or replace table t1 (x int) with system versioning; insert into t1 values (1), (2); @@ -59,7 +50,7 @@ set @t3=now(6); set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'"); prepare stmt from @tmp; execute stmt; drop prepare stmt; -select * from vt1 for system_time all; +select * from vt1; --echo # VIEW with parameters [#151] create or replace table t1 (x int) with system versioning; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 7c34eacbc11..c94680a0cbe 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7857,6 +7857,9 @@ ER_VERS_VIEW_PROHIBITED ER_VERS_DERIVED_PROHIBITED eng "Derived table is prohibited!" +ER_VERS_SYSTEM_TIME_CLASH + eng "SYSTEM_TIME is not allowed outside historical %`s" + ER_VERS_UNUSED_CLAUSE eng "Unused clause: '%s'" diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c15d050eb4d..c20d0d5aa18 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -575,6 +575,10 @@ public: */ uint8 uncacheable; enum sub_select_type linkage; + bool is_linkage_set() const + { + return linkage == UNION_TYPE || linkage == INTERSECT_TYPE || linkage == EXCEPT_TYPE; + } bool no_table_names_allowed; /* used for global order by */ static void *operator new(size_t size, MEM_ROOT *mem_root) throw () diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 67f41797a12..86bdeda8af7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -773,7 +773,15 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr, { for (table= outer_slex->table_list.first; table; table= table->next_local) { - if (!table->vers_conditions) + if (table->vers_conditions) + { + if (!slex->is_linkage_set() && !table->vers_conditions.from_inner) + { + my_error(ER_VERS_SYSTEM_TIME_CLASH, MYF(0), table->alias); + DBUG_RETURN(-1); + } + } + else { table->vers_conditions= slex->vers_export_outer; table->vers_conditions.from_inner= true;