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
24 changes: 24 additions & 0 deletions mysql-test/main/join.result
Original file line number Diff line number Diff line change
Expand Up @@ -3657,3 +3657,27 @@ DROP TABLE t1,t2,t3;
#
# End of 11.0 tests
#
#
# MDEV-37932: FULL OUTER JOIN: Make the parser support FULL OUTER JOIN
# syntax
#
create table t1 (a int);
insert into t1 (a) values (1),(2),(3);
create table t2 (a int);
insert into t2 (a) values (1),(2),(3);
select * from t1 full join t2 on t1.a = t2.a;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
select * from t1 full outer join t2 on t1.a = t2.a;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
select * from t1 natural full outer join t2;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
select * from t1 natural full join t2;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
create view v1 as select * from t1 full outer join t2 on t1.a = t2.a;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
select * from (select t1.a from t1 full outer join t2 on t1.a = t2.a union select * from t1) dt;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
with cte as (select t1.a from t1 natural full join t2) select * from cte;
ERROR 42000: This version of MariaDB doesn't yet support 'full join'
drop table t1, t2;
# End of 12.3 tests
27 changes: 27 additions & 0 deletions mysql-test/main/join.test
Original file line number Diff line number Diff line change
Expand Up @@ -2046,3 +2046,30 @@ DROP TABLE t1,t2,t3;
--echo #
--echo # End of 11.0 tests
--echo #

--echo #
--echo # MDEV-37932: FULL OUTER JOIN: Make the parser support FULL OUTER JOIN
--echo # syntax
--echo #
create table t1 (a int);
insert into t1 (a) values (1),(2),(3);
create table t2 (a int);
insert into t2 (a) values (1),(2),(3);
# This test only verifies syntax acceptance.
--error ER_NOT_SUPPORTED_YET
select * from t1 full join t2 on t1.a = t2.a;
--error ER_NOT_SUPPORTED_YET
select * from t1 full outer join t2 on t1.a = t2.a;
--error ER_NOT_SUPPORTED_YET
select * from t1 natural full outer join t2;
--error ER_NOT_SUPPORTED_YET
select * from t1 natural full join t2;
--error ER_NOT_SUPPORTED_YET
create view v1 as select * from t1 full outer join t2 on t1.a = t2.a;
--error ER_NOT_SUPPORTED_YET
select * from (select t1.a from t1 full outer join t2 on t1.a = t2.a union select * from t1) dt;
--error ER_NOT_SUPPORTED_YET
with cte as (select t1.a from t1 natural full join t2) select * from cte;
drop table t1, t2;

--echo # End of 12.3 tests
1 change: 1 addition & 0 deletions sql/sql_lex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,7 @@ void LEX::start(THD *thd_arg)

memset(&trg_chistics, 0, sizeof(trg_chistics));
selects_for_hint_resolution.empty();
has_full_outer_join= false;
DBUG_VOID_RETURN;
}

Expand Down
3 changes: 3 additions & 0 deletions sql/sql_lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -3593,6 +3593,9 @@ struct LEX: public Query_tables_list
vers_select_conds_t vers_conditions;
vers_select_conds_t period_conditions;

/* False by default, this will be true if the query has a full join. */
bool has_full_outer_join;

inline void free_set_stmt_mem_root()
{
DBUG_ASSERT(!is_arena_for_set_stmt());
Expand Down
5 changes: 5 additions & 0 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10305,6 +10305,11 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
bool mysql_parse_status= thd->variables.sql_mode & MODE_ORACLE
? ORAparse(thd) : MYSQLparse(thd);

/* While we accept full join syntax, such joins are not yet supported. */
mysql_parse_status|= thd->lex->has_full_outer_join;
if (thd->lex->has_full_outer_join)
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "full join");

if (mysql_parse_status)
/*
Restore the original LEX if it was replaced when parsing
Expand Down
67 changes: 63 additions & 4 deletions sql/sql_yacc.yy
Original file line number Diff line number Diff line change
Expand Up @@ -1183,8 +1183,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token <kwd> ST_COLLECT_SYM
/* A dummy token to force the priority of table_ref production in a join. */
%left CONDITIONLESS_JOIN
%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT ON_SYM USING
%left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT ON_SYM USING FULL

%left SET_VAR
%left OR_SYM OR2_SYM
%left XOR
Expand Down Expand Up @@ -12365,8 +12365,66 @@ join_table:
if (unlikely(!($$= lex->current_select->convert_right_join())))
MYSQL_YYABORT;
}
;

/* FULL OUTER JOIN variants */
| table_ref FULL opt_outer JOIN_SYM table_ref
ON
{
MYSQL_YYABORT_UNLESS($1 && $5);

Select->add_joined_table($1);
$1->outer_join|= (JOIN_TYPE_LEFT |
JOIN_TYPE_FULL);

Select->add_joined_table($5);
$5->outer_join|= (JOIN_TYPE_RIGHT |
JOIN_TYPE_FULL);

/* Change the current name resolution context to a local context. */
if (unlikely(push_new_name_resolution_context(thd, $1, $5)))
MYSQL_YYABORT;
Select->parsing_place= IN_ON;
}
expr
{
add_join_on(thd, $1, $8);
$1->on_context= Lex->pop_context();
Select->parsing_place= NO_MATTER;
$$= $1;
Lex->has_full_outer_join= true;
}
| table_ref FULL opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $5);
Select->add_joined_table($1);
$1->outer_join|= (JOIN_TYPE_LEFT |
JOIN_TYPE_FULL);

Select->add_joined_table($5);
$5->outer_join|= (JOIN_TYPE_RIGHT |
JOIN_TYPE_FULL);
}
USING '(' using_list ')'
{
add_join_natural($1,$5,$9,Select);
Lex->has_full_outer_join= true;
}
| table_ref NATURAL FULL opt_outer JOIN_SYM table_factor
{
MYSQL_YYABORT_UNLESS($1 && $6);

Select->add_joined_table($1);
$1->outer_join|= (JOIN_TYPE_LEFT |
JOIN_TYPE_FULL);

Select->add_joined_table($6);
$6->outer_join|= (JOIN_TYPE_RIGHT |
JOIN_TYPE_FULL);

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

inner_join: /* $$ set if using STRAIGHT_JOIN, false otherwise */
JOIN_SYM { $$ = 0; }
Expand Down Expand Up @@ -16691,7 +16749,6 @@ keyword_func_sp_var_and_label:
| FILE_SYM
| FIRST_SYM
| FOUND_SYM
| FULL
| GENERAL
| GENERATED_SYM
| GRANTS
Expand Down Expand Up @@ -17021,6 +17078,7 @@ reserved_keyword_udt_not_param_type:
| FIRST_VALUE_SYM
| FOREIGN
| FROM
| FULL
| FULLTEXT_SYM
| GOTO_ORACLE_SYM
| GRANT
Expand Down Expand Up @@ -17748,6 +17806,7 @@ set_expr_or_default:
set_expr_misc:
ON { $$= new (thd->mem_root) Item_string_sys(thd, "ON", 2); }
| ALL { $$= new (thd->mem_root) Item_string_sys(thd, "ALL", 3); }
| FULL { $$= new (thd->mem_root) Item_string_sys(thd, "FULL", 4); }
| BINARY { $$= new (thd->mem_root) Item_string_sys(thd, "binary", 6); }
;

Expand Down
3 changes: 2 additions & 1 deletion sql/table.h
Original file line number Diff line number Diff line change
Expand Up @@ -2214,7 +2214,8 @@ class IS_table_read_plan;

#define JOIN_TYPE_LEFT 1U
#define JOIN_TYPE_RIGHT 2U
#define JOIN_TYPE_OUTER 4U /* Marker that this is an outer join */
#define JOIN_TYPE_FULL 4U
#define JOIN_TYPE_OUTER 8U /* Marker that this is an outer join */

/* view WITH CHECK OPTION parameter options */
#define VIEW_CHECK_NONE 0
Expand Down