From a0e137c4a9e8a86aeca2b56456f75e1278b7460c Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Tue, 12 Dec 2017 20:27:47 +0300 Subject: [PATCH] SQL: RIGHT JOIN in derived [fix #383] --- mysql-test/suite/versioning/r/derived.result | 78 ++++++++++++++++++++ mysql-test/suite/versioning/t/derived.test | 56 ++++++++++++++ sql/sql_select.cc | 39 ++++++---- sql/sql_select.h | 4 + 4 files changed, 163 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/versioning/r/derived.result b/mysql-test/suite/versioning/r/derived.result index 4e2e136d5bd..bc1176da175 100644 --- a/mysql-test/suite/versioning/r/derived.result +++ b/mysql-test/suite/versioning/r/derived.result @@ -215,5 +215,83 @@ select y from t2 for system_time as of @t1; x 1 10 +# LEFT/RIGHT JOIN +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); +## 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 +from t1 left join t2 on t1.x = t2.x) +as derived; +LJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +alter table t2 drop system versioning; +## LEFT JOIN: t1 versioned +select * from ( +select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 +from t1 left join t2 on t1.x = t2.x) +as derived; +LJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +alter table t1 drop system versioning; +alter table t2 add system versioning; +## LEFT JOIN: t2 versioned +select * from ( +select t1.x as LJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2 +from t1 left join t2 on t1.x = t2.x) +as derived; +LJ3_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +4 4 NULL NULL +5 5 NULL NULL +alter table t1 add system versioning; +## RIGHT JOIN: t1, t2 versioned +select * from ( +select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 +from t1 right join t2 on t1.x = t2.x) +as derived; +RJ1_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 +alter table t2 drop system versioning; +## RIGHT JOIN: t1 versioned +select * from ( +select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 +from t1 right join t2 on t1.x = t2.x) +as derived; +RJ2_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 +alter table t1 drop system versioning; +alter table t2 add system versioning; +## RIGHT JOIN: t2 versioned +select * from ( +select t1.x as RJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2 +from t1 right join t2 on t1.x = t2.x) +as derived; +RJ3_x1 y1 x2 y2 +1 1 1 2 +1 2 1 2 +1 3 1 2 +NULL NULL 2 1 +NULL NULL 3 1 drop table t1, t2; drop view vt1, vt2; diff --git a/mysql-test/suite/versioning/t/derived.test b/mysql-test/suite/versioning/t/derived.test index 5c9d0c18793..590f4bc9292 100644 --- a/mysql-test/suite/versioning/t/derived.test +++ b/mysql-test/suite/versioning/t/derived.test @@ -151,5 +151,61 @@ 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; +--echo # LEFT/RIGHT JOIN +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); + +--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 + from t1 left join t2 on t1.x = t2.x) +as derived; + +alter table t2 drop system versioning; + +--echo ## LEFT JOIN: t1 versioned +select * from ( + select t1.x as LJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 left join t2 on t1.x = t2.x) +as derived; + +alter table t1 drop system versioning; +alter table t2 add system versioning; + +--echo ## LEFT JOIN: t2 versioned +select * from ( + select t1.x as LJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 left join t2 on t1.x = t2.x) +as derived; + +alter table t1 add system versioning; + +--echo ## RIGHT JOIN: t1, t2 versioned +select * from ( + select t1.x as RJ1_x1, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 right join t2 on t1.x = t2.x) +as derived; + +alter table t2 drop system versioning; + +--echo ## RIGHT JOIN: t1 versioned +select * from ( + select t1.x as RJ2_x1, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 right join t2 on t1.x = t2.x) +as derived; + +alter table t1 drop system versioning; +alter table t2 add system versioning; + +--echo ## RIGHT JOIN: t2 versioned +select * from ( + select t1.x as RJ3_x1, t1.y as y1, t2.x as x2, t2.y as y2 + from t1 right join t2 on t1.x = t2.x) +as derived; + drop table t1, t2; drop view vt1, vt2; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e0e160b45aa..184cad22f67 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -818,6 +818,9 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr } } + COND** dst_cond= where_expr; + COND* vers_cond= NULL; + for (table= tables; table; table= table->next_local) { if (table->table && table->table->versioned()) @@ -869,7 +872,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr continue; } // if (vers_conditions) - COND** dst_cond= where_expr; if (table->on_expr) { dst_cond= &table->on_expr; @@ -888,7 +890,6 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr newx Item_field(thd, &this->context, table->db, table->alias, fstart); Item *row_end= newx Item_field(thd, &this->context, table->db, table->alias, fend); - Item *row_end2= row_end; bool tmp_from_ib= table->table->s->table_category == TABLE_CATEGORY_TEMPORARY && @@ -929,7 +930,7 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr else { curr= newx Item_int(thd, ULONGLONG_MAX); - cond1= newx Item_func_eq(thd, row_end2, curr); + cond1= newx Item_func_eq(thd, row_end, curr); } break; case FOR_SYSTEM_TIME_AS_OF: @@ -968,7 +969,7 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr { case FOR_SYSTEM_TIME_UNSPECIFIED: curr= newx Item_int(thd, ULONGLONG_MAX); - cond1= newx Item_func_eq(thd, row_end2, curr); + cond1= newx Item_func_eq(thd, row_end, curr); break; case FOR_SYSTEM_TIME_AS_OF: trx_id0= vers_conditions.unit_start == UNIT_TIMESTAMP ? @@ -1003,23 +1004,33 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr if (cond1) { - cond1= and_items(thd, - *dst_cond, + vers_cond= and_items(thd, + vers_cond, and_items(thd, cond2, cond1)); - - if (on_stmt_arena.arena_replaced()) - *dst_cond= cond1; - else - thd->change_item_tree(dst_cond, cond1); - - this->where= *dst_cond; - this->where->top_level_item(); + if (table->is_view_or_derived()) + vers_cond= or_items(thd, vers_cond, newx Item_func_isnull(thd, row_end)); } } // if (... table->table->versioned()) } // for (table= tables; ...) + if (vers_cond) + { + COND *all_cond= and_items(thd, *dst_cond, vers_cond); + bool from_where= dst_cond == where_expr; + if (on_stmt_arena.arena_replaced()) + *dst_cond= all_cond; + else + thd->change_item_tree(dst_cond, all_cond); + + if (from_where) + { + this->where= *dst_cond; + this->where->top_level_item(); + } + } + DBUG_RETURN(0); #undef newx } diff --git a/sql/sql_select.h b/sql/sql_select.h index 659bc4e7827..662047c02e3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2215,6 +2215,10 @@ inline Item * and_items(THD *thd, Item* cond, Item *item) { return (cond ? (new (thd->mem_root) Item_cond_and(thd, cond, item)) : item); } +inline Item * or_items(THD *thd, Item* cond, Item *item) +{ + return (cond ? (new (thd->mem_root) Item_cond_or(thd, cond, item)) : item); +} bool choose_plan(JOIN *join, table_map join_tables); void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab, table_map last_remaining_tables,