diff options
author | unknown <timour@mysql.com> | 2005-08-12 17:57:19 +0300 |
---|---|---|
committer | unknown <timour@mysql.com> | 2005-08-12 17:57:19 +0300 |
commit | 7517d7e11298da9ce9aaea8e2e42c25a640d5be9 (patch) | |
tree | 98cc5c366d6eaba9f415323933356e53cf8d3a92 /sql/sql_yacc.yy | |
parent | 6eb7a80aff5363f3f0d714d5c7c1d46561a42ba1 (diff) | |
download | mariadb-git-7517d7e11298da9ce9aaea8e2e42c25a640d5be9.tar.gz |
Implementation of WL#2486 -
"Process NATURAL and USING joins according to SQL:2003".
* Some of the main problems fixed by the patch:
- in "select *" queries the * expanded correctly according to
ANSI for arbitrary natural/using joins
- natural/using joins are correctly transformed into JOIN ... ON
for any number/nesting of the joins.
- column references are correctly resolved against natural joins
of any nesting and combined with arbitrary other joins.
* This patch also contains a fix for name resolution of items
inside the ON condition of JOIN ... ON - in this case items must
be resolved only against the JOIN operands. To support such
'local' name resolution, the patch introduces a stack of
name resolution contexts used at parse time.
NOTICE:
- This patch is not complete in the sense that
- there are 2 test cases that still do not pass -
one in join.test, one in select.test. Both are marked
with a comment "TODO: WL#2486".
- it does not include a new test specific for the task
mysql-test/include/ps_query.inc:
Adjusted according to standard NATURAL/USING join semantics.,
mysql-test/r/bdb.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/derived.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/errors.result:
The column as a whole cannot be resolved, so different error message.
mysql-test/r/fulltext.result:
Adjusted according to standard JOIN ... ON semantics =>
the ON condition can refer only to the join operands.
mysql-test/r/fulltext_order_by.result:
More detailed error message.
mysql-test/r/innodb.result:
Adjusted according to standard NATURAL/USING join semantics.
This test doesn't pass completetly yet!
mysql-test/r/insert_select.result:
More detailed error message.
mysql-test/r/join.result:
Adjusted according to standard NATURAL/USING join semantics.
NOTICE: there is one test case that still fails, and it is
commeted out and marked with WL#2486 in the test file.
mysql-test/r/join_crash.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/join_nested.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/join_outer.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/multi_update.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/null_key.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/order_by.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_2myisam.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_3innodb.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_4heap.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_5merge.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_6bdb.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_7ndb.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/select.result:
Adjusted according to standard NATURAL/USING join semantics.
NOTICE: there is one failing test case which is commented with
WL#2486 in the test file.
mysql-test/r/subselect.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/type_ranges.result:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/union.result:
More detailed error message.
mysql-test/t/bdb.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/errors.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/fulltext.test:
Adjusted according to standard JOIN ... ON semantics =>
the ON condition can refer only to the join operands.
mysql-test/t/fulltext_order_by.test:
More detailed error message.
mysql-test/t/innodb.test:
Adjusted according to standard NATURAL/USING join semantics.
This test doesn't pass completetly yet!
mysql-test/t/insert_select.test:
More detailed error message.
mysql-test/t/join.test:
Adjusted according to standard NATURAL/USING join semantics.
NOTICE: there is one test case that still fails, and it is
commeted out and marked with WL#2486 in the test file.
mysql-test/t/join_crash.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/join_nested.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/join_outer.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/null_key.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/order_by.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/select.test:
Adjusted according to standard NATURAL/USING join semantics.
NOTICE: there is one test case that still fails, and it is
commeted out and marked with WL#2486 in the test file.
mysql-test/t/subselect.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/type_ranges.test:
Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/union.test:
More detailed error message.
sql/item.cc:
- extra parameter to find_field_in_tables
- find_field_in_real_table renamed to find_field_in_table
- fixed comments/typos
sql/item.h:
- added [first | last]_name_resolution_table to class
Name_resolution_context
- commented old code
- standardized formatting
sql/mysql_priv.h:
- refactored the find_field_in_XXX procedures,
- added a new procedure for natural join table references,
- renamed the find_field_in_XXX procedures to clearer names
sql/sp.cc:
- pass the top-most list of the FROM clause to setup_tables
- extra parameter to find_field_in_tables
sql/sql_acl.cc:
- renamed find_field_in_table => find_field_in_table_ref
- extra parameter to find_field_in_table_ref
- commented old code
sql/sql_base.cc:
This file contains the core of the implementation of the processing
of NATURAL/USING joins (WL#2486).
- added many comments to old code
- refactored the group of find_field_in_XXX procedures, and added a
new procedure for natural joins. There is one find_field_in_XXX procedure
per each type of table reference (stored table, merge view, or natural
join); one meta-procedure that selects the correct one depeneding on the
table reference; and one procedure that goes over a list of table
referenes.
- NATURAL/USING joins are processed through the procedures:
mark_common_columns, store_natural_using_join_columns,
store_top_level_join_columns, setup_natural_join_row_types.
The entry point to processing NATURAL/USING joins is the
procedure 'setup_natural_join_row_types'.
- Replaced the specialized Field_iterator_XXX iterators with one
generic iterator over the fields of a table reference.
- Simplified 'insert_fields' and 'setup_conds' due to encapsulation of
the processing of natural joins in a separate set of procedures.
sql/sql_class.h:
- Commented old code.
sql/sql_delete.cc:
- Pass the FROM clause to setup_tables.
sql/sql_help.cc:
- pass the end name resolution table to find_field_in_tables
- adjust the list of tables for name resolution
sql/sql_insert.cc:
- Changed the code that saves and restores the current context to
support the list of tables for name resolution -
context->first_name_resolution_table, and
table_list->next_name_resolution_table.
Needed to support an ugly trick to resolve inserted columns only in
the first table.
- Added Name_resolution_context::[first | last]_name_resolution_table.
- Commented old code
sql/sql_lex.cc:
- set select_lex.parent_lex correctly
- set correct state of the current name resolution context
sql/sql_lex.h:
- Added a stack of name resolution contexts to support local
contexts for JOIN ... ON conditions.
- Commented old code.
sql/sql_load.cc:
- Pass the FROM clause to setup_tables.
sql/sql_olap.cc:
- Pass the FROM clause to setup_tables.
sql/sql_parse.cc:
- correctly set SELECT_LEX::parent_lex
- set the first table of the current name resoltion context
- added support for NATURAL/USING joins
- commented old code
sql/sql_select.cc:
- Pass the FROM clause to setup_tables.
- Pass the end table to find_field_in_tables
- Improved comments
sql/sql_show.cc:
- Set SELECT_LEX::parent_lex.
sql/sql_update.cc:
- Pass the FROM clause to setup_tables.
sql/sql_yacc.yy:
- Added support for a stack of name resolution contexts needed to
implement name resolution for JOIN ... ON. A context is pushed
for each new JOIN ... ON, and popped afterwards.
- Added support for NATURAL/USING joins.
sql/table.cc:
- Added new class Natural_join_column to hide the heterogeneous
representation of column references for stored tables and for
views.
- Added a new list TABLE_LIST::next_name_resolution_table to
support name resolution with NATURAL/USING joins. Also added
other members to TABLE_LIST to support NATURAL/USING joins.
- Added a generic iterator over the fields of table references
of various types - class Field_iterator_table_ref
sql/table.h:
- Added new class Natural_join_column to hide the heterogeneous
representation of column references for stored tables and for
views.
- Added a new list TABLE_LIST::next_name_resolution_table to
support name resolution with NATURAL/USING joins. Also added
other members to TABLE_LIST to support NATURAL/USING joins.
- Added a generic iterator over the fields of table references
of various types - class Field_iterator_table_ref
tests/mysql_client_test.c:
Adjusted according to standard NATURAL JOIN syntax.
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 191 |
1 files changed, 123 insertions, 68 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b680787b9a3..d5d0ac8fff0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -717,7 +717,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); bool_term bool_factor bool_test bool_pri predicate bit_expr bit_term bit_factor value_expr term factor table_wild simple_expr udf_expr - using_list expr_or_default set_expr_or_default interval_expr + expr_or_default set_expr_or_default interval_expr param_marker singlerow_subselect singlerow_subselect_init exists_subselect exists_subselect_init geometry_function signed_literal now_or_signed_literal opt_escape @@ -739,7 +739,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); key_alg opt_btree_or_rtree %type <string_list> - key_usage_list + key_usage_list using_list %type <key_part> key_part @@ -4420,10 +4420,10 @@ simple_expr: my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str); YYABORT; } - $$= new Item_default_value(&Select->context, $3); + $$= new Item_default_value(Lex->current_context(), $3); } | VALUES '(' simple_ident ')' - { $$= new Item_insert_value(&Select->context, $3); } + { $$= new Item_insert_value(Lex->current_context(), $3); } | FUNC_ARG0 '(' ')' { if (!$1.symbol->create_func) @@ -4714,9 +4714,9 @@ simple_expr: name->init_qname(YYTHD); sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); if ($5) - $$= new Item_func_sp(&lex->current_select->context, name, *$5); + $$= new Item_func_sp(Lex->current_context(), name, *$5); else - $$= new Item_func_sp(&lex->current_select->context, name); + $$= new Item_func_sp(Lex->current_context(), name); lex->safe_to_cache_query=0; } | IDENT_sys '(' udf_expr_list ')' @@ -4804,9 +4804,9 @@ simple_expr: sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); if ($3) - $$= new Item_func_sp(&lex->current_select->context, name, *$3); + $$= new Item_func_sp(Lex->current_context(), name, *$3); else - $$= new Item_func_sp(&lex->current_select->context, name); + $$= new Item_func_sp(Lex->current_context(), name); lex->safe_to_cache_query=0; } } @@ -5010,7 +5010,7 @@ sum_expr: { SELECT_LEX *sel= Select; sel->in_sum_expr--; - $$=new Item_func_group_concat(&sel->context, $3, $5, + $$=new Item_func_group_concat(Lex->current_context(), $3, $5, sel->gorder_list, $7); $5->empty(); }; @@ -5146,68 +5146,116 @@ join_table: table_ref normal_join table_ref { YYERROR_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; } - | table_ref normal_join table_ref ON expr - { YYERROR_UNLESS($1 && ($$=$3)); add_join_on($3,$5); } - | table_ref STRAIGHT_JOIN table_factor ON expr - { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; add_join_on($3,$5); } + | table_ref normal_join table_ref + ON + { + YYERROR_UNLESS($1 && ($$=$3)); + /* Change the current name resolution context to a local context. */ + Name_resolution_context *on_context; + if (!(on_context= make_join_on_context(YYTHD,$1,$3))) + YYABORT; + Lex->push_context(on_context); + } + expr + { + add_join_on($3,$6); + Lex->pop_context(); + } + | table_ref STRAIGHT_JOIN table_factor + ON + { + YYERROR_UNLESS($1 && ($$=$3)); + /* Change the current name resolution context to a local context. */ + Name_resolution_context *on_context; + if (!(on_context= make_join_on_context(YYTHD,$1,$3))) + YYABORT; + Lex->push_context(on_context); + } + expr + { + $3->straight=1; + add_join_on($3,$6); + Lex->pop_context(); + } | table_ref normal_join table_ref USING { SELECT_LEX *sel= Select; YYERROR_UNLESS($1 && $3); - sel->save_names_for_using_list($1, $3); } '(' using_list ')' - { add_join_on($3,$7); $$=$3; } - - | table_ref LEFT opt_outer JOIN_SYM table_ref ON expr - { YYERROR_UNLESS($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } + { add_join_natural($1,$3,$7); $$=$3; } + | table_ref LEFT opt_outer JOIN_SYM table_ref + ON + { + /* Change the current name resolution context to a local context. */ + Name_resolution_context *on_context; + if (!(on_context= make_join_on_context(YYTHD,$1,$5))) + YYABORT; + Lex->push_context(on_context); + } + expr + { + YYERROR_UNLESS($1 && $5); + add_join_on($5,$8); + Lex->pop_context(); + $5->outer_join|=JOIN_TYPE_LEFT; + $$=$5; + } | table_ref LEFT opt_outer JOIN_SYM table_factor { SELECT_LEX *sel= Select; YYERROR_UNLESS($1 && $5); - sel->save_names_for_using_list($1, $5); } USING '(' using_list ')' - { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } + { add_join_natural($1,$5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; } | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { YYERROR_UNLESS($1 && $6); - add_join_natural($1,$6); + add_join_natural($1,$6,NULL); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; } - | table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr + | table_ref RIGHT opt_outer JOIN_SYM table_ref + ON + { + /* Change the current name resolution context to a local context. */ + Name_resolution_context *on_context; + if (!(on_context= make_join_on_context(YYTHD,$1,$5))) + YYABORT; + Lex->push_context(on_context); + } + expr { LEX *lex= Lex; YYERROR_UNLESS($1 && $5); if (!($$= lex->current_select->convert_right_join())) YYABORT; - add_join_on($$, $7); + add_join_on($$, $8); + Lex->pop_context(); } | table_ref RIGHT opt_outer JOIN_SYM table_factor { SELECT_LEX *sel= Select; YYERROR_UNLESS($1 && $5); - sel->save_names_for_using_list($1, $5); } USING '(' using_list ')' { LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; - add_join_on($$, $9); + add_join_natural($$,$5,$9); } | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { YYERROR_UNLESS($1 && $6); - add_join_natural($6,$1); + add_join_natural($6,$1,NULL); LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) YYABORT; } | table_ref NATURAL JOIN_SYM table_factor - { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4); }; + { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4,NULL); }; normal_join: @@ -5235,8 +5283,23 @@ table_factor: YYABORT; sel->add_joined_table($$); } - | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}' - { YYERROR_UNLESS($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; } + | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref + ON + { + /* Change the current name resolution context to a local context. */ + Name_resolution_context *on_context; + if (!(on_context= make_join_on_context(YYTHD,$3,$7))) + YYABORT; + Lex->push_context(on_context); + } + expr '}' + { + YYERROR_UNLESS($3 && $7); + add_join_on($7,$10); + Lex->pop_context(); + $7->outer_join|=JOIN_TYPE_LEFT; + $$=$7; + } | select_derived_init get_select_lex select_derived2 { LEX *lex= Lex; @@ -5290,6 +5353,7 @@ table_factor: YYABORT; sel->add_joined_table($$); + lex->pop_context(); } else if ($4 || $6) @@ -5429,32 +5493,18 @@ key_usage_list2: using_list: ident { - SELECT_LEX *sel= Select; - if (!($$= new Item_func_eq(new Item_field(&sel->context, - sel->db1, sel->table1, - $1.str), - new Item_field(&sel->context, - sel->db2, sel->table2, - $1.str)))) + if (!($$= new List<String>)) YYABORT; + $$->push_back(new (YYTHD->mem_root) + String((const char *) $1.str, $1.length, + system_charset_info)); } | using_list ',' ident { - SELECT_LEX *sel= Select; - if (!($$= - new Item_cond_and(new - Item_func_eq(new - Item_field(&sel->context, - sel->db1, - sel->table1, - $3.str), - new - Item_field(&sel->context, - sel->db2, - sel->table2, - $3.str)), - $1))) - YYABORT; + $1->push_back(new (YYTHD->mem_root) + String((const char *) $3.str, $3.length, + system_charset_info)); + $$= $1; }; interval: @@ -6095,7 +6145,7 @@ values: expr_or_default: expr { $$= $1;} - | DEFAULT {$$= new Item_default_value(&Select->context); } + | DEFAULT {$$= new Item_default_value(Lex->current_context()); } ; opt_insert_update: @@ -7051,13 +7101,13 @@ table_wild: ident '.' '*' { SELECT_LEX *sel= Select; - $$ = new Item_field(&sel->context, NullS, $1.str, "*"); + $$ = new Item_field(Lex->current_context(), NullS, $1.str, "*"); sel->with_wild++; } | ident '.' ident '.' '*' { SELECT_LEX *sel= Select; - $$ = new Item_field(&sel->context, (YYTHD->client_capabilities & + $$ = new Item_field(Lex->current_context(), (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str,"*"); sel->with_wild++; @@ -7085,8 +7135,8 @@ simple_ident: SELECT_LEX *sel=Select; $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) : - (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str); + (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) : + (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str); } } | simple_ident_q { $$= $1; } @@ -7098,8 +7148,8 @@ simple_ident_nospvar: SELECT_LEX *sel=Select; $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) : - (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str); + (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) : + (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str); } | simple_ident_q { $$= $1; } ; @@ -7136,7 +7186,7 @@ simple_ident_q: YYABORT; } - if (!(trg_fld= new Item_trigger_field(&lex->current_select->context, + if (!(trg_fld= new Item_trigger_field(Lex->current_context(), new_row ? Item_trigger_field::NEW_ROW: Item_trigger_field::OLD_ROW, @@ -7162,8 +7212,8 @@ simple_ident_q: } $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(&sel->context, NullS, $1.str, $3.str) : - (Item*) new Item_ref(&sel->context, NullS, $1.str, $3.str); + (Item*) new Item_field(Lex->current_context(), NullS, $1.str, $3.str) : + (Item*) new Item_ref(Lex->current_context(), NullS, $1.str, $3.str); } } | '.' ident '.' ident @@ -7178,8 +7228,8 @@ simple_ident_q: } $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(&sel->context, NullS, $2.str, $4.str) : - (Item*) new Item_ref(&sel->context, NullS, $2.str, $4.str); + (Item*) new Item_field(Lex->current_context(), NullS, $2.str, $4.str) : + (Item*) new Item_ref(Lex->current_context(), NullS, $2.str, $4.str); } | ident '.' ident '.' ident { @@ -7193,11 +7243,11 @@ simple_ident_q: } $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(&sel->context, + (Item*) new Item_field(Lex->current_context(), (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str) : - (Item*) new Item_ref(&sel->context, + (Item*) new Item_ref(Lex->current_context(), (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str); @@ -7761,8 +7811,7 @@ sys_option_value: it= new Item_null(); } - if (!(trg_fld= new Item_trigger_field(&lex->current_select-> - context, + if (!(trg_fld= new Item_trigger_field(Lex->current_context(), Item_trigger_field::NEW_ROW, $2.base_name.str)) || !(i= new sp_instr_set_trigger_field(lex->sphead-> @@ -8618,7 +8667,12 @@ union_list: lex->current_select->master_unit()->union_distinct= lex->current_select; } - select_init {} + select_init + { + /* Remove from the name resolution context stack the context of the + last select in the union. */ + Lex->pop_context(); + } ; union_opt: @@ -8722,6 +8776,7 @@ subselect_end: ')' { LEX *lex=Lex; + lex->pop_context(); lex->current_select = lex->current_select->return_after_parsing(); }; |