From 05a878c139963d4859ef8f2c974fee5dae56ee51 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 5 Oct 2020 12:50:51 +0200 Subject: precedence bugfixing fix printing precedence for BETWEEN, LIKE/ESCAPE, REGEXP, IN don't use precedence for printing CASE/WHEN/THEN/ELSE/END fix parsing precedence of BETWEEN, LIKE/ESCAPE, REGEXP, IN support predicate arguments for IN, BETWEEN, SOUNDS LIKE, LIKE/ESCAPE, REGEXP use %nonassoc for unary operators fix parsing of IS TRUE/FALSE/UNKNOWN/NULL remove parser_precedence test as superseded by the precedence test --- sql/sql_yacc.yy | 115 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 60 insertions(+), 55 deletions(-) (limited to 'sql/sql_yacc.yy') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 138d5e13701..2eabc4f0a6d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -149,6 +149,14 @@ void LEX::parse_error() } +static Item* escape(THD *thd) +{ + thd->lex->escape_used= false; + const char *esc= thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES ? "" : "\\"; + return new (thd->mem_root) Item_string_ascii(thd, esc, MY_TEST(esc[0])); +} + + /** @brief Bison callback to report a syntax/OOM error @@ -1022,10 +1030,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 102 shift/reduce conflicts. + Currently there are 105 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 101 +%expect 105 /* Comments for TOKENS. @@ -1721,17 +1729,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %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 '=' EQUAL_SYM GE '>' LE '<' NE IS LIKE REGEXP IN_SYM +%nonassoc NOT_SYM +%left '=' EQUAL_SYM GE '>' LE '<' NE +%nonassoc IS +%right BETWEEN_SYM +%left LIKE REGEXP IN_SYM %left '|' %left '&' %left SHIFT_LEFT SHIFT_RIGHT %left '-' '+' %left '*' '/' '%' DIV_SYM MOD_SYM %left '^' -%left NEG '~' -%right NOT_SYM NOT2_SYM -%right BINARY COLLATE_SYM +%nonassoc NEG '~' NOT2_SYM BINARY +%nonassoc COLLATE_SYM %left INTERVAL_SYM %type @@ -1831,7 +1841,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); table_wild simple_expr column_default_non_parenthesized_expr udf_expr expr_or_default set_expr_or_default geometry_function signed_literal expr_or_literal - opt_escape sp_opt_default simple_ident_nospvar simple_ident_q field_or_var limit_option @@ -8915,59 +8924,59 @@ expr: if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS TRUE_SYM %prec IS + | expr IS TRUE_SYM %prec IS { $$= new (thd->mem_root) Item_func_istrue(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS not TRUE_SYM %prec IS + | expr IS not TRUE_SYM %prec IS { $$= new (thd->mem_root) Item_func_isnottrue(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS FALSE_SYM %prec IS + | expr IS FALSE_SYM %prec IS { $$= new (thd->mem_root) Item_func_isfalse(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS not FALSE_SYM %prec IS + | expr IS not FALSE_SYM %prec IS { $$= new (thd->mem_root) Item_func_isnotfalse(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS UNKNOWN_SYM %prec IS + | expr IS UNKNOWN_SYM %prec IS { $$= new (thd->mem_root) Item_func_isnull(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS not UNKNOWN_SYM %prec IS + | expr IS not UNKNOWN_SYM %prec IS { $$= new (thd->mem_root) Item_func_isnotnull(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri - ; - -bool_pri: - bool_pri IS NULL_SYM %prec IS + | expr IS NULL_SYM %prec IS { $$= new (thd->mem_root) Item_func_isnull(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri IS not NULL_SYM %prec IS + | expr IS not NULL_SYM %prec IS { $$= new (thd->mem_root) Item_func_isnotnull(thd, $1); if ($$ == NULL) MYSQL_YYABORT; } - | bool_pri EQUAL_SYM predicate %prec EQUAL_SYM + | bool_pri + ; + +bool_pri: + bool_pri EQUAL_SYM predicate %prec EQUAL_SYM { $$= new (thd->mem_root) Item_func_equal(thd, $1, $3); if ($$ == NULL) @@ -8989,13 +8998,13 @@ bool_pri: ; predicate: - bit_expr IN_SYM '(' subselect ')' + predicate IN_SYM '(' subselect ')' { $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4); if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr not IN_SYM '(' subselect ')' + | predicate not IN_SYM '(' subselect ')' { Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5); if (item == NULL) @@ -9004,13 +9013,13 @@ predicate: if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr IN_SYM '(' expr ')' + | predicate IN_SYM '(' expr ')' { $$= handle_sql2003_note184_exception(thd, $1, true, $4); if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr IN_SYM '(' expr ',' expr_list ')' + | predicate IN_SYM '(' expr ',' expr_list ')' { $6->push_front($4, thd->mem_root); $6->push_front($1, thd->mem_root); @@ -9018,13 +9027,13 @@ predicate: if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr not IN_SYM '(' expr ')' + | predicate not IN_SYM '(' expr ')' { $$= handle_sql2003_note184_exception(thd, $1, false, $5); if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr not IN_SYM '(' expr ',' expr_list ')' + | predicate not IN_SYM '(' expr ',' expr_list ')' { $7->push_front($5, thd->mem_root); $7->push_front($1, thd->mem_root); @@ -9033,13 +9042,13 @@ predicate: MYSQL_YYABORT; $$= item->neg_transformer(thd); } - | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate + | predicate BETWEEN_SYM predicate AND_SYM predicate %prec BETWEEN_SYM { $$= new (thd->mem_root) Item_func_between(thd, $1, $3, $5); if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate + | predicate not BETWEEN_SYM predicate AND_SYM predicate %prec BETWEEN_SYM { Item_func_between *item; item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6); @@ -9047,7 +9056,7 @@ predicate: MYSQL_YYABORT; $$= item->neg_transformer(thd); } - | bit_expr SOUNDS_SYM LIKE bit_expr + | predicate SOUNDS_SYM LIKE predicate { Item *item1= new (thd->mem_root) Item_func_soundex(thd, $1); Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4); @@ -9057,28 +9066,41 @@ predicate: if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr LIKE simple_expr opt_escape + | predicate LIKE predicate + { + $$= new (thd->mem_root) Item_func_like(thd, $1, $3, escape(thd), false); + if ($$ == NULL) + MYSQL_YYABORT; + } + | predicate LIKE predicate ESCAPE_SYM predicate %prec LIKE { - $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4, - Lex->escape_used); + Lex->escape_used= true; + $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $5, true); if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr not LIKE simple_expr opt_escape + | predicate not LIKE predicate + { + Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, escape(thd), false); + if (item == NULL) + MYSQL_YYABORT; + $$= item->neg_transformer(thd); + } + | predicate not LIKE predicate ESCAPE_SYM predicate %prec LIKE { - Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5, - Lex->escape_used); + Lex->escape_used= true; + Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $6, true); if (item == NULL) MYSQL_YYABORT; $$= item->neg_transformer(thd); } - | bit_expr REGEXP bit_expr + | predicate REGEXP predicate { $$= new (thd->mem_root) Item_func_regex(thd, $1, $3); if ($$ == NULL) MYSQL_YYABORT; } - | bit_expr not REGEXP bit_expr + | predicate not REGEXP predicate { Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4); if (item == NULL) @@ -11468,23 +11490,6 @@ opt_having_clause: } ; -opt_escape: - ESCAPE_SYM simple_expr - { - Lex->escape_used= TRUE; - $$= $2; - } - | /* empty */ - { - Lex->escape_used= FALSE; - $$= ((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ? - new (thd->mem_root) Item_string_ascii(thd, "", 0) : - new (thd->mem_root) Item_string_ascii(thd, "\\", 1)); - if ($$ == NULL) - MYSQL_YYABORT; - } - ; - /* group by statement in select */ -- cgit v1.2.1