diff --git a/mysql-test/suite/compat/oracle/r/func_concat.result b/mysql-test/suite/compat/oracle/r/func_concat.result index 463b5272363..230b36b94a5 100644 --- a/mysql-test/suite/compat/oracle/r/func_concat.result +++ b/mysql-test/suite/compat/oracle/r/func_concat.result @@ -3,12 +3,12 @@ EXPLAIN EXTENDED SELECT 'a'||'b'||'c'; 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 'a' || 'b' || 'c' AS "'a'||'b'||'c'" +Note 1003 select concat_operator_oracle(concat_operator_oracle('a','b'),'c') AS "'a'||'b'||'c'" EXPLAIN EXTENDED SELECT CONCAT('a'||'b'||'c'); 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 'a' || 'b' || 'c' AS "CONCAT('a'||'b'||'c')" +Note 1003 select concat_operator_oracle(concat_operator_oracle(concat_operator_oracle('a','b'),'c')) AS "CONCAT('a'||'b'||'c')" SELECT '' || ''; '' || '' @@ -204,3 +204,54 @@ NULL NULL 2 ab 3 abc DROP TABLE t1; +# +# MDEV-12478 CONCAT function inside view casts values incorrectly with Oracle sql_mode +# +SET sql_mode=ORACLE; +CREATE VIEW v1 AS SELECT 'foo'||NULL||'bar' AS test; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select concat_operator_oracle(concat_operator_oracle('foo',NULL),'bar') AS "test" latin1 latin1_swedish_ci +SELECT * FROM v1; +test +foobar +SET sql_mode=DEFAULT; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select concat_operator_oracle(concat_operator_oracle('foo',NULL),'bar') AS `test` latin1 latin1_swedish_ci +SELECT * FROM v1; +test +foobar +DROP VIEW v1; +SET sql_mode=DEFAULT; +CREATE VIEW v1 AS SELECT CONCAT('foo',NULL,'bar') AS test; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select concat('foo',NULL,'bar') AS `test` latin1 latin1_swedish_ci +SELECT * FROM v1; +test +NULL +SET sql_mode=ORACLE; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select concat('foo',NULL,'bar') AS "test" latin1 latin1_swedish_ci +SELECT * FROM v1; +test +NULL +DROP VIEW v1; +SET sql_mode=DEFAULT; +CREATE VIEW v1 AS SELECT '0'||'1' AS test; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select '0' or '1' AS `test` latin1 latin1_swedish_ci +SELECT * FROM v1; +test +1 +SET sql_mode=ORACLE; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select '0' or '1' AS "test" latin1 latin1_swedish_ci +SELECT * FROM v1; +test +1 +DROP VIEW v1; diff --git a/mysql-test/suite/compat/oracle/r/ps.result b/mysql-test/suite/compat/oracle/r/ps.result index 4ecbe3c7695..ed7cb4c51d5 100644 --- a/mysql-test/suite/compat/oracle/r/ps.result +++ b/mysql-test/suite/compat/oracle/r/ps.result @@ -178,9 +178,9 @@ EXECUTE IMMEDIATE 'SELECT :1 FROM DUAL' USING 10; # Testing erroneous and diallowed prepare source # EXECUTE IMMEDIATE _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL'; -ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation '||' +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle' PREPARE stmt FROM _latin1'SELECT 1 AS c FROM ' || _latin2 'DUAL'; -ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation '||' +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'concat_operator_oracle' EXECUTE IMMEDIATE (SELECT 'SELECT 1'); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 'SELECT 1')' at line 1 PREPARE stmt FROM (SELECT 'SELECT 1'); diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result index 288d4492c84..0ca20a0d5cb 100644 --- a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result +++ b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result @@ -758,7 +758,7 @@ END; END; $$ CALL p1(); -ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation '||' +ERROR HY000: Illegal mix of collations (latin1_bin,EXPLICIT) and (latin1_swedish_ci,EXPLICIT) for operation 'concat_operator_oracle' DROP PROCEDURE p1; # # Non-existing field diff --git a/mysql-test/suite/compat/oracle/t/func_concat.test b/mysql-test/suite/compat/oracle/t/func_concat.test index 89f986bc9e2..e1d8a5c477f 100644 --- a/mysql-test/suite/compat/oracle/t/func_concat.test +++ b/mysql-test/suite/compat/oracle/t/func_concat.test @@ -83,3 +83,34 @@ SELECT LENGTH(a||b||c), a||b||c FROM t1 ORDER BY a,b,c; SELECT LENGTH(CONCAT(a||b||c)), CONCAT(a||b||c) FROM t1 ORDER BY a,b,c; DROP TABLE t1; + +--echo # +--echo # MDEV-12478 CONCAT function inside view casts values incorrectly with Oracle sql_mode +--echo # + +SET sql_mode=ORACLE; +CREATE VIEW v1 AS SELECT 'foo'||NULL||'bar' AS test; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +SET sql_mode=DEFAULT; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; + +SET sql_mode=DEFAULT; +CREATE VIEW v1 AS SELECT CONCAT('foo',NULL,'bar') AS test; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +SET sql_mode=ORACLE; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; + +SET sql_mode=DEFAULT; +CREATE VIEW v1 AS SELECT '0'||'1' AS test; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +SET sql_mode=ORACLE; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; diff --git a/sql/item_create.cc b/sql/item_create.cc index d488b5f26c0..6eb0aac3e4c 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -644,6 +644,19 @@ protected: }; +class Create_func_concat_operator_oracle : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_concat_operator_oracle s_singleton; + +protected: + Create_func_concat_operator_oracle() {} + virtual ~Create_func_concat_operator_oracle() {} +}; + + class Create_func_decode_histogram : public Create_func_arg2 { public: @@ -3862,6 +3875,27 @@ Create_func_concat::create_native(THD *thd, LEX_STRING name, new (thd->mem_root) Item_func_concat(thd, *item_list); } +Create_func_concat_operator_oracle + Create_func_concat_operator_oracle::s_singleton; + +Item* +Create_func_concat_operator_oracle::create_native(THD *thd, LEX_STRING name, + List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 1) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_concat_operator_oracle(thd, *item_list); +} + Create_func_decode_histogram Create_func_decode_histogram::s_singleton; Item * @@ -6737,6 +6771,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("COLUMN_JSON") }, BUILDER(Create_func_dyncol_json)}, { { C_STRING_WITH_LEN("COMPRESS") }, BUILDER(Create_func_compress)}, { { C_STRING_WITH_LEN("CONCAT") }, BUILDER(Create_func_concat)}, + { { C_STRING_WITH_LEN("CONCAT_OPERATOR_ORACLE") }, BUILDER(Create_func_concat_operator_oracle)}, { { C_STRING_WITH_LEN("CONCAT_WS") }, BUILDER(Create_func_concat_ws)}, { { C_STRING_WITH_LEN("CONNECTION_ID") }, BUILDER(Create_func_connection_id)}, { { C_STRING_WITH_LEN("CONV") }, BUILDER(Create_func_conv)}, diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 5bd7bb14687..58bd6c99f80 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -303,12 +303,8 @@ public: Item_func_concat_operator_oracle(THD *thd, Item *a, Item *b) :Item_func_concat(thd, a, b) { } - void print(String *str, enum_query_type query_type) - { - print_op(str, query_type); - } String *val_str(String *); - const char *func_name() const { return "||"; } + const char *func_name() const { return "concat_operator_oracle"; } Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy(thd, mem_root, this); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index fb4c2c3d835..1d6fe38b66b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1363,7 +1363,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, * MODE_NO_UNSIGNED_SUBTRACTION affect execution - MODE_NO_DIR_IN_CREATE affect table creation only - MODE_POSTGRESQL compounded from other modes - - MODE_ORACLE compounded from other modes + - MODE_ORACLE affects Item creation (e.g for CONCAT) - MODE_MSSQL compounded from other modes - MODE_DB2 compounded from other modes - MODE_MAXDB affect only CREATE TABLE parsing @@ -1378,7 +1378,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, + MODE_NO_BACKSLASH_ESCAPES affect expression parsing */ thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES); + MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES | + MODE_ORACLE); /* Parse the query. */