summaryrefslogtreecommitdiff
path: root/sql/sql_yacc.yy
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r--sql/sql_yacc.yy330
1 files changed, 188 insertions, 142 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2d6baf5b846..efd8c20e6d7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -31,7 +31,7 @@
#define MYSQL_YACC
#define YYINITDEPTH 100
-#define YYMAXDEPTH 3200 /* Because of 64K stack */
+#define YYMAXDEPTH 3200 /* Because of 64K stack */
#define Lex (YYTHD->lex)
#define Select Lex->current_select
#include "mysql_priv.h"
@@ -506,12 +506,12 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%}
-%pure_parser /* We have threads */
+%pure_parser /* We have threads */
/*
- Currently there is 286 shift/reduce conflict. We should not introduce
- new conflicts any more.
+ Currently there are 280 shift/reduce conflicts.
+ We should not introduce new conflicts any more.
*/
-%expect 286
+%expect 280
/*
Comments for TOKENS.
@@ -1091,7 +1091,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
/* A dummy token to force the priority of table_ref production in a join. */
%left TABLE_REF_PRIORITY
%left SET_VAR
-%left OR_OR_SYM OR_SYM OR2_SYM XOR
+%left OR_OR_SYM OR_SYM OR2_SYM
+%left XOR
%left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
%left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM
@@ -1104,6 +1105,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left NEG '~'
%right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM
+%left INTERVAL_SYM
%type <lex_str>
IDENT IDENT_QUOTED TEXT_STRING DECIMAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM
@@ -1152,8 +1154,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
- variable variable_aux bool_term bool_factor bool_test bool_pri
- predicate bit_expr bit_term bit_factor value_expr term factor
+ variable variable_aux bool_pri
+ predicate bit_expr
table_wild simple_expr udf_expr
expr_or_default set_expr_or_default interval_expr
param_marker geometry_function
@@ -1171,7 +1173,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
NUM_literal
%type <item_list>
- expr_list udf_expr_list udf_expr_list2 when_list
+ expr_list opt_udf_expr_list udf_expr_list when_list
ident_list ident_list_arg opt_expr_list
%type <var_type>
@@ -1245,7 +1247,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
- expr_list2 udf_expr_list3 handler
+ handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock
@@ -1315,10 +1317,11 @@ rule: <-- starts at col 1
}
; <-- on a line by itself, starts at col 9
-Also, please do not use any <TAB>, but spaces.
-Having a uniform indentation in this file helps
-code reviews, patches, merges, and make maintenance easier.
-Thanks.
+ Also, please do not use any <TAB>, but spaces.
+ Having a uniform indentation in this file helps
+ code reviews, patches, merges, and make maintenance easier.
+ Tip: grep [[:cntrl:]] sql_yacc.yy
+ Thanks.
*/
query:
@@ -5157,7 +5160,7 @@ opt_bin_charset:
MYSQL_YYABORT;
}
}
- | charset charset_name { Lex->charset=$2; }
+ | charset charset_name { Lex->charset=$2; }
;
opt_primary:
@@ -5379,7 +5382,7 @@ alter:
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_info.reset();
lex->no_write_to_binlog= 0;
- lex->create_info.storage_media= HA_SM_DEFAULT;
+ lex->create_info.storage_media= HA_SM_DEFAULT;
}
alter_commands
{}
@@ -6564,83 +6567,131 @@ optional_braces:
;
/* all possible expressions */
-expr:
- bool_term { Select->expr_list.push_front(new List<Item>); }
- bool_or_expr
+expr:
+ expr or expr %prec OR_SYM
{
- List<Item> *list= Select->expr_list.pop();
- if (list->elements)
+ /*
+ Design notes:
+ Do not use a manually maintained stack like thd->lex->xxx_list,
+ but use the internal bison stack ($$, $1 and $3) instead.
+ Using the bison stack is:
+ - more robust to changes in the grammar,
+ - guaranteed to be in sync with the parser state,
+ - better for performances (no memory allocation).
+ */
+ Item_cond_or *item1;
+ Item_cond_or *item3;
+ if (is_cond_or($1))
{
- list->push_front($1);
- $$= new Item_cond_or(*list);
- /* optimize construction of logical OR to reduce
- amount of objects for complex expressions */
+ item1= (Item_cond_or*) $1;
+ if (is_cond_or($3))
+ {
+ item3= (Item_cond_or*) $3;
+ /*
+ (X1 OR X2) OR (Y1 OR Y2) ==> OR (X1, X2, Y1, Y2)
+ */
+ item3->add_at_head(item1->argument_list());
+ $$ = $3;
+ }
+ else
+ {
+ /*
+ (X1 OR X2) OR Y ==> OR (X1, X2, Y)
+ */
+ item1->add($3);
+ $$ = $1;
+ }
+ }
+ else if (is_cond_or($3))
+ {
+ item3= (Item_cond_or*) $3;
+ /*
+ X OR (Y1 OR Y2) ==> OR (X, Y1, Y2)
+ */
+ item3->add_at_head($1);
+ $$ = $3;
}
else
- $$= $1;
- delete list;
+ {
+ /* X OR Y */
+ $$ = new (YYTHD->mem_root) Item_cond_or($1, $3);
+ }
}
- ;
-
-bool_or_expr:
- /* empty */
- | bool_or_expr or bool_term
- { Select->expr_list.head()->push_back($3); }
- ;
-
-bool_term:
- bool_term XOR bool_term { $$= new Item_cond_xor($1,$3); }
- | bool_factor { Select->expr_list.push_front(new List<Item>); }
- bool_and_expr
+ | expr XOR expr %prec XOR
+ {
+ /* XOR is a proprietary extension */
+ $$ = new (YYTHD->mem_root) Item_cond_xor($1, $3);
+ }
+ | expr and expr %prec AND_SYM
{
- List<Item> *list= Select->expr_list.pop();
- if (list->elements)
+ /* See comments in rule expr: expr or expr */
+ Item_cond_and *item1;
+ Item_cond_and *item3;
+ if (is_cond_and($1))
{
- list->push_front($1);
- $$= new Item_cond_and(*list);
- /* optimize construction of logical AND to reduce
- amount of objects for complex expressions */
+ item1= (Item_cond_and*) $1;
+ if (is_cond_and($3))
+ {
+ item3= (Item_cond_and*) $3;
+ /*
+ (X1 AND X2) AND (Y1 AND Y2) ==> AND (X1, X2, Y1, Y2)
+ */
+ item3->add_at_head(item1->argument_list());
+ $$ = $3;
+ }
+ else
+ {
+ /*
+ (X1 AND X2) AND Y ==> AND (X1, X2, Y)
+ */
+ item1->add($3);
+ $$ = $1;
+ }
+ }
+ else if (is_cond_and($3))
+ {
+ item3= (Item_cond_and*) $3;
+ /*
+ X AND (Y1 AND Y2) ==> AND (X, Y1, Y2)
+ */
+ item3->add_at_head($1);
+ $$ = $3;
}
else
- $$= $1;
- delete list;
+ {
+ /* X AND Y */
+ $$ = new (YYTHD->mem_root) Item_cond_and($1, $3);
+ }
}
- ;
-
-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); }
- | bool_test
- ;
-
-bool_test:
- bool_pri IS TRUE_SYM
+ | NOT_SYM expr %prec NOT_SYM
+ { $$= negate_expression(YYTHD, $2); }
+ | bool_pri IS TRUE_SYM %prec IS
{ $$= new (YYTHD->mem_root) Item_func_istrue($1); }
- | bool_pri IS not TRUE_SYM
+ | bool_pri IS not TRUE_SYM %prec IS
{ $$= new (YYTHD->mem_root) Item_func_isnottrue($1); }
- | bool_pri IS FALSE_SYM
+ | bool_pri IS FALSE_SYM %prec IS
{ $$= new (YYTHD->mem_root) Item_func_isfalse($1); }
- | bool_pri IS not FALSE_SYM
+ | bool_pri IS not FALSE_SYM %prec IS
{ $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); }
- | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); }
- | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); }
+ | bool_pri IS UNKNOWN_SYM %prec IS
+ { $$= new Item_func_isnull($1); }
+ | bool_pri IS not UNKNOWN_SYM %prec IS
+ { $$= new Item_func_isnotnull($1); }
| bool_pri
;
bool_pri:
- bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); }
- | bool_pri IS not NULL_SYM { $$= new Item_func_isnotnull($1); }
- | bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); }
+ bool_pri IS NULL_SYM %prec IS
+ { $$= new Item_func_isnull($1); }
+ | bool_pri IS not NULL_SYM %prec IS
+ { $$= new Item_func_isnotnull($1); }
+ | bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
+ { $$= new Item_func_equal($1,$3); }
| bool_pri comp_op predicate %prec EQ
{ $$= (*$2)(0)->create($1,$3); }
| bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
{ $$= all_any_subquery_creator($1, $2, $3, $5); }
- | predicate
+ | predicate ;
;
predicate:
@@ -6700,44 +6751,34 @@ predicate:
;
bit_expr:
- bit_expr '|' bit_term { $$= new Item_func_bit_or($1,$3); }
- | bit_term
- ;
-
-bit_term:
- bit_term '&' bit_factor { $$= new Item_func_bit_and($1,$3); }
- | bit_factor
- ;
-
-bit_factor:
- bit_factor SHIFT_LEFT value_expr
+ bit_expr '|' bit_expr %prec '|'
+ { $$= new Item_func_bit_or($1,$3); }
+ | bit_expr '&' bit_expr %prec '&'
+ { $$= new Item_func_bit_and($1,$3); }
+ | bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT
{ $$= new Item_func_shift_left($1,$3); }
- | bit_factor SHIFT_RIGHT value_expr
+ | bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT
{ $$= new Item_func_shift_right($1,$3); }
- | value_expr
- ;
-
-value_expr:
- value_expr '+' term { $$= new Item_func_plus($1,$3); }
- | value_expr '-' term { $$= new Item_func_minus($1,$3); }
- | value_expr '+' interval_expr interval
+ | bit_expr '+' bit_expr %prec '+'
+ { $$= new Item_func_plus($1,$3); }
+ | bit_expr '-' bit_expr %prec '-'
+ { $$= new Item_func_minus($1,$3); }
+ | bit_expr '+' interval_expr interval %prec '+'
{ $$= new Item_date_add_interval($1,$3,$4,0); }
- | value_expr '-' interval_expr interval
+ | bit_expr '-' interval_expr interval %prec '-'
{ $$= new Item_date_add_interval($1,$3,$4,1); }
- | term
- ;
-
-term:
- term '*' factor { $$= new Item_func_mul($1,$3); }
- | term '/' factor { $$= new Item_func_div($1,$3); }
- | term '%' factor { $$= new Item_func_mod($1,$3); }
- | term DIV_SYM factor { $$= new Item_func_int_div($1,$3); }
- | term MOD_SYM factor { $$= new Item_func_mod($1,$3); }
- | factor
- ;
-
-factor:
- factor '^' simple_expr { $$= new Item_func_bit_xor($1,$3); }
+ | bit_expr '*' bit_expr %prec '*'
+ { $$= new Item_func_mul($1,$3); }
+ | bit_expr '/' bit_expr %prec '/'
+ { $$= new Item_func_div($1,$3); }
+ | bit_expr '%' bit_expr %prec '%'
+ { $$= new Item_func_mod($1,$3); }
+ | bit_expr DIV_SYM bit_expr %prec DIV_SYM
+ { $$= new Item_func_int_div($1,$3); }
+ | bit_expr MOD_SYM bit_expr %prec MOD_SYM
+ { $$= new Item_func_mod($1,$3); }
+ | bit_expr '^' bit_expr
+ { $$= new Item_func_bit_xor($1,$3); }
| simple_expr
;
@@ -6776,7 +6817,8 @@ all_or_any:
;
interval_expr:
- INTERVAL_SYM expr { $$=$2; }
+ INTERVAL_SYM expr %prec INTERVAL_SYM
+ { $$=$2; }
;
simple_expr:
@@ -6799,7 +6841,7 @@ simple_expr:
| sum_expr
| simple_expr OR_OR_SYM simple_expr
{ $$= new (YYTHD->mem_root) Item_func_concat($1, $3); }
- | '+' simple_expr %prec NEG { $$= $2; }
+ | '+' simple_expr %prec NEG { $$= $2; }
| '-' simple_expr %prec NEG
{ $$= new (YYTHD->mem_root) Item_func_neg($2); }
| '~' simple_expr %prec NEG
@@ -7210,7 +7252,7 @@ function_call_generic:
$<udf>$= udf;
#endif
}
- udf_expr_list ')'
+ opt_udf_expr_list ')'
{
THD *thd= YYTHD;
Create_func *builder;
@@ -7307,27 +7349,23 @@ opt_query_expansion:
| WITH QUERY_SYM EXPANSION_SYM { $$= FT_EXPAND; }
;
+opt_udf_expr_list:
+ /* empty */ { $$= NULL; }
+ | udf_expr_list { $$= $1; }
+ ;
+
udf_expr_list:
- /* empty */ { $$= NULL; }
- | udf_expr_list2 { $$= $1;}
- ;
-
-udf_expr_list2:
- { Select->expr_list.push_front(new List<Item>); }
- udf_expr_list3
- { $$= Select->expr_list.pop(); }
- ;
-
-udf_expr_list3:
- udf_expr
- {
- Select->expr_list.head()->push_back($1);
- }
- | udf_expr_list3 ',' udf_expr
- {
- Select->expr_list.head()->push_back($3);
- }
- ;
+ udf_expr
+ {
+ $$= new (YYTHD->mem_root) List<Item>;
+ $$->push_back($1);
+ }
+ | udf_expr_list ',' udf_expr
+ {
+ $1->push_back($3);
+ $$= $1;
+ }
+ ;
udf_expr:
remember_name expr remember_end select_alias
@@ -7525,13 +7563,17 @@ opt_expr_list:
;
expr_list:
- { Select->expr_list.push_front(new List<Item>); }
- expr_list2
- { $$= Select->expr_list.pop(); };
-
-expr_list2:
- expr { Select->expr_list.head()->push_back($1); }
- | expr_list2 ',' expr { Select->expr_list.head()->push_back($3); };
+ expr
+ {
+ $$= new (YYTHD->mem_root) List<Item>;
+ $$->push_back($1);
+ }
+ | expr_list ',' expr
+ {
+ $1->push_back($3);
+ $$= $1;
+ }
+ ;
ident_list_arg:
ident_list { $$= $1; }
@@ -7539,13 +7581,17 @@ ident_list_arg:
;
ident_list:
- { Select->expr_list.push_front(new List<Item>); }
- ident_list2
- { $$= Select->expr_list.pop(); };
-
-ident_list2:
- simple_ident { Select->expr_list.head()->push_back($1); }
- | ident_list2 ',' simple_ident { Select->expr_list.head()->push_back($3); };
+ simple_ident
+ {
+ $$= new (YYTHD->mem_root) List<Item>;
+ $$->push_back($1);
+ }
+ | ident_list ',' simple_ident
+ {
+ $1->push_back($3);
+ $$= $1;
+ }
+ ;
opt_expr:
/* empty */ { $$= NULL; }