Commit 05a878c1 authored by Sergei Golubchik's avatar Sergei Golubchik

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
parent 7f974e5a
...@@ -10052,11 +10052,11 @@ EXPLAIN ...@@ -10052,11 +10052,11 @@ EXPLAIN
"access_type": "ALL", "access_type": "ALL",
"rows": 3, "rows": 3,
"filtered": 100, "filtered": 100,
"attached_condition": "case when (tab2.max_a = 1 or tab2.max_a = 2) then 1 else 0 end = 1", "attached_condition": "case when tab2.max_a = 1 or tab2.max_a = 2 then 1 else 0 end = 1",
"materialized": { "materialized": {
"query_block": { "query_block": {
"select_id": 3, "select_id": 3,
"having_condition": "case when (max_a = 1 or max_a = 2) then 1 else 0 end = 1", "having_condition": "case when max_a = 1 or max_a = 2 then 1 else 0 end = 1",
"filesort": { "filesort": {
"sort_key": "t1.b", "sort_key": "t1.b",
"temporary_table": { "temporary_table": {
...@@ -10101,11 +10101,11 @@ EXPLAIN ...@@ -10101,11 +10101,11 @@ EXPLAIN
"access_type": "ALL", "access_type": "ALL",
"rows": 3, "rows": 3,
"filtered": 100, "filtered": 100,
"attached_condition": "case when (tab2.max_a = 1 or tab2.max_a > 2 and tab2.max_a < 4) then 1 else 0 end = 1", "attached_condition": "case when tab2.max_a = 1 or tab2.max_a > 2 and tab2.max_a < 4 then 1 else 0 end = 1",
"materialized": { "materialized": {
"query_block": { "query_block": {
"select_id": 3, "select_id": 3,
"having_condition": "case when (max_a = 1 or max_a > 2 and max_a < 4) then 1 else 0 end = 1", "having_condition": "case when max_a = 1 or max_a > 2 and max_a < 4 then 1 else 0 end = 1",
"filesort": { "filesort": {
"sort_key": "t1.b", "sort_key": "t1.b",
"temporary_table": { "temporary_table": {
...@@ -10150,11 +10150,11 @@ EXPLAIN ...@@ -10150,11 +10150,11 @@ EXPLAIN
"access_type": "ALL", "access_type": "ALL",
"rows": 3, "rows": 3,
"filtered": 100, "filtered": 100,
"attached_condition": "case when (tab2.max_a > 1 and (tab2.max_a = 2 or tab2.max_a > 2)) then 1 else 0 end = 1", "attached_condition": "case when tab2.max_a > 1 and (tab2.max_a = 2 or tab2.max_a > 2) then 1 else 0 end = 1",
"materialized": { "materialized": {
"query_block": { "query_block": {
"select_id": 3, "select_id": 3,
"having_condition": "case when (max_a > 1 and (max_a = 2 or max_a > 2)) then 1 else 0 end = 1", "having_condition": "case when max_a > 1 and (max_a = 2 or max_a > 2) then 1 else 0 end = 1",
"filesort": { "filesort": {
"sort_key": "t1.b", "sort_key": "t1.b",
"temporary_table": { "temporary_table": {
...@@ -10199,7 +10199,7 @@ EXPLAIN ...@@ -10199,7 +10199,7 @@ EXPLAIN
"access_type": "ALL", "access_type": "ALL",
"rows": 3, "rows": 3,
"filtered": 100, "filtered": 100,
"attached_condition": "case when (tab2.b = 2 or tab2.b = 4) then 1 else 0 end = 1", "attached_condition": "case when tab2.b = 2 or tab2.b = 4 then 1 else 0 end = 1",
"materialized": { "materialized": {
"query_block": { "query_block": {
"select_id": 3, "select_id": 3,
...@@ -10211,7 +10211,7 @@ EXPLAIN ...@@ -10211,7 +10211,7 @@ EXPLAIN
"access_type": "ALL", "access_type": "ALL",
"rows": 3, "rows": 3,
"filtered": 100, "filtered": 100,
"attached_condition": "case when (t1.b = 2 or t1.b = 4) then 1 else 0 end = 1" "attached_condition": "case when t1.b = 2 or t1.b = 4 then 1 else 0 end = 1"
} }
} }
} }
......
...@@ -89,15 +89,6 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -89,15 +89,6 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings: Warnings:
Note 1003 select -1 AS `- a` from dual Note 1003 select -1 AS `- a` from dual
drop table t1; drop table t1;
select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1
0 1
select 1 and 2 between 2 and 10, 2 between 2 and 10 and 1;
1 and 2 between 2 and 10 2 between 2 and 10 and 1
1 1
select 1 and 0 or 2, 2 or 1 and 0;
1 and 0 or 2 2 or 1 and 0
1 1
select _koi8r'a' = _koi8r'A'; select _koi8r'a' = _koi8r'A';
_koi8r'a' = _koi8r'A' _koi8r'a' = _koi8r'A'
1 1
......
...@@ -1321,3 +1321,20 @@ t1 CREATE TABLE `t1` ( ...@@ -1321,3 +1321,20 @@ t1 CREATE TABLE `t1` (
UNIQUE KEY `id` (`id`) UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
create or replace view v1 as select 1 between (2 between 3 and 4) and 5;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
view_definition
select 1 between 2 between 3 and 4 and 5 AS `1 between (2 between 3 and 4) and 5`
create or replace view v1 as select 1 between (2 in (3,4)) and 5;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
view_definition
select 1 between 2 in (3,4) and 5 AS `1 between (2 in (3,4)) and 5`
create or replace view v1 as select 1 between (2 like 3) and 4;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
view_definition
select 1 between 2 like 3 and 4 AS `1 between (2 like 3) and 4`
create or replace view v1 as select 1 not between (2 like 3) and 4;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
view_definition
select 1 not between 2 like 3 and 4 AS `1 not between (2 like 3) and 4`
drop view v1;
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -35,14 +35,6 @@ select - a from t1; ...@@ -35,14 +35,6 @@ select - a from t1;
explain extended select - a from t1; explain extended select - a from t1;
drop table t1; drop table t1;
#
# Wrong usage of functions
#
select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
select 1 and 2 between 2 and 10, 2 between 2 and 10 and 1;
select 1 and 0 or 2, 2 or 1 and 0;
# #
# Coercibility # Coercibility
# #
......
...@@ -1351,3 +1351,17 @@ create function fs() returns serial return 1; ...@@ -1351,3 +1351,17 @@ create function fs() returns serial return 1;
create table t1 ( id serial ); create table t1 ( id serial );
show create table t1; show create table t1;
drop table t1; drop table t1;
#
# BETWEEN syntax
#
create or replace view v1 as select 1 between (2 between 3 and 4) and 5;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
create or replace view v1 as select 1 between (2 in (3,4)) and 5;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
create or replace view v1 as select 1 between (2 like 3) and 4;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
create or replace view v1 as select 1 not between (2 like 3) and 4;
Select view_definition from information_schema.views where table_schema='test' and table_name='v1';
drop view v1;
This diff is collapsed.
...@@ -82,8 +82,9 @@ enum precedence { ...@@ -82,8 +82,9 @@ enum precedence {
XOR_PRECEDENCE, // XOR XOR_PRECEDENCE, // XOR
AND_PRECEDENCE, // AND, && AND_PRECEDENCE, // AND, &&
NOT_PRECEDENCE, // NOT (unless HIGH_NOT_PRECEDENCE) NOT_PRECEDENCE, // NOT (unless HIGH_NOT_PRECEDENCE)
BETWEEN_PRECEDENCE, // BETWEEN, CASE, WHEN, THEN, ELSE CMP_PRECEDENCE, // =, <=>, >=, >, <=, <, <>, !=, IS
CMP_PRECEDENCE, // =, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN BETWEEN_PRECEDENCE, // BETWEEN
IN_PRECEDENCE, // IN, LIKE, REGEXP
BITOR_PRECEDENCE, // | BITOR_PRECEDENCE, // |
BITAND_PRECEDENCE, // & BITAND_PRECEDENCE, // &
SHIFT_PRECEDENCE, // <<, >> SHIFT_PRECEDENCE, // <<, >>
...@@ -1381,6 +1382,8 @@ class Item: public Value_source, ...@@ -1381,6 +1382,8 @@ class Item: public Value_source,
mysql_register_view(). mysql_register_view().
*/ */
virtual enum precedence precedence() const { return DEFAULT_PRECEDENCE; } virtual enum precedence precedence() const { return DEFAULT_PRECEDENCE; }
enum precedence higher_precedence() const
{ return (enum precedence)(precedence() + 1); }
void print_parenthesised(String *str, enum_query_type query_type, void print_parenthesised(String *str, enum_query_type query_type,
enum precedence parent_prec); enum precedence parent_prec);
/** /**
......
...@@ -2312,7 +2312,7 @@ longlong Item_func_between::val_int() ...@@ -2312,7 +2312,7 @@ longlong Item_func_between::val_int()
void Item_func_between::print(String *str, enum_query_type query_type) void Item_func_between::print(String *str, enum_query_type query_type)
{ {
args[0]->print_parenthesised(str, query_type, precedence()); args[0]->print_parenthesised(str, query_type, higher_precedence());
if (negated) if (negated)
str->append(STRING_WITH_LEN(" not")); str->append(STRING_WITH_LEN(" not"));
str->append(STRING_WITH_LEN(" between ")); str->append(STRING_WITH_LEN(" between "));
...@@ -3375,15 +3375,15 @@ void Item_func_case::print(String *str, enum_query_type query_type) ...@@ -3375,15 +3375,15 @@ void Item_func_case::print(String *str, enum_query_type query_type)
for (uint i= first_expr_num + 1 ; i < nwhens + first_expr_num + 1; i++) for (uint i= first_expr_num + 1 ; i < nwhens + first_expr_num + 1; i++)
{ {
str->append(STRING_WITH_LEN("when ")); str->append(STRING_WITH_LEN("when "));
args[i]->print_parenthesised(str, query_type, precedence()); args[i]->print(str, query_type);
str->append(STRING_WITH_LEN(" then ")); str->append(STRING_WITH_LEN(" then "));
args[i+nwhens]->print_parenthesised(str, query_type, precedence()); args[i+nwhens]->print(str, query_type);
str->append(' '); str->append(' ');
} }
if (else_expr_num != -1) if (else_expr_num != -1)
{ {
str->append(STRING_WITH_LEN("else ")); str->append(STRING_WITH_LEN("else "));
args[else_expr_num]->print_parenthesised(str, query_type, precedence()); args[else_expr_num]->print(str, query_type);
str->append(' '); str->append(' ');
} }
str->append(STRING_WITH_LEN("end")); str->append(STRING_WITH_LEN("end"));
...@@ -5243,12 +5243,14 @@ void Item_func_like::print(String *str, enum_query_type query_type) ...@@ -5243,12 +5243,14 @@ void Item_func_like::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN(" not ")); str->append(STRING_WITH_LEN(" not "));
str->append(func_name()); str->append(func_name());
str->append(' '); str->append(' ');
args[1]->print_parenthesised(str, query_type, precedence());
if (escape_used_in_parsing) if (escape_used_in_parsing)
{ {
args[1]->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" escape ")); str->append(STRING_WITH_LEN(" escape "));
escape_item->print(str, query_type); escape_item->print_parenthesised(str, query_type, higher_precedence());
} }
else
args[1]->print_parenthesised(str, query_type, higher_precedence());
} }
......
...@@ -1590,7 +1590,6 @@ class Item_func_case :public Item_func_hybrid_field_type ...@@ -1590,7 +1590,6 @@ class Item_func_case :public Item_func_hybrid_field_type
uint decimal_precision() const; uint decimal_precision() const;
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
Item *find_item(String *str); Item *find_item(String *str);
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; } CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
...@@ -1704,7 +1703,7 @@ class Item_func_in :public Item_func_opt_neg ...@@ -1704,7 +1703,7 @@ class Item_func_in :public Item_func_opt_neg
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
enum Functype functype() const { return IN_FUNC; } enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return "in"; } const char *func_name() const { return "in"; }
enum precedence precedence() const { return CMP_PRECEDENCE; } enum precedence precedence() const { return IN_PRECEDENCE; }
bool eval_not_null_tables(void *opt_arg); bool eval_not_null_tables(void *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg); bool count_sargable_conds(void *arg);
...@@ -1999,7 +1998,7 @@ class Item_func_like :public Item_bool_func2 ...@@ -1999,7 +1998,7 @@ class Item_func_like :public Item_bool_func2
return this; return this;
} }
const char *func_name() const { return "like"; } const char *func_name() const { return "like"; }
enum precedence precedence() const { return CMP_PRECEDENCE; } enum precedence precedence() const { return IN_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
bool fix_length_and_dec() bool fix_length_and_dec()
{ {
...@@ -2127,7 +2126,7 @@ class Item_func_regex :public Item_bool_func ...@@ -2127,7 +2126,7 @@ class Item_func_regex :public Item_bool_func
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
bool fix_length_and_dec(); bool fix_length_and_dec();
const char *func_name() const { return "regexp"; } const char *func_name() const { return "regexp"; }
enum precedence precedence() const { return CMP_PRECEDENCE; } enum precedence precedence() const { return IN_PRECEDENCE; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
void print(String *str, enum_query_type query_type) void print(String *str, enum_query_type query_type)
{ {
......
...@@ -481,8 +481,7 @@ void Item_func::print_op(String *str, enum_query_type query_type) ...@@ -481,8 +481,7 @@ void Item_func::print_op(String *str, enum_query_type query_type)
str->append(func_name()); str->append(func_name());
str->append(' '); str->append(' ');
} }
args[arg_count-1]->print_parenthesised(str, query_type, args[arg_count-1]->print_parenthesised(str, query_type, higher_precedence());
(enum precedence)(precedence() + 1));
} }
......
...@@ -3283,7 +3283,7 @@ void Item_in_subselect::print(String *str, enum_query_type query_type) ...@@ -3283,7 +3283,7 @@ void Item_in_subselect::print(String *str, enum_query_type query_type)
str->append(STRING_WITH_LEN("<exists>")); str->append(STRING_WITH_LEN("<exists>"));
else else
{ {
left_expr->print(str, query_type); left_expr->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" in ")); str->append(STRING_WITH_LEN(" in "));
} }
Item_subselect::print(str, query_type); Item_subselect::print(str, query_type);
......
...@@ -628,7 +628,7 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -628,7 +628,7 @@ class Item_in_subselect :public Item_exists_subselect
bool val_bool(); bool val_bool();
bool test_limit(st_select_lex_unit *unit); bool test_limit(st_select_lex_unit *unit);
void print(String *str, enum_query_type query_type); void print(String *str, enum_query_type query_type);
enum precedence precedence() const { return CMP_PRECEDENCE; } enum precedence precedence() const { return IN_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref); bool fix_fields(THD *thd, Item **ref);
bool fix_length_and_dec(); bool fix_length_and_dec();
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
......
...@@ -149,6 +149,14 @@ void LEX::parse_error() ...@@ -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 @brief Bison callback to report a syntax/OOM error
...@@ -1022,10 +1030,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1022,10 +1030,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%parse-param { THD *thd } %parse-param { THD *thd }
%lex-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. We should not introduce new conflicts any more.
*/ */
%expect 101 %expect 105
/* /*
Comments for TOKENS. Comments for TOKENS.
...@@ -1721,17 +1729,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1721,17 +1729,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left OR_OR_SYM OR_SYM OR2_SYM %left OR_OR_SYM OR_SYM OR2_SYM
%left XOR %left XOR
%left AND_SYM AND_AND_SYM %left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE %nonassoc NOT_SYM
%left '=' EQUAL_SYM GE '>' LE '<' NE IS LIKE REGEXP IN_SYM %left '=' EQUAL_SYM GE '>' LE '<' NE
%nonassoc IS
%right BETWEEN_SYM
%left LIKE REGEXP IN_SYM
%left '|' %left '|'
%left '&' %left '&'
%left SHIFT_LEFT SHIFT_RIGHT %left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+' %left '-' '+'
%left '*' '/' '%' DIV_SYM MOD_SYM %left '*' '/' '%' DIV_SYM MOD_SYM
%left '^' %left '^'
%left NEG '~' %nonassoc NEG '~' NOT2_SYM BINARY
%right NOT_SYM NOT2_SYM %nonassoc COLLATE_SYM
%right BINARY COLLATE_SYM
%left INTERVAL_SYM %left INTERVAL_SYM
%type <lex_str> %type <lex_str>
...@@ -1831,7 +1841,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1831,7 +1841,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_wild simple_expr column_default_non_parenthesized_expr udf_expr table_wild simple_expr column_default_non_parenthesized_expr udf_expr
expr_or_default set_expr_or_default expr_or_default set_expr_or_default
geometry_function signed_literal expr_or_literal geometry_function signed_literal expr_or_literal
opt_escape
sp_opt_default sp_opt_default
simple_ident_nospvar simple_ident_q simple_ident_nospvar simple_ident_q
field_or_var limit_option field_or_var limit_option
...@@ -8915,59 +8924,59 @@ expr: ...@@ -8915,59 +8924,59 @@ expr:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bool_pri IS TRUE_SYM %prec IS | expr IS TRUE_SYM %prec IS
{ {
$$= new (thd->mem_root) Item_func_istrue(thd, $1); $$= new (thd->mem_root) Item_func_istrue(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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); $$= new (thd->mem_root) Item_func_isnottrue(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bool_pri IS FALSE_SYM %prec IS | expr IS FALSE_SYM %prec IS
{ {
$$= new (thd->mem_root) Item_func_isfalse(thd, $1); $$= new (thd->mem_root) Item_func_isfalse(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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); $$= new (thd->mem_root) Item_func_isnotfalse(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bool_pri IS UNKNOWN_SYM %prec IS | expr IS UNKNOWN_SYM %prec IS
{ {
$$= new (thd->mem_root) Item_func_isnull(thd, $1); $$= new (thd->mem_root) Item_func_isnull(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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); $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bool_pri | expr IS NULL_SYM %prec IS
;
bool_pri:
bool_pri IS NULL_SYM %prec IS
{ {
$$= new (thd->mem_root) Item_func_isnull(thd, $1); $$= new (thd->mem_root) Item_func_isnull(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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); $$= new (thd->mem_root) Item_func_isnotnull(thd, $1);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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); $$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
if ($$ == NULL) if ($$ == NULL)
...@@ -8989,13 +8998,13 @@ bool_pri: ...@@ -8989,13 +8998,13 @@ bool_pri:
; ;
predicate: predicate:
bit_expr IN_SYM '(' subselect ')' predicate IN_SYM '(' subselect ')'
{ {
$$= new (thd->mem_root) Item_in_subselect(thd, $1, $4); $$= new (thd->mem_root) Item_in_subselect(thd, $1, $4);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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); Item *item= new (thd->mem_root) Item_in_subselect(thd, $1, $5);
if (item == NULL) if (item == NULL)
...@@ -9004,13 +9013,13 @@ predicate: ...@@ -9004,13 +9013,13 @@ predicate:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bit_expr IN_SYM '(' expr ')' | predicate IN_SYM '(' expr ')'
{ {
$$= handle_sql2003_note184_exception(thd, $1, true, $4); $$= handle_sql2003_note184_exception(thd, $1, true, $4);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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($4, thd->mem_root);
$6->push_front($1, thd->mem_root); $6->push_front($1, thd->mem_root);
...@@ -9018,13 +9027,13 @@ predicate: ...@@ -9018,13 +9027,13 @@ predicate:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bit_expr not IN_SYM '(' expr ')' | predicate not IN_SYM '(' expr ')'
{ {
$$= handle_sql2003_note184_exception(thd, $1, false, $5); $$= handle_sql2003_note184_exception(thd, $1, false, $5);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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($5, thd->mem_root);
$7->push_front($1, thd->mem_root); $7->push_front($1, thd->mem_root);
...@@ -9033,13 +9042,13 @@ predicate: ...@@ -9033,13 +9042,13 @@ predicate:
MYSQL_YYABORT; MYSQL_YYABORT;
$$= item->neg_transformer(thd); $$= 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); $$= new (thd->mem_root) Item_func_between(thd, $1, $3, $5);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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_func_between *item;
item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6); item= new (thd->mem_root) Item_func_between(thd, $1, $4, $6);
...@@ -9047,7 +9056,7 @@ predicate: ...@@ -9047,7 +9056,7 @@ predicate:
MYSQL_YYABORT; MYSQL_YYABORT;
$$= item->neg_transformer(thd); $$= 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 *item1= new (thd->mem_root) Item_func_soundex(thd, $1);
Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4); Item *item4= new (thd->mem_root) Item_func_soundex(thd, $4);
...@@ -9057,28 +9066,41 @@ predicate: ...@@ -9057,28 +9066,41 @@ predicate:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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= true;
Lex->escape_used); $$= new (thd->mem_root) Item_func_like(thd, $1, $3, $5, true);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; 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= true;
Lex->escape_used); Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $6, true);
if (item == NULL) if (item == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
$$= item->neg_transformer(thd); $$= item->neg_transformer(thd);
} }
| bit_expr REGEXP bit_expr | predicate REGEXP predicate
{ {
$$= new (thd->mem_root) Item_func_regex(thd, $1, $3); $$= new (thd->mem_root) Item_func_regex(thd, $1, $3);
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| bit_expr not REGEXP bit_expr | predicate not REGEXP predicate
{ {
Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4); Item *item= new (thd->mem_root) Item_func_regex(thd, $1, $4);
if (item == NULL) if (item == NULL)
...@@ -11468,23 +11490,6 @@ opt_having_clause: ...@@ -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 group by statement in select
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment