summaryrefslogtreecommitdiff
path: root/sql/sql_yacc.yy
diff options
context:
space:
mode:
authorunknown <timour@mysql.com>2005-08-12 17:57:19 +0300
committerunknown <timour@mysql.com>2005-08-12 17:57:19 +0300
commit7517d7e11298da9ce9aaea8e2e42c25a640d5be9 (patch)
tree98cc5c366d6eaba9f415323933356e53cf8d3a92 /sql/sql_yacc.yy
parent6eb7a80aff5363f3f0d714d5c7c1d46561a42ba1 (diff)
downloadmariadb-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.yy191
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();
};