Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion mysql-test/main/join.result
Original file line number Diff line number Diff line change
Expand Up @@ -3969,6 +3969,8 @@ create table two (v int);
insert into two (v) values (2);
create table three (v int);
insert into three (v) values (3);
create table four (v int);
insert into three (v) values (4);
# (FULL)FULL to (INNER)INNER JOIN
select * from one full join two on one.v = two.v full join three on two.v = three.v where one.v is not null and two.v is not null and three.v is not null;
v v v
Expand Down Expand Up @@ -4006,9 +4008,11 @@ NULL 2 NULL
select * from one left join two on one.v = two.v full join three on two.v = three.v where three.v is not null;
v v v
NULL NULL 3
NULL NULL 4
select * from one left join two on one.v = two.v right join three on two.v = three.v;
v v v
NULL NULL 3
NULL NULL 4
# (LEFT)FULL to (LEFT)LEFT JOIN
insert into one (v) values (2),(3);
insert into two (v) values (1);
Expand All @@ -4032,5 +4036,65 @@ v v v
select * from three left join one on one.v = 1 left join two on two.v = 1;
v v v
1 1 1
drop table one, two, three;
# Interleaved JOIN checks
explain extended select * from one full outer join (two, three) on one.v=two.v;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE one UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE two UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three UNKNOWN NULL NULL NULL NULL 0 0.00
Warnings:
Note 1003 select `test`.`one`.`v` AS `v`,`test`.`two`.`v` AS `v`,`test`.`three`.`v` AS `v` from `test`.`one` full join (`test`.`two` join `test`.`three`) on(multiple equal(`test`.`one`.`v`, `test`.`two`.`v`))
# ^^^ join order must be one, two, three
explain extended select * from (one, two) full outer join three on one.v=two.v;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE one UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE two UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three UNKNOWN NULL NULL NULL NULL 0 0.00
Warnings:
Note 1003 select `test`.`one`.`v` AS `v`,`test`.`two`.`v` AS `v`,`test`.`three`.`v` AS `v` from `test`.`one` join `test`.`two` full join `test`.`three` on(multiple equal(`test`.`one`.`v`, `test`.`two`.`v`))
# ^^^ join order must be one, two, three
explain extended select * from one full outer join (three, two) on one.v=two.v;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE one UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE two UNKNOWN NULL NULL NULL NULL 0 0.00
Warnings:
Note 1003 select `test`.`one`.`v` AS `v`,`test`.`three`.`v` AS `v`,`test`.`two`.`v` AS `v` from `test`.`one` full join (`test`.`three` join `test`.`two`) on(multiple equal(`test`.`one`.`v`, `test`.`two`.`v`))
# ^^^ join order must be one, three, two
explain extended select * from (one, two t) full outer join (two v, three) on true;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE one UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE t UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE v UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three UNKNOWN NULL NULL NULL NULL 0 0.00
Warnings:
Note 1003 select `test`.`one`.`v` AS `v`,`test`.`t`.`v` AS `v`,`test`.`v`.`v` AS `v`,`test`.`three`.`v` AS `v` from `test`.`one` join `test`.`two` `t` full join (`test`.`two` `v` join `test`.`three`) on(1)
# ^^^ join order must be one, t, v, three
explain extended select * from (one full outer join two on true) full outer join (three full outer join four on true) on true;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE one UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE two UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE four UNKNOWN NULL NULL NULL NULL 0 0.00
Warnings:
Note 1003 select `test`.`one`.`v` AS `v`,`test`.`two`.`v` AS `v`,`test`.`three`.`v` AS `v`,`test`.`four`.`v` AS `v` from `test`.`one` full join `test`.`two` on(1) full join (`test`.`three` full join `test`.`four` on(1)) on(1)
# ^^^ join order must be one, two, three, four
explain extended select * from (one full outer join two on true) inner join (three full outer join four on true);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE one UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE two UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three system NULL NULL NULL NULL 1 100.00
1 SIMPLE four system NULL NULL NULL NULL 0 0.00 Const row not found
Warnings:
Note 1003 select `test`.`one`.`v` AS `v`,`test`.`two`.`v` AS `v`,1 AS `v`,NULL AS `v` from `test`.`one` full join `test`.`two` on(1)
# ^^^ join order must be one, two, three, four
explain extended select * from four full outer join (two full outer join three on true) on true;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE four system NULL NULL NULL NULL 0 0.00 Const row not found
1 SIMPLE two UNKNOWN NULL NULL NULL NULL 0 0.00
1 SIMPLE three UNKNOWN NULL NULL NULL NULL 0 0.00
Warnings:
Note 1003 select NULL AS `v`,`test`.`two`.`v` AS `v`,`test`.`three`.`v` AS `v` from (`test`.`two` full join `test`.`three` on(1))
# ^^^ join order must be four, two, three
drop table one, two, three, four;
# End of 12.3 tests
20 changes: 19 additions & 1 deletion mysql-test/main/join.test
Original file line number Diff line number Diff line change
Expand Up @@ -2187,6 +2187,8 @@ create table two (v int);
insert into two (v) values (2);
create table three (v int);
insert into three (v) values (3);
create table four (v int);
insert into three (v) values (4);

--echo # (FULL)FULL to (INNER)INNER JOIN
select * from one full join two on one.v = two.v full join three on two.v = three.v where one.v is not null and two.v is not null and three.v is not null;
Expand Down Expand Up @@ -2223,7 +2225,23 @@ select * from three;
select * from one left join two on one.v = two.v full join three on two.v = three.v where three.v = 1;
select * from three left join one on one.v = 1 left join two on two.v = 1;

drop table one, two, three;
--echo # Interleaved JOIN checks
explain extended select * from one full outer join (two, three) on one.v=two.v;
--echo # ^^^ join order must be one, two, three
explain extended select * from (one, two) full outer join three on one.v=two.v;
--echo # ^^^ join order must be one, two, three
explain extended select * from one full outer join (three, two) on one.v=two.v;
--echo # ^^^ join order must be one, three, two
explain extended select * from (one, two t) full outer join (two v, three) on true;
--echo # ^^^ join order must be one, t, v, three
explain extended select * from (one full outer join two on true) full outer join (three full outer join four on true) on true;
--echo # ^^^ join order must be one, two, three, four
explain extended select * from (one full outer join two on true) inner join (three full outer join four on true);
--echo # ^^^ join order must be one, two, three, four
explain extended select * from four full outer join (two full outer join three on true) on true;
--echo # ^^^ join order must be four, two, three

drop table one, two, three, four;

# TODO fix PS protocol before end of FULL OUTER JOIN development
--enable_ps_protocol
Expand Down
4 changes: 2 additions & 2 deletions sql/item_subselect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4722,7 +4722,7 @@ void subselect_union_engine::print(String *str, enum_query_type query_type)
void subselect_uniquesubquery_engine::print(String *str,
enum_query_type query_type)
{
TABLE *table= tab->tab_list ? tab->tab_list->table : tab->table;
TABLE *table= tab->get_tab_list() ? tab->get_tab_list()->table : tab->table;
str->append(STRING_WITH_LEN("<primary_index_lookup>("));
tab->ref.items[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" in "));
Expand Down Expand Up @@ -4775,7 +4775,7 @@ void subselect_uniquesubquery_engine::print(String *str)
void subselect_indexsubquery_engine::print(String *str,
enum_query_type query_type)
{
TABLE *table= tab->tab_list ? tab->tab_list->table : tab->table;
TABLE *table= tab->get_tab_list() ? tab->get_tab_list()->table : tab->table;
str->append(STRING_WITH_LEN("<index_lookup>("));
tab->ref.items[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" in "));
Expand Down
12 changes: 6 additions & 6 deletions sql/opt_hints.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,7 @@ bool Opt_hints_qb::set_join_hint_deps(JOIN *join,
bool hint_table_found= false;
for (uint i= 0; i < join->table_count; i++)
{
TABLE_LIST *table= join->join_tab[i].tab_list;
TABLE_LIST *table= join->join_tab[i].get_tab_list();
if (!compare_table_name(&tbl_name_and_qb, table))
{
hint_table_found= true;
Expand All @@ -1337,7 +1337,7 @@ bool Opt_hints_qb::set_join_hint_deps(JOIN *join,
// Hint tables are always dependent on preceding tables
join_tab->dependent |= hint_tab_map;
update_nested_join_deps(join, join_tab, hint_tab_map);
hint_tab_map |= join_tab->tab_list->get_map();
hint_tab_map |= join_tab->get_tab_list()->get_map();
break;
}
}
Expand All @@ -1356,7 +1356,7 @@ bool Opt_hints_qb::set_join_hint_deps(JOIN *join,
JOIN_TAB *join_tab= &join->join_tab[i];
const table_map dependent_tables=
get_other_dep(join, hint->hint_type, hint_tab_map,
join_tab->tab_list->get_map());
join_tab->get_tab_list()->get_map());
update_nested_join_deps(join, join_tab, dependent_tables);
join_tab->dependent |= dependent_tables;
}
Expand Down Expand Up @@ -1422,14 +1422,14 @@ bool Opt_hints_qb::set_join_hint_deps(JOIN *join,
void Opt_hints_qb::update_nested_join_deps(JOIN *join, const JOIN_TAB *hint_tab,
table_map hint_tab_map)
{
const TABLE_LIST *table= hint_tab->tab_list;
const TABLE_LIST *table= hint_tab->get_tab_list();
if (table->embedding)
{
for (uint i= 0; i < join->table_count; i++)
{
JOIN_TAB *tab= &join->join_tab[i];
/* Walk up the nested joins that tab->table is a part of */
for (TABLE_LIST *emb= tab->tab_list->embedding; emb; emb=emb->embedding)
for (TABLE_LIST *emb= tab->get_tab_list()->embedding; emb; emb=emb->embedding)
{
/*
Apply the rule only for outer joins. Semi-joins do not impose such
Expand All @@ -1439,7 +1439,7 @@ void Opt_hints_qb::update_nested_join_deps(JOIN *join, const JOIN_TAB *hint_tab,
{
const NESTED_JOIN *const nested_join= emb->nested_join;
/* Is hint_tab somewhere inside this nested join, too? */
if (hint_tab->embedding_map & nested_join->nj_map)
if (hint_tab->embedding_map & nested_join->get_nj_map())
{
/*
Yes, it is. Then, tab->table be also dependent on all outside
Expand Down
2 changes: 1 addition & 1 deletion sql/opt_trace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ void trace_plan_prefix(Json_writer_object *jsobj, JOIN *join, uint idx,
prefix_str.length(0);
for (uint i= join->const_tables; i < idx; i++)
{
TABLE_LIST *const tr= join->positions[i].table->tab_list;
TABLE_LIST *const tr= join->positions[i].table->get_tab_list();
if (!(tr->map & join_tables))
{
String str;
Expand Down
2 changes: 2 additions & 0 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8346,6 +8346,8 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
if (prev_join_using)
ptr->join_using_fields= prev_join_using;
}
if (table->outer_join & JOIN_TYPE_FULL)
nested_join->is_foj= true;
}
nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
DBUG_RETURN(ptr);
Expand Down
Loading
Loading