From 2e3b580ba4bcb830a87ca969e77a6392eca9e615 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 14 Dec 2017 13:43:37 +0300 Subject: [PATCH] SQL: inner/outer system_time consistency [fixes #384] --- mysql-test/suite/versioning/r/derived.result | 31 +++++++------- mysql-test/suite/versioning/t/derived.test | 43 +++++++++++++++---- sql/sql_derived.cc | 2 - sql/sql_lex.cc | 1 - sql/sql_lex.h | 1 - sql/sql_select.cc | 44 +++++++++++--------- 6 files changed, 77 insertions(+), 45 deletions(-) diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result index 138f43fa4bd..d5b2b60ae38 100644 --- a/mysql-test/suite/versioning/r/derived.result +++ b/mysql-test/suite/versioning/r/derived.result @@ -96,9 +96,10 @@ where name = 'bill' for system_time as of timestamp @ts union select ee.emp_id, ee.name, ee.mgr -from emp as ee, ancestors as a +from emp +for system_time as of timestamp @ts as ee, +ancestors as a where ee.mgr = a.emp_id -for system_time as of timestamp @ts ) select * from ancestors; emp_id name mgr @@ -116,9 +117,9 @@ as for system_time as of timestamp @ts union select ee.emp_id, ee.name, ee.mgr - from emp as ee, ancestors as a + from emp for system_time as of timestamp @ts as ee, + ancestors as a where ee.mgr = a.emp_id - for system_time as of timestamp @ts ) select * from ancestors"; prepare stmt from @tmp; @@ -154,16 +155,6 @@ y x 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 -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; -y x -10 1 -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; @@ -216,6 +207,18 @@ create or replace table t1 (x int, y int) with system versioning; create or replace table t2 (x int, y int) with system versioning; insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5); insert into t2 values (1, 2), (2, 1), (3, 1); +## Outer or inner SYSTEM_TIME produces same expression +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) +Query A: +Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`sys_trx_end` > (current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= (current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > (current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= (current_timestamp(6)) +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) +Query B: +Note 1003 select `test`.`t1`.`x` AS `x`,`test`.`t1`.`y` AS `y1`,`test`.`t2`.`x` AS `x2`,`test`.`t2`.`y` AS `y2` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` FOR SYSTEM_TIME ALL where `test`.`t1`.`x` = `test`.`t2`.`x` and `test`.`t1`.`sys_trx_end` > (current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= (current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > (current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= (current_timestamp(6)) +Fine result: queries A and B are equal. ## LEFT JOIN: t1, t2 versioned select * from ( select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 diff --git a/mysql-test/suite/versioning/t/derived.test b/mysql-test/suite/versioning/t/derived.test index 3ef57aef1a8..20bec5a7bdf 100644 --- a/mysql-test/suite/versioning/t/derived.test +++ b/mysql-test/suite/versioning/t/derived.test @@ -67,9 +67,10 @@ as for system_time as of timestamp @ts union select ee.emp_id, ee.name, ee.mgr - from emp as ee, ancestors as a + from emp + for system_time as of timestamp @ts as ee, + ancestors as a where ee.mgr = a.emp_id - for system_time as of timestamp @ts ) select * from ancestors; set @tmp= " @@ -83,9 +84,9 @@ as for system_time as of timestamp @ts union select ee.emp_id, ee.name, ee.mgr - from emp as ee, ancestors as a + from emp for system_time as of timestamp @ts as ee, + ancestors as a where ee.mgr = a.emp_id - for system_time as of timestamp @ts ) select * from ancestors"; prepare stmt from @tmp; execute stmt; drop prepare stmt; @@ -111,10 +112,6 @@ with s1 as (select * from t1 for system_time as of timestamp @t0, t2) select * f --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; ---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; --echo ### VIEW instead of t1 set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'"); @@ -156,6 +153,36 @@ create or replace table t2 (x int, y int) with system versioning; insert into t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5); insert into t2 values (1, 2), (2, 1), (3, 1); +--echo ## Outer or inner SYSTEM_TIME produces same expression + +--disable_warnings +--disable_query_log +explain extended +select * from ( + select t1.x, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 join t2 on t1.x = t2.x) for system_time as of now() as t; + +let $a=`show warnings`; +--echo Query A: +echo $a; + +explain extended +select * from ( + select t1.x, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 for system_time as of now() + join t2 for system_time as of now() on t1.x = t2.x) as t; + +let $b=`show warnings`; +--echo Query B: +echo $b; + +if ($a == $b) +{ + --echo Fine result: queries A and B are equal. +} +--enable_query_log +--enable_warnings + --echo ## LEFT JOIN: t1, t2 versioned select * from ( select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 5646903dfb3..7d83eef9c72 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -849,8 +849,6 @@ expli_table_err: if (!expli_end && (res= sl->vers_push_field(thd, impli_table, impli_end))) goto exit; } - - sl->vers_check_clash= impli_table->vers_conditions; } } // if (sl->table_list.elements > 0) // System Versioning end diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 797c79ccc3d..099bf59b32b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2312,7 +2312,6 @@ void st_select_lex::init_select() curr_tvc_name= 0; in_tvc= false; vers_saved_where= NULL; - vers_check_clash= false; versioned_tables= 0; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2ac1eb499d2..c00ca301384 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1048,7 +1048,6 @@ public: private: Item *vers_saved_where; public: - bool vers_check_clash; uint versioned_tables; int vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr); /* push new Item_field into item_list */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 194bc29a472..cd6c7877354 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -797,17 +797,23 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr } } - SELECT_LEX *outer_slex= next_select_in_list(); - // propagate derived conditions to outer SELECT_LEX - if (outer_slex && vers_check_clash) + // find outer system_time + SELECT_LEX *outer_slex= outer_select(); + TABLE_LIST* outer_table= NULL; + + if (outer_slex) { - for (table= outer_slex->table_list.first; table; table= table->next_local) + TABLE_LIST* derived= master_unit()->derived; + // inner SELECT may not be a derived table (derived == NULL) + while (derived && outer_slex && !derived->vers_conditions) { - if (table->vers_conditions && !is_linkage_set()) - { - my_error(ER_VERS_SYSTEM_TIME_CLASH, MYF(0), table->alias); - DBUG_RETURN(-1); - } + derived= outer_slex->master_unit()->derived; + outer_slex= outer_slex->outer_select(); + } + if (derived && outer_slex) + { + DBUG_ASSERT(derived->vers_conditions); + outer_table= derived; } } @@ -821,20 +827,17 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr vers_select_conds_t &vers_conditions= table->vers_conditions; - // propagate system_time from nearest outer SELECT_LEX - if (!vers_conditions && outer_slex) + if (outer_table && table != outer_table) // inner table may be outer in recursive CTE { - TABLE_LIST* derived= master_unit()->derived; - // inner SELECT may not be a derived table (derived == NULL) - while (derived && outer_slex && !derived->vers_conditions) + if (vers_conditions) { - derived= outer_slex->master_unit()->derived; - outer_slex= outer_slex->next_select_in_list(); + my_error(ER_VERS_SYSTEM_TIME_CLASH, MYF(0), outer_table->alias); + DBUG_RETURN(-1); } - if (derived && outer_slex) + else { - DBUG_ASSERT(derived->vers_conditions); - vers_conditions= derived->vers_conditions; + // propagate system_time from nearest outer SELECT_LEX + vers_conditions= outer_table->vers_conditions; } } @@ -1022,6 +1025,9 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr this->where= *dst_cond; this->where->top_level_item(); } + + if (outer_table) + outer_table->vers_conditions.type= FOR_SYSTEM_TIME_ALL; } DBUG_RETURN(0);