Commit 191fa299 authored by unknown's avatar unknown

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"


mysql-test/r/ansi.result:
  Fix test for new BROKEN_NOT mode bit
mysql-test/r/bool.result:
  WL#638
    New test for BROKEN_NOT mode
    New test for "expr IS [NOT] truth_value" syntax
mysql-test/r/sql_mode.result:
  Fix test for new BROKEN_NOT mode bit
mysql-test/t/bool.test:
  WL#638
    New test for BROKEN_NOT mode
    New test for "expr IS [NOT] truth_value" syntax
sql/lex.h:
  WL#638
    "&&" and "AND" return different tokens,
    NOT token changed to NOT_SYM
    OR_OR_CONCAT token changed to OR_OR_SYM
    New token "UNKNOWN"
sql/mysql_priv.h:
  WL#638
    New mode: BROKEN_NOT
sql/mysqld.cc:
  WL#638
    New mode: BROKEN_NOT
sql/set_var.cc:
  WL#638
    New mode: BROKEN_NOT
    BROKEN_NOT is set in MYSQL323 and MYSQL40 modes
sql/sql_lex.cc:
  Bug#638
    Alter tokens returned by lexer depending upon sql_mode:
    Return NOT2_SYM token instead of NOT_SYM when in BROKEN_NOT mode
    Return OR2_SYM token instead of OR_OR_SYM when not in PIPES_AS_CONCAT mode
sql/sql_yacc.yy:
  WL#638
    Change grammar to respect proper SQL syntax for NOT
    Clean up grammar, eliminate >100 shift/reduce conflicts
    New support for "expr IS [NOT] truth_value" SQL syntax
    Remove or_or_concat() support func. New support func is_truth_value()
parent 1dad6550
...@@ -2,7 +2,7 @@ drop table if exists t1; ...@@ -2,7 +2,7 @@ drop table if exists t1;
set sql_mode="MySQL40"; set sql_mode="MySQL40";
select @@sql_mode; select @@sql_mode;
@@sql_mode @@sql_mode
NO_FIELD_OPTIONS,MYSQL40 NO_FIELD_OPTIONS,MYSQL40,BROKEN_NOT
set @@sql_mode="ANSI"; set @@sql_mode="ANSI";
select @@sql_mode; select @@sql_mode;
@@sql_mode @@sql_mode
......
...@@ -33,6 +33,24 @@ a ...@@ -33,6 +33,24 @@ a
SELECT * FROM t1 where (1 AND a) IS NULL; SELECT * FROM t1 where (1 AND a) IS NULL;
a a
NULL 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; SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1); SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
a a
......
...@@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` ( ...@@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` (
set @@sql_mode="no_field_options,mysql323,mysql40"; set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode'; show variables like 'sql_mode';
Variable_name Value Variable_name Value
sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40 sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,BROKEN_NOT
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
......
...@@ -20,6 +20,16 @@ SELECT * FROM t1 where (1 AND a)=0; ...@@ -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)=1;
SELECT * FROM t1 where (1 AND a) IS NULL; 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: # Verify that NULL optimisation works in AND clause:
SET @a=0, @b=0; SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1); SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
......
...@@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"}; ...@@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
*/ */
static SYMBOL symbols[] = { static SYMBOL symbols[] = {
{ "&&", SYM(AND_SYM)}, { "&&", SYM(AND_AND_SYM)},
{ "<", SYM(LT)}, { "<", SYM(LT)},
{ "<=", SYM(LE)}, { "<=", SYM(LE)},
{ "<>", SYM(NE)}, { "<>", SYM(NE)},
...@@ -334,7 +334,7 @@ static SYMBOL symbols[] = { ...@@ -334,7 +334,7 @@ static SYMBOL symbols[] = {
{ "NEXT", SYM(NEXT_SYM)}, { "NEXT", SYM(NEXT_SYM)},
{ "NO", SYM(NO_SYM)}, { "NO", SYM(NO_SYM)},
{ "NONE", SYM(NONE_SYM)}, { "NONE", SYM(NONE_SYM)},
{ "NOT", SYM(NOT)}, { "NOT", SYM(NOT_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)}, { "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
{ "NULL", SYM(NULL_SYM)}, { "NULL", SYM(NULL_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)}, { "NUMERIC", SYM(NUMERIC_SYM)},
...@@ -489,6 +489,7 @@ static SYMBOL symbols[] = { ...@@ -489,6 +489,7 @@ static SYMBOL symbols[] = {
{ "UNICODE", SYM(UNICODE_SYM)}, { "UNICODE", SYM(UNICODE_SYM)},
{ "UNION", SYM(UNION_SYM)}, { "UNION", SYM(UNION_SYM)},
{ "UNIQUE", SYM(UNIQUE_SYM)}, { "UNIQUE", SYM(UNIQUE_SYM)},
{ "UNKNOWN", SYM(UNKNOWN_SYM)},
{ "UNLOCK", SYM(UNLOCK_SYM)}, { "UNLOCK", SYM(UNLOCK_SYM)},
{ "UNSIGNED", SYM(UNSIGNED)}, { "UNSIGNED", SYM(UNSIGNED)},
{ "UNTIL", SYM(UNTIL_SYM)}, { "UNTIL", SYM(UNTIL_SYM)},
...@@ -523,7 +524,7 @@ static SYMBOL symbols[] = { ...@@ -523,7 +524,7 @@ static SYMBOL symbols[] = {
{ "YEAR", SYM(YEAR_SYM)}, { "YEAR", SYM(YEAR_SYM)},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM)}, { "YEAR_MONTH", SYM(YEAR_MONTH_SYM)},
{ "ZEROFILL", SYM(ZEROFILL)}, { "ZEROFILL", SYM(ZEROFILL)},
{ "||", SYM(OR_OR_CONCAT)} { "||", SYM(OR_OR_SYM)}
}; };
......
...@@ -282,6 +282,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -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_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2)
#define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2) #define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2)
#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*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 #define RAID_BLOCK_SIZE 1024
......
...@@ -221,7 +221,7 @@ const char *sql_mode_names[] = ...@@ -221,7 +221,7 @@ const char *sql_mode_names[] =
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES", "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", "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 NullS
}; };
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
......
...@@ -3111,9 +3111,9 @@ ulong fix_sql_mode(ulong sql_mode) ...@@ -3111,9 +3111,9 @@ ulong fix_sql_mode(ulong sql_mode)
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
if (sql_mode & MODE_MYSQL40) 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) 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) if (sql_mode & MODE_TRADITIONAL)
sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
......
...@@ -200,6 +200,14 @@ static int find_keyword(LEX *lex, uint len, bool function) ...@@ -200,6 +200,14 @@ static int find_keyword(LEX *lex, uint len, bool function)
lex->yylval->symbol.symbol=symbol; lex->yylval->symbol.symbol=symbol;
lex->yylval->symbol.str= (char*) tok; lex->yylval->symbol.str= (char*) tok;
lex->yylval->symbol.length=len; 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 symbol->tok;
} }
return 0; return 0;
......
...@@ -51,10 +51,13 @@ int yylex(void *yylval, void *yythd); ...@@ -51,10 +51,13 @@ int yylex(void *yylval, void *yythd);
ER_WARN_DEPRECATED_SYNTAX, \ ER_WARN_DEPRECATED_SYNTAX, \
ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); 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 ? return new Item_func_if(create_func_ifnull(A,
(Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B)); 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); ...@@ -197,6 +200,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ALGORITHM_SYM %token ALGORITHM_SYM
%token ALL %token ALL
%token AND_SYM %token AND_SYM
%token AND_AND_SYM
%token AS %token AS
%token ASC %token ASC
%token AUTO_INC %token AUTO_INC
...@@ -341,7 +345,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -341,7 +345,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NCHAR_SYM %token NCHAR_SYM
%token NCHAR_STRING %token NCHAR_STRING
%token NVARCHAR_SYM %token NVARCHAR_SYM
%token NOT %token NOT_SYM
%token NOT2_SYM
%token NO_SYM %token NO_SYM
%token NULL_SYM %token NULL_SYM
%token NUM %token NUM
...@@ -352,7 +357,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -352,7 +357,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token OPTION %token OPTION
%token OPTIONALLY %token OPTIONALLY
%token OR_SYM %token OR_SYM
%token OR_OR_CONCAT %token OR2_SYM
%token OR_OR_SYM
%token ORDER_SYM %token ORDER_SYM
%token OUT_SYM %token OUT_SYM
%token OUTER %token OUTER
...@@ -436,6 +442,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -436,6 +442,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UNICODE_SYM %token UNICODE_SYM
%token UNION_SYM %token UNION_SYM
%token UNIQUE_SYM %token UNIQUE_SYM
%token UNKNOWN_SYM
%token USAGE %token USAGE
%token USE_FRM %token USE_FRM
%token USE_SYM %token USE_SYM
...@@ -638,8 +645,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -638,8 +645,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token BEFORE_SYM %token BEFORE_SYM
%left SET_VAR %left SET_VAR
%left OR_OR_CONCAT OR_SYM XOR %left OR_OR_SYM OR_SYM OR2_SYM XOR
%left AND_SYM %left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE %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 EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM
%left '|' %left '|'
...@@ -649,7 +656,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -649,7 +656,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left '*' '/' '%' DIV_SYM MOD_SYM %left '*' '/' '%' DIV_SYM MOD_SYM
%left '^' %left '^'
%left NEG '~' %left NEG '~'
%right NOT %right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM %right BINARY COLLATE_SYM
%type <lex_str> %type <lex_str>
...@@ -692,7 +699,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -692,7 +699,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item> %type <item>
literal text_literal insert_ident order_ident literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr 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 using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function exists_subselect exists_subselect_init geometry_function
...@@ -805,7 +814,7 @@ END_OF_INPUT ...@@ -805,7 +814,7 @@ END_OF_INPUT
%type <NONE> %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 THEN_SYM WHEN_SYM DIV_SYM MOD_SYM
%% %%
...@@ -1405,7 +1414,7 @@ sp_chistic: ...@@ -1405,7 +1414,7 @@ sp_chistic:
sp_c_chistic: sp_c_chistic:
sp_chistic { } sp_chistic { }
| DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; } | 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: sp_suid:
...@@ -1756,7 +1765,7 @@ sp_hcond: ...@@ -1756,7 +1765,7 @@ sp_hcond:
$$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
$$->type= sp_cond_type_t::warning; $$->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)); $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
$$->type= sp_cond_type_t::notfound; $$->type= sp_cond_type_t::notfound;
...@@ -2495,7 +2504,7 @@ table_option: ...@@ -2495,7 +2504,7 @@ table_option:
opt_if_not_exists: opt_if_not_exists:
/* empty */ { $$= 0; } /* empty */ { $$= 0; }
| IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; }; | IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
opt_create_table_options: opt_create_table_options:
/* empty */ /* empty */
...@@ -2917,7 +2926,7 @@ opt_attribute_list: ...@@ -2917,7 +2926,7 @@ opt_attribute_list:
attribute: attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; } 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; } | DEFAULT now_or_signed_literal { Lex->default_value=$2; }
| ON UPDATE_SYM NOW_SYM optional_braces | ON UPDATE_SYM NOW_SYM optional_braces
{ Lex->on_update_value= new Item_func_now_local(); } { Lex->on_update_value= new Item_func_now_local(); }
...@@ -3956,9 +3965,102 @@ optional_braces: ...@@ -3956,9 +3965,102 @@ optional_braces:
/* all possible expressions */ /* all possible expressions */
expr: expr:
expr_expr { $$= $1; } expr or bool_term { $$= new Item_cond_or($1,$3); }
| simple_expr { $$= $1; } | 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; } comp_op: EQ { $$ = &comp_eq_creator; }
| GE { $$ = &comp_ge_creator; } | GE { $$ = &comp_ge_creator; }
...@@ -3972,169 +4074,6 @@ all_or_any: ALL { $$ = 1; } ...@@ -3972,169 +4074,6 @@ all_or_any: ALL { $$ = 1; }
| ANY_SYM { $$ = 0; } | 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_expr:
INTERVAL_SYM expr { $$=$2; } INTERVAL_SYM expr { $$=$2; }
; ;
...@@ -4177,17 +4116,12 @@ simple_expr: ...@@ -4177,17 +4116,12 @@ simple_expr:
Lex->variables_used= 1; Lex->variables_used= 1;
} }
| sum_expr | sum_expr
| '+' expr %prec NEG { $$= $2; } | simple_expr OR_OR_SYM simple_expr
| '-' expr %prec NEG { $$= new Item_func_neg($2); } { $$= new Item_func_concat($1, $3); }
| '~' expr %prec NEG { $$= new Item_func_bit_neg($2); } | '+' simple_expr %prec NEG { $$= $2; }
| NOT expr %prec NEG | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
{ | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
$$= negate_expression(YYTHD, $2); | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
}
| '!' expr %prec NEG
{
$$= negate_expression(YYTHD, $2);
}
| '(' expr ')' { $$= $2; } | '(' expr ')' { $$= $2; }
| '(' expr ',' expr_list ')' | '(' expr ',' expr_list ')'
{ {
...@@ -4202,12 +4136,12 @@ simple_expr: ...@@ -4202,12 +4136,12 @@ simple_expr:
| EXISTS exists_subselect { $$= $2; } | EXISTS exists_subselect { $$= $2; }
| singlerow_subselect { $$= $1; } | singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; } | '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr fulltext_options ')' | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{ $2->push_front($5); { $2->push_front($5);
Select->add_ftfunc_to_list((Item_func_match*) Select->add_ftfunc_to_list((Item_func_match*)
($$=new Item_func_match(*$2,$6))); } ($$=new Item_func_match(*$2,$6))); }
| ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); } | 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); $$= create_func_cast($2, ITEM_CAST_CHAR, -1, &my_charset_bin);
} }
...@@ -4452,7 +4386,7 @@ simple_expr: ...@@ -4452,7 +4386,7 @@ simple_expr:
} }
| OLD_PASSWORD '(' expr ')' | OLD_PASSWORD '(' expr ')'
{ $$= new Item_func_old_password($3); } { $$= 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); } { $$ = new Item_func_locate($5,$3); }
| QUARTER_SYM '(' expr ')' | QUARTER_SYM '(' expr ')'
{ $$ = new Item_func_quarter($3); } { $$ = new Item_func_quarter($3); }
...@@ -7107,6 +7041,7 @@ keyword: ...@@ -7107,6 +7041,7 @@ keyword:
| UNCOMMITTED_SYM {} | UNCOMMITTED_SYM {}
| UNDEFINED_SYM {} | UNDEFINED_SYM {}
| UNICODE_SYM {} | UNICODE_SYM {}
| UNKNOWN_SYM {}
| UNTIL_SYM {} | UNTIL_SYM {}
| USER {} | USER {}
| USE_FRM {} | 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