Commit c2df4e9d authored by Alexander Barkov's avatar Alexander Barkov

MDEV-16186 Concatenation operator || returns wrong results in sql_mode=ORACLE

parent 66360506
......@@ -46,3 +46,73 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`i`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-16186 Concatenation operator || returns wrong results in sql_mode=ORACLE
#
SET sql_mode=ANSI;
SELECT -1<<1||1 AS a FROM DUAL;
a
18446744073709549568
SELECT -1||0<<1 AS a FROM DUAL;
a
18446744073709551596
EXPLAIN EXTENDED SELECT -1<<1||1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select -1 << concat(1,1) AS "a"
EXPLAIN EXTENDED SELECT -1||0<<1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat(-1,0) << 1 AS "a"
SELECT -1+1||1 AS a FROM DUAL;
a
10
SELECT -1||0+1 AS a FROM DUAL;
a
-9
EXPLAIN EXTENDED SELECT -1+1||1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select -1 + concat(1,1) AS "a"
EXPLAIN EXTENDED SELECT -1||0+1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat(-1,0) + 1 AS "a"
SELECT 1*1||-1 AS a FROM DUAL;
a
1
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: '1-1'
SELECT 1||1*-1 AS a FROM DUAL;
a
-11
EXPLAIN EXTENDED SELECT 1*1||-1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select 1 * concat(1,-1) AS "a"
EXPLAIN EXTENDED SELECT 1||1*-1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat(1,1) * -1 AS "a"
SELECT -1^1||1 AS a FROM DUAL;
a
18446744073709551604
SELECT -1||0^1 AS a FROM DUAL;
a
18446744073709551607
EXPLAIN EXTENDED SELECT -1^1||1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select -1 ^ concat(1,1) AS "a"
EXPLAIN EXTENDED SELECT -1||0^1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat(-1,0) ^ 1 AS "a"
......@@ -39,3 +39,36 @@ SHOW CREATE TABLE t1;
DROP TABLE t1;
# End of 4.1 tests
--echo #
--echo # MDEV-16186 Concatenation operator || returns wrong results in sql_mode=ORACLE
--echo #
SET sql_mode=ANSI;
# Concatenation operator || is stronger than numeric dyadic operators ^ * + <<
SELECT -1<<1||1 AS a FROM DUAL;
SELECT -1||0<<1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1<<1||1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1||0<<1 AS a FROM DUAL;
SELECT -1+1||1 AS a FROM DUAL;
SELECT -1||0+1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1+1||1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1||0+1 AS a FROM DUAL;
SELECT 1*1||-1 AS a FROM DUAL;
SELECT 1||1*-1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT 1*1||-1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT 1||1*-1 AS a FROM DUAL;
SELECT -1^1||1 AS a FROM DUAL;
SELECT -1||0^1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1^1||1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1||0^1 AS a FROM DUAL;
......@@ -255,3 +255,70 @@ SELECT * FROM v1;
test
1
DROP VIEW v1;
#
# MDEV-16186 Concatenation operator || returns wrong results in sql_mode=ORACLE
#
SELECT -1<<1||1 AS a FROM DUAL;
a
18446744073709549568
SELECT -1||0<<1 AS a FROM DUAL;
a
18446744073709551596
EXPLAIN EXTENDED SELECT -1<<1||1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select -1 << concat_operator_oracle(1,1) AS "a"
EXPLAIN EXTENDED SELECT -1||0<<1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(-1,0) << 1 AS "a"
SELECT -1+1||1 AS a FROM DUAL;
a
01
SELECT -1||0+1 AS a FROM DUAL;
a
-9
EXPLAIN EXTENDED SELECT -1+1||1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(-1 + 1,1) AS "a"
EXPLAIN EXTENDED SELECT -1||0+1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(-1,0) + 1 AS "a"
SELECT 1*1||-1 AS a FROM DUAL;
a
1-1
SELECT 1||1*-1 AS a FROM DUAL;
a
1-1
EXPLAIN EXTENDED SELECT 1*1||-1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(1 * 1,-1) AS "a"
EXPLAIN EXTENDED SELECT 1||1*-1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(1,1 * -1) AS "a"
SELECT -1^1||1 AS a FROM DUAL;
a
184467440737095516141
SELECT -1||0^1 AS a FROM DUAL;
a
-11
EXPLAIN EXTENDED SELECT -1^1||1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(-1 ^ 1,1) AS "a"
EXPLAIN EXTENDED SELECT -1||0^1 AS a FROM DUAL;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select concat_operator_oracle(-1,0 ^ 1) AS "a"
......@@ -114,3 +114,35 @@ SET sql_mode=ORACLE;
SHOW CREATE VIEW v1;
SELECT * FROM v1;
DROP VIEW v1;
--echo #
--echo # MDEV-16186 Concatenation operator || returns wrong results in sql_mode=ORACLE
--echo #
# Concatenation operator || has the same precedence with +
# (stronger than << and weaker than * ^)
SELECT -1<<1||1 AS a FROM DUAL;
SELECT -1||0<<1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1<<1||1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1||0<<1 AS a FROM DUAL;
SELECT -1+1||1 AS a FROM DUAL;
SELECT -1||0+1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1+1||1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1||0+1 AS a FROM DUAL;
SELECT 1*1||-1 AS a FROM DUAL;
SELECT 1||1*-1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT 1*1||-1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT 1||1*-1 AS a FROM DUAL;
SELECT -1^1||1 AS a FROM DUAL;
SELECT -1||0^1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1^1||1 AS a FROM DUAL;
EXPLAIN EXTENDED SELECT -1||0^1 AS a FROM DUAL;
......@@ -722,7 +722,7 @@ static SYMBOL symbols[] = {
{ "YEAR", SYM(YEAR_SYM)},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM)},
{ "ZEROFILL", SYM(ZEROFILL)},
{ "||", SYM(OR_OR_SYM)}
{ "||", SYM(OR2_SYM)}
};
......
......@@ -839,9 +839,12 @@ int Lex_input_stream::find_keyword(Lex_ident_cli_st *kwd,
if ((symbol->tok == NOT_SYM) &&
(m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
return NOT2_SYM;
if ((symbol->tok == OR_OR_SYM) &&
!(m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
return OR2_SYM;
if ((symbol->tok == OR2_SYM) &&
(m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
{
return (m_thd->variables.sql_mode & MODE_ORACLE) ?
ORACLE_CONCAT_SYM : MYSQL_CONCAT_SYM;
}
return symbol->tok;
}
......
......@@ -892,10 +892,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
Currently there are 127 shift/reduce conflicts.
Currently there are 122 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 127
%expect 122
/*
Comments for TOKENS.
......@@ -1073,6 +1073,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token MIN_SYM /* SQL-2003-N */
%token MODIFIES_SYM /* SQL-2003-R */
%token MOD_SYM /* SQL-2003-N */
%token MYSQL_CONCAT_SYM /* OPERATOR */
%token NATURAL /* SQL-2003-R */
%token NCHAR_STRING
%token NE /* OPERATOR */
......@@ -1089,9 +1090,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token ON /* SQL-2003-R */
%token OPTIMIZE
%token OPTIONALLY
%token ORACLE_CONCAT_SYM /* INTERNAL */
%token OR2_SYM
%token ORDER_SYM /* SQL-2003-R */
%token OR_OR_SYM /* OPERATOR */
%token OR_SYM /* SQL-2003-R */
%token OUTER
%token OUTFILE
......@@ -1654,7 +1655,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
/* A dummy token to force the priority of table_ref production in a join. */
%left TABLE_REF_PRIORITY
%left SET_VAR
%left OR_OR_SYM OR_SYM OR2_SYM
%left OR_SYM OR2_SYM
%left XOR
%left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
......@@ -1662,9 +1663,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%left '|'
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+'
%left '-' '+' ORACLE_CONCAT_SYM
%left '*' '/' '%' DIV_SYM MOD_SYM
%left '^'
%left MYSQL_CONCAT_SYM
%left NEG '~'
%right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM
......@@ -1803,6 +1805,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
variable variable_aux bool_pri
predicate bit_expr parenthesized_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr
primary_expr string_factor_expr mysql_concatenation_expr
select_sublist_qualified_asterisk
expr_or_default set_expr_or_default
geometry_function signed_literal expr_or_literal
......@@ -2056,8 +2059,9 @@ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM BETWEEN_SYM CASE_SYM
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
MYSQL_CONCAT_SYM ORACLE_CONCAT_SYM
%type <with_clause> opt_with_clause with_clause
......@@ -9697,14 +9701,14 @@ predicate:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr LIKE simple_expr opt_escape
| bit_expr LIKE mysql_concatenation_expr opt_escape
{
$$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4,
Lex->escape_used);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr not LIKE simple_expr opt_escape
| bit_expr not LIKE mysql_concatenation_expr opt_escape
{
Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5,
Lex->escape_used);
......@@ -9755,6 +9759,13 @@ bit_expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr ORACLE_CONCAT_SYM bit_expr
{
$$= new (thd->mem_root) Item_func_concat_operator_oracle(thd,
$1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr '+' bit_expr %prec '+'
{
$$= new (thd->mem_root) Item_func_plus(thd, $1, $3);
......@@ -9834,7 +9845,7 @@ bit_expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| simple_expr
| mysql_concatenation_expr %prec '^'
;
or:
......@@ -10113,26 +10124,28 @@ column_default_non_parenthesized_expr:
}
;
simple_expr:
primary_expr:
column_default_non_parenthesized_expr
| simple_expr COLLATE_SYM collation_name %prec NEG
| '(' parenthesized_expr ')' { $$= $2; }
;
string_factor_expr:
primary_expr
| string_factor_expr COLLATE_SYM collation_name
{
if (unlikely(!($$= new (thd->mem_root) Item_func_set_collation(thd, $1, $3))))
MYSQL_YYABORT;
}
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
;
simple_expr:
string_factor_expr %prec NEG
| BINARY simple_expr
{
Type_cast_attributes at(&my_charset_bin);
if (unlikely(!($$= type_handler_long_blob.create_typecast_item(thd, $2, at))))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| '+' simple_expr %prec NEG
{
$$= $2;
......@@ -10157,6 +10170,16 @@ simple_expr:
}
;
mysql_concatenation_expr:
simple_expr
| mysql_concatenation_expr MYSQL_CONCAT_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
;
function_call_keyword_timestamp:
TIMESTAMP '(' expr ')'
{
......
......@@ -278,10 +278,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
Currently there are 104 shift/reduce conflicts.
Currently there are 99 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 104
%expect 99
/*
Comments for TOKENS.
......@@ -459,6 +459,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token MIN_SYM /* SQL-2003-N */
%token MODIFIES_SYM /* SQL-2003-R */
%token MOD_SYM /* SQL-2003-N */
%token MYSQL_CONCAT_SYM /* OPERATOR */
%token NATURAL /* SQL-2003-R */
%token NCHAR_STRING
%token NE /* OPERATOR */
......@@ -475,9 +476,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token ON /* SQL-2003-R */
%token OPTIMIZE
%token OPTIONALLY
%token ORACLE_CONCAT_SYM /* INTERNAL */
%token OR2_SYM
%token ORDER_SYM /* SQL-2003-R */
%token OR_OR_SYM /* OPERATOR */
%token OR_SYM /* SQL-2003-R */
%token OUTER
%token OUTFILE
......@@ -1040,7 +1041,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
/* A dummy token to force the priority of table_ref production in a join. */
%left TABLE_REF_PRIORITY
%left SET_VAR
%left OR_OR_SYM OR_SYM OR2_SYM
%left OR_SYM OR2_SYM
%left XOR
%left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
......@@ -1048,9 +1049,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%left '|'
%left '&'
%left SHIFT_LEFT SHIFT_RIGHT
%left '-' '+'
%left '-' '+' ORACLE_CONCAT_SYM
%left '*' '/' DIV_SYM MOD_SYM
%left '^'
%left MYSQL_CONCAT_SYM
%left NEG '~'
%right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM
......@@ -1196,6 +1198,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
variable variable_aux bool_pri
predicate bit_expr parenthesized_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr
primary_expr string_factor_expr mysql_concatenation_expr
select_sublist_qualified_asterisk
expr_or_default set_expr_or_default
geometry_function signed_literal expr_or_literal
......@@ -1469,8 +1472,9 @@ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM BETWEEN_SYM CASE_SYM
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
MYSQL_CONCAT_SYM ORACLE_CONCAT_SYM
%type <with_clause> opt_with_clause with_clause
......@@ -9443,14 +9447,14 @@ predicate:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr LIKE simple_expr opt_escape
| bit_expr LIKE mysql_concatenation_expr opt_escape
{
$$= new (thd->mem_root) Item_func_like(thd, $1, $3, $4,
Lex->escape_used);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr not LIKE simple_expr opt_escape
| bit_expr not LIKE mysql_concatenation_expr opt_escape
{
Item *item= new (thd->mem_root) Item_func_like(thd, $1, $4, $5,
Lex->escape_used);
......@@ -9501,6 +9505,13 @@ bit_expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr ORACLE_CONCAT_SYM bit_expr
{
$$= new (thd->mem_root) Item_func_concat_operator_oracle(thd,
$1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| bit_expr '+' bit_expr %prec '+'
{
$$= new (thd->mem_root) Item_func_plus(thd, $1, $3);
......@@ -9574,7 +9585,7 @@ bit_expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| simple_expr
| mysql_concatenation_expr %prec '^'
;
or:
......@@ -9909,28 +9920,29 @@ column_default_non_parenthesized_expr:
}
;
simple_expr:
primary_expr:
column_default_non_parenthesized_expr
| explicit_cursor_attr
| simple_expr COLLATE_SYM collation_name %prec NEG
| '(' parenthesized_expr ')' { $$= $2; }
;
string_factor_expr:
primary_expr
| string_factor_expr COLLATE_SYM collation_name
{
if (unlikely(!($$= new (thd->mem_root) Item_func_set_collation(thd, $1, $3))))
MYSQL_YYABORT;
}
| '(' parenthesized_expr ')' { $$= $2; }
| BINARY simple_expr %prec NEG
;
simple_expr:
string_factor_expr %prec NEG
| BINARY simple_expr
{
Type_cast_attributes at(&my_charset_bin);
if (unlikely(!($$= type_handler_long_blob.create_typecast_item(thd, $2, at))))
MYSQL_YYABORT;
}
| simple_expr OR_OR_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat_operator_oracle(thd,
$1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
| '+' simple_expr %prec NEG
{
$$= $2;
......@@ -9955,6 +9967,17 @@ simple_expr:
}
;
mysql_concatenation_expr:
simple_expr
| mysql_concatenation_expr MYSQL_CONCAT_SYM simple_expr
{
$$= new (thd->mem_root) Item_func_concat(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
;
/*
Function call syntax using official SQL 2003 keywords.
Because the function name is an official token,
......
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