summaryrefslogtreecommitdiff
path: root/sql/sql_yacc.yy
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2005-03-16 22:59:06 +0200
committerunknown <monty@mysql.com>2005-03-16 22:59:06 +0200
commit06f59b28ab4e2c2d4a67c50d56b734c96750ed8b (patch)
tree119cb9dbad08d53c1b012a9b6a5a4b37020923e4 /sql/sql_yacc.yy
parent284b8b8b63bec8f2d246f6748ab695baa9aaf746 (diff)
parentf9792042eb815d6b5e1e4dfe0da599b2e1599424 (diff)
downloadmariadb-git-06f59b28ab4e2c2d4a67c50d56b734c96750ed8b.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/my/mysql-5.0 sql/item_func.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r--sql/sql_yacc.yy317
1 files changed, 245 insertions, 72 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index cb247f900d8..cc6eadf5fd5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -52,6 +52,13 @@ const LEX_STRING null_lex_str={0,0};
ER_WARN_DEPRECATED_SYNTAX, \
ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
+#define TEST_ASSERT(A) \
+ if (!(A)) \
+ { \
+ yyerror(ER(ER_SYNTAX_ERROR)); \
+ YYABORT; \
+ }
+
/* Helper for parsing "IS [NOT] truth_value" */
inline Item *is_truth_value(Item *A, bool v1, bool v2)
{
@@ -686,12 +693,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
text_string opt_gconcat_separator
%type <num>
- type int_type real_type order_dir opt_field_spec lock_option
+ type int_type real_type order_dir lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type
opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
start_transaction_opts opt_chain opt_release
+ union_opt select_derived_init
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -714,6 +722,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
signed_literal now_or_signed_literal opt_escape
sp_opt_default
simple_ident_nospvar simple_ident_q
+ field_or_var
%type <item_num>
NUM_literal
@@ -737,6 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <table_list>
join_table_list join_table
table_factor table_ref
+ select_derived derived_table_list
%type <date_time_type> date_time_type;
%type <interval> interval
@@ -771,6 +781,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <variable> internal_variable_name
%type <select_lex> in_subselect in_subselect_init
+ get_select_lex
%type <boolfunc2creator> comp_op
@@ -809,6 +820,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
prepare prepare_src execute deallocate
statement sp_suid opt_view_list view_list or_replace algorithm
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
+ load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -4026,13 +4038,53 @@ optional_braces:
/* all possible expressions */
expr:
- expr or bool_term { $$= new Item_cond_or($1,$3); }
- | expr XOR bool_term { $$= new Item_cond_xor($1,$3); }
- | bool_term ;
+ bool_term { Select->expr_list.push_front(new List<Item>); }
+ bool_or_expr
+ {
+ List<Item> *list= Select->expr_list.pop();
+ if (list->elements)
+ {
+ list->push_front($1);
+ $$= new Item_cond_or(*list);
+ /* optimize construction of logical OR to reduce
+ amount of objects for complex expressions */
+ }
+ else
+ $$= $1;
+ delete list;
+ }
+ ;
+
+bool_or_expr:
+ /* empty */
+ | bool_or_expr or bool_term
+ { Select->expr_list.head()->push_back($3); }
+ ;
bool_term:
- bool_term and bool_factor { $$= new Item_cond_and($1,$3); }
- | bool_factor ;
+ bool_term XOR bool_term { $$= new Item_cond_xor($1,$3); }
+ | bool_factor { Select->expr_list.push_front(new List<Item>); }
+ bool_and_expr
+ {
+ List<Item> *list= Select->expr_list.pop();
+ if (list->elements)
+ {
+ list->push_front($1);
+ $$= new Item_cond_and(*list);
+ /* optimize construction of logical AND to reduce
+ amount of objects for complex expressions */
+ }
+ else
+ $$= $1;
+ delete list;
+ }
+ ;
+
+bool_and_expr:
+ /* empty */
+ | bool_and_expr and bool_factor
+ { Select->expr_list.head()->push_back($3); }
+ ;
bool_factor:
NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); }
@@ -4917,6 +4969,7 @@ when_list2:
sel->when_list.head()->push_back($5);
};
+/* Warning - may return NULL in case of incomplete SELECT */
table_ref:
table_factor { $$=$1; }
| join_table { $$=$1; }
@@ -4928,36 +4981,47 @@ table_ref:
;
join_table_list:
+ derived_table_list { TEST_ASSERT($$=$1); }
+ ;
+
+/* Warning - may return NULL in case of incomplete SELECT */
+derived_table_list:
table_ref { $$=$1; }
- | join_table_list ',' table_ref { $$=$3; }
+ | derived_table_list ',' table_ref
+ {
+ TEST_ASSERT($1 && ($$=$3));
+ }
;
join_table:
- table_ref normal_join table_ref { $$=$3; }
+ table_ref normal_join table_ref { TEST_ASSERT($1 && ($$=$3)); }
| table_ref STRAIGHT_JOIN table_factor
- { $3->straight=1; $$=$3 ; }
+ { TEST_ASSERT($1 && ($$=$3)); $3->straight=1; }
| table_ref normal_join table_ref ON expr
- { add_join_on($3,$5); $$=$3; }
+ { TEST_ASSERT($1 && ($$=$3)); add_join_on($3,$5); }
| table_ref normal_join table_ref
USING
{
SELECT_LEX *sel= Select;
+ TEST_ASSERT($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
- { add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
+ { TEST_ASSERT($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
+ TEST_ASSERT($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; }
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
{
+ TEST_ASSERT($1 && $6);
add_join_natural($1,$6);
$6->outer_join|=JOIN_TYPE_LEFT;
$$=$6;
@@ -4965,6 +5029,7 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr
{
LEX *lex= Lex;
+ TEST_ASSERT($1 && $5);
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
add_join_on($$, $7);
@@ -4972,6 +5037,7 @@ join_table:
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
+ TEST_ASSERT($1 && $5);
sel->save_names_for_using_list($1, $5);
}
USING '(' using_list ')'
@@ -4983,13 +5049,14 @@ join_table:
}
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
{
+ TEST_ASSERT($1 && $6);
add_join_natural($6,$1);
LEX *lex= Lex;
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
}
| table_ref NATURAL JOIN_SYM table_factor
- { add_join_natural($1,$4); $$=$4; };
+ { TEST_ASSERT($1 && ($$=$4)); add_join_natural($1,$4); };
normal_join:
@@ -4998,6 +5065,7 @@ normal_join:
| CROSS JOIN_SYM {}
;
+/* Warning - may return NULL in case of incomplete SELECT */
table_factor:
{
SELECT_LEX *sel= Select;
@@ -5016,50 +5084,96 @@ table_factor:
YYABORT;
sel->add_joined_table($$);
}
- | '('
+ | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}'
+ { TEST_ASSERT($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
+ | select_derived_init get_select_lex select_derived2
{
LEX *lex= Lex;
- if (lex->current_select->init_nested_join(lex->thd))
- YYABORT;
+ SELECT_LEX *sel= lex->current_select;
+ if ($1)
+ {
+ if (sel->set_braces(1))
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ /* select in braces, can't contain global parameters */
+ if (sel->master_unit()->fake_select_lex)
+ sel->master_unit()->global_parameters=
+ sel->master_unit()->fake_select_lex;
+ }
+ if ($2->init_nested_join(lex->thd))
+ YYABORT;
+ $$= 0;
+ /* incomplete derived tables return NULL, we must be
+ nested in select_derived rule to be here. */
}
- join_table_list ')'
+ | '(' get_select_lex select_derived union_opt ')' opt_table_alias
+ {
+ /* Use $2 instead of Lex->current_select as derived table will
+ alter value of Lex->current_select. */
+
+ if (!($3 || $6) && $2->embedding &&
+ !$2->embedding->nested_join->join_list.elements)
{
- LEX *lex= Lex;
- if (!($$= lex->current_select->end_nested_join(lex->thd)))
- YYABORT;
+ /* we have a derived table ($3 == NULL) but no alias,
+ Since we are nested in further parentheses so we
+ can pass NULL to the outer level parentheses
+ Permits parsing of "((((select ...))) as xyz)" */
+ $$= 0;
}
- | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}'
- { add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
- | '(' select_derived union_opt ')' opt_table_alias
- {
- LEX *lex=Lex;
- SELECT_LEX_UNIT *unit= lex->current_select->master_unit();
- lex->current_select= unit->outer_select();
- if (!($$= lex->current_select->
- add_table_to_list(lex->thd, new Table_ident(unit), $5, 0,
- TL_READ,(List<String> *)0,
- (List<String> *)0)))
+ else
+ if (!$3)
+ {
+ /* Handle case of derived table, alias may be NULL if there
+ are no outer parentheses, add_table_to_list() will throw
+ error in this case */
+ LEX *lex=Lex;
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel->master_unit();
+ lex->current_select= sel= unit->outer_select();
+ if (!($$= sel->
+ add_table_to_list(lex->thd, new Table_ident(unit), $6, 0,
+ TL_READ,(List<String> *)0,
+ (List<String> *)0)))
+ YYABORT;
+ sel->add_joined_table($$);
+ }
+ else
+ if ($4 || $6)
+ {
+ /* simple nested joins cannot have aliases or unions */
+ yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
- lex->current_select->add_joined_table($$);
- };
-
+ }
+ else
+ $$= $3;
+ }
+ ;
+/* handle contents of parentheses in join expression */
select_derived:
- SELECT_SYM select_derived2
- | '(' select_derived ')'
+ get_select_lex
{
- SELECT_LEX *sel= Select;
- if (sel->set_braces(1))
- {
+ LEX *lex= Lex;
+ if ($1->init_nested_join(lex->thd))
+ YYABORT;
+ }
+ derived_table_list
+ {
+ LEX *lex= Lex;
+ /* for normal joins, $3 != NULL and end_nested_join() != NULL,
+ for derived tables, both must equal NULL */
+
+ if (!($$= $1->end_nested_join(lex->thd)) && $3)
+ YYABORT;
+ if (!$3 && $$)
+ {
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
- }
- /* select in braces, can't contain global parameters */
- if (sel->master_unit()->fake_select_lex)
- sel->master_unit()->global_parameters=
- sel->master_unit()->fake_select_lex;
- }
+ }
+ }
;
select_derived2:
@@ -5087,6 +5201,29 @@ select_derived2:
opt_select_from
;
+get_select_lex:
+ /* Empty */ { $$= Select; }
+ ;
+
+select_derived_init:
+ SELECT_SYM
+ {
+ LEX *lex= Lex;
+ SELECT_LEX *sel= lex->current_select;
+ TABLE_LIST *embedding;
+ if (!sel->embedding || sel->end_nested_join(lex->thd))
+ {
+ /* we are not in parentheses */
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ embedding= Select->embedding;
+ $$= embedding &&
+ !embedding->nested_join->join_list.elements;
+ /* return true if we are deeply nested */
+ }
+ ;
+
opt_outer:
/* empty */ {}
| OUTER {};
@@ -5707,11 +5844,6 @@ insert_field_spec:
}
ident_eq_list;
-opt_field_spec:
- /* empty */ { }
- | '(' fields ')' { }
- | '(' ')' { };
-
fields:
fields ',' insert_ident { Lex->field_list.push_back($3); }
| insert_ident { Lex->field_list.push_back($1); };
@@ -6413,34 +6545,53 @@ use: USE_SYM ident
/* import, export of files */
-load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys
+load: LOAD DATA_SYM
+ {
+ LEX *lex=Lex;
+ lex->fname_start= lex->ptr;
+ }
+ load_data
+ {}
+ |
+ LOAD TABLE_SYM table_ident FROM MASTER_SYM
+ {
+ Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
+ if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
+ YYABORT;
+ };
+
+load_data:
+ load_data_lock opt_local INFILE TEXT_STRING_sys
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->lock_option= $3;
- lex->local_file= $4;
+ lex->lock_option= $1;
+ lex->local_file= $2;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
- if (!(lex->exchange= new sql_exchange($6.str,0)))
- YYABORT;
- lex->field_list.empty();
- }
- opt_duplicate INTO TABLE_SYM table_ident opt_field_term opt_line_term
- opt_ignore_lines opt_field_spec
- {
- if (!Select->add_table_to_list(YYTHD, $11, NULL, TL_OPTION_UPDATING))
+ if (!(lex->exchange= new sql_exchange($4.str, 0)))
YYABORT;
+ }
+ opt_duplicate INTO
+ {
+ LEX *lex=Lex;
+ lex->fname_end= lex->ptr;
}
- |
- LOAD TABLE_SYM table_ident FROM MASTER_SYM
+ TABLE_SYM table_ident
{
- Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
- if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
- YYABORT;
-
+ LEX *lex=Lex;
+ if (!Select->add_table_to_list(YYTHD, $10, NULL, TL_OPTION_UPDATING,
+ lex->lock_option))
+ YYABORT;
+ lex->field_list.empty();
+ lex->update_list.empty();
+ lex->value_list.empty();
}
+ opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
+ opt_load_data_set_spec
+ {}
|
- LOAD DATA_SYM FROM MASTER_SYM
+ FROM MASTER_SYM
{
Lex->sql_command = SQLCOM_LOAD_MASTER_DATA;
};
@@ -6520,6 +6671,29 @@ opt_ignore_lines:
Lex->exchange->skip_lines= atol($2.str);
};
+opt_field_or_var_spec:
+ /* empty */ { }
+ | '(' fields_or_vars ')' { }
+ | '(' ')' { };
+
+fields_or_vars:
+ fields_or_vars ',' field_or_var
+ { Lex->field_list.push_back($3); }
+ | field_or_var
+ { Lex->field_list.push_back($1); }
+ ;
+
+field_or_var:
+ simple_ident_nospvar {$$= $1;}
+ | '@' ident_or_text
+ { $$= new Item_user_var_as_out_param($2); }
+ ;
+
+opt_load_data_set_spec:
+ /* empty */ { }
+ | SET insert_update_list { };
+
+
/* Common definitions */
text_literal:
@@ -8083,13 +8257,12 @@ union_list:
;
union_opt:
- union_list {}
- | optional_order_or_limit {}
+ /* Empty */ { $$= 0; }
+ | union_list { $$= 1; }
+ | union_order_or_limit { $$= 1; }
;
-optional_order_or_limit:
- /* Empty */ {}
- |
+union_order_or_limit:
{
THD *thd= YYTHD;
LEX *lex= thd->lex;