diff --git a/mysql-test/columnstore/compat/oracle/func_concat_oracle.result b/mysql-test/columnstore/compat/oracle/func_concat_oracle.result new file mode 100644 index 000000000..f7ea05140 --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_concat_oracle.result @@ -0,0 +1,389 @@ +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; +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 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 concat_operator_oracle(concat_operator_oracle(concat_operator_oracle('a','b'),'c')) AS "CONCAT('a'||'b'||'c')" +SELECT '' || ''; +'' || '' + +SELECT '' || 'b'; +'' || 'b' +b +SELECT '' || NULL; +'' || NULL + +SELECT 'a' || ''; +'a' || '' +a +SELECT 'a' || 'b'; +'a' || 'b' +ab +SELECT 'a' || NULL; +'a' || NULL +a +SELECT NULL || ''; +NULL || '' + +SELECT NULL || 'b'; +NULL || 'b' +b +SELECT NULL || NULL; +NULL || NULL +NULL +SELECT '' || '' || ''; +'' || '' || '' + +SELECT '' || '' || 'c'; +'' || '' || 'c' +c +SELECT '' || '' || NULL; +'' || '' || NULL + +SELECT '' || 'b' || ''; +'' || 'b' || '' +b +SELECT '' || 'b' || 'c'; +'' || 'b' || 'c' +bc +SELECT '' || 'b' || NULL; +'' || 'b' || NULL +b +SELECT '' || NULL || ''; +'' || NULL || '' + +SELECT '' || NULL || 'c'; +'' || NULL || 'c' +c +SELECT '' || NULL || NULL; +'' || NULL || NULL + +SELECT 'a' || '' || ''; +'a' || '' || '' +a +SELECT 'a' || '' || 'c'; +'a' || '' || 'c' +ac +SELECT 'a' || '' || NULL; +'a' || '' || NULL +a +SELECT 'a' || 'b' || ''; +'a' || 'b' || '' +ab +SELECT 'a' || 'b' || 'c'; +'a' || 'b' || 'c' +abc +SELECT 'a' || 'b' || NULL; +'a' || 'b' || NULL +ab +SELECT 'a' || NULL || ''; +'a' || NULL || '' +a +SELECT 'a' || NULL || 'c'; +'a' || NULL || 'c' +ac +SELECT 'a' || NULL || NULL; +'a' || NULL || NULL +a +SELECT NULL || '' || ''; +NULL || '' || '' + +SELECT NULL || '' || 'c'; +NULL || '' || 'c' +c +SELECT NULL || '' || NULL; +NULL || '' || NULL + +SELECT NULL || 'b' || ''; +NULL || 'b' || '' +b +SELECT NULL || 'b' || 'c'; +NULL || 'b' || 'c' +bc +SELECT NULL || 'b' || NULL; +NULL || 'b' || NULL +b +SELECT NULL || NULL || ''; +NULL || NULL || '' + +SELECT NULL || NULL || 'c'; +NULL || NULL || 'c' +c +SELECT NULL || NULL || NULL; +NULL || NULL || NULL +NULL +CREATE TABLE t1 (a VARCHAR(10), b VARCHAR(10), c VARCHAR(10)); +INSERT INTO t1 VALUES ('', '', ''); +INSERT INTO t1 VALUES ('', '', 'c'); +INSERT INTO t1 VALUES ('', '', NULL); +INSERT INTO t1 VALUES ('', 'b', ''); +INSERT INTO t1 VALUES ('', 'b', 'c'); +INSERT INTO t1 VALUES ('', 'b', NULL); +INSERT INTO t1 VALUES ('', NULL, ''); +INSERT INTO t1 VALUES ('', NULL, 'c'); +INSERT INTO t1 VALUES ('', NULL, NULL); +INSERT INTO t1 VALUES ('a', '', ''); +INSERT INTO t1 VALUES ('a', '', 'c'); +INSERT INTO t1 VALUES ('a', '', NULL); +INSERT INTO t1 VALUES ('a', 'b', ''); +INSERT INTO t1 VALUES ('a', 'b', 'c'); +INSERT INTO t1 VALUES ('a', 'b', NULL); +INSERT INTO t1 VALUES ('a', NULL, ''); +INSERT INTO t1 VALUES ('a', NULL, 'c'); +INSERT INTO t1 VALUES ('a', NULL, NULL); +INSERT INTO t1 VALUES (NULL, '', ''); +INSERT INTO t1 VALUES (NULL, '', 'c'); +INSERT INTO t1 VALUES (NULL, '', NULL); +INSERT INTO t1 VALUES (NULL, 'b', ''); +INSERT INTO t1 VALUES (NULL, 'b', 'c'); +INSERT INTO t1 VALUES (NULL, 'b', NULL); +INSERT INTO t1 VALUES (NULL, NULL, ''); +INSERT INTO t1 VALUES (NULL, NULL, 'c'); +INSERT INTO t1 VALUES (NULL, NULL, NULL); +SELECT LENGTH(a||b||c), a||b||c FROM t1 ORDER BY a,b,c; +LENGTH(a||b||c) a||b||c +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +1 c +1 c +1 c +1 c +1 b +1 b +1 b +1 b +2 bc +2 bc +1 a +1 a +1 a +1 a +2 ac +2 ac +2 ab +2 ab +3 abc +SELECT LENGTH(CONCAT(a||b||c)), CONCAT(a||b||c) FROM t1 ORDER BY a,b,c; +LENGTH(CONCAT(a||b||c)) CONCAT(a||b||c) +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +0 NULL +1 c +1 c +1 c +1 c +1 b +1 b +1 b +1 b +2 bc +2 bc +1 a +1 a +1 a +1 a +2 ac +2 ac +2 ab +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; +# +# 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" +# +# MDEV-17359 Concatenation operator || in like expression failed in sql_mode=ORACLE +# +SELECT 'abc' LIKE 'a'||'%'; +'abc' LIKE 'a'||'%' +1 +EXPLAIN EXTENDED SELECT 'abc' LIKE 'a'||'%'; +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 'abc' like concat_operator_oracle('a','%') AS "'abc' LIKE 'a'||'%'" +SELECT 'x' FROM DUAL WHERE 11 LIKE 1||1; +x +x +SELECT 'x' FROM DUAL WHERE 1||1 LIKE 11; +x +x +SELECT 'x' FROM DUAL WHERE 1||1 LIKE 1||1; +x +x +CREATE TABLE t1 (c1 VARCHAR(10),c2 VARCHAR(10), ord INTEGER); +INSERT INTO t1 VALUES ('a', 'ab' ,1); +INSERT INTO t1 VALUES ('ab', 'ab', 2); +INSERT INTO t1 VALUES ('abc', 'ab', 3); +SELECT c1 FROM t1 WHERE c1 LIKE '%'||'b' ORDER BY ord; +c1 +ab +EXPLAIN EXTENDED SELECT c1 FROM t1 WHERE c1 LIKE '%'||'b' ORDER BY ord; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 select "test"."t1"."c1" AS "c1" from "test"."t1" USE INDEX () where "test"."t1"."c1" like concat_operator_oracle('%','b') order by "test"."t1"."ord" +SELECT c1 FROM t1 WHERE c1 LIKE c2||'%'||'c' ORDER BY ord; +c1 +abc +EXPLAIN EXTENDED SELECT c1 FROM t1 WHERE c1 LIKE c2||'%'||'c' ORDER BY ord; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 select "test"."t1"."c1" AS "c1" from "test"."t1" USE INDEX () where "test"."t1"."c1" like concat_operator_oracle(concat_operator_oracle("test"."t1"."c2",'%'),'c') order by "test"."t1"."ord" +SELECT 'x' FROM t1 WHERE c1||c2 LIKE 'aa%'; +x +x +EXPLAIN EXTENDED SELECT 'x' FROM t1 WHERE c1||c2 LIKE 'aa%'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 select 'x' AS "x" from "test"."t1" USE INDEX () where concat_operator_oracle("test"."t1"."c1","test"."t1"."c2") like 'aa%' +SELECT 'x' FROM t1 WHERE c1||c2 LIKE c2||c1; +x +x +EXPLAIN EXTENDED SELECT 'x' FROM t1 WHERE c1||c2 LIKE c2||c1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 select 'x' AS "x" from "test"."t1" USE INDEX () where concat_operator_oracle("test"."t1"."c1","test"."t1"."c2") like concat_operator_oracle("test"."t1"."c2","test"."t1"."c1") +CREATE VIEW v1 AS SELECT c1, c2, c1 LIKE c2||'_' FROM t1 ORDER BY ord; +EXPLAIN EXTENDED SELECT * FROM v1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 select "test"."t1"."c1" AS "c1","test"."t1"."c2" AS "c2","test"."t1"."c1" like concat_operator_oracle("test"."t1"."c2",'_') AS "c1 LIKE c2||'_'" from "test"."t1" USE INDEX () order by "test"."t1"."ord" +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/columnstore/compat/oracle/func_concat_oracle.test b/mysql-test/columnstore/compat/oracle/func_concat_oracle.test new file mode 100644 index 000000000..f33914eb8 --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_concat_oracle.test @@ -0,0 +1,189 @@ +# +# Testing CONCAT with null values +# + +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; + +EXPLAIN EXTENDED SELECT 'a'||'b'||'c'; +EXPLAIN EXTENDED SELECT CONCAT('a'||'b'||'c'); + +SELECT '' || ''; +SELECT '' || 'b'; +SELECT '' || NULL; +SELECT 'a' || ''; +SELECT 'a' || 'b'; +SELECT 'a' || NULL; +SELECT NULL || ''; +SELECT NULL || 'b'; +SELECT NULL || NULL; + +SELECT '' || '' || ''; +SELECT '' || '' || 'c'; +SELECT '' || '' || NULL; +SELECT '' || 'b' || ''; +SELECT '' || 'b' || 'c'; +SELECT '' || 'b' || NULL; +SELECT '' || NULL || ''; +SELECT '' || NULL || 'c'; +SELECT '' || NULL || NULL; + +SELECT 'a' || '' || ''; +SELECT 'a' || '' || 'c'; +SELECT 'a' || '' || NULL; +SELECT 'a' || 'b' || ''; +SELECT 'a' || 'b' || 'c'; +SELECT 'a' || 'b' || NULL; +SELECT 'a' || NULL || ''; +SELECT 'a' || NULL || 'c'; +SELECT 'a' || NULL || NULL; + +SELECT NULL || '' || ''; +SELECT NULL || '' || 'c'; +SELECT NULL || '' || NULL; +SELECT NULL || 'b' || ''; +SELECT NULL || 'b' || 'c'; +SELECT NULL || 'b' || NULL; +SELECT NULL || NULL || ''; +SELECT NULL || NULL || 'c'; +SELECT NULL || NULL || NULL; + + +CREATE TABLE t1 (a VARCHAR(10), b VARCHAR(10), c VARCHAR(10)); + +INSERT INTO t1 VALUES ('', '', ''); +INSERT INTO t1 VALUES ('', '', 'c'); +INSERT INTO t1 VALUES ('', '', NULL); +INSERT INTO t1 VALUES ('', 'b', ''); +INSERT INTO t1 VALUES ('', 'b', 'c'); +INSERT INTO t1 VALUES ('', 'b', NULL); +INSERT INTO t1 VALUES ('', NULL, ''); +INSERT INTO t1 VALUES ('', NULL, 'c'); +INSERT INTO t1 VALUES ('', NULL, NULL); + +INSERT INTO t1 VALUES ('a', '', ''); +INSERT INTO t1 VALUES ('a', '', 'c'); +INSERT INTO t1 VALUES ('a', '', NULL); +INSERT INTO t1 VALUES ('a', 'b', ''); +INSERT INTO t1 VALUES ('a', 'b', 'c'); +INSERT INTO t1 VALUES ('a', 'b', NULL); +INSERT INTO t1 VALUES ('a', NULL, ''); +INSERT INTO t1 VALUES ('a', NULL, 'c'); +INSERT INTO t1 VALUES ('a', NULL, NULL); + +INSERT INTO t1 VALUES (NULL, '', ''); +INSERT INTO t1 VALUES (NULL, '', 'c'); +INSERT INTO t1 VALUES (NULL, '', NULL); +INSERT INTO t1 VALUES (NULL, 'b', ''); +INSERT INTO t1 VALUES (NULL, 'b', 'c'); +INSERT INTO t1 VALUES (NULL, 'b', NULL); +INSERT INTO t1 VALUES (NULL, NULL, ''); +INSERT INTO t1 VALUES (NULL, NULL, 'c'); +INSERT INTO t1 VALUES (NULL, NULL, NULL); + +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; + + +--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; + + +--echo # +--echo # MDEV-17359 Concatenation operator || in like expression failed in sql_mode=ORACLE +--echo # + +SELECT 'abc' LIKE 'a'||'%'; +EXPLAIN EXTENDED SELECT 'abc' LIKE 'a'||'%'; + +SELECT 'x' FROM DUAL WHERE 11 LIKE 1||1; +SELECT 'x' FROM DUAL WHERE 1||1 LIKE 11; +SELECT 'x' FROM DUAL WHERE 1||1 LIKE 1||1; + +CREATE TABLE t1 (c1 VARCHAR(10),c2 VARCHAR(10), ord INTEGER); +INSERT INTO t1 VALUES ('a', 'ab' ,1); +INSERT INTO t1 VALUES ('ab', 'ab', 2); +INSERT INTO t1 VALUES ('abc', 'ab', 3); + +SELECT c1 FROM t1 WHERE c1 LIKE '%'||'b' ORDER BY ord; +EXPLAIN EXTENDED SELECT c1 FROM t1 WHERE c1 LIKE '%'||'b' ORDER BY ord; + +SELECT c1 FROM t1 WHERE c1 LIKE c2||'%'||'c' ORDER BY ord; +EXPLAIN EXTENDED SELECT c1 FROM t1 WHERE c1 LIKE c2||'%'||'c' ORDER BY ord; + +SELECT 'x' FROM t1 WHERE c1||c2 LIKE 'aa%'; +EXPLAIN EXTENDED SELECT 'x' FROM t1 WHERE c1||c2 LIKE 'aa%'; + +SELECT 'x' FROM t1 WHERE c1||c2 LIKE c2||c1; +EXPLAIN EXTENDED SELECT 'x' FROM t1 WHERE c1||c2 LIKE c2||c1; + +CREATE VIEW v1 AS SELECT c1, c2, c1 LIKE c2||'_' FROM t1 ORDER BY ord; +EXPLAIN EXTENDED SELECT * FROM v1; + +DROP VIEW v1; +DROP TABLE t1; \ No newline at end of file diff --git a/mysql-test/columnstore/compat/oracle/func_decode_oracle.result b/mysql-test/columnstore/compat/oracle/func_decode_oracle.result new file mode 100644 index 000000000..d70c69a60 --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_decode_oracle.result @@ -0,0 +1,171 @@ +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; +SELECT DECODE(10); +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 ')' at line 1 +SELECT DECODE(10,10); +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 ')' at line 1 +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_oracle(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: 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 ')' at line 1 +SELECT DECODE(10,10); +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 ')' at line 1 +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_oracle(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_oracle(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_oracle(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_oracle(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_oracle("t1"."a",1,'x1',NULL,'xNULL') AS "d1",decode_oracle("t1"."a",1,'x1',NULL,'xNULL','xELSE') AS "d2",decode_oracle("t1"."a",1,'x1',NULL,'xNULL') AS "d3",decode_oracle("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 diff --git a/mysql-test/columnstore/compat/oracle/func_decode_oracle.test b/mysql-test/columnstore/compat/oracle/func_decode_oracle.test new file mode 100644 index 000000000..e7b77e3db --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_decode_oracle.test @@ -0,0 +1,94 @@ +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; +--error ER_PARSE_ERROR +SELECT DECODE(10); +--error ER_PARSE_ERROR +SELECT DECODE(10,10); + +SELECT DECODE(10,10,'x10'); +SELECT DECODE(11,10,'x10'); + +SELECT DECODE(10,10,'x10','def'); +SELECT DECODE(11,10,'x10','def'); + +SELECT DECODE(10,10,'x10',11,'x11','def'); +SELECT DECODE(11,10,'x10',11,'x11','def'); +SELECT DECODE(12,10,'x10',11,'x11','def'); + +EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def'); + +CREATE TABLE decode (decode int); +DROP TABLE decode; + + +--echo # +--echo # MDEV-13863 sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent +--echo # + +--error ER_PARSE_ERROR +SELECT DECODE(10); +--error ER_PARSE_ERROR +SELECT DECODE(10,10); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE_ORACLE(10); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT DECODE_ORACLE(10,10); + + +EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11'); +EXPLAIN EXTENDED SELECT DECODE(12,10,'x10',11,'x11','def'); +EXPLAIN EXTENDED SELECT DECODE_ORACLE(12,10,'x10',11,'x11'); +EXPLAIN EXTENDED SELECT 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; +DROP VIEW v1; +DROP TABLE t1; + +SELECT DECODE(TIME'10:20:31','10:20:31','then1','10:20:32','then2','def'); +SELECT DECODE(TIME'10:20:32','10:20:31','then1','10:20:32','then2','def'); +SELECT DECODE(TIME'10:20:33','10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def'); +SELECT DECODE(NULL,TIME'10:20:31','then1',NULL,'then2NULL','10:20:33','then3','def'); + +SELECT DECODE(TIMESTAMP'2001-01-01 10:20:31','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def'); +SELECT DECODE(TIMESTAMP'2001-01-01 10:20:32','2001-01-01 10:20:31','then1','2001-01-01 10:20:32','then2','def'); +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'); +SELECT DECODE(NULL,TIMESTAMP'2001-01-01 10:20:31','then1',NULL,'then2NULL','2001-01-01 10:20:33','then3','def'); + +SELECT DECODE('w1','w1','then1','w2','then2','def'); +SELECT DECODE('w2','w1','then1','w2','then2','def'); +SELECT DECODE('w3','w1','then1',NULL,'then2NULL','w3','then3','def'); +SELECT DECODE(NULL,'w1','then1',NULL,'then2NULL','w3','then3','def'); + +SELECT DECODE(1,1,'then1',2,'then2','def'); +SELECT DECODE(2,1,'then1',2,'then2','def'); +SELECT DECODE(3,1,'then1',NULL,'then2NULL',3,'then3','def'); +SELECT DECODE(NULL,1,'then1',NULL,'then2NULL',3,'then3','def'); +SELECT DECODE(CAST(NULL AS SIGNED),1,'then1',NULL,'then2NULL',3,'then3','def'); + +SELECT DECODE(1.0,1.0,'then1',2.0,'then2','def'); +SELECT DECODE(2.0,1.0,'then1',2.0,'then2','def'); +SELECT DECODE(3.0,1.0,'then1',NULL,'then2NULL',3.0,'then3','def'); +SELECT DECODE(NULL,1.0,'then1',NULL,'then2NULL',3.0,'then3','def'); +SELECT DECODE(CAST(NULL AS DECIMAL),1.0,'then1',NULL,'then2NULL',3.0,'then3','def'); + +SELECT DECODE(1e0,1e0,'then1',2e0,'then2','def'); +SELECT DECODE(2e0,1e0,'then1',2e0,'then2','def'); +SELECT DECODE(3e0,1e0,'then1',NULL,'then2NULL',3e0,'then3','def'); +SELECT DECODE(NULL,1e0,'then1',NULL,'then2NULL',3e0,'then3','def'); +SELECT DECODE(CAST(NULL AS DOUBLE),1e0,'then1',NULL,'then2NULL',3e0,'then3','def'); + +SELECT DECODE(NULL,NULL,1,2) FROM DUAL; +SELECT DECODE(NULL,10,10,NULL,1,2) FROM DUAL; + +SELECT DECODE_ORACLE(NULL,NULL,1,2) FROM DUAL; +SELECT DECODE_ORACLE(NULL,10,10,NULL,1,2) FROM DUAL; + diff --git a/mysql-test/columnstore/compat/oracle/func_replace_oracle.result b/mysql-test/columnstore/compat/oracle/func_replace_oracle.result new file mode 100644 index 000000000..9ef949a2c --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_replace_oracle.result @@ -0,0 +1,33 @@ +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; +# +# MDEV-13003 - Oracle compatibility : Replace function +# +SELECT REPLACE(null,'a','b') ; +REPLACE(null,'a','b') +NULL +SELECT REPLACE('ab',null,'b') ; +REPLACE('ab',null,'b') +ab +SELECT REPLACE('ab','a',null) ; +REPLACE('ab','a',null) +b +SELECT REPLACE('ab',null,null) ; +REPLACE('ab',null,null) +ab +SELECT REPLACE('aaa','a',null) ; +REPLACE('aaa','a',null) +NULL +EXPLAIN EXTENDED SELECT REPLACE('ab','a',null) ; +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 replace_oracle('ab','a',NULL) AS "REPLACE('ab','a',null)" +CREATE VIEW v1 AS SELECT REPLACE('ab','a',null) ; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select replace_oracle('ab','a',NULL) AS "REPLACE('ab','a',null)" latin1 latin1_swedish_ci +SELECT * FROM v1; +REPLACE('ab','a',null) +b +DROP VIEW v1; diff --git a/mysql-test/columnstore/compat/oracle/func_replace_oracle.test b/mysql-test/columnstore/compat/oracle/func_replace_oracle.test new file mode 100644 index 000000000..87dc1d87a --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_replace_oracle.test @@ -0,0 +1,22 @@ +# +# Testing replace with null args +# + +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; +--echo # +--echo # MDEV-13003 - Oracle compatibility : Replace function +--echo # + +SELECT REPLACE(null,'a','b') ; +SELECT REPLACE('ab',null,'b') ; +SELECT REPLACE('ab','a',null) ; +SELECT REPLACE('ab',null,null) ; +SELECT REPLACE('aaa','a',null) ; + +EXPLAIN EXTENDED SELECT REPLACE('ab','a',null) ; + +CREATE VIEW v1 AS SELECT REPLACE('ab','a',null) ; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; diff --git a/mysql-test/columnstore/compat/oracle/func_trim_oracle.result b/mysql-test/columnstore/compat/oracle/func_trim_oracle.result new file mode 100644 index 000000000..ad05d3aa2 --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_trim_oracle.result @@ -0,0 +1,171 @@ +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; +# +# MDEV-15664 sql_mode=ORACLE: Make TRIM return NULL instead of empty string +# +SELECT TRIM('abc'), TRIM('abc ')||'.', '.'||TRIM(' abc ')||'.', TRIM(' '), TRIM(NULL), TRIM(SPACE(0)),TRIM(SPACE(10)) FROM dual; +TRIM('abc') TRIM('abc ')||'.' '.'||TRIM(' abc ')||'.' TRIM(' ') TRIM(NULL) TRIM(SPACE(0)) TRIM(SPACE(10)) +abc abc. .abc. NULL NULL NULL NULL +SELECT TRIM(TRAILING 'abc' FROM 'abc'); +TRIM(TRAILING 'abc' FROM 'abc') +NULL +SELECT TRIM(TRAILING 'abc' FROM 'abc '); +TRIM(TRAILING 'abc' FROM 'abc ') +abc +SELECT TRIM(TRAILING 'abc' FROM ' abc'); +TRIM(TRAILING 'abc' FROM ' abc') + +SELECT TRIM(LEADING 'abc' FROM 'abc'); +TRIM(LEADING 'abc' FROM 'abc') +NULL +SELECT TRIM(LEADING 'abc' FROM 'abc '); +TRIM(LEADING 'abc' FROM 'abc ') + +SELECT TRIM(LEADING 'abc' FROM ' abc'); +TRIM(LEADING 'abc' FROM ' abc') + abc +SELECT TRIM(BOTH 'abc' FROM 'abc'); +TRIM(BOTH 'abc' FROM 'abc') +NULL +SELECT TRIM(BOTH 'abc' FROM 'abc '); +TRIM(BOTH 'abc' FROM 'abc ') + +SELECT TRIM(BOTH 'abc' FROM ' abc'); +TRIM(BOTH 'abc' FROM ' abc') + +SELECT RTRIM('abc'), RTRIM('abc ')||'.', RTRIM(' abc ')||'.', RTRIM(' '), RTRIM(NULL), RTRIM(SPACE(0)),RTRIM(SPACE(10)) FROM dual; +RTRIM('abc') RTRIM('abc ')||'.' RTRIM(' abc ')||'.' RTRIM(' ') RTRIM(NULL) RTRIM(SPACE(0)) RTRIM(SPACE(10)) +abc abc. abc. NULL NULL NULL NULL +SELECT LTRIM('abc'), LTRIM('abc '), LTRIM(' abc '), LTRIM(' '), LTRIM(NULL), LTRIM(SPACE(0)),LTRIM(SPACE(10)) FROM dual; +LTRIM('abc') LTRIM('abc ') LTRIM(' abc ') LTRIM(' ') LTRIM(NULL) LTRIM(SPACE(0)) LTRIM(SPACE(10)) +abc abc abc NULL NULL NULL NULL +CREATE TABLE t1 (c1 VARCHAR(10),ord INTEGER); +INSERT INTO t1 VALUES ('abc',1); +INSERT INTO t1 VALUES (SPACE(0),2); +INSERT INTO t1 VALUES ('',3); +INSERT INTO t1 VALUES (' ',4); +INSERT INTO t1 VALUES (' ',5); +INSERT INTO t1 VALUES (' a ',6); +INSERT INTO t1 VALUES ('aa',7); +INSERT INTO t1 VALUES ('aabb',8); +INSERT INTO t1 VALUES ('bbaa',9); +INSERT INTO t1 VALUES ('aabbaa',10); +SELECT ord,'['||c1||']','.'||COALESCE(TRIM(LEADING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord; +ord '['||c1||']' '.'||COALESCE(TRIM(LEADING 'a' FROM c1),'NULL')||'.' +1 [abc] .bc. +2 [] .NULL. +3 [] .NULL. +4 [ ] . . +5 [ ] . . +6 [ a ] . a . +7 [aa] .NULL. +8 [aabb] .bb. +9 [bbaa] .bbaa. +10 [aabbaa] .bbaa. +SELECT ord,'['||c1||']','.'||COALESCE(TRIM(TRAILING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord; +ord '['||c1||']' '.'||COALESCE(TRIM(TRAILING 'a' FROM c1),'NULL')||'.' +1 [abc] .abc. +2 [] .NULL. +3 [] .NULL. +4 [ ] . . +5 [ ] . . +6 [ a ] . a . +7 [aa] .NULL. +8 [aabb] .aabb. +9 [bbaa] .bb. +10 [aabbaa] .aabb. +SELECT ord,'['||c1||']','.'||COALESCE(TRIM(BOTH 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord; +ord '['||c1||']' '.'||COALESCE(TRIM(BOTH 'a' FROM c1),'NULL')||'.' +1 [abc] .bc. +2 [] .NULL. +3 [] .NULL. +4 [ ] . . +5 [ ] . . +6 [ a ] . a . +7 [aa] .NULL. +8 [aabb] .bb. +9 [bbaa] .bb. +10 [aabbaa] .bb. +SELECT ord,'['||c1||']',COALESCE(LTRIM(c1),'NULL') FROM t1 ORDER BY ord; +ord '['||c1||']' COALESCE(LTRIM(c1),'NULL') +1 [abc] abc +2 [] NULL +3 [] NULL +4 [ ] NULL +5 [ ] NULL +6 [ a ] a +7 [aa] aa +8 [aabb] aabb +9 [bbaa] bbaa +10 [aabbaa] aabbaa +SELECT ord,'['||c1||']',COALESCE(RTRIM(c1),'NULL')||'.' FROM t1 ORDER BY ord; +ord '['||c1||']' COALESCE(RTRIM(c1),'NULL')||'.' +1 [abc] abc. +2 [] NULL. +3 [] NULL. +4 [ ] NULL. +5 [ ] NULL. +6 [ a ] a. +7 [aa] aa. +8 [aabb] aabb. +9 [bbaa] bbaa. +10 [aabbaa] aabbaa. +EXPLAIN EXTENDED SELECT TRIM('abc'), +TRIM(BOTH 'a' FROM 'abc'), +TRIM(LEADING 'a' FROM 'abc'), +TRIM(TRAILING 'a' FROM 'abc') ; +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 trim_oracle('abc') AS "TRIM('abc')",trim_oracle(both 'a' from 'abc') AS "TRIM(BOTH 'a' FROM 'abc')",trim_oracle(leading 'a' from 'abc') AS "TRIM(LEADING 'a' FROM 'abc')",trim_oracle(trailing 'a' from 'abc') AS "TRIM(TRAILING 'a' FROM 'abc')" +EXPLAIN EXTENDED SELECT RTRIM('abc'), +LTRIM('abc'); +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 rtrim_oracle('abc') AS "RTRIM('abc')",ltrim_oracle('abc') AS "LTRIM('abc')" +CREATE VIEW v1 AS SELECT ord,TRIM('abc'),RTRIM('abc'),LTRIM('abc'), +'['||c1||']', +TRIM(LEADING 'a' FROM c1), +TRIM(TRAILING 'a' FROM c1), +TRIM(BOTH 'a' FROM c1), +LTRIM(c1), +RTRIM(c1) +FROM t1 ORDER BY ord ; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE VIEW "v1" AS select "t1"."ord" AS "ord",trim_oracle('abc') AS "TRIM('abc')",rtrim_oracle('abc') AS "RTRIM('abc')",ltrim_oracle('abc') AS "LTRIM('abc')",concat_operator_oracle(concat_operator_oracle('[',"t1"."c1"),']') AS "'['||c1||']'",trim_oracle(leading 'a' from "t1"."c1") AS "TRIM(LEADING 'a' FROM c1)",trim_oracle(trailing 'a' from "t1"."c1") AS "TRIM(TRAILING 'a' FROM c1)",trim_oracle(both 'a' from "t1"."c1") AS "TRIM(BOTH 'a' FROM c1)",ltrim_oracle("t1"."c1") AS "LTRIM(c1)",rtrim_oracle("t1"."c1") AS "RTRIM(c1)" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci +SELECT * FROM v1; +ord TRIM('abc') RTRIM('abc') LTRIM('abc') '['||c1||']' TRIM(LEADING 'a' FROM c1) TRIM(TRAILING 'a' FROM c1) TRIM(BOTH 'a' FROM c1) LTRIM(c1) RTRIM(c1) +1 abc abc abc [abc] bc abc bc abc abc +2 abc abc abc [] NULL NULL NULL NULL NULL +3 abc abc abc [] NULL NULL NULL NULL NULL +4 abc abc abc [ ] NULL NULL +5 abc abc abc [ ] NULL NULL +6 abc abc abc [ a ] a a a a a +7 abc abc abc [aa] NULL NULL NULL aa aa +8 abc abc abc [aabb] bb aabb bb aabb aabb +9 abc abc abc [bbaa] bbaa bb bb bbaa bbaa +10 abc abc abc [aabbaa] bbaa aabb bb aabbaa aabbaa +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (c1 VARCHAR(10) NOT NULL); +CREATE TABLE t2 AS SELECT TRIM(LEADING 'a' FROM c1) AS C1, +TRIM(TRAILING 'a' FROM c1) AS C2, +TRIM(BOTH 'a' FROM c1) AS C3, +LTRIM(c1) AS C4, +RTRIM(c1) AS C5 +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE "t2" ( + "C1" varchar(10) DEFAULT NULL, + "C2" varchar(10) DEFAULT NULL, + "C3" varchar(10) DEFAULT NULL, + "C4" varchar(10) DEFAULT NULL, + "C5" varchar(10) DEFAULT NULL +) +DROP TABLE t2; +DROP TABLE t1; +CREATE TABLE trim_oracle (trim_oracle int); +DROP TABLE trim_oracle; diff --git a/mysql-test/columnstore/compat/oracle/func_trim_oracle.test b/mysql-test/columnstore/compat/oracle/func_trim_oracle.test new file mode 100644 index 000000000..a09617118 --- /dev/null +++ b/mysql-test/columnstore/compat/oracle/func_trim_oracle.test @@ -0,0 +1,78 @@ +SET sql_mode=ORACLE; +SET default_storage_engine=ColumnStore; + +--echo # +--echo # MDEV-15664 sql_mode=ORACLE: Make TRIM return NULL instead of empty string +--echo # + +SELECT TRIM('abc'), TRIM('abc ')||'.', '.'||TRIM(' abc ')||'.', TRIM(' '), TRIM(NULL), TRIM(SPACE(0)),TRIM(SPACE(10)) FROM dual; + +SELECT TRIM(TRAILING 'abc' FROM 'abc'); +SELECT TRIM(TRAILING 'abc' FROM 'abc '); +SELECT TRIM(TRAILING 'abc' FROM ' abc'); + +SELECT TRIM(LEADING 'abc' FROM 'abc'); +SELECT TRIM(LEADING 'abc' FROM 'abc '); +SELECT TRIM(LEADING 'abc' FROM ' abc'); + +SELECT TRIM(BOTH 'abc' FROM 'abc'); +SELECT TRIM(BOTH 'abc' FROM 'abc '); +SELECT TRIM(BOTH 'abc' FROM ' abc'); + +SELECT RTRIM('abc'), RTRIM('abc ')||'.', RTRIM(' abc ')||'.', RTRIM(' '), RTRIM(NULL), RTRIM(SPACE(0)),RTRIM(SPACE(10)) FROM dual; +SELECT LTRIM('abc'), LTRIM('abc '), LTRIM(' abc '), LTRIM(' '), LTRIM(NULL), LTRIM(SPACE(0)),LTRIM(SPACE(10)) FROM dual; + +CREATE TABLE t1 (c1 VARCHAR(10),ord INTEGER); +INSERT INTO t1 VALUES ('abc',1); +INSERT INTO t1 VALUES (SPACE(0),2); +INSERT INTO t1 VALUES ('',3); +INSERT INTO t1 VALUES (' ',4); +INSERT INTO t1 VALUES (' ',5); +INSERT INTO t1 VALUES (' a ',6); +INSERT INTO t1 VALUES ('aa',7); +INSERT INTO t1 VALUES ('aabb',8); +INSERT INTO t1 VALUES ('bbaa',9); +INSERT INTO t1 VALUES ('aabbaa',10); + +SELECT ord,'['||c1||']','.'||COALESCE(TRIM(LEADING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord; +SELECT ord,'['||c1||']','.'||COALESCE(TRIM(TRAILING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord; +SELECT ord,'['||c1||']','.'||COALESCE(TRIM(BOTH 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord; +SELECT ord,'['||c1||']',COALESCE(LTRIM(c1),'NULL') FROM t1 ORDER BY ord; +SELECT ord,'['||c1||']',COALESCE(RTRIM(c1),'NULL')||'.' FROM t1 ORDER BY ord; + +EXPLAIN EXTENDED SELECT TRIM('abc'), + TRIM(BOTH 'a' FROM 'abc'), + TRIM(LEADING 'a' FROM 'abc'), + TRIM(TRAILING 'a' FROM 'abc') ; + +EXPLAIN EXTENDED SELECT RTRIM('abc'), + LTRIM('abc'); + + +CREATE VIEW v1 AS SELECT ord,TRIM('abc'),RTRIM('abc'),LTRIM('abc'), + '['||c1||']', + TRIM(LEADING 'a' FROM c1), + TRIM(TRAILING 'a' FROM c1), + TRIM(BOTH 'a' FROM c1), + LTRIM(c1), + RTRIM(c1) + FROM t1 ORDER BY ord ; +SHOW CREATE VIEW v1; +SELECT * FROM v1; +DROP VIEW v1; + +DROP TABLE t1; + +CREATE TABLE t1 (c1 VARCHAR(10) NOT NULL); +CREATE TABLE t2 AS SELECT TRIM(LEADING 'a' FROM c1) AS C1, + TRIM(TRAILING 'a' FROM c1) AS C2, + TRIM(BOTH 'a' FROM c1) AS C3, + LTRIM(c1) AS C4, + RTRIM(c1) AS C5 + FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; + +CREATE TABLE trim_oracle (trim_oracle int); +DROP TABLE trim_oracle; diff --git a/utils/funcexp/CMakeLists.txt b/utils/funcexp/CMakeLists.txt index 84aa16b70..0d47d21ed 100644 --- a/utils/funcexp/CMakeLists.txt +++ b/utils/funcexp/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories( ${ENGINE_COMMON_INCLUDES} ) ########### next target ############### +# func_decode_oracle.cpp set(funcexp_LIB_SRCS functor.cpp @@ -20,6 +21,7 @@ set(funcexp_LIB_SRCS func_char_length.cpp func_coalesce.cpp func_concat.cpp + func_concat_oracle.cpp func_concat_ws.cpp func_conv.cpp func_crc32.cpp @@ -31,6 +33,7 @@ set(funcexp_LIB_SRCS func_dayofweek.cpp func_dayofyear.cpp func_decode.cpp + func_decode_oracle.cpp func_div.cpp func_elt.cpp func_encode.cpp @@ -60,6 +63,7 @@ set(funcexp_LIB_SRCS func_length.cpp func_lpad.cpp func_ltrim.cpp + func_ltrim_oracle.cpp func_makedate.cpp func_maketime.cpp func_math.cpp @@ -79,11 +83,13 @@ set(funcexp_LIB_SRCS func_regexp.cpp func_repeat.cpp func_replace.cpp + func_replace_oracle.cpp func_reverse.cpp func_right.cpp func_round.cpp func_rpad.cpp func_rtrim.cpp + func_rtrim_oracle.cpp func_second.cpp func_sec_to_time.cpp func_sha.cpp @@ -101,6 +107,7 @@ set(funcexp_LIB_SRCS func_timestampdiff.cpp func_to_days.cpp func_trim.cpp + func_trim_oracle.cpp func_truncate.cpp func_ucase.cpp func_unhex.cpp diff --git a/utils/funcexp/func_concat_oracle.cpp b/utils/funcexp/func_concat_oracle.cpp new file mode 100644 index 000000000..fbc0be844 --- /dev/null +++ b/utils/funcexp/func_concat_oracle.cpp @@ -0,0 +1,78 @@ +/* Copyright (C) 2021 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include +using namespace std; + +#include "functor_str.h" +#include "functioncolumn.h" +#include "utils_utf8.h" +using namespace execplan; + +#include "rowgroup.h" +using namespace rowgroup; + +#include "dataconvert.h" +using namespace dataconvert; + +namespace funcexp +{ + +CalpontSystemCatalog::ColType Func_concat_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType ) +{ + // operation type is not used by this functor + return fp[0]->data()->resultType(); +} + + +// Returns the string that results from concatenating the arguments. +// concat_oracle() returns NULL all arguments are NULL. +// single arguments null is replaced by "". +// +string Func_concat_oracle::getStrVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType&) +{ + string ret; + string tmp; + stringValue(parm[0], row, isNull, ret); + // Oracle Mode should replace NULL with "" unless all values are NULL + if (isNull) + { + ret = ""; + isNull = false; + } + // TODO: do a better job of cutting down the number re-allocations. + // look at Item_func_concat::realloc_result for ideas and use + // std::string:resize() appropriatly. + for ( unsigned int id = 1 ; id < parm.size() ; id++) + { + stringValue(parm[id], row, isNull, tmp); + if (isNull) + { + tmp = ""; + isNull = false; + } + ret.append(tmp); + } + + return ret; +} + +} // namespace funcexp +// vim:ts=4 sw=4: diff --git a/utils/funcexp/func_decode.cpp b/utils/funcexp/func_decode.cpp index 92442cee1..14b8e9e88 100644 --- a/utils/funcexp/func_decode.cpp +++ b/utils/funcexp/func_decode.cpp @@ -1,3 +1,20 @@ +/* Copyright (C) 2021 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + #include #include using namespace std; diff --git a/utils/funcexp/func_decode_oracle.cpp b/utils/funcexp/func_decode_oracle.cpp new file mode 100644 index 000000000..11bb3a0b7 --- /dev/null +++ b/utils/funcexp/func_decode_oracle.cpp @@ -0,0 +1,585 @@ +/* Copyright (C) 2021 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include +//#define NDEBUG +#include +using namespace std; + +#include "functor_all.h" +#include "functioncolumn.h" +#include "predicateoperator.h" +using namespace execplan; + +#include "rowgroup.h" +using namespace rowgroup; + +#include "errorcodes.h" +#include "idberrorinfo.h" +#include "errorids.h" +using namespace logging; + +#include "utils_utf8.h" +using namespace funcexp; + +#include "collation.h" + +namespace +{ +using namespace funcexp; + +inline uint64_t simple_case_cmp(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = 0; // index to the parm list + uint64_t n = 0; // remove expression from count of expression_i + result_i + uint64_t hasElse = (parm.size() - 1) % 2; // if 1, then ELSE exist + uint64_t whereCount = hasElse ? (parm.size() - 2) / 2 : (parm.size() - 1) / 2; + bool foundIt = false; + + switch (operationColType.colDataType) + { + case execplan::CalpontSystemCatalog::TINYINT: + case execplan::CalpontSystemCatalog::SMALLINT: + case execplan::CalpontSystemCatalog::MEDINT: + case execplan::CalpontSystemCatalog::INT: + case execplan::CalpontSystemCatalog::BIGINT: + case execplan::CalpontSystemCatalog::DATE: + { + int64_t ev = parm[n]->data()->getIntVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getIntVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::DATETIME: + { + int64_t ev = parm[n]->data()->getDatetimeIntVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getDatetimeIntVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::TIMESTAMP: + { + int64_t ev = parm[n]->data()->getTimestampIntVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getTimestampIntVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::TIME: + { + int64_t ev = parm[n]->data()->getTimeIntVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getTimeIntVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + + case execplan::CalpontSystemCatalog::UBIGINT: + case execplan::CalpontSystemCatalog::UINT: + case execplan::CalpontSystemCatalog::UMEDINT: + case execplan::CalpontSystemCatalog::UTINYINT: + case execplan::CalpontSystemCatalog::USMALLINT: + { + uint64_t ev = parm[n]->data()->getUintVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getUintVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::CHAR: + case execplan::CalpontSystemCatalog::TEXT: + case execplan::CalpontSystemCatalog::VARCHAR: + { + const string& ev = parm[n]->data()->getStrVal(row, isNull); + if (isNull) + break; + CHARSET_INFO* cs = parm[n]->data()->resultType().getCharset(); + + for (i = 1; i <= whereCount; i++) + { + //BUG 5362 + const string& p1 = parm[i]->data()->getStrVal(row, isNull); + if (isNull) + break; + if (cs->strnncoll(ev.c_str(), ev.length(), p1.c_str(), p1.length()) == 0) + { + foundIt = true; + break; + } + } + + break; + } + + case execplan::CalpontSystemCatalog::DECIMAL: + case execplan::CalpontSystemCatalog::UDECIMAL: + { + IDB_Decimal ev = parm[n]->data()->getDecimalVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getDecimalVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::DOUBLE: + case execplan::CalpontSystemCatalog::UDOUBLE: + { + double ev = parm[n]->data()->getDoubleVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getDoubleVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::FLOAT: + case execplan::CalpontSystemCatalog::UFLOAT: + { + float ev = parm[n]->data()->getFloatVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getFloatVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + case execplan::CalpontSystemCatalog::LONGDOUBLE: + { + long double ev = parm[n]->data()->getLongDoubleVal(row, isNull); + + if (isNull) + break; + + for (i = 1; i <= whereCount; i++) + { + if (ev == parm[i]->data()->getLongDoubleVal(row, isNull) && !isNull) + { + foundIt = true; + break; + } + else + isNull = false; + } + + break; + } + + default: + { + std::ostringstream oss; + oss << "case: datatype of " << execplan::colDataTypeToString(operationColType.colDataType); + throw logging::IDBExcept(oss.str(), ERR_DATATYPE_NOT_SUPPORT); + } + } + + if (!foundIt && !hasElse) + isNull = true; + else if (!foundIt && hasElse && !isNull) + { + i = parm.size() - 1; + } + else if (isNull && hasElse) + // BUG 5110. Only way we can exit above with isNull == true is when ev is NULL + // if so and we have else condition we need to use it by setting i = else + { + i = parm.size() - 1; + isNull = false; + } + + if (foundIt) + { + i += whereCount; + } + + return i; +} + +CalpontSystemCatalog::ColType caseOperationType(FunctionParm& fp, + CalpontSystemCatalog::ColType& resultType, + bool simpleCase) +{ + uint64_t simple = simpleCase ? 1 : 0; + bool hasElse = (((fp.size()-simple) % 2) != 0); // if 1, then ELSE exist + + uint64_t parmCount = hasElse ? (fp.size() - 2) : (fp.size() - 1); + uint64_t whereCount = hasElse ? (fp.size() - 2 + simple) / 2 : (fp.size() - 1) / 2 + simple; + + bool allStringO = true; + bool allStringR = true; + + FunctionParm::size_type l = fp.size() - 1; // last fp index + idbassert(fp[l]->data()); + CalpontSystemCatalog::ColType oct = fp[l]->data()->resultType(); + CalpontSystemCatalog::ColType rct = resultType; + bool operation = true; + + for (uint64_t i = 0; i <= parmCount; i++) + { + // for SimpleCase, we return the type of the case expression, + // which will always be in position 0. + if (i == 0 && simpleCase) + { + if (fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::CHAR && + fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::TEXT && + fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::VARCHAR) + { + PredicateOperator op; + op.setOpType(oct, fp[i]->data()->resultType()); + allStringO = false; + oct = op.operationType(); + } + + i += 1; + } + + // operation or result type + operation = ((i > 0+simple) && (i <= whereCount)); + + if (fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::CHAR && + fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::TEXT && + fp[i]->data()->resultType().colDataType != CalpontSystemCatalog::VARCHAR) + { + // this is not a string column + PredicateOperator op; + + if (operation) + { + if (!simpleCase) + { + op.setOpType(oct, fp[i]->data()->resultType()); + allStringO = false; + oct = op.operationType(); + } + } + + // If any parm is of string type, the result type should be string. (same as if) + else if (rct.colDataType != CalpontSystemCatalog::CHAR && + rct.colDataType != CalpontSystemCatalog::TEXT && + rct.colDataType != CalpontSystemCatalog::VARCHAR) + { + op.setOpType(rct, fp[i]->data()->resultType()); + allStringR = false; + rct = op.operationType(); + } + } + else + { + // this is a string + // If any parm is of string type, the result type should be string. (same as if) + allStringR = true; + } + } + + if (allStringO) + { + oct.colDataType = CalpontSystemCatalog::VARCHAR; + oct.colWidth = 255; + } + + if (allStringR) + { + rct.colDataType = CalpontSystemCatalog::VARCHAR; + rct.colWidth = 255; + } + + if (rct.scale != 0 && rct.colDataType == CalpontSystemCatalog::BIGINT) + rct.colDataType = CalpontSystemCatalog::DECIMAL; + + if (oct.scale != 0 && oct.colDataType == CalpontSystemCatalog::BIGINT) + oct.colDataType = CalpontSystemCatalog::DECIMAL; + + resultType = rct; + return oct; +} + +} + + +namespace funcexp +{ + +// simple CASE: +// SELECT CASE ("expression") +// WHEN "condition1" THEN "result1" +// WHEN "condition2" THEN "result2" +// ... +// [ELSE "resultN"] +// END +// +// simple CASE parm order: +// expression condition1 condition2 ... result1 result2 ... [resultN] +// +// Note that this order changed in 10.2.14, see MCOL-1341 + +CalpontSystemCatalog::ColType Func_decode_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) +{ + return caseOperationType(fp, resultType, true); +} + + +bool Func_decode_oracle::getBoolVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return false; + + ParseTree* lop = parm[i]->left(); + ParseTree* rop = parm[i]->right(); + if (lop && rop) + { + return (reinterpret_cast(parm[i]->data()))->getBoolVal(row, isNull, lop, rop); + } + + return parm[i]->data()->getBoolVal(row, isNull); +} + + +int64_t Func_decode_oracle::getIntVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return joblist::BIGINTNULL; + + return parm[i]->data()->getIntVal(row, isNull); +} + + +string Func_decode_oracle::getStrVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return string(""); + + return parm[i]->data()->getStrVal(row, isNull); +} + + +IDB_Decimal Func_decode_oracle::getDecimalVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return IDB_Decimal(); // need a null value for IDB_Decimal?? + + return parm[i]->data()->getDecimalVal(row, isNull); +} + + +double Func_decode_oracle::getDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return doubleNullVal(); + + return parm[i]->data()->getDoubleVal(row, isNull); +} + +long double Func_decode_oracle::getLongDoubleVal(Row& row, + FunctionParm& parm, + bool& isNull, + CalpontSystemCatalog::ColType& operationColType) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, operationColType); + + if (isNull) + return doubleNullVal(); + + return parm[i]->data()->getLongDoubleVal(row, isNull); +} + + +int32_t Func_decode_oracle::getDateIntVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, op_ct); + + if (isNull) + return joblist::DATENULL; + + return parm[i]->data()->getDateIntVal(row, isNull); +} + + +int64_t Func_decode_oracle::getDatetimeIntVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, op_ct); + + if (isNull) + return joblist::DATETIMENULL; + + return parm[i]->data()->getDatetimeIntVal(row, isNull); +} + + +int64_t Func_decode_oracle::getTimestampIntVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, op_ct); + + if (isNull) + return joblist::TIMESTAMPNULL; + + return parm[i]->data()->getTimestampIntVal(row, isNull); +} + + +int64_t Func_decode_oracle::getTimeIntVal(rowgroup::Row& row, + FunctionParm& parm, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + uint64_t i = simple_case_cmp(row, parm, isNull, op_ct); + + if (isNull) + return joblist::TIMENULL; + + return parm[i]->data()->getTimeIntVal(row, isNull); +} + + + +} diff --git a/utils/funcexp/func_encode.cpp b/utils/funcexp/func_encode.cpp index 5e1d27360..5d6d1f05f 100644 --- a/utils/funcexp/func_encode.cpp +++ b/utils/funcexp/func_encode.cpp @@ -1,3 +1,21 @@ +/* Copyright (C) 2014 InfiniDB, Inc. + Copyright (C) 2021 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + #include #include using namespace std; diff --git a/utils/funcexp/func_ltrim_oracle.cpp b/utils/funcexp/func_ltrim_oracle.cpp new file mode 100644 index 000000000..522459449 --- /dev/null +++ b/utils/funcexp/func_ltrim_oracle.cpp @@ -0,0 +1,107 @@ +/* Copyright (C) 2014 InfiniDB, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/**************************************************************************** +* $Id: func_ltrim.cpp 3923 2013-06-19 21:43:06Z bwilkinson $ +* +* +****************************************************************************/ + +#include +using namespace std; + +#include "functor_str.h" +#include "functioncolumn.h" +#include "utils_utf8.h" +using namespace execplan; + +#include "rowgroup.h" +using namespace rowgroup; + +#include "joblisttypes.h" +using namespace joblist; + +#include "collation.h" + +namespace funcexp +{ + +CalpontSystemCatalog::ColType Func_ltrim_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) +{ + // operation type is not used by this functor + return fp[0]->data()->resultType(); +} + + +std::string Func_ltrim_oracle::getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& type) +{ + CHARSET_INFO* cs = type.getCharset(); + // The original string + const string& src = fp[0]->data()->getStrVal(row, isNull); + if (isNull) + return ""; + if (src.empty() || src.length() == 0) + return src; + // binLen represents the number of bytes in src + size_t binLen = src.length(); + const char* pos = src.c_str(); + const char* end = pos + binLen; + // strLen = the number of characters in src + size_t strLen = cs->numchars(pos, end); + + // The trim characters. + const string& trim = (fp.size() > 1 ? fp[1]->data()->getStrVal(row, isNull) : " "); + // binTLen represents the number of bytes in trim + size_t binTLen = trim.length(); + const char* posT = trim.c_str(); + // strTLen = the number of characters in trim + size_t strTLen = cs->numchars(posT, posT+binTLen); + if (strTLen == 0 || strTLen > strLen) + return src; + + if (binTLen == 1) + { + // If the trim string is 1 byte, don't waste cpu for memcmp + while (pos < end && *pos == *posT) + { + ++pos; + --binLen; + } + } + else + { + while (pos+binTLen <= end && memcmp(pos,posT,binTLen) == 0) + { + pos += binTLen; + binLen -= binTLen; + } + } + // Turn back to a string + std::string ret(pos, binLen); + if (binLen == 0) + { + isNull = true; + } + return ret; +} + +} // namespace funcexp +// vim:ts=4 sw=4: + diff --git a/utils/funcexp/func_replace_oracle.cpp b/utils/funcexp/func_replace_oracle.cpp new file mode 100644 index 000000000..312d2243f --- /dev/null +++ b/utils/funcexp/func_replace_oracle.cpp @@ -0,0 +1,178 @@ +/* Copyright (C) 2021 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include +using namespace std; + +#include "functor_str.h" +#include "functioncolumn.h" +using namespace execplan; + +#include "rowgroup.h" +using namespace rowgroup; + +#include "joblisttypes.h" +using namespace joblist; + +#include "collation.h" + +namespace funcexp +{ + +CalpontSystemCatalog::ColType Func_replace_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) +{ + // operation type is not used by this functor + return fp[0]->data()->resultType(); +} + + +std::string Func_replace_oracle::getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& ct) +{ + CHARSET_INFO* cs = ct.getCharset(); + + const string& str = fp[0]->data()->getStrVal(row, isNull); + if (isNull) + return ""; + size_t strLen = str.length(); + + const string& fromstr = fp[1]->data()->getStrVal(row, isNull); + if (isNull) + return ""; + if (fromstr.length() == 0) + return str; + size_t fromLen = fromstr.length(); + + const string& tostr = fp[2]->data()->getStrVal(row, isNull); + if (isNull) + return ""; + size_t toLen = tostr.length(); + + bool binaryCmp = (cs->state & MY_CS_BINSORT) || !cs->use_mb(); + string newstr; + size_t pos = 0; + if (binaryCmp) + { + // Count the number of fromstr in strend so we can reserve buffer space. + int count = 0; + do + { + ++count; + pos = str.find(fromstr, pos + fromLen); + } + while (pos != string::npos); + + newstr.reserve(strLen + (count * ((int)toLen - (int)fromLen)) + 1); + + uint32_t i = 0; + pos = str.find(fromstr); + if (pos == string::npos) + return str; + // Move the stuff into newstr + do + { + if (pos > i) + newstr = newstr + str.substr(i, pos - i); + + newstr = newstr + tostr; + i = pos + fromLen; + pos = str.find(fromstr, i); + } + while (pos != string::npos); + + newstr = newstr + str.substr(i, string::npos); + } + else + { + // UTF + const char* src = str.c_str(); + const char* srcEnd = src + strLen; + const char* srchEnd = srcEnd - fromLen + 1; + const char* from = fromstr.c_str(); + const char* fromEnd = from + fromLen; + const char* to = tostr.c_str(); + const char* ptr = src; + char *i,*j; + size_t count = 10; // Some arbitray number to reserve some space to start. + int growlen = (int)toLen - (int)fromLen; + growlen = growlen < 1 ? 1 : growlen; + growlen *= count; + newstr.reserve(strLen + (count * growlen) + 1); + size_t maxsize = newstr.capacity(); + uint32_t l; + + // We don't know where byte patterns might match so + // we start at the beginning of the string and move forward + // one character at a time until we find a match. Then we can + // move the src bytes and add in the to bytes,then try again. + while (ptr < srchEnd) + { + bool found = false; + if (*ptr == *from) // If the first byte matches, maybe we have a match + { + // Do a byte by byte compare of src at that spot against from + i = const_cast(ptr) + 1; + j = const_cast(from) + 1; + found = true; + while (j != fromEnd) + { + if (*i++ != *j++) + { + found = false; + break; + } + } + } + if (found) + { + if (ptr < i) + { + int mvsize = ptr - src; + if (newstr.length() + mvsize + toLen > maxsize) + { + // We need a re-alloc + newstr.reserve(maxsize + growlen); + maxsize = newstr.capacity(); + growlen *= 2; + } + newstr.append(src, ptr - src); + src += mvsize + fromLen; + ptr = src; + } + newstr.append(to, toLen); + } + else + { + // move to the next character + if ((l = my_ismbchar(cs, ptr, srcEnd))) // returns the number of bytes in the leading char or zero if one byte + ptr += l; + else + ++ptr; + } + } + // Copy in the trailing src chars. + newstr.append(src, srcEnd - src); + } + return newstr; +} + + +} // namespace funcexp +// vim:ts=4 sw=4: + diff --git a/utils/funcexp/func_rtrim_oracle.cpp b/utils/funcexp/func_rtrim_oracle.cpp new file mode 100644 index 000000000..d45136aa1 --- /dev/null +++ b/utils/funcexp/func_rtrim_oracle.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2014 InfiniDB, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/**************************************************************************** +* $Id: func_rtrim.cpp 3923 2013-06-19 21:43:06Z bwilkinson $ +* +* +****************************************************************************/ + +#include +using namespace std; + +#include "functor_str.h" +#include "functioncolumn.h" +#include "utils_utf8.h" +using namespace execplan; + +#include "rowgroup.h" +using namespace rowgroup; + +#include "joblisttypes.h" +using namespace joblist; + +#include "collation.h" + +namespace funcexp +{ + +CalpontSystemCatalog::ColType Func_rtrim_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) +{ + // operation type is not used by this functor + return fp[0]->data()->resultType(); +} + + +std::string Func_rtrim_oracle::getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& type) +{ + CHARSET_INFO* cs = type.getCharset(); + // The original string + const string& src = fp[0]->data()->getStrVal(row, isNull); + if (isNull) + return ""; + if (src.empty() || src.length() == 0) + return src; + // binLen represents the number of bytes in src + size_t binLen = src.length(); + const char* pos = src.c_str(); + const char* end = pos + binLen; + // strLen = the number of characters in src + size_t strLen = cs->numchars(pos, end); + + // The trim characters. + const string& trim = (fp.size() > 1 ? fp[1]->data()->getStrVal(row, isNull) : " "); + // binTLen represents the number of bytes in trim + size_t binTLen = trim.length(); + const char* posT = trim.c_str(); + // strTLen = the number of characters in trim + size_t strTLen = cs->numchars(posT, posT+binTLen); + if (strTLen == 0 || strTLen > strLen) + return src; + + if (binTLen == 1) + { + const char* ptr = pos; + if (cs->use_mb()) // This is a multi-byte charset + { + const char* p = pos; + uint32 l; + // Multibyte characters in the string give us alignment problems + // What we do here is skip past any multibyte characters. Whn + // don with this loop, ptr is pointing to a singlebyte char that + // is after all multibyte chars in the string, or to end. + while (ptr < end) + { + if ((l = my_ismbchar(cs, ptr, end))) // returns the number of bytes in the leading char or zero if one byte + { + ptr += l; + p = ptr; + } + else + { + ++ptr; + } + } + ptr = p; + } + while (ptr < end && end[-1] == *posT) + { + --end; + --binLen; + } + } + else + { + // An uncommon case where the space character is > 1 byte + if (cs->use_mb()) // This is a multi-byte charset + { + // The problem is that the byte pattern at the end could + // match memcmp, but not be correct since the first byte compared + // may actually be a second or later byte from a previous char. + + // We start at the beginning of the string and move forward + // one character at a time until we reach the end. Then we can + // safely compare and remove on character. Then back to the beginning + // and try again. + while (end - binTLen >= pos) + { + const char* p = pos; + uint32 l; + while (p + binTLen < end) + { + if ((l = my_ismbchar(cs, p, end))) // returns the number of bytes in the leading char or zero if one byte + p += l; + else + ++p; + } + if (p + binTLen == end && memcmp(p,posT,binTLen) == 0) + { + end -= binTLen; + binLen -= binTLen; + } + else + { + break; // We've run out of places to look + } + } + } + else + { + // This implies we have a single byte charset and a multibyte + // space character. + // Should never get here, since rtrim only trims space characters + // Included for completeness. + while (end-binTLen >= pos && memcmp(end-binTLen,posT,binTLen) == 0) + { + end -= binTLen; + binLen -= binTLen; + } + } + } + // Turn back to a string + std::string ret(pos, binLen); + if (binLen == 0) + { + isNull = true; + } + return ret; +} + +} // namespace funcexp +// vim:ts=4 sw=4: + diff --git a/utils/funcexp/func_trim_oracle.cpp b/utils/funcexp/func_trim_oracle.cpp new file mode 100644 index 000000000..4b27a4d56 --- /dev/null +++ b/utils/funcexp/func_trim_oracle.cpp @@ -0,0 +1,175 @@ +/* Copyright (C) 2021 MariaDB Corporation + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + + +#include +using namespace std; + +#include "functor_str.h" +#include "functioncolumn.h" +#include "utils_utf8.h" +using namespace execplan; + +#include "rowgroup.h" +using namespace rowgroup; + +#include "joblisttypes.h" +using namespace joblist; + +#include "collation.h" + +namespace funcexp +{ +CalpontSystemCatalog::ColType Func_trim_oracle::operationType(FunctionParm& fp, CalpontSystemCatalog::ColType& resultType) +{ + // operation type is not used by this functor + return fp[0]->data()->resultType(); +} + + +std::string Func_trim_oracle::getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& type) +{ + CHARSET_INFO* cs = type.getCharset(); + // The original string + const string& src = fp[0]->data()->getStrVal(row, isNull); + if (isNull) + return ""; + if (src.empty() || src.length() == 0) + return src; + // binLen represents the number of bytes in src + size_t binLen = src.length(); + const char* pos = src.c_str(); + const char* end = pos + binLen; + // strLen = the number of characters in src + size_t strLen = cs->numchars(pos, end); + + // The trim characters. + const string& trim = (fp.size() > 1 ? fp[1]->data()->getStrVal(row, isNull) : " "); + // binTLen represents the number of bytes in trim + size_t binTLen = trim.length(); + const char* posT = trim.c_str(); + // strTLen = the number of characters in trim + size_t strTLen = cs->numchars(posT, posT+binTLen); + if (strTLen == 0 || strTLen > strLen) + return src; + + if (binTLen == 1) + { + // If the trim string is 1 byte, don't waste cpu for memcmp + // Trim leading + while (pos < end && *pos == *posT) + { + ++pos; + --binLen; + } + // Trim trailing + const char* ptr = pos; + if (cs->use_mb()) // This is a multi-byte charset + { + const char* p = pos; + uint32 l; + // Multibyte characters in the string give us alignment problems + // What we do here is skip past any multibyte characters. Whn + // don with this loop, ptr is pointing to a singlebyte char that + // is after all multibyte chars in the string, or to end. + while (ptr < end) + { + if ((l = my_ismbchar(cs, ptr, end))) // returns the number of bytes in the leading char or zero if one byte + { + ptr += l; + p = ptr; + } + else + { + ++ptr; + } + } + ptr = p; + } + while (ptr < end && end[-1] == *posT) + { + --end; + --binLen; + } + } + else + { + // Trim leading is easy + while (pos+binTLen <= end && memcmp(pos,posT,binTLen) == 0) + { + pos += binTLen; + binLen -= binTLen; + } + + // Trim trailing + if (cs->use_mb()) // This is a multi-byte charset + { + // The problem is that the byte pattern at the end could + // match memcmp, but not be correct since the first byte compared + // may actually be a second or later byte from a previous char. + + // We start at the beginning of the string and move forward + // one character at a time until we reach the end. Then we can + // safely compare and remove one character. Then back to the beginning + // and try again. + while (end - binTLen >= pos) + { + const char* p = pos; + uint32_t l; + while (p + binTLen < end) + { + if ((l = my_ismbchar(cs, p, end))) // returns the number of bytes in the leading char or zero if one byte + p += l; + else + ++p; + } + if (p + binTLen == end && memcmp(p,posT,binTLen) == 0) + { + end -= binTLen; + binLen -= binTLen; + } + else + { + break; // We've run out of places to look + } + } + } + else + { + while (end-binTLen >= pos && memcmp(end-binTLen,posT,binTLen) == 0) + { + end -= binTLen; + binLen -= binTLen; + } + } + } + // Turn back to a string + std::string ret(pos, binLen); + if (binLen == 0) + { + isNull = true; + } + return ret; +} + + +} // namespace funcexp +// vim:ts=4 sw=4: + diff --git a/utils/funcexp/funcexp.cpp b/utils/funcexp/funcexp.cpp index 6b33bad6e..1b80fa978 100644 --- a/utils/funcexp/funcexp.cpp +++ b/utils/funcexp/funcexp.cpp @@ -97,6 +97,7 @@ FuncExp::FuncExp() fFuncMap["char_length"] = new Func_char_length(); //dlh fFuncMap["character_length"] = new Func_char_length(); //dlh fFuncMap["coalesce"] = new Func_coalesce(); + fFuncMap["concat_operator_oracle"] = new Func_concat_oracle(); fFuncMap["concat"] = new Func_concat(); fFuncMap["concat_ws"] = new Func_concat_ws(); fFuncMap["conv"] = new Func_conv(); @@ -112,6 +113,7 @@ FuncExp::FuncExp() fFuncMap["dayofweek"] = new Func_dayofweek(); //dlh fFuncMap["dayofyear"] = new Func_dayofyear(); //dlh fFuncMap["decode"] = new Func_decode(); // BT + fFuncMap["decode_oracle"] = new Func_decode_oracle(); // BT fFuncMap["degrees"] = new Func_degrees(); fFuncMap["DIV"] = new Func_div(); // MySQL use upper case for this function name fFuncMap["elt"] = new Func_elt(); @@ -156,6 +158,7 @@ FuncExp::FuncExp() fFuncMap["lower"] = new Func_lcase(); //dlh fFuncMap["lpad"] = new Func_lpad(); //dlh fFuncMap["ltrim"] = new Func_ltrim(); //dlh + fFuncMap["ltrim_oracle"] = new Func_ltrim_oracle(); //dlh fFuncMap["makedate"] = new Func_makedate(); fFuncMap["maketime"] = new Func_maketime(); fFuncMap["microsecond"] = new Func_microsecond(); @@ -183,11 +186,13 @@ FuncExp::FuncExp() fFuncMap["regexp"] = new Func_regexp(); //dlh fFuncMap["repeat"] = new Func_repeat(); //dlh fFuncMap["replace"] = new Func_replace(); //dlh + fFuncMap["replace_oracle"] = new Func_replace_oracle(); //dlh fFuncMap["reverse"] = new Func_reverse(); //dlh fFuncMap["right"] = new Func_right(); //dlh fFuncMap["round"] = new Func_round(); fFuncMap["rpad"] = new Func_rpad(); //dlh fFuncMap["rtrim"] = new Func_rtrim(); //dlh + fFuncMap["rtrim_oracle"] = new Func_rtrim_oracle(); //dlh fFuncMap["second"] = new Func_second(); //dlh fFuncMap["sec_to_time"] = new Func_sec_to_time(); fFuncMap["sha"] = new Func_sha(); @@ -210,6 +215,7 @@ FuncExp::FuncExp() fFuncMap["time_to_sec"] = new Func_time_to_sec(); //dlh fFuncMap["to_days"] = new Func_to_days(); //dlh fFuncMap["trim"] = new Func_trim(); //dlh + fFuncMap["trim_oracle"] = new Func_trim_oracle(); //dlh fFuncMap["truncate"] = new Func_truncate(); //dlh fFuncMap["ucase"] = new Func_ucase(); //dlh fFuncMap["unhex"] = new Func_unhex(); diff --git a/utils/funcexp/functor_all.h b/utils/funcexp/functor_all.h index 155e00656..c0568f463 100644 --- a/utils/funcexp/functor_all.h +++ b/utils/funcexp/functor_all.h @@ -122,6 +122,65 @@ public: execplan::CalpontSystemCatalog::ColType& op_ct); }; +class Func_decode_oracle : public Func_All +{ +public: + Func_decode_oracle(): Func_All("decode_oracle") {} + virtual ~Func_decode_oracle() {} + + execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType); + + bool getBoolVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getIntVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + double getDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + long double getLongDoubleVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + std::string getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + execplan::IDB_Decimal getDecimalVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + int32_t getDateIntVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getDatetimeIntVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getTimestampIntVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getTimeIntVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); +}; + /** @brief Func_searched_case class */ diff --git a/utils/funcexp/functor_str.h b/utils/funcexp/functor_str.h index 8229aab8a..e6abccf5c 100644 --- a/utils/funcexp/functor_str.h +++ b/utils/funcexp/functor_str.h @@ -183,6 +183,22 @@ public: }; +/** @brief Func_concat_oracle class + */ +class Func_concat_oracle : public Func_Str +{ +public: + Func_concat_oracle() : Func_Str("concat_operator_oracle") {} + virtual ~Func_concat_oracle() {} + + execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType); + + std::string getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); +}; + /** @brief Func_substr class */ class Func_substr : public Func_Str @@ -333,6 +349,55 @@ public: execplan::CalpontSystemCatalog::ColType& op_ct); }; +/** @brief Func_ltrim class + */ +class Func_ltrim_oracle : public Func_Str +{ +public: + Func_ltrim_oracle() : Func_Str("ltrim_oracle") {} + virtual ~Func_ltrim_oracle() {} + + execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType); + + std::string getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); +}; + + +/** @brief Func_rtrim class + */ +class Func_rtrim_oracle : public Func_Str +{ +public: + Func_rtrim_oracle() : Func_Str("rtrim_oracle") {} + virtual ~Func_rtrim_oracle() {} + + execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType); + + std::string getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); +}; + + +/** @brief Func_trim class + */ +class Func_trim_oracle : public Func_Str +{ +public: + Func_trim_oracle() : Func_Str("trim_oracle") {} + virtual ~Func_trim_oracle() {} + + execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType); + + std::string getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); +}; /** @brief Func_lpad class */ @@ -386,6 +451,19 @@ public: execplan::CalpontSystemCatalog::ColType& op_ct); }; +class Func_replace_oracle : public Func_Str +{ +public: + Func_replace_oracle() : Func_Str("replace_oracle") {} + virtual ~Func_replace_oracle() {} + + execplan::CalpontSystemCatalog::ColType operationType(FunctionParm& fp, execplan::CalpontSystemCatalog::ColType& resultType); + + std::string getStrVal(rowgroup::Row& row, + FunctionParm& fp, + bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); +}; /** @brief Func_right class */