diff options
-rw-r--r-- | mysql-test/r/ansi.result | 2 | ||||
-rw-r--r-- | mysql-test/r/bool.result | 18 | ||||
-rw-r--r-- | mysql-test/r/sql_mode.result | 2 | ||||
-rw-r--r-- | mysql-test/t/bool.test | 10 | ||||
-rw-r--r-- | sql/lex.h | 7 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.cc | 8 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 323 |
10 files changed, 175 insertions, 202 deletions
diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result index 0b86634f67b..56676abba33 100644 --- a/mysql-test/r/ansi.result +++ b/mysql-test/r/ansi.result @@ -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 diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result index a054eceec0c..1ef4b55fc36 100644 --- a/mysql-test/r/bool.result +++ b/mysql-test/r/bool.result @@ -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 diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 67446829eca..c25ae99b530 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -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` ( diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test index b263ecfded2..644fdbfbf60 100644 --- a/mysql-test/t/bool.test +++ b/mysql-test/t/bool.test @@ -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); diff --git a/sql/lex.h b/sql/lex.h index db31b3af994..cf0059a1397 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -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)} }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 7a49799c7cd..27d7f104e44 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -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 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a3a3290565a..5f59914c77c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -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,"", diff --git a/sql/set_var.cc b/sql/set_var.cc index e5f3e17d17d..f8e344f9a58 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -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 | diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b65d9465b43..1cbe004caa0 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -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; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e6e7c9b59ae..1ca6973e172 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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 {} |