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;
......
This diff is collapsed.
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