mirror of
https://github.com/MariaDB/server.git
synced 2025-02-04 21:02:17 +01:00
2b6d241ee4
The crash happened with an indexed virtual column whose value is evaluated using a function that has a different meaning in sql_mode='' vs sql_mode=ORACLE: - DECODE() - LTRIM() - RTRIM() - LPAD() - RPAD() - REPLACE() - SUBSTR() For example: CREATE TABLE t1 ( b VARCHAR(1), g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, KEY g(g) ); So far we had replacement XXX_ORACLE() functions for all mentioned function, e.g. SUBSTR_ORACLE() for SUBSTR(). So it was possible to correctly re-parse SUBSTR_ORACLE() even in sql_mode=''. But it was not possible to re-parse the MariaDB version of SUBSTR() after switching to sql_mode=ORACLE. It was erroneously mis-interpreted as SUBSTR_ORACLE(). As a result, this combination worked fine: SET sql_mode=ORACLE; CREATE TABLE t1 ... g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, ...; INSERT ... FLUSH TABLES; SET sql_mode=''; INSERT ... But the other way around it crashed: SET sql_mode=''; CREATE TABLE t1 ... g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, ...; INSERT ... FLUSH TABLES; SET sql_mode=ORACLE; INSERT ... At CREATE time, SUBSTR was instantiated as Item_func_substr and printed in the FRM file as substr(). At re-open time with sql_mode=ORACLE, "substr()" was erroneously instantiated as Item_func_substr_oracle. Fix: The fix proposes a symmetric solution. It provides a way to re-parse reliably all sql_mode dependent functions to their original CREATE TABLE time meaning, no matter what the open-time sql_mode is. We take advantage of the same idea we previously used to resolve sql_mode dependent data types. Now all sql_mode dependent functions are printed by SHOW using a schema qualifier when the current sql_mode differs from the function sql_mode: SET sql_mode=''; CREATE TABLE t1 ... SUBSTR(a,b,c) ..; SET sql_mode=ORACLE; SHOW CREATE TABLE t1; -> mariadb_schema.substr(a,b,c) SET sql_mode=ORACLE; CREATE TABLE t2 ... SUBSTR(a,b,c) ..; SET sql_mode=''; SHOW CREATE TABLE t1; -> oracle_schema.substr(a,b,c) Old replacement names like substr_oracle() are still understood for backward compatibility and used in FRM files (for downgrade compatibility), but they are not printed by SHOW any more.
177 lines
7.6 KiB
Text
177 lines
7.6 KiB
Text
SET sql_mode=ORACLE;
|
|
SELECT DECODE(10);
|
|
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE'
|
|
SELECT DECODE(10,10);
|
|
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE'
|
|
SELECT DECODE(10,10,'x10');
|
|
DECODE(10,10,'x10')
|
|
x10
|
|
SELECT DECODE(11,10,'x10');
|
|
DECODE(11,10,'x10')
|
|
NULL
|
|
SELECT DECODE(10,10,'x10','def');
|
|
DECODE(10,10,'x10','def')
|
|
x10
|
|
SELECT DECODE(11,10,'x10','def');
|
|
DECODE(11,10,'x10','def')
|
|
def
|
|
SELECT DECODE(10,10,'x10',11,'x11','def');
|
|
DECODE(10,10,'x10',11,'x11','def')
|
|
x10
|
|
SELECT DECODE(11,10,'x10',11,'x11','def');
|
|
DECODE(11,10,'x10',11,'x11','def')
|
|
x11
|
|
SELECT DECODE(12,10,'x10',11,'x11','def');
|
|
DECODE(12,10,'x10',11,'x11','def')
|
|
def
|
|
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
|
|
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 decode(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')"
|
|
CREATE TABLE decode (decode int);
|
|
DROP TABLE decode;
|
|
#
|
|
# MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent
|
|
#
|
|
SELECT DECODE(10);
|
|
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE'
|
|
SELECT DECODE(10,10);
|
|
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE'
|
|
SELECT DECODE_ORACLE(10);
|
|
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE'
|
|
SELECT DECODE_ORACLE(10,10);
|
|
ERROR 42000: Incorrect parameter count in the call to native function 'DECODE_ORACLE'
|
|
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11');
|
|
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 decode(12,10,'x10',11,'x11') AS "DECODE(12,10,'x10',11,'x11')"
|
|
EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def');
|
|
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 decode(12,10,'x10',11,'x11','def') AS "DECODE(12,10,'x10',11,'x11','def')"
|
|
EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11');
|
|
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 decode(12,10,'x10',11,'x11') AS "DECODE_ORACLE(12,10,'x10',11,'x11')"
|
|
EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11','def');
|
|
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 decode(12,10,'x10',11,'x11','def') AS "DECODE_ORACLE(12,10,'x10',11,'x11','def')"
|
|
CREATE TABLE t1 (a INT);
|
|
CREATE VIEW v1 AS
|
|
SELECT
|
|
DECODE(a,1,'x1',NULL,'xNULL') AS d1,
|
|
DECODE(a,1,'x1',NULL,'xNULL','xELSE') AS d2,
|
|
DECODE_ORACLE(a,1,'x1',NULL,'xNULL') AS d3,
|
|
DECODE_ORACLE(a,1,'x1',NULL,'xNULL','xELSE') AS d4
|
|
FROM t1;
|
|
SHOW CREATE VIEW v1;
|
|
View Create View character_set_client collation_connection
|
|
v1 CREATE VIEW "v1" AS select decode("t1"."a",1,'x1',NULL,'xNULL') AS "d1",decode("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d2",decode("t1"."a",1,'x1',NULL,'xNULL') AS "d3",decode("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d4" from "t1" latin1 latin1_swedish_ci
|
|
DROP VIEW v1;
|
|
DROP TABLE t1;
|
|
SELECT DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def');
|
|
DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def')
|
|
then1
|
|
SELECT DECODE(TIME'10:20:32','10:20:31','then1','10:20:32','then2','def');
|
|
DECODE(TIME'10:20:32','10:20:31','then1','10:20:32','then2','def')
|
|
then2
|
|
SELECT DECODE(TIME'10:20:33','10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def');
|
|
DECODE(TIME'10:20:33','10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def')
|
|
then3
|
|
SELECT DECODE(NULL,TIME'10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def');
|
|
DECODE(NULL,TIME'10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def')
|
|
then2NULL
|
|
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:31','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def');
|
|
DECODE(TIMESTAMP'2001-01-01 10:20:31','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def')
|
|
then1
|
|
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:32','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def');
|
|
DECODE(TIMESTAMP'2001-01-01 10:20:32','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def')
|
|
then2
|
|
SELECT DECODE(TIMESTAMP'2001-01-01 10:20:33','2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def');
|
|
DECODE(TIMESTAMP'2001-01-01 10:20:33','2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def')
|
|
then3
|
|
SELECT DECODE(NULL,TIMESTAMP'2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def');
|
|
DECODE(NULL,TIMESTAMP'2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def')
|
|
then2NULL
|
|
SELECT DECODE('w1','w1','then1','w2','then2','def');
|
|
DECODE('w1','w1','then1','w2','then2','def')
|
|
then1
|
|
SELECT DECODE('w2','w1','then1','w2','then2','def');
|
|
DECODE('w2','w1','then1','w2','then2','def')
|
|
then2
|
|
SELECT DECODE('w3','w1','then1',NULL,'then2NULL','w3','then3','def');
|
|
DECODE('w3','w1','then1',NULL,'then2NULL','w3','then3','def')
|
|
then3
|
|
SELECT DECODE(NULL,'w1','then1',NULL,'then2NULL','w3','then3','def');
|
|
DECODE(NULL,'w1','then1',NULL,'then2NULL','w3','then3','def')
|
|
then2NULL
|
|
SELECT DECODE(1,1,'then1',2,'then2','def');
|
|
DECODE(1,1,'then1',2,'then2','def')
|
|
then1
|
|
SELECT DECODE(2,1,'then1',2,'then2','def');
|
|
DECODE(2,1,'then1',2,'then2','def')
|
|
then2
|
|
SELECT DECODE(3,1,'then1',NULL,'then2NULL',3,'then3','def');
|
|
DECODE(3,1,'then1',NULL,'then2NULL',3,'then3','def')
|
|
then3
|
|
SELECT DECODE(NULL,1,'then1',NULL,'then2NULL',3,'then3','def');
|
|
DECODE(NULL,1,'then1',NULL,'then2NULL',3,'then3','def')
|
|
then2NULL
|
|
SELECT DECODE(CAST(NULL AS SIGNED),1,'then1',NULL,'then2NULL',3,'then3','def');
|
|
DECODE(CAST(NULL AS SIGNED),1,'then1',NULL,'then2NULL',3,'then3','def')
|
|
then2NULL
|
|
SELECT DECODE(1.0,1.0,'then1',2.0,'then2','def');
|
|
DECODE(1.0,1.0,'then1',2.0,'then2','def')
|
|
then1
|
|
SELECT DECODE(2.0,1.0,'then1',2.0,'then2','def');
|
|
DECODE(2.0,1.0,'then1',2.0,'then2','def')
|
|
then2
|
|
SELECT DECODE(3.0,1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
|
|
DECODE(3.0,1.0,'then1',NULL,'then2NULL',3.0,'then3','def')
|
|
then3
|
|
SELECT DECODE(NULL,1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
|
|
DECODE(NULL,1.0,'then1',NULL,'then2NULL',3.0,'then3','def')
|
|
then2NULL
|
|
SELECT DECODE(CAST(NULL AS DECIMAL),1.0,'then1',NULL,'then2NULL',3.0,'then3','def');
|
|
DECODE(CAST(NULL AS DECIMAL),1.0,'then1',NULL,'then2NULL',3.0,'then3','def')
|
|
then2NULL
|
|
SELECT DECODE(1e0,1e0,'then1',2e0,'then2','def');
|
|
DECODE(1e0,1e0,'then1',2e0,'then2','def')
|
|
then1
|
|
SELECT DECODE(2e0,1e0,'then1',2e0,'then2','def');
|
|
DECODE(2e0,1e0,'then1',2e0,'then2','def')
|
|
then2
|
|
SELECT DECODE(3e0,1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
|
|
DECODE(3e0,1e0,'then1',NULL,'then2NULL',3e0,'then3','def')
|
|
then3
|
|
SELECT DECODE(NULL,1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
|
|
DECODE(NULL,1e0,'then1',NULL,'then2NULL',3e0,'then3','def')
|
|
then2NULL
|
|
SELECT DECODE(CAST(NULL AS DOUBLE),1e0,'then1',NULL,'then2NULL',3e0,'then3','def');
|
|
DECODE(CAST(NULL AS DOUBLE),1e0,'then1',NULL,'then2NULL',3e0,'then3','def')
|
|
then2NULL
|
|
SELECT DECODE(NULL,NULL,1,2) FROM DUAL;
|
|
DECODE(NULL,NULL,1,2)
|
|
1
|
|
SELECT DECODE(NULL,10,10,NULL,1,2) FROM DUAL;
|
|
DECODE(NULL,10,10,NULL,1,2)
|
|
1
|
|
SELECT DECODE_ORACLE(NULL,NULL,1,2) FROM DUAL;
|
|
DECODE_ORACLE(NULL,NULL,1,2)
|
|
1
|
|
SELECT DECODE_ORACLE(NULL,10,10,NULL,1,2) FROM DUAL;
|
|
DECODE_ORACLE(NULL,10,10,NULL,1,2)
|
|
1
|
|
CREATE OR REPLACE TABLE t1 (a VARCHAR(10) DEFAULT NULL);
|
|
INSERT INTO t1 VALUES (NULL),(1);
|
|
SELECT a, DECODE(a,NULL,1,2) FROM t1;
|
|
a DECODE(a,NULL,1,2)
|
|
NULL 1
|
|
1 2
|
|
DROP TABLE t1;
|