mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
SQL: inner/outer system_time consistency [fixes #384]
This commit is contained in:
@ -96,9 +96,10 @@ where name = 'bill'
|
|||||||
for system_time as of timestamp @ts
|
for system_time as of timestamp @ts
|
||||||
union
|
union
|
||||||
select ee.emp_id, ee.name, ee.mgr
|
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
|
where ee.mgr = a.emp_id
|
||||||
for system_time as of timestamp @ts
|
|
||||||
)
|
)
|
||||||
select * from ancestors;
|
select * from ancestors;
|
||||||
emp_id name mgr
|
emp_id name mgr
|
||||||
@ -116,9 +117,9 @@ as
|
|||||||
for system_time as of timestamp @ts
|
for system_time as of timestamp @ts
|
||||||
union
|
union
|
||||||
select ee.emp_id, ee.name, ee.mgr
|
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
|
where ee.mgr = a.emp_id
|
||||||
for system_time as of timestamp @ts
|
|
||||||
)
|
)
|
||||||
select * from ancestors";
|
select * from ancestors";
|
||||||
prepare stmt from @tmp;
|
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;
|
with s3 as (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) select * from s3;
|
||||||
y x
|
y x
|
||||||
10 1
|
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
|
### VIEW instead of t1
|
||||||
set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'");
|
set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'");
|
||||||
prepare q from @q;
|
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;
|
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 t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
|
||||||
insert into t2 values (1, 2), (2, 1), (3, 1);
|
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` > <cache>(current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= <cache>(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` > <cache>(current_timestamp(6)) and `test`.`t1`.`sys_trx_start` <= <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_end` > <cache>(current_timestamp(6)) and `test`.`t2`.`sys_trx_start` <= <cache>(current_timestamp(6))
|
||||||
|
Fine result: queries A and B are equal.
|
||||||
## LEFT JOIN: t1, t2 versioned
|
## LEFT JOIN: t1, t2 versioned
|
||||||
select * from (
|
select * from (
|
||||||
select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
|
select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
|
||||||
|
@ -67,9 +67,10 @@ as
|
|||||||
for system_time as of timestamp @ts
|
for system_time as of timestamp @ts
|
||||||
union
|
union
|
||||||
select ee.emp_id, ee.name, ee.mgr
|
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
|
where ee.mgr = a.emp_id
|
||||||
for system_time as of timestamp @ts
|
|
||||||
)
|
)
|
||||||
select * from ancestors;
|
select * from ancestors;
|
||||||
set @tmp= "
|
set @tmp= "
|
||||||
@ -83,9 +84,9 @@ as
|
|||||||
for system_time as of timestamp @ts
|
for system_time as of timestamp @ts
|
||||||
union
|
union
|
||||||
select ee.emp_id, ee.name, ee.mgr
|
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
|
where ee.mgr = a.emp_id
|
||||||
for system_time as of timestamp @ts
|
|
||||||
)
|
)
|
||||||
select * from ancestors";
|
select * from ancestors";
|
||||||
prepare stmt from @tmp; execute stmt; drop prepare stmt;
|
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
|
--echo # leading table selection
|
||||||
select * from (select *, t1.sys_trx_end from t2, t1 for system_time as of timestamp @t0) as s2;
|
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;
|
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
|
--echo ### VIEW instead of t1
|
||||||
set @q= concat("create view vt1 as select * from t1 for system_time as of timestamp '", @t0, "'");
|
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 t1 values (1, 1), (1, 2), (1, 3), (4, 4), (5, 5);
|
||||||
insert into t2 values (1, 2), (2, 1), (3, 1);
|
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
|
--echo ## LEFT JOIN: t1, t2 versioned
|
||||||
select * from (
|
select * from (
|
||||||
select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
|
select t1.x as LJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2
|
||||||
|
@ -849,8 +849,6 @@ expli_table_err:
|
|||||||
if (!expli_end && (res= sl->vers_push_field(thd, impli_table, impli_end)))
|
if (!expli_end && (res= sl->vers_push_field(thd, impli_table, impli_end)))
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
sl->vers_check_clash= impli_table->vers_conditions;
|
|
||||||
}
|
}
|
||||||
} // if (sl->table_list.elements > 0)
|
} // if (sl->table_list.elements > 0)
|
||||||
// System Versioning end
|
// System Versioning end
|
||||||
|
@ -2312,7 +2312,6 @@ void st_select_lex::init_select()
|
|||||||
curr_tvc_name= 0;
|
curr_tvc_name= 0;
|
||||||
in_tvc= false;
|
in_tvc= false;
|
||||||
vers_saved_where= NULL;
|
vers_saved_where= NULL;
|
||||||
vers_check_clash= false;
|
|
||||||
versioned_tables= 0;
|
versioned_tables= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1048,7 +1048,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
Item *vers_saved_where;
|
Item *vers_saved_where;
|
||||||
public:
|
public:
|
||||||
bool vers_check_clash;
|
|
||||||
uint versioned_tables;
|
uint versioned_tables;
|
||||||
int vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr);
|
int vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr);
|
||||||
/* push new Item_field into item_list */
|
/* push new Item_field into item_list */
|
||||||
|
@ -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();
|
// find outer system_time
|
||||||
// propagate derived conditions to outer SELECT_LEX
|
SELECT_LEX *outer_slex= outer_select();
|
||||||
if (outer_slex && vers_check_clash)
|
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())
|
derived= outer_slex->master_unit()->derived;
|
||||||
{
|
outer_slex= outer_slex->outer_select();
|
||||||
my_error(ER_VERS_SYSTEM_TIME_CLASH, MYF(0), table->alias);
|
}
|
||||||
DBUG_RETURN(-1);
|
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;
|
vers_select_conds_t &vers_conditions= table->vers_conditions;
|
||||||
|
|
||||||
// propagate system_time from nearest outer SELECT_LEX
|
if (outer_table && table != outer_table) // inner table may be outer in recursive CTE
|
||||||
if (!vers_conditions && outer_slex)
|
|
||||||
{
|
{
|
||||||
TABLE_LIST* derived= master_unit()->derived;
|
if (vers_conditions)
|
||||||
// inner SELECT may not be a derived table (derived == NULL)
|
|
||||||
while (derived && outer_slex && !derived->vers_conditions)
|
|
||||||
{
|
{
|
||||||
derived= outer_slex->master_unit()->derived;
|
my_error(ER_VERS_SYSTEM_TIME_CLASH, MYF(0), outer_table->alias);
|
||||||
outer_slex= outer_slex->next_select_in_list();
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
if (derived && outer_slex)
|
else
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(derived->vers_conditions);
|
// propagate system_time from nearest outer SELECT_LEX
|
||||||
vers_conditions= derived->vers_conditions;
|
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= *dst_cond;
|
||||||
this->where->top_level_item();
|
this->where->top_level_item();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (outer_table)
|
||||||
|
outer_table->vers_conditions.type= FOR_SYSTEM_TIME_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
Reference in New Issue
Block a user