Skip to content

Commit d6c2697

Browse files
MDEV-37995: FULL OUTER JOIN name resolution
Allow FULL OUTER JOIN queries to proceed through name resolution. Permits limited EXPLAIN EXTENDED support so tests can prove that the JOIN_TYPE_* table markings are reflected when the query is echoed back by the server. This happens in at least two places: via a Warning message during EXPLAIN EXTENDED and during VIEW .frm file creation. While the query plan output is mostly meaningless at this point, this limited EXPLAIN support improves the SELECT_LEX print function for the new JOIN types.
1 parent 1fa730f commit d6c2697

File tree

7 files changed

+205
-19
lines changed

7 files changed

+205
-19
lines changed

mysql-test/main/join.result

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3667,17 +3667,117 @@ create table t2 (a int);
36673667
insert into t2 (a) values (1),(2),(3);
36683668
select * from t1 full join t2 on t1.a = t2.a;
36693669
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3670+
explain extended select * from t1 full join t2 on t1.a = t2.a;
3671+
id select_type table type possible_keys key key_len ref rows filtered Extra
3672+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3673+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3674+
Warnings:
3675+
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` full join `test`.`t2` on(multiple equal(`test`.`t1`.`a`, `test`.`t2`.`a`))
36703676
select * from t1 full outer join t2 on t1.a = t2.a;
36713677
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3678+
explain extended select * from t1 full outer join t2 on t1.a = t2.a;
3679+
id select_type table type possible_keys key key_len ref rows filtered Extra
3680+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3681+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3682+
Warnings:
3683+
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` full join `test`.`t2` on(multiple equal(`test`.`t1`.`a`, `test`.`t2`.`a`))
36723684
select * from t1 natural full outer join t2;
36733685
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3686+
explain extended select * from t1 natural full outer join t2;
3687+
id select_type table type possible_keys key key_len ref rows filtered Extra
3688+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3689+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3690+
Warnings:
3691+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2`
36743692
select * from t1 natural full join t2;
36753693
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3694+
explain extended select * from t1 natural full join t2;
3695+
id select_type table type possible_keys key key_len ref rows filtered Extra
3696+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3697+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3698+
Warnings:
3699+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2`
3700+
create view v1 as select * from t1 full join t2 on t1.a = t2.a;
3701+
select * from v1;
3702+
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3703+
explain extended select * from v1;
3704+
id select_type table type possible_keys key key_len ref rows filtered Extra
3705+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3706+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3707+
Warnings:
3708+
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` full join `test`.`t2` on(multiple equal(`test`.`t1`.`a`, `test`.`t2`.`a`))
3709+
drop view v1;
36763710
create view v1 as select * from t1 full outer join t2 on t1.a = t2.a;
3711+
select * from v1;
3712+
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3713+
explain extended select * from v1;
3714+
id select_type table type possible_keys key key_len ref rows filtered Extra
3715+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3716+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3717+
Warnings:
3718+
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t1` full join `test`.`t2` on(multiple equal(`test`.`t1`.`a`, `test`.`t2`.`a`))
3719+
drop view v1;
3720+
create view v1 as select * from t1 natural full join t2;
3721+
select * from v1;
3722+
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3723+
explain extended select * from v1;
3724+
id select_type table type possible_keys key key_len ref rows filtered Extra
3725+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3726+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3727+
Warnings:
3728+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2`
3729+
drop view v1;
3730+
create view v1 as select * from t1 natural full outer join t2;
3731+
select * from v1;
36773732
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3733+
explain extended select * from v1;
3734+
id select_type table type possible_keys key key_len ref rows filtered Extra
3735+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3736+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3737+
Warnings:
3738+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2`
3739+
drop view v1;
3740+
select * from (select t1.a from t1 full join t2 on t1.a = t2.a union select * from t1) dt;
3741+
ERROR 42S22: Unknown column 't1.a' in 'SELECT'
36783742
select * from (select t1.a from t1 full outer join t2 on t1.a = t2.a union select * from t1) dt;
3743+
ERROR 42S22: Unknown column 't1.a' in 'SELECT'
3744+
select * from (select t1.a from t1 natural full join t2 union select * from t1) dt;
3745+
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3746+
explain extended select * from (select t1.a from t1 natural full join t2 union select * from t1) dt;
3747+
id select_type table type possible_keys key key_len ref rows filtered Extra
3748+
1 PRIMARY <derived2> UNKNOWN NULL NULL NULL NULL 0 0.00
3749+
2 DERIVED t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3750+
2 DERIVED t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3751+
3 UNION t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3752+
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
3753+
Warnings:
3754+
Note 1003 /* select#1 */ select `dt`.`a` AS `a` from (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2` union /* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1`) `dt`
3755+
select * from (select t1.a from t1 natural full outer join t2 union select * from t1) dt;
36793756
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3757+
explain extended select * from (select t1.a from t1 natural full outer join t2 union select * from t1) dt;
3758+
id select_type table type possible_keys key key_len ref rows filtered Extra
3759+
1 PRIMARY <derived2> UNKNOWN NULL NULL NULL NULL 0 0.00
3760+
2 DERIVED t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3761+
2 DERIVED t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3762+
3 UNION t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3763+
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
3764+
Warnings:
3765+
Note 1003 /* select#1 */ select `dt`.`a` AS `a` from (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2` union /* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1`) `dt`
36803766
with cte as (select t1.a from t1 natural full join t2) select * from cte;
36813767
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
3768+
explain extended with cte as (select t1.a from t1 natural full join t2) select * from cte;
3769+
id select_type table type possible_keys key key_len ref rows filtered Extra
3770+
1 SIMPLE t1 UNKNOWN NULL NULL NULL NULL 0 0.00
3771+
1 SIMPLE t2 UNKNOWN NULL NULL NULL NULL 0 0.00
3772+
Warnings:
3773+
Note 1003 with cte as (select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2`)select `test`.`t1`.`a` AS `a` from `test`.`t1` natural full join `test`.`t2`
3774+
select * from t1, t2 full join t3 on t2.c=t3.e and t3.f=t1.a;
3775+
ERROR 42S02: Table 'test.t3' doesn't exist
3776+
select * from t1, t2 full outer join t3 on t2.c=t3.e and t3.f=t1.a;
3777+
ERROR 42S02: Table 'test.t3' doesn't exist
3778+
select * from t1, t2 natural full join t3;
3779+
ERROR 42S02: Table 'test.t3' doesn't exist
3780+
select * from t1, t2 natural full outer join t3;
3781+
ERROR 42S02: Table 'test.t3' doesn't exist
36823782
drop table t1, t2;
36833783
# End of 12.3 tests

mysql-test/main/join.test

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,21 +2055,79 @@ create table t1 (a int);
20552055
insert into t1 (a) values (1),(2),(3);
20562056
create table t2 (a int);
20572057
insert into t2 (a) values (1),(2),(3);
2058-
# This test only verifies syntax acceptance.
2058+
# TODO fix PS protocol before end of FULL OUTER JOIN development
2059+
--disable_ps_protocol
20592060
--error ER_NOT_SUPPORTED_YET
20602061
select * from t1 full join t2 on t1.a = t2.a;
2062+
explain extended select * from t1 full join t2 on t1.a = t2.a;
2063+
20612064
--error ER_NOT_SUPPORTED_YET
20622065
select * from t1 full outer join t2 on t1.a = t2.a;
2066+
explain extended select * from t1 full outer join t2 on t1.a = t2.a;
2067+
20632068
--error ER_NOT_SUPPORTED_YET
20642069
select * from t1 natural full outer join t2;
2070+
explain extended select * from t1 natural full outer join t2;
2071+
20652072
--error ER_NOT_SUPPORTED_YET
20662073
select * from t1 natural full join t2;
2074+
explain extended select * from t1 natural full join t2;
2075+
2076+
create view v1 as select * from t1 full join t2 on t1.a = t2.a;
20672077
--error ER_NOT_SUPPORTED_YET
2078+
select * from v1;
2079+
explain extended select * from v1;
2080+
drop view v1;
2081+
20682082
create view v1 as select * from t1 full outer join t2 on t1.a = t2.a;
20692083
--error ER_NOT_SUPPORTED_YET
2084+
select * from v1;
2085+
explain extended select * from v1;
2086+
drop view v1;
2087+
2088+
create view v1 as select * from t1 natural full join t2;
2089+
--error ER_NOT_SUPPORTED_YET
2090+
select * from v1;
2091+
explain extended select * from v1;
2092+
drop view v1;
2093+
2094+
create view v1 as select * from t1 natural full outer join t2;
2095+
--error ER_NOT_SUPPORTED_YET
2096+
select * from v1;
2097+
explain extended select * from v1;
2098+
drop view v1;
2099+
2100+
--error ER_BAD_FIELD_ERROR
2101+
select * from (select t1.a from t1 full join t2 on t1.a = t2.a union select * from t1) dt;
2102+
2103+
--error ER_BAD_FIELD_ERROR
20702104
select * from (select t1.a from t1 full outer join t2 on t1.a = t2.a union select * from t1) dt;
2105+
2106+
--error ER_NOT_SUPPORTED_YET
2107+
select * from (select t1.a from t1 natural full join t2 union select * from t1) dt;
2108+
explain extended select * from (select t1.a from t1 natural full join t2 union select * from t1) dt;
2109+
2110+
--error ER_NOT_SUPPORTED_YET
2111+
select * from (select t1.a from t1 natural full outer join t2 union select * from t1) dt;
2112+
explain extended select * from (select t1.a from t1 natural full outer join t2 union select * from t1) dt;
2113+
20712114
--error ER_NOT_SUPPORTED_YET
20722115
with cte as (select t1.a from t1 natural full join t2) select * from cte;
2073-
drop table t1, t2;
2116+
explain extended with cte as (select t1.a from t1 natural full join t2) select * from cte;
2117+
2118+
--error ER_NO_SUCH_TABLE
2119+
select * from t1, t2 full join t3 on t2.c=t3.e and t3.f=t1.a;
2120+
2121+
--error ER_NO_SUCH_TABLE
2122+
select * from t1, t2 full outer join t3 on t2.c=t3.e and t3.f=t1.a;
20742123

2124+
--error ER_NO_SUCH_TABLE
2125+
select * from t1, t2 natural full join t3;
2126+
2127+
--error ER_NO_SUCH_TABLE
2128+
select * from t1, t2 natural full outer join t3;
2129+
2130+
drop table t1, t2;
2131+
# TODO fix PS protocol before end of FULL OUTER JOIN development
2132+
--enable_ps_protocol
20752133
--echo # End of 12.3 tests

sql/sql_parse.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10305,11 +10305,6 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
1030510305
bool mysql_parse_status= thd->variables.sql_mode & MODE_ORACLE
1030610306
? ORAparse(thd) : MYSQLparse(thd);
1030710307

10308-
/* While we accept full join syntax, such joins are not yet supported. */
10309-
mysql_parse_status|= thd->lex->has_full_outer_join;
10310-
if (thd->lex->has_full_outer_join)
10311-
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "full join");
10312-
1031310308
if (mysql_parse_status)
1031410309
/*
1031510310
Restore the original LEX if it was replaced when parsing

sql/sql_select.cc

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,18 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
18941894
goto err;
18951895
prepared= true;
18961896

1897+
/*
1898+
This check gates FULL JOIN functionality while it is under
1899+
development. This check will be removed once FULL JOIN
1900+
has been completed and it allows some aspects of FULL JOIN
1901+
(see below) while exluding others, driven by whatever has
1902+
been implemented up to this point.
1903+
*/
1904+
if (thd->lex->has_full_outer_join && // FULL JOIN not yet supported...
1905+
!thd->lex->is_view_context_analysis() && // ...but allow VIEW creation...
1906+
!thd->lex->describe) // ...and limited EXPLAIN support during development
1907+
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "full join");
1908+
18971909
DBUG_RETURN(0); // All OK
18981910

18991911
err:
@@ -2767,7 +2779,13 @@ JOIN::optimize_inner()
27672779
with_two_phase_optimization= check_two_phase_optimization(thd);
27682780
if (with_two_phase_optimization)
27692781
optimization_state= JOIN::OPTIMIZATION_PHASE_1_DONE;
2770-
else
2782+
/*
2783+
Only during the FULL JOIN development cycle, disable second stage
2784+
optimization for FULL JOIN queries until the implementation is
2785+
mature enough to correctly execute the queries. But for now
2786+
this allows for some EXPLAIN EXTENDED support.
2787+
*/
2788+
else if (!thd->lex->has_full_outer_join)
27712789
{
27722790
if (optimize_stage2())
27732791
DBUG_RETURN(1);
@@ -31710,8 +31728,13 @@ static void print_table_array(THD *thd,
3171031728
continue;
3171131729
}
3171231730

31713-
/* JOIN_TYPE_OUTER is just a marker unrelated to real join */
31714-
if (curr->outer_join & (JOIN_TYPE_LEFT|JOIN_TYPE_RIGHT))
31731+
if (curr->outer_join & JOIN_TYPE_FULL)
31732+
{
31733+
if (curr->outer_join & JOIN_TYPE_NATURAL)
31734+
str->append(STRING_WITH_LEN(" natural"));
31735+
str->append(STRING_WITH_LEN(" full join "));
31736+
}
31737+
else if (curr->outer_join & (JOIN_TYPE_LEFT|JOIN_TYPE_RIGHT))
3171531738
{
3171631739
/* MySQL converts right to left joins */
3171731740
str->append(STRING_WITH_LEN(" left join "));
@@ -31722,9 +31745,15 @@ static void print_table_array(THD *thd,
3172231745
str->append(STRING_WITH_LEN(" semi join "));
3172331746
else
3172431747
str->append(STRING_WITH_LEN(" join "));
31725-
31748+
3172631749
curr->print(thd, eliminated_tables, str, query_type);
31727-
if (curr->on_expr)
31750+
/*
31751+
NATURAL JOINs don't expose explicit join columns, so don't
31752+
print them as they're considered invalid syntax (this is
31753+
important for VIEWs as when VIEWs are loaded, their SQL
31754+
syntax is parsed again and must be valid).
31755+
*/
31756+
if (curr->on_expr && !(curr->outer_join & JOIN_TYPE_NATURAL))
3172831757
{
3172931758
str->append(STRING_WITH_LEN(" on("));
3173031759
curr->on_expr->print(str, query_type);

sql/sql_view.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *view_table_alias,
19091909
DBUG_ASSERT(view_query_lex == thd->lex);
19101910
thd->lex= parent_query_lex; // Needed for prepare_security
19111911
result= !view_table_alias->prelocking_placeholder && view_table_alias->prepare_security(thd);
1912+
parent_query_lex->has_full_outer_join= view_query_lex->has_full_outer_join;
19121913

19131914
lex_end(view_query_lex);
19141915
end:

sql/sql_yacc.yy

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12387,7 +12387,7 @@ join_table:
1238712387
}
1238812388
expr
1238912389
{
12390-
add_join_on(thd, $1, $8);
12390+
add_join_on(thd, $5, $8);
1239112391
$1->on_context= Lex->pop_context();
1239212392
Select->parsing_place= NO_MATTER;
1239312393
$$= $1;
@@ -12415,11 +12415,13 @@ join_table:
1241512415

1241612416
Select->add_joined_table($1);
1241712417
$1->outer_join|= (JOIN_TYPE_LEFT |
12418-
JOIN_TYPE_FULL);
12418+
JOIN_TYPE_FULL |
12419+
JOIN_TYPE_NATURAL);
1241912420

1242012421
Select->add_joined_table($6);
1242112422
$6->outer_join|= (JOIN_TYPE_RIGHT |
12422-
JOIN_TYPE_FULL);
12423+
JOIN_TYPE_FULL |
12424+
JOIN_TYPE_NATURAL);
1242312425

1242412426
add_join_natural($6,$1,NULL,Select);
1242512427
Lex->has_full_outer_join= true;

sql/table.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,10 +2212,11 @@ class IS_table_read_plan;
22122212
#define VIEW_ALGORITHM_MERGE_FRM 1U
22132213
#define VIEW_ALGORITHM_TMPTABLE_FRM 2U
22142214

2215-
#define JOIN_TYPE_LEFT 1U
2216-
#define JOIN_TYPE_RIGHT 2U
2217-
#define JOIN_TYPE_FULL 4U
2218-
#define JOIN_TYPE_OUTER 8U /* Marker that this is an outer join */
2215+
#define JOIN_TYPE_LEFT 1U
2216+
#define JOIN_TYPE_RIGHT 2U
2217+
#define JOIN_TYPE_FULL 4U
2218+
#define JOIN_TYPE_OUTER 8U /* Marker that this is an outer join */
2219+
#define JOIN_TYPE_NATURAL 16U
22192220

22202221
/* view WITH CHECK OPTION parameter options */
22212222
#define VIEW_CHECK_NONE 0

0 commit comments

Comments
 (0)