From f08b8fd58d6ef7d08d7e5a1956da0a4c9ff3a031 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Fri, 27 Apr 2018 18:09:05 +0300 Subject: [PATCH] MDEV-15980 FOR SYSTEM_TIME BETWEEN and FROM .. TO work with negative intervals Fixed by using exactly the same filtering conditions as specified by standard in 7.6 General Rules --- mysql-test/suite/versioning/r/select.result | 24 +++++++++++ mysql-test/suite/versioning/t/select.test | 20 +++++++++ sql/sql_select.cc | 46 ++++++++++++--------- 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/mysql-test/suite/versioning/r/select.result b/mysql-test/suite/versioning/r/select.result index 4d0c529bdb3..75f9fc25263 100644 --- a/mysql-test/suite/versioning/r/select.result +++ b/mysql-test/suite/versioning/r/select.result @@ -512,6 +512,30 @@ Warnings: Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` FOR SYSTEM_TIME ALL join `test`.`t2` left join (`test`.`t3` left join `test`.`t4` FOR SYSTEM_TIME ALL on(`test`.`t4`.`f4` = `test`.`t2`.`f2` and `test`.`t4`.`row_end` = TIMESTAMP'2038-01-19 03:14:07.999999')) on(`test`.`t3`.`f3` = `test`.`t2`.`f2`) where `test`.`t1`.`row_end` = TIMESTAMP'2038-01-19 03:14:07.999999' drop view v1; drop table t1, t2, t3, t4; +# +# MDEV-15980 FOR SYSTEM_TIME BETWEEN and FROM .. TO work with negative intervals +# +create or replace table t1 ( +a int, +row_start SYS_DATATYPE as row start invisible, +row_end SYS_DATATYPE as row end invisible, +period for system_time (row_start, row_end) +) with system versioning; +insert into t1 values (1); +delete from t1; +select row_start from t1 for system_time all into @t1; +select row_end from t1 for system_time all into @t2; +select * from t1 for system_time between @t1 and @t2; +a +1 +select * from t1 for system_time between @t2 and @t1; +a +select * from t1 for system_time from @t1 to @t2; +a +1 +select * from t1 for system_time from @t2 to @t1; +a +drop table t1; call verify_trt_dummy(34); No A B C D 1 1 1 1 1 diff --git a/mysql-test/suite/versioning/t/select.test b/mysql-test/suite/versioning/t/select.test index 590384b6fd4..8d2c5f69e2c 100644 --- a/mysql-test/suite/versioning/t/select.test +++ b/mysql-test/suite/versioning/t/select.test @@ -326,6 +326,26 @@ select f1 from t1 join t2 left join t3 left join t4 on f3 = f4 on f3 = f2; drop view v1; drop table t1, t2, t3, t4; +--echo # +--echo # MDEV-15980 FOR SYSTEM_TIME BETWEEN and FROM .. TO work with negative intervals +--echo # +--replace_result $sys_datatype_expl SYS_DATATYPE +eval create or replace table t1 ( + a int, + row_start $sys_datatype_expl as row start invisible, + row_end $sys_datatype_expl as row end invisible, + period for system_time (row_start, row_end) +) with system versioning; +insert into t1 values (1); +delete from t1; +select row_start from t1 for system_time all into @t1; +select row_end from t1 for system_time all into @t2; +select * from t1 for system_time between @t1 and @t2; +select * from t1 for system_time between @t2 and @t1; +select * from t1 for system_time from @t1 to @t2; +select * from t1 for system_time from @t2 to @t1; +drop table t1; + call verify_trt_dummy(34); -- source suite/versioning/common_finish.inc diff --git a/sql/sql_select.cc b/sql/sql_select.cc index dc6f8aedd9b..2728bae429a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -848,10 +848,9 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) } } - Item *cond1= 0, *cond2= 0, *curr= 0; - // Temporary tables of can be created from INNODB tables and thus will - // have uint64 type of sys_trx_(start|end) field. - // They need special handling. + Item *cond1= NULL, *cond2= NULL, *cond3= NULL, *curr= NULL; + Item *point_in_time1= vers_conditions.start.item; + Item *point_in_time2= vers_conditions.end.item; TABLE *t= table->table; if (t->versioned(VERS_TIMESTAMP)) { @@ -865,19 +864,21 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) cond1= newx Item_func_eq(thd, row_end, curr); break; case SYSTEM_TIME_AS_OF: - cond1= newx Item_func_le(thd, row_start, vers_conditions.start.item); - cond2= newx Item_func_gt(thd, row_end, vers_conditions.start.item); + cond1= newx Item_func_le(thd, row_start, point_in_time1); + cond2= newx Item_func_gt(thd, row_end, point_in_time1); break; case SYSTEM_TIME_FROM_TO: - cond1= newx Item_func_lt(thd, row_start, vers_conditions.end.item); - cond2= newx Item_func_ge(thd, row_end, vers_conditions.start.item); + cond1= newx Item_func_lt(thd, row_start, point_in_time2); + cond2= newx Item_func_gt(thd, row_end, point_in_time1); + cond3= newx Item_func_lt(thd, point_in_time1, point_in_time2); break; case SYSTEM_TIME_BETWEEN: - cond1= newx Item_func_le(thd, row_start, vers_conditions.end.item); - cond2= newx Item_func_ge(thd, row_end, vers_conditions.start.item); + cond1= newx Item_func_le(thd, row_start, point_in_time2); + cond2= newx Item_func_gt(thd, row_end, point_in_time1); + cond3= newx Item_func_le(thd, point_in_time1, point_in_time2); break; case SYSTEM_TIME_BEFORE: - cond1= newx Item_func_lt(thd, row_end, vers_conditions.start.item); + cond1= newx Item_func_lt(thd, row_end, point_in_time1); break; default: DBUG_ASSERT(0); @@ -897,29 +898,33 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) break; case SYSTEM_TIME_AS_OF: trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP - ? newx Item_func_trt_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID) - : vers_conditions.start.item; + ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID) + : point_in_time1; cond1= newx Item_func_trt_trx_sees_eq(thd, trx_id0, row_start); cond2= newx Item_func_trt_trx_sees(thd, row_end, trx_id0); break; case SYSTEM_TIME_FROM_TO: + cond3= newx Item_func_lt(thd, point_in_time1, point_in_time2); + /* fall through */ case SYSTEM_TIME_BETWEEN: trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP - ? newx Item_func_trt_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID, true) - : vers_conditions.start.item; + ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID, true) + : point_in_time1; trx_id1= vers_conditions.end.unit == VERS_TIMESTAMP - ? newx Item_func_trt_id(thd, vers_conditions.end.item, TR_table::FLD_TRX_ID, false) - : vers_conditions.end.item; + ? newx Item_func_trt_id(thd, point_in_time2, TR_table::FLD_TRX_ID, false) + : point_in_time2; cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO ? newx Item_func_trt_trx_sees(thd, trx_id1, row_start) : newx Item_func_trt_trx_sees_eq(thd, trx_id1, row_start); cond2= newx Item_func_trt_trx_sees_eq(thd, row_end, trx_id0); + if (!cond3) + cond3= newx Item_func_le(thd, point_in_time1, point_in_time2); break; case SYSTEM_TIME_BEFORE: trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP - ? newx Item_func_trt_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID) - : vers_conditions.start.item; - cond1= newx Item_func_lt(thd, row_end, trx_id0); + ? newx Item_func_trt_id(thd, point_in_time1, TR_table::FLD_TRX_ID, true) + : point_in_time1; + cond1= newx Item_func_trt_trx_sees(thd, trx_id0, row_end); break; default: DBUG_ASSERT(0); @@ -929,6 +934,7 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables) if (cond1) { cond1= and_items(thd, cond2, cond1); + cond1= and_items(thd, cond3, cond1); table->on_expr= and_items(thd, table->on_expr, cond1); }