WL#638 - Fix precedence for parsing NOT ... LIKE expression s

  Rework parser expression rules
  Rework handling for "||" concat/or
  Eliminate some shift/reduce conflicts
  Add support for "xxx IS [ NOT ] truth_value"
parent 505324c1
......@@ -2,7 +2,7 @@ drop table if exists t1;
set sql_mode="MySQL40";
select @@sql_mode;
@@sql_mode
NO_FIELD_OPTIONS,MYSQL40
NO_FIELD_OPTIONS,MYSQL40,BROKEN_NOT
set @@sql_mode="ANSI";
select @@sql_mode;
@@sql_mode
......
......@@ -33,6 +33,24 @@ a
SELECT * FROM t1 where (1 AND a) IS NULL;
a
NULL
set sql_mode='broken_not';
select * from t1 where not a between 2 and 3;
a
set sql_mode=default;
select * from t1 where not a between 2 and 3;
a
0
1
select a, a is false, a is true, a is unknown from t1;
a a is false a is true a is unknown
0 1 0 0
1 0 1 0
NULL 0 0 1
select a, a is not false, a is not true, a is not unknown from t1;
a a is not false a is not true a is not unknown
0 0 1 1
1 1 0 1
NULL 1 1 0
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
a
......
......@@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` (
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
Variable_name Value
sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40
sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,BROKEN_NOT
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
......
......@@ -20,6 +20,16 @@ SELECT * FROM t1 where (1 AND a)=0;
SELECT * FROM t1 where (1 AND a)=1;
SELECT * FROM t1 where (1 AND a) IS NULL;
# WL#638 - Behaviour of NOT does not follow SQL specification
set sql_mode='broken_not';
select * from t1 where not a between 2 and 3;
set sql_mode=default;
select * from t1 where not a between 2 and 3;
# SQL boolean tests
select a, a is false, a is true, a is unknown from t1;
select a, a is not false, a is not true, a is not unknown from t1;
# Verify that NULL optimisation works in AND clause:
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
......
......@@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
*/
static SYMBOL symbols[] = {
{ "&&", SYM(AND_SYM)},
{ "&&", SYM(AND_AND_SYM)},
{ "<", SYM(LT)},
{ "<=", SYM(LE)},
{ "<>", SYM(NE)},
......@@ -334,7 +334,7 @@ static SYMBOL symbols[] = {
{ "NEXT", SYM(NEXT_SYM)},
{ "NO", SYM(NO_SYM)},
{ "NONE", SYM(NONE_SYM)},
{ "NOT", SYM(NOT)},
{ "NOT", SYM(NOT_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
{ "NULL", SYM(NULL_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)},
......@@ -489,6 +489,7 @@ static SYMBOL symbols[] = {
{ "UNICODE", SYM(UNICODE_SYM)},
{ "UNION", SYM(UNION_SYM)},
{ "UNIQUE", SYM(UNIQUE_SYM)},
{ "UNKNOWN", SYM(UNKNOWN_SYM)},
{ "UNLOCK", SYM(UNLOCK_SYM)},
{ "UNSIGNED", SYM(UNSIGNED)},
{ "UNTIL", SYM(UNTIL_SYM)},
......@@ -523,7 +524,7 @@ static SYMBOL symbols[] = {
{ "YEAR", SYM(YEAR_SYM)},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM)},
{ "ZEROFILL", SYM(ZEROFILL)},
{ "||", SYM(OR_OR_CONCAT)}
{ "||", SYM(OR_OR_SYM)}
};
......
......@@ -282,6 +282,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2)
#define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2)
#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2)
#define MODE_BROKEN_NOT (MODE_NO_AUTO_CREATE_USER*2)
#define RAID_BLOCK_SIZE 1024
......
......@@ -221,7 +221,7 @@ const char *sql_mode_names[] =
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES",
"NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO",
"TRADITIONAL", "NO_AUTO_CREATE_USER",
"TRADITIONAL", "NO_AUTO_CREATE_USER", "BROKEN_NOT",
NullS
};
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
......
......@@ -3111,9 +3111,9 @@ ulong fix_sql_mode(ulong sql_mode)
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
if (sql_mode & MODE_MYSQL40)
sql_mode|= MODE_NO_FIELD_OPTIONS;
sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_BROKEN_NOT;
if (sql_mode & MODE_MYSQL323)
sql_mode|= MODE_NO_FIELD_OPTIONS;
sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_BROKEN_NOT;
if (sql_mode & MODE_TRADITIONAL)
sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
......
......@@ -200,6 +200,14 @@ static int find_keyword(LEX *lex, uint len, bool function)
lex->yylval->symbol.symbol=symbol;
lex->yylval->symbol.str= (char*) tok;
lex->yylval->symbol.length=len;
if ((symbol->tok == NOT_SYM) &&
(lex->thd->variables.sql_mode & MODE_BROKEN_NOT))
return NOT2_SYM;
if ((symbol->tok == OR_OR_SYM) &&
!(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
return OR2_SYM;
return symbol->tok;
}
return 0;
......
......@@ -51,10 +51,13 @@ int yylex(void *yylval, void *yythd);
ER_WARN_DEPRECATED_SYNTAX, \
ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
inline Item *or_or_concat(THD *thd, Item* A, Item* B)
/* Helper for parsing "IS [NOT] truth_value" */
inline Item *is_truth_value(Item *A, bool v1, bool v2)
{
return (thd->variables.sql_mode & MODE_PIPES_AS_CONCAT ?
(Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B));
return new Item_func_if(create_func_ifnull(A,
new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)),
new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1),
new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1));
}
%}
......@@ -197,6 +200,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ALGORITHM_SYM
%token ALL
%token AND_SYM
%token AND_AND_SYM
%token AS
%token ASC
%token AUTO_INC
......@@ -341,7 +345,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NCHAR_SYM
%token NCHAR_STRING
%token NVARCHAR_SYM
%token NOT
%token NOT_SYM
%token NOT2_SYM
%token NO_SYM
%token NULL_SYM
%token NUM
......@@ -352,7 +357,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token OPTION
%token OPTIONALLY
%token OR_SYM
%token OR_OR_CONCAT
%token OR2_SYM
%token OR_OR_SYM
%token ORDER_SYM
%token OUT_SYM
%token OUTER
......@@ -436,6 +442,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UNICODE_SYM
%token UNION_SYM
%token UNIQUE_SYM
%token UNKNOWN_SYM
%token USAGE
%token USE_FRM
%token USE_SYM
......@@ -638,8 +645,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token BEFORE_SYM
%left SET_VAR
%left OR_OR_CONCAT OR_SYM XOR
%left AND_SYM
%left OR_OR_SYM OR_SYM OR2_SYM 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
%left '|'
......@@ -649,7 +656,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left '*' '/' '%' DIV_SYM MOD_SYM
%left '^'
%left NEG '~'
%right NOT
%right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM
%type <lex_str>
......@@ -692,7 +699,9 @@ 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
table_wild no_in_expr expr_expr simple_expr no_and_expr udf_expr
bool_term bool_factor bool_test bool_pri
predicate bit_expr bit_term bit_factor value_expr term factor
table_wild simple_expr udf_expr
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
......@@ -805,7 +814,7 @@ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_CONCAT BETWEEN_SYM CASE_SYM
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM
%%
......@@ -1405,7 +1414,7 @@ sp_chistic:
sp_c_chistic:
sp_chistic { }
| DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; }
| NOT DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
| not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
;
sp_suid:
......@@ -1756,7 +1765,7 @@ sp_hcond:
$$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
$$->type= sp_cond_type_t::warning;
}
| NOT FOUND_SYM /* SQLSTATEs 02??? */
| not FOUND_SYM /* SQLSTATEs 02??? */
{
$$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
$$->type= sp_cond_type_t::notfound;
......@@ -2495,7 +2504,7 @@ table_option:
opt_if_not_exists:
/* empty */ { $$= 0; }
| IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
| IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
opt_create_table_options:
/* empty */
......@@ -2917,7 +2926,7 @@ opt_attribute_list:
attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
| NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
| ON UPDATE_SYM NOW_SYM optional_braces
{ Lex->on_update_value= new Item_func_now_local(); }
......@@ -3956,9 +3965,102 @@ optional_braces:
/* all possible expressions */
expr:
expr_expr { $$= $1; }
| simple_expr { $$= $1; }
;
expr or bool_term { $$= new Item_cond_or($1,$3); }
| expr XOR bool_term { $$= new Item_cond_xor($1,$3); }
| bool_term ;
bool_term:
bool_term and bool_factor { $$= new Item_cond_and($1,$3); }
| bool_factor ;
bool_factor:
NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); }
| bool_test ;
bool_test:
bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); }
| bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); }
| bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); }
| bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); }
| bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); }
| bool_pri IS not UNKNOWN_SYM { $$= 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); }
| predicate BETWEEN_SYM bit_expr AND_SYM bool_pri
{ $$= new Item_func_between($1,$3,$5); }
| predicate not BETWEEN_SYM bit_expr AND_SYM bool_pri
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| predicate ;
predicate:
bit_expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| bit_expr not IN_SYM '(' expr_list ')'
{ $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| bit_expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
| bit_expr not IN_SYM in_subselect
{ $$= new Item_func_not(new Item_in_subselect($1, $4)); }
| bit_expr SOUNDS_SYM LIKE bit_expr
{ $$= new Item_func_eq(new Item_func_soundex($1),
new Item_func_soundex($4)); }
| bit_expr LIKE simple_expr opt_escape
{ $$= new Item_func_like($1,$3,$4); }
| bit_expr not LIKE simple_expr opt_escape
{ $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| bit_expr REGEXP bit_expr { $$= new Item_func_regex($1,$3); }
| bit_expr not REGEXP bit_expr
{ $$= new Item_func_not(new Item_func_regex($1,$4)); }
| bit_expr EQUAL_SYM bit_expr { $$= new Item_func_equal($1,$3); }
| bit_expr comp_op bit_expr %prec EQ
{ $$= (*$2)(0)->create($1,$3); }
| bit_expr comp_op all_or_any in_subselect %prec EQ
{ $$= all_any_subquery_creator($1, $2, $3, $4); }
| bit_expr ;
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
{ $$= new Item_func_shift_left($1,$3); }
| bit_factor SHIFT_RIGHT value_expr
{ $$= 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
{ $$= new Item_date_add_interval($1,$3,$4,0); }
| value_expr '-' interval_expr interval
{ $$= 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); }
| simple_expr ;
or: OR_SYM | OR2_SYM;
and: AND_SYM | AND_AND_SYM;
not: NOT_SYM | NOT2_SYM;
not2: '!' | NOT2_SYM;
comp_op: EQ { $$ = &comp_eq_creator; }
| GE { $$ = &comp_ge_creator; }
......@@ -3972,169 +4074,6 @@ all_or_any: ALL { $$ = 1; }
| ANY_SYM { $$ = 0; }
;
/* expressions that begin with 'expr' */
expr_expr:
expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| expr NOT IN_SYM '(' expr_list ')'
{ $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
| expr NOT IN_SYM in_subselect
{
$$= new Item_func_not(new Item_in_subselect($1, $4));
}
| expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
| expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr AND_SYM expr { $$= new Item_cond_and($1,$3); }
| expr SOUNDS_SYM LIKE expr
{
$$= new Item_func_eq(new Item_func_soundex($1),
new Item_func_soundex($4));
}
| expr LIKE simple_expr opt_escape
{ $$= new Item_func_like($1,$3,$4); }
| expr NOT LIKE simple_expr opt_escape
{ $$= new Item_func_not(new Item_func_like($1,$4,$5));}
| expr REGEXP expr { $$= new Item_func_regex($1,$3); }
| expr NOT REGEXP expr
{ $$= new Item_func_not(new Item_func_regex($1,$4)); }
| expr IS NULL_SYM { $$= new Item_func_isnull($1); }
| expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
| expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
| expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
| expr comp_op all_or_any in_subselect %prec EQ
{
$$= all_any_subquery_creator($1, $2, $3, $4);
}
| expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
| expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
| expr '+' expr { $$= new Item_func_plus($1,$3); }
| expr '-' expr { $$= new Item_func_minus($1,$3); }
| expr '*' expr { $$= new Item_func_mul($1,$3); }
| expr '/' expr { $$= new Item_func_div($1,$3); }
| expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
| expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
| expr '|' expr { $$= new Item_func_bit_or($1,$3); }
| expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| expr '%' expr { $$= new Item_func_mod($1,$3); }
| expr '+' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,0); }
| expr '-' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,1); }
;
/* expressions that begin with 'expr' that do NOT follow IN_SYM */
no_in_expr:
no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
| no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr AND_SYM expr { $$= new Item_cond_and($1,$3); }
| no_in_expr SOUNDS_SYM LIKE expr
{
$$= new Item_func_eq(new Item_func_soundex($1),
new Item_func_soundex($4));
}
| no_in_expr LIKE simple_expr opt_escape
{ $$= new Item_func_like($1,$3,$4); }
| no_in_expr NOT LIKE simple_expr opt_escape
{ $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
| no_in_expr NOT REGEXP expr
{ $$= new Item_func_not(new Item_func_regex($1,$4)); }
| no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
| no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
| no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
| no_in_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
| no_in_expr comp_op all_or_any in_subselect %prec EQ
{
all_any_subquery_creator($1, $2, $3, $4);
}
| no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
| no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
| no_in_expr '+' expr { $$= new Item_func_plus($1,$3); }
| no_in_expr '-' expr { $$= new Item_func_minus($1,$3); }
| no_in_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_in_expr '/' expr { $$= new Item_func_div($1,$3); }
| no_in_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
| no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
| no_in_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_in_expr '%' expr { $$= new Item_func_mod($1,$3); }
| no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
| no_in_expr '+' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,0); }
| no_in_expr '-' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,1); }
| simple_expr;
/* expressions that begin with 'expr' that does NOT follow AND */
no_and_expr:
no_and_expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
{ $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| no_and_expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
| no_and_expr NOT IN_SYM in_subselect
{
$$= new Item_func_not(new Item_in_subselect($1, $4));
}
| no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
| no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_and_expr SOUNDS_SYM LIKE expr
{
$$= new Item_func_eq(new Item_func_soundex($1),
new Item_func_soundex($4));
}
| no_and_expr LIKE simple_expr opt_escape
{ $$= new Item_func_like($1,$3,$4); }
| no_and_expr NOT LIKE simple_expr opt_escape
{ $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
| no_and_expr NOT REGEXP expr
{ $$= new Item_func_not(new Item_func_regex($1,$4)); }
| no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
| no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
| no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
| no_and_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
| no_and_expr comp_op all_or_any in_subselect %prec EQ
{
all_any_subquery_creator($1, $2, $3, $4);
}
| no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
| no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
| no_and_expr '+' expr { $$= new Item_func_plus($1,$3); }
| no_and_expr '-' expr { $$= new Item_func_minus($1,$3); }
| no_and_expr '*' expr { $$= new Item_func_mul($1,$3); }
| no_and_expr '/' expr { $$= new Item_func_div($1,$3); }
| no_and_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
| no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
| no_and_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
| no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
| no_and_expr '%' expr { $$= new Item_func_mod($1,$3); }
| no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
| no_and_expr '+' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,0); }
| no_and_expr '-' interval_expr interval
{ $$= new Item_date_add_interval($1,$3,$4,1); }
| simple_expr;
interval_expr:
INTERVAL_SYM expr { $$=$2; }
;
......@@ -4177,17 +4116,12 @@ simple_expr:
Lex->variables_used= 1;
}
| sum_expr
| '+' expr %prec NEG { $$= $2; }
| '-' expr %prec NEG { $$= new Item_func_neg($2); }
| '~' expr %prec NEG { $$= new Item_func_bit_neg($2); }
| NOT expr %prec NEG
{
$$= negate_expression(YYTHD, $2);
}
| '!' expr %prec NEG
{
$$= negate_expression(YYTHD, $2);
}
| simple_expr OR_OR_SYM simple_expr
{ $$= new Item_func_concat($1, $3); }
| '+' simple_expr %prec NEG { $$= $2; }
| '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
| '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
| not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
| '(' expr ')' { $$= $2; }
| '(' expr ',' expr_list ')'
{
......@@ -4202,12 +4136,12 @@ simple_expr:
| EXISTS exists_subselect { $$= $2; }
| singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr fulltext_options ')'
| MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{ $2->push_front($5);
Select->add_ftfunc_to_list((Item_func_match*)
($$=new Item_func_match(*$2,$6))); }
| ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); }
| BINARY expr %prec NEG
| BINARY simple_expr %prec NEG
{
$$= create_func_cast($2, ITEM_CAST_CHAR, -1, &my_charset_bin);
}
......@@ -4452,7 +4386,7 @@ simple_expr:
}
| OLD_PASSWORD '(' expr ')'
{ $$= new Item_func_old_password($3); }
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
| POSITION_SYM '(' bit_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
| QUARTER_SYM '(' expr ')'
{ $$ = new Item_func_quarter($3); }
......@@ -7107,6 +7041,7 @@ keyword:
| UNCOMMITTED_SYM {}
| UNDEFINED_SYM {}
| UNICODE_SYM {}
| UNKNOWN_SYM {}
| UNTIL_SYM {}
| USER {}
| USE_FRM {}
......
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