diff options
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r-- | sql/sql_yacc.yy | 330 |
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; } |