mirror of
https://github.com/MariaDB/server.git
synced 2025-11-09 11:41:36 +03:00
MDEV-13817 add support for oracle left join syntax - the ( + )
Parser changes made by Alexander Barkov <bar@mariadb.com>. Part of the tests made by Iqbal Hassan <iqbal@hasprime.com>. Initially marking with ORA_JOIN flag made also by Iqbal Hassan <iqbal@hasprime.com>. Main idea is that parser mark fields with (+) with a flag (ORA_JOIN). During Prepare the flag bring to the new created items if needed. Later after preparing (fix_firlds()) WHERE confition the relations betweel the tables analyzed and tables reordered so to make JOIN/LEFT JOIN operators in chain equivalent to the query with oracle outer join operator (+). Then the flags of (+) removed.
This commit is contained in:
@@ -92,6 +92,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
||||
../sql/sql_lex.cc ../sql/keycaches.cc
|
||||
../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc
|
||||
../sql/sql_binlog.cc ../sql/sql_manager.cc
|
||||
../sql/sql_oracle_outer_join.cc
|
||||
../sql/sql_parse.cc ../sql/sql_bootstrap.cc
|
||||
../sql/sql_partition.cc ../sql/sql_plugin.cc
|
||||
../sql/debug_sync.cc ../sql/debug.cc
|
||||
|
||||
951
mysql-test/suite/compat/oracle/r/ora_outer_join.result
Normal file
951
mysql-test/suite/compat/oracle/r/ora_outer_join.result
Normal file
@@ -0,0 +1,951 @@
|
||||
set SQL_MODE= oracle;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create table t3 (c int, e int);
|
||||
insert into t3 values (3,2),(10,3),(2,20);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (3),(1),(20);
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t1, t2, t3, t4
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
a d b c
|
||||
3 3 NULL 3
|
||||
1 1 1 NULL
|
||||
1 3 NULL NULL
|
||||
2 3 NULL NULL
|
||||
2 1 NULL NULL
|
||||
3 1 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 20 NULL NULL
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t1, t2, t3, t4
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
1 SIMPLE t4 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t4"."d" AS "d","test"."t2"."b" AS "b","test"."t3"."c" AS "c" from "test"."t1" join "test"."t4" left join "test"."t2" on("test"."t4"."d" = "test"."t1"."a" and "test"."t2"."b" = "test"."t1"."a") left join "test"."t3" on("test"."t4"."d" = "test"."t1"."a" and "test"."t3"."c" = "test"."t1"."a") where 1
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t4, t3, t2, t1
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
a d b c
|
||||
1 1 1 NULL
|
||||
3 3 NULL 3
|
||||
1 3 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 3 NULL NULL
|
||||
2 1 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 1 NULL NULL
|
||||
3 20 NULL NULL
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t4, t3, t2, t1
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ALL NULL NULL NULL NULL 3 100.00
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t4"."d" AS "d","test"."t2"."b" AS "b","test"."t3"."c" AS "c" from "test"."t4" join "test"."t1" left join "test"."t3" on("test"."t1"."a" = "test"."t4"."d" and "test"."t3"."c" = "test"."t4"."d") left join "test"."t2" on("test"."t1"."a" = "test"."t4"."d" and "test"."t2"."b" = "test"."t4"."d") where 1
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t2, t1, t4, t3
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
a d b c
|
||||
3 3 NULL 3
|
||||
1 1 1 NULL
|
||||
1 3 NULL NULL
|
||||
2 3 NULL NULL
|
||||
2 1 NULL NULL
|
||||
3 1 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 20 NULL NULL
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t2, t1, t4, t3
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
1 SIMPLE t4 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t4"."d" AS "d","test"."t2"."b" AS "b","test"."t3"."c" AS "c" from "test"."t1" join "test"."t4" left join "test"."t2" on("test"."t4"."d" = "test"."t1"."a" and "test"."t2"."b" = "test"."t1"."a") left join "test"."t3" on("test"."t4"."d" = "test"."t1"."a" and "test"."t3"."c" = "test"."t1"."a") where 1
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t3, t4, t1, t2
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
a d b c
|
||||
1 1 1 NULL
|
||||
3 3 NULL 3
|
||||
1 3 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 3 NULL NULL
|
||||
2 1 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 1 NULL NULL
|
||||
3 20 NULL NULL
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t3, t4, t1, t2
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t4 ALL NULL NULL NULL NULL 3 100.00
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t4"."d" AS "d","test"."t2"."b" AS "b","test"."t3"."c" AS "c" from "test"."t4" join "test"."t1" left join "test"."t3" on("test"."t1"."a" = "test"."t4"."d" and "test"."t3"."c" = "test"."t4"."d") left join "test"."t2" on("test"."t1"."a" = "test"."t4"."d" and "test"."t2"."b" = "test"."t4"."d") where 1
|
||||
drop table t1, t2, t3, t4;
|
||||
#
|
||||
# tests of Iqbal Hassan <iqbal@hasprime.com>
|
||||
# (with 2 fixes)
|
||||
#
|
||||
CREATE TABLE tj1(a int, b int);
|
||||
CREATE TABLE tj2(c int, d int);
|
||||
CREATE TABLE tj3(e int, f int);
|
||||
CREATE TABLE tj4(b int, c int);
|
||||
INSERT INTO tj1 VALUES (1, 1);
|
||||
INSERT INTO tj1 VALUES (2, 2);
|
||||
INSERT INTO tj2 VALUES (2, 3);
|
||||
INSERT INTO tj3 VALUES (1, 4);
|
||||
#
|
||||
# Basic test
|
||||
#
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+);
|
||||
a b c d
|
||||
2 2 2 3
|
||||
1 1 NULL NULL
|
||||
#
|
||||
# Compare marked with literal
|
||||
#
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND tj2.d(+) > 4;
|
||||
a b c d
|
||||
1 1 NULL NULL
|
||||
2 2 NULL NULL
|
||||
explain extended
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND tj2.d(+) > 4;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE tj1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 SIMPLE tj2 ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."tj1"."a" AS "a","test"."tj1"."b" AS "b","test"."tj2"."c" AS "c","test"."tj2"."d" AS "d" from "test"."tj1" left join "test"."tj2" on("test"."tj2"."c" = "test"."tj1"."a" and "test"."tj2"."d" > 4) where 1
|
||||
#
|
||||
# Use both marked and unmarked field in the same condition
|
||||
#
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND tj2.d = 3;
|
||||
a b c d
|
||||
2 2 2 3
|
||||
#
|
||||
# Use both marked and unmarked field in OR condition
|
||||
#
|
||||
SELECT * FROM tj2,tj1 WHERE tj1.a = tj2.c(+) OR tj2.d=4;
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj3.e(+) AND (tj1.a = tj2.c(+) OR tj2.d=4);
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
#
|
||||
# Use unmarked fields in OR condition
|
||||
#
|
||||
SELECT * FROM tj2,tj1 WHERE tj1.a = tj2.c(+) AND (tj2.d=3 OR tj2.d * 2=3);
|
||||
c d a b
|
||||
2 3 2 2
|
||||
#
|
||||
# Use marked fields in OR condition when all fields are marked
|
||||
#
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND (tj2.d(+)=3 OR tj2.c(+)=1);
|
||||
a b c d
|
||||
2 2 2 3
|
||||
1 1 NULL NULL
|
||||
#
|
||||
# Use more than one marked table per condition
|
||||
#
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) + tj3.e(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: both tables tj2 and tj3 are of INNER type in the relation
|
||||
#
|
||||
# Use different tables per `AND` operand
|
||||
#
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) AND tj1.a = tj3.e(+);
|
||||
a b c d e f
|
||||
1 1 NULL NULL 1 4
|
||||
2 2 2 3 NULL NULL
|
||||
#
|
||||
# Ensure table dependencies are properly resolved
|
||||
#
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj3.e AND tj1.a + 1 = tj2.c(+);
|
||||
a b c d e f
|
||||
1 1 2 3 1 4
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) AND tj2.c = tj3.e(+) + 1;
|
||||
a b c d e f
|
||||
2 2 2 3 1 4
|
||||
1 1 NULL NULL NULL NULL
|
||||
SELECT * FROM tj1, tj2, tj3 WHERE tj1.a + tj3.e = tj2.c(+);
|
||||
a b c d e f
|
||||
1 1 2 3 1 4
|
||||
2 2 NULL NULL 1 4
|
||||
#
|
||||
# Cyclic dependency of tables
|
||||
# ORA-01416 two tables cannot be outer-joined to each other
|
||||
#
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) AND tj2.c = tj3.e(+) + 1 AND tj3.e = tj1.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
#
|
||||
# Table not referenced in where condition (must be cross-joined)
|
||||
#
|
||||
SELECT * FROM tj1, tj2, tj3 WHERE tj1.a + 1 = tj2.c(+);
|
||||
a b c d e f
|
||||
1 1 2 3 1 4
|
||||
2 2 NULL NULL 1 4
|
||||
#
|
||||
# Alias
|
||||
#
|
||||
SELECT * FROM tj1, tj2 b WHERE tj1.a + 1 = b.c(+);
|
||||
a b c d
|
||||
1 1 2 3
|
||||
2 2 NULL NULL
|
||||
#
|
||||
# Subselect
|
||||
#
|
||||
SELECT * FROM tj1, (SELECT * from tj2) b WHERE tj1.a + 1 = b.c(+);
|
||||
a b c d
|
||||
1 1 2 3
|
||||
2 2 NULL NULL
|
||||
SELECT * FROM tj1, (SELECT * FROM tj1, tj2 d WHERE tj1.a = d.c(+)) b WHERE tj1.a + 1 = b.c(+);
|
||||
a b a b c d
|
||||
1 1 2 2 2 3
|
||||
2 2 NULL NULL NULL NULL
|
||||
#
|
||||
# Single table
|
||||
#
|
||||
SELECT * FROM tj1 WHERE tj1.a(+) = 1;
|
||||
a b
|
||||
1 1
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '"test"."tj1"."a" = 1'
|
||||
#
|
||||
# Self outer join
|
||||
#
|
||||
SELECT * FROM tj1 a, tj1 b WHERE a.a + 1 = b.a(+);
|
||||
a b a b
|
||||
1 1 2 2
|
||||
2 2 NULL NULL
|
||||
#
|
||||
# Self outer join without alias
|
||||
#
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a + 1 = tj1.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
#
|
||||
# Outer join condition is independent of other tables
|
||||
# In this case we need to restrict the marked table(s) to appear
|
||||
# after the unmarked table(s) during topological sort. This test
|
||||
# ensures that the topological sort is working correctly.
|
||||
#
|
||||
# correct result in is empty result set (tj2.c = 1 filters all out)
|
||||
SELECT * FROM tj1, tj2 WHERE tj2.c(+) = 1;
|
||||
a b c d
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '"test"."tj2"."c" = 1'
|
||||
# one row (there is tj1.a = 1)
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a(+) = 1;
|
||||
a b c d
|
||||
1 1 2 3
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '"test"."tj1"."a" = 1'
|
||||
#
|
||||
# Outer join in 'IN' condition
|
||||
# ORA-01719
|
||||
#
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a IN (tj2.c(+), tj2.d(+));
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a NOT IN (tj2.c(+), tj2.d(+));
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
#
|
||||
# Outer join in 'IN' condition with a single expression
|
||||
# This is also allowed in oracle since the expression is
|
||||
# can be simplified to 'equal' or 'not equal' condition
|
||||
#
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a IN (tj2.c(+));
|
||||
a b c d
|
||||
2 2 2 3
|
||||
1 1 NULL NULL
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a NOT IN (tj2.c(+));
|
||||
a b c d
|
||||
1 1 2 3
|
||||
2 2 NULL NULL
|
||||
#
|
||||
# Oracle outer join not in WHERE clause
|
||||
#
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c GROUP BY tj2.c(+);
|
||||
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 * FROM tj1, tj2 WHERE tj1.a = tj2.c GROUP BY tj2.c HAVING tj2.c(+) > 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 ') > 1' at line 1
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c ORDER BY tj2.c(+);
|
||||
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 tj2.c(+) FROM tj2;
|
||||
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 ') FROM tj2' at line 1
|
||||
#
|
||||
# Mix ANSI and Oracle outer join
|
||||
# ORA-25156
|
||||
SELECT * FROM tj1 LEFT JOIN tj2 ON tj2.c = 1 WHERE tj1.a = tj2.c(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
SELECT * FROM tj1 INNER JOIN tj2 ON tj2.c = 1 WHERE tj1.a = tj2.c(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
SELECT * FROM tj1 NATURAL JOIN tj2 WHERE tj1.a = tj2.c(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
#
|
||||
# View with oracle outer join
|
||||
#
|
||||
CREATE VIEW v1 AS SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c(+);
|
||||
SELECT * FROM v1;
|
||||
a b c d
|
||||
2 2 2 3
|
||||
1 1 NULL NULL
|
||||
#
|
||||
# Cursor with oracle outer join
|
||||
#
|
||||
DECLARE
|
||||
CURSOR c1 IS SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c(+);
|
||||
BEGIN
|
||||
FOR r1 IN c1 LOOP
|
||||
SELECT r1.a || ' ' || r1.c;
|
||||
END LOOP;
|
||||
END
|
||||
$$
|
||||
r1.a || ' ' || r1.c
|
||||
2 2
|
||||
r1.a || ' ' || r1.c
|
||||
1
|
||||
#
|
||||
# Marking ROW type
|
||||
#
|
||||
DECLARE
|
||||
v1 ROW (a INT, b INT);
|
||||
BEGIN
|
||||
SELECT * FROM tj1 WHERE tj1.a = v1.a(+);
|
||||
END
|
||||
$$
|
||||
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 ');
|
||||
END' at line 4
|
||||
#
|
||||
# Unspecified table used in WHERE clause that contains (+)
|
||||
#
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj3.c(+);
|
||||
ERROR 42S22: Unknown column 'tj3.c' in 'WHERE'
|
||||
#
|
||||
# '.' prefixed table name
|
||||
#
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = .tj2.c(+);
|
||||
a b c d
|
||||
2 2 2 3
|
||||
1 1 NULL NULL
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE tj1(a int, b int);
|
||||
INSERT INTO tj1 VALUES (3, 3);
|
||||
INSERT INTO tj1 VALUES (4, 4);
|
||||
#
|
||||
# DB qualifed ident with oracle outer join (aliased)
|
||||
#
|
||||
SELECT * FROM test.tj2 a, tj1 WHERE a.c(+) = tj1.a - 1;
|
||||
c d a b
|
||||
2 3 3 3
|
||||
NULL NULL 4 4
|
||||
#
|
||||
# DB qualifed ident with oracle outer join (non-aliased)
|
||||
#
|
||||
SELECT * FROM test.tj2, tj1 WHERE test.tj2.c(+) = tj1.a - 1;
|
||||
c d a b
|
||||
2 3 3 3
|
||||
NULL NULL 4 4
|
||||
#
|
||||
# DB qualifed ident with oracle outer join (aliased but use table name)
|
||||
#
|
||||
SELECT * FROM test.tj2 a, tj1 WHERE test.tj2.c(+) = tj1.a - 1;
|
||||
ERROR 42S22: Unknown column 'test.tj2.c' in 'WHERE'
|
||||
USE test;
|
||||
#
|
||||
# UPDATE with oracle outer join
|
||||
#
|
||||
UPDATE tj1, tj2 SET tj1.a = tj2.c WHERE tj1.a = tj2.c(+);
|
||||
SELECT * FROM tj1;
|
||||
a b
|
||||
NULL 1
|
||||
2 2
|
||||
#
|
||||
# DELETE with oracle outer join
|
||||
#
|
||||
DELETE tj1 FROM tj1, tj2 WHERE tj1.b(+) = tj2.c;
|
||||
SELECT * FROM tj1;
|
||||
a b
|
||||
NULL 1
|
||||
DROP DATABASE db1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE tj4;
|
||||
DROP TABLE tj3;
|
||||
DROP TABLE tj2;
|
||||
DROP TABLE tj1;
|
||||
#
|
||||
# End of iqbal-rsec tests
|
||||
#
|
||||
#
|
||||
# Test from the MDEV comments
|
||||
#
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create table t3 (c int, e int);
|
||||
insert into t3 values (3,2),(10,3),(2,20);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (3),(1),(20);
|
||||
select t1.a, t4.d, t2.b, t3.c from t1, t2, t3, t4 where t1.a = t2.b(+) and t1.a = t3.c(+) and t4.d = t2.b(+) and t4.d = t3.c(+);
|
||||
a d b c
|
||||
3 3 NULL 3
|
||||
1 1 1 NULL
|
||||
1 3 NULL NULL
|
||||
2 3 NULL NULL
|
||||
2 1 NULL NULL
|
||||
3 1 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 20 NULL NULL
|
||||
select t1.a, t4.d, t2.b, t3.c from t1, t2, t3, t4 where t1.a + t3.c = t2.b(+) and t1.a = t3.c(+) and t4.d = t2.b(+) and t4.d = t3.c(+);
|
||||
a d b c
|
||||
3 3 NULL 3
|
||||
1 3 NULL NULL
|
||||
2 3 NULL NULL
|
||||
1 1 NULL NULL
|
||||
2 1 NULL NULL
|
||||
3 1 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 20 NULL NULL
|
||||
select t1.a, t4.d, t2.b, t3.c from t1, t2, t3, t4 where (t2.b(+) in (t1.a, t1.a+1)) and t1.a = t3.c(+) and t4.d = t2.b(+) and t4.d = t3.c(+);
|
||||
a d b c
|
||||
3 3 NULL 3
|
||||
1 1 1 NULL
|
||||
1 3 NULL NULL
|
||||
2 3 NULL NULL
|
||||
2 1 NULL NULL
|
||||
3 1 NULL NULL
|
||||
1 20 NULL NULL
|
||||
2 20 NULL NULL
|
||||
3 20 NULL NULL
|
||||
drop tables t1, t2, t3, t4;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create table t3 (c int, f int);
|
||||
insert into t3 values (3,2),(10,3),(2,20);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (3),(1),(20);
|
||||
create table t5 (e int);
|
||||
insert into t5 values (3),(2),(20);
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, t2, t3, t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and t3.c=t5.e(+);
|
||||
a b c d e
|
||||
2 2 2 NULL NULL
|
||||
3 NULL NULL 3 NULL
|
||||
1 1 NULL 1 NULL
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, t2, t3, t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and 1=t5.e(+);
|
||||
a b c d e
|
||||
3 NULL NULL 3 NULL
|
||||
1 1 NULL 1 NULL
|
||||
2 2 2 NULL NULL
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, t2, t3, t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and 3=t5.e(+);
|
||||
a b c d e
|
||||
3 NULL NULL 3 3
|
||||
1 1 NULL 1 NULL
|
||||
2 2 2 NULL NULL
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, (t2, t3), t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and 3=t5.e(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
drop tables t1, t2, t3, t4, t5;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
select t1.a, t2.b from t1, t2 where 1 = t2.b(+);
|
||||
a b
|
||||
1 1
|
||||
2 1
|
||||
3 1
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '1 = "test"."t2"."b"'
|
||||
select t1.a, t2.b from t2, t1 where 1 = t2.b(+);
|
||||
a b
|
||||
1 1
|
||||
2 1
|
||||
3 1
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '1 = "test"."t2"."b"'
|
||||
select t1.a,t2.b from t2,t1 where t2.b(+) in (1,2);
|
||||
a b
|
||||
1 2
|
||||
1 1
|
||||
2 2
|
||||
2 1
|
||||
3 2
|
||||
3 1
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '"test"."t2"."b" in (1,2)'
|
||||
select t2.b from t2 where 1 = t2.b(+);
|
||||
b
|
||||
1
|
||||
Warnings:
|
||||
Warning 4237 Oracle outer join operator (+) ignored in '1 = "test"."t2"."b"'
|
||||
drop tables t1, t2;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(4),(5),(20),(21),(23);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (1),(4),(6),(7),(8),(23);
|
||||
create table t3 (c int);
|
||||
insert into t3 values (4),(7),(9),(4),(6),(10),(11),(1);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (1),(4),(10),(12),(20),(21),(23);
|
||||
SELECT * FROM t1,t2,t3,t4 WHERE t1.a = t2.b(+) AND t1.a = t3.c(+) AND t2.b=t4.d(+) AND t3.c=t4.d(+);
|
||||
a b c d
|
||||
1 1 1 1
|
||||
4 4 4 4
|
||||
4 4 4 4
|
||||
23 23 NULL NULL
|
||||
2 NULL NULL NULL
|
||||
5 NULL NULL NULL
|
||||
20 NULL NULL NULL
|
||||
21 NULL NULL NULL
|
||||
select * from t1, t2, t3 where (t1.a + t2.b = t3.c(+));
|
||||
a b c
|
||||
1 6 7
|
||||
1 8 9
|
||||
2 7 9
|
||||
5 4 9
|
||||
2 4 6
|
||||
5 1 6
|
||||
2 8 10
|
||||
4 6 10
|
||||
4 7 11
|
||||
5 6 11
|
||||
1 1 NULL
|
||||
1 4 NULL
|
||||
1 7 NULL
|
||||
1 23 NULL
|
||||
2 1 NULL
|
||||
2 6 NULL
|
||||
2 23 NULL
|
||||
4 1 NULL
|
||||
4 4 NULL
|
||||
4 8 NULL
|
||||
4 23 NULL
|
||||
5 7 NULL
|
||||
5 8 NULL
|
||||
5 23 NULL
|
||||
20 1 NULL
|
||||
20 4 NULL
|
||||
20 6 NULL
|
||||
20 7 NULL
|
||||
20 8 NULL
|
||||
20 23 NULL
|
||||
21 1 NULL
|
||||
21 4 NULL
|
||||
21 6 NULL
|
||||
21 7 NULL
|
||||
21 8 NULL
|
||||
21 23 NULL
|
||||
23 1 NULL
|
||||
23 4 NULL
|
||||
23 6 NULL
|
||||
23 7 NULL
|
||||
23 8 NULL
|
||||
23 23 NULL
|
||||
# no tables mentioned
|
||||
select * from t2, t3 where b = c(+);
|
||||
b c
|
||||
4 4
|
||||
7 7
|
||||
4 4
|
||||
6 6
|
||||
1 1
|
||||
8 NULL
|
||||
23 NULL
|
||||
# should be the same as above
|
||||
select * from t2, t3 where t2.b = t3.c(+);
|
||||
b c
|
||||
4 4
|
||||
7 7
|
||||
4 4
|
||||
6 6
|
||||
1 1
|
||||
8 NULL
|
||||
23 NULL
|
||||
drop tables t1, t2, t3, t4;
|
||||
#
|
||||
# View creation and usage
|
||||
#
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create view v1 as
|
||||
select t1.a, t2.b from t1, t2 where t1.a = t2.b(+);
|
||||
show create view v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE VIEW "v1" AS select "t1"."a" AS "a","t2"."b" AS "b" from ("t1" left join "t2" on("t1"."a" = "t2"."b")) latin1 latin1_swedish_ci
|
||||
select * from v1;
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
select t1.a, t2.b from t1, t2 where t1.a = t2.b(+);
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
usage without oracle sql mode
|
||||
set SQL_MODE= '';
|
||||
select * from v1;
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
select t1.a, t2.b from t1, t2 where t1.a = t2.b(+);
|
||||
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
|
||||
set SQL_MODE= oracle;
|
||||
drop view v1;
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-36830: Oracle outer join syntax (+): outer join not converted to inner
|
||||
#
|
||||
create table t1 (
|
||||
a int not null,
|
||||
b int not null
|
||||
);
|
||||
insert into t1 select seq,seq from seq_1_to_10;
|
||||
create table t2 (
|
||||
a int not null,
|
||||
b int not null
|
||||
);
|
||||
insert into t2 select seq,seq from seq_1_to_3;
|
||||
# Must be converted to inner join:
|
||||
explain extended
|
||||
select * from t1, t2
|
||||
where
|
||||
t1.a=1 and
|
||||
t1.b=t2.b(+) and
|
||||
t2.b=1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."b" AS "b","test"."t2"."a" AS "a","test"."t2"."b" AS "b" from "test"."t1" join "test"."t2" where "test"."t1"."a" = 1 and "test"."t2"."b" = 1 and "test"."t1"."b" = 1
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-36838: Oracle outer join syntax (+): server crash on derived tables
|
||||
#
|
||||
select a.a
|
||||
from (select 1 as a) a,
|
||||
(select 2 as b) b
|
||||
where a.a=b.b(+);
|
||||
a
|
||||
1
|
||||
#
|
||||
# MDEV-36866: Oracle outer join syntax (+): query with checking for
|
||||
# null of non-null column uses wrong query plan and returns wrong
|
||||
# result
|
||||
#
|
||||
create table t1 (a int default NULL);
|
||||
create table t2 (a int not null);
|
||||
insert into t1 values (1), (2), (3), (4), (5), (6), (NULL);
|
||||
insert into t2 values (1), (4), (5), (6), (7);
|
||||
select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
|
||||
a a
|
||||
explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
|
||||
a a
|
||||
2 NULL
|
||||
3 NULL
|
||||
NULL NULL
|
||||
explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 7
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
||||
select t1.*,t2.* from t1,t2 where t1.a=t2.a(+) and isnull(t2.a)=1;
|
||||
a a
|
||||
2 NULL
|
||||
3 NULL
|
||||
NULL NULL
|
||||
explain extended select t1.*,t2.* from t1,t2 where t1.a=t2.a(+) and isnull(t2.a)=1;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t2"."a" AS "a" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where "test"."t2"."a" is null = 1
|
||||
drop table t1,t2;
|
||||
#
|
||||
# Correct nullability test
|
||||
#
|
||||
create table t1 (a int not null, s varchar(10) not null);
|
||||
create table t2 (a int not null, s varchar(10) not null);
|
||||
insert into t1 values (1, 'one');
|
||||
insert into t1 values (2, 'two');
|
||||
insert into t2 values (2, 'two');
|
||||
insert into t2 values (3, 'three');
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t2.a);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Not exists; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where "test"."t2"."a" is null
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t1.a+t2.a);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where "test"."t1"."a" + "test"."t2"."a" is null
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(coalesce(t2.s, '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 Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on(multiple equal("test"."t1"."a", "test"."t2"."a")) where 0
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(ifnull(t2.s, '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 Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on(multiple equal("test"."t1"."a", "test"."t2"."a")) where 0
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(coalesce(t2.s, null));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where coalesce("test"."t2"."s",NULL) is null
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(ifnull(t2.s, null));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where ifnull("test"."t2"."s",NULL) is null
|
||||
# Our optimizer does not optimize out never-null-subselects under
|
||||
# isnull() so we do not test it. The following test is to make
|
||||
# sure that nullable one stay in the WHERE.
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t2.a in (select a from t1));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
Warnings:
|
||||
Note 1003 /* select#1 */ select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where <expr_cache><"test"."t2"."a">(<in_optimizer>("test"."t2"."a","test"."t2"."a" in ( <materialize> (/* select#2 */ select "test"."t1"."a" from "test"."t1" ), <primary_index_lookup>("test"."t2"."a" in <temporary table> on distinct_key where "test"."t2"."a" = "<subquery2>"."a")))) is null
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t2.a in (1, 2, 3));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on("test"."t2"."a" = "test"."t1"."a") where "test"."t2"."a" in (1,2,3) is null
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t1.a in (1, 2, 3));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on(multiple equal("test"."t1"."a", "test"."t2"."a")) where 0
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(isnull(t2.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 Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on(multiple equal("test"."t1"."a", "test"."t2"."a")) where 0
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(field(t2.a, 2, 23));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on(multiple equal("test"."t1"."a", "test"."t2"."a")) where 0
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(benchmark(10, t2.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 Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t1"."s" AS "s","test"."t2"."a" AS "a","test"."t2"."s" AS "s" from "test"."t1" left join "test"."t2" on(multiple equal("test"."t1"."a", "test"."t2"."a")) where 0
|
||||
drop table t1, t2;
|
||||
#
|
||||
# MDEV-36895: Oracle outer join syntax (+): some NULLs missing from
|
||||
# result of the query with derived tables and limit
|
||||
#
|
||||
create table t2 (b int);
|
||||
insert into t2 values (3),(7),(1);
|
||||
create table t3 (c int);
|
||||
insert into t3 values (3),(1);
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(7),(1);
|
||||
select * from
|
||||
(
|
||||
select * from
|
||||
(select 'Z' as z, t1.a from t1) dt1
|
||||
left join
|
||||
(select 'Y' as y, t2.b from t2) dt2
|
||||
left join
|
||||
(select 'X' as x, t3.c from t3) dt3
|
||||
on dt2.b=dt3.c
|
||||
on dt1.a=dt2.b
|
||||
order by z, a, y, b, x, c
|
||||
limit 9
|
||||
) dt;
|
||||
z a y b x c
|
||||
Z 1 Y 1 X 1
|
||||
Z 1 Y 1 X 1
|
||||
Z 2 NULL NULL NULL NULL
|
||||
Z 7 Y 7 NULL NULL
|
||||
select * from
|
||||
(
|
||||
select * from
|
||||
(select 'Z' as z, t1.a from t1) dt1
|
||||
,(select * from
|
||||
(select 'Y' as y, t2.b from t2) dt2
|
||||
,
|
||||
(select 'X' as x, t3.c from t3) dt3
|
||||
where dt2.b=dt3.c(+)
|
||||
) tdt2
|
||||
where dt1.a=tdt2.b(+)
|
||||
order by z, a, y, b, x, c
|
||||
limit 9
|
||||
) dt;
|
||||
z a y b x c
|
||||
Z 1 Y 1 X 1
|
||||
Z 1 Y 1 X 1
|
||||
Z 2 NULL NULL NULL NULL
|
||||
Z 7 Y 7 NULL NULL
|
||||
drop table t1, t2, t3;
|
||||
#
|
||||
# MDEV-37337: Oracle outer join syntax (+): IN equal to = allow (+) on right side
|
||||
#
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
set SQL_MODE= oracle;
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a = t2.b(+);
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
explain extended
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t2"."b" AS "b" from "test"."t1" left join "test"."t2" on("test"."t2"."b" = "test"."t1"."a") where 1
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+), 29);
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
DROP TABLE t1, t2;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
set SQL_MODE= oracle;
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a = t2.b(+);
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
a b
|
||||
2 2
|
||||
1 1
|
||||
3 NULL
|
||||
explain extended
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
||||
Warnings:
|
||||
Note 1003 select "test"."t1"."a" AS "a","test"."t2"."b" AS "b" from "test"."t1" left join "test"."t2" on("test"."t2"."b" = "test"."t1"."a") where 1
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+), 29);
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
DROP TABLE t1, t2;
|
||||
# End of 12.1 tests
|
||||
107
mysql-test/suite/compat/oracle/r/ora_outer_join_err.result
Normal file
107
mysql-test/suite/compat/oracle/r/ora_outer_join_err.result
Normal file
@@ -0,0 +1,107 @@
|
||||
SET sql_mode=ORACLE;
|
||||
#
|
||||
# Cycles
|
||||
#
|
||||
create table t1 (a int);
|
||||
create table t2 (b int);
|
||||
create table t3 (c int);
|
||||
# b - cyrcle
|
||||
select * from t1, t2, t3
|
||||
where t1.a = t2.b(+) AND t2.b = t3.c(+) AND
|
||||
t3.c = t2.b(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
# O - cyrcle
|
||||
select * from t1, t2, t3
|
||||
where t1.a = t2.b(+) AND t2.b = t3.c(+) AND
|
||||
t3.c = t1.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
# self-reference cyrcle
|
||||
select * from t1, t2, t3
|
||||
where t1.a = t2.b(+) AND t2.b = t3.c(+) AND
|
||||
t3.c = t3.c(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
DROP TABLE t1,t2,t3;
|
||||
create table t1 (a int);
|
||||
create table t2 (b int);
|
||||
create table t3 (c int);
|
||||
create table t4 (d int);
|
||||
create table t5 (e int);
|
||||
# complex case
|
||||
select * from t1, t2, t3, t4, t5
|
||||
where
|
||||
t3.c = t4.d(+) AND t4.d = t3.c(+) AND
|
||||
t1.a = t5.e(+) AND t2.b = t5.e(+) AND
|
||||
t2.b = t3.c(+)
|
||||
;
|
||||
ERROR HY000: Invalid usage of (+) operator: cycle dependencies
|
||||
DROP TABLE t1,t2,t3,t4,t5;
|
||||
#
|
||||
# mix with other join operatirs
|
||||
#
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
create table t3 (a int);
|
||||
# mixing with left join
|
||||
select * from t1, t2 left join t3 on (t2.a = t3.a)
|
||||
where t1.a = t2.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
# mixing with right join
|
||||
select * from t1, t2 right join t3 on (t2.a = t3.a)
|
||||
where t1.a = t2.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
# mixing with natural join
|
||||
select * from t1, t2 natural join t3
|
||||
where t1.a = t2.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
# mixing with nested join
|
||||
select * from t1, t2 join t3
|
||||
where t1.a = t2.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
# mixing with nested join
|
||||
select * from t1, (t2, t3)
|
||||
where t1.a = t2.a(+);
|
||||
ERROR HY000: Invalid usage of (+) operator: mixed with other type of join
|
||||
DROP TABLE t1,t2,t3;
|
||||
#
|
||||
# misplaced usage of (+)
|
||||
#
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
select t1.a(+), t2.a from t1,t2;
|
||||
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 '), t2.a from t1,t2' at line 1
|
||||
select t1.a, t2.a from t1,t2 HAVING t1.a(+) = t2.a;
|
||||
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 ') = t2.a' at line 1
|
||||
select t1.a, t2.a from t1 join t2 on (t1.a(+) = t2.a);
|
||||
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 ') = t2.a)' at line 1
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# outer reference
|
||||
#
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
select u2.a, (select t1.a, t2.a from t1,t2 where u1.a(+) = t2.a)
|
||||
from t1 as u1, t2 as u2 where u1.a(+) = u2.a;
|
||||
ERROR HY000: Invalid usage of (+) operator with outer reference a
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# MDEV-36883: Oracle outer join syntax (+): operator (+) is not
|
||||
# processed in condition like "(t2.b(+) , t1.b) in (select ...)"
|
||||
#
|
||||
create table t1 ( c int, b char(1));
|
||||
insert into t1 values (1,'b');
|
||||
create table t2 ( a int , b char(1));
|
||||
insert into t2 values (1,'a');
|
||||
create table t3 (c1 char(1), c2 char(2));
|
||||
insert into t3 values ('c','d');
|
||||
insert into t3 values ('c','d');
|
||||
SELECT t2.b
|
||||
FROM t1, t2 WHERE t1.c = t2.a(+) AND (t2.b(+), t1.b) IN (SELECT * from t3);
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
SELECT t2.b
|
||||
FROM t1, t2 WHERE t1.c = t2.a(+) AND (t2.b(+), t1.b) IN (('a','a'),('b','b'));
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
SELECT t2.b
|
||||
FROM t1, t2 WHERE t1.c = t2.a(+) AND (t2.b(+), t1.b) = (SELECT * from t3
|
||||
ORDER BY a LIMIT 1);
|
||||
ERROR HY000: Invalid usage of (+) operator: used in OR, IN or ROW operation
|
||||
drop tables t1,t2,t3;
|
||||
667
mysql-test/suite/compat/oracle/t/ora_outer_join.test
Normal file
667
mysql-test/suite/compat/oracle/t/ora_outer_join.test
Normal file
@@ -0,0 +1,667 @@
|
||||
|
||||
set SQL_MODE= oracle;
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create table t3 (c int, e int);
|
||||
insert into t3 values (3,2),(10,3),(2,20);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (3),(1),(20);
|
||||
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t1, t2, t3, t4
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t1, t2, t3, t4
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t4, t3, t2, t1
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t4, t3, t2, t1
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t2, t1, t4, t3
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t2, t1, t4, t3
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t3, t4, t1, t2
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
explain extended
|
||||
select t1.a, t4.d, t2.b, t3.c
|
||||
from t3, t4, t1, t2
|
||||
where
|
||||
t1.a = t2.b(+) and
|
||||
t1.a = t3.c(+) and
|
||||
t4.d = t2.b(+) and
|
||||
t4.d = t3.c(+);
|
||||
|
||||
drop table t1, t2, t3, t4;
|
||||
|
||||
--echo #
|
||||
--echo # tests of Iqbal Hassan <iqbal@hasprime.com>
|
||||
--echo # (with 2 fixes)
|
||||
--echo #
|
||||
|
||||
CREATE TABLE tj1(a int, b int);
|
||||
CREATE TABLE tj2(c int, d int);
|
||||
CREATE TABLE tj3(e int, f int);
|
||||
CREATE TABLE tj4(b int, c int);
|
||||
INSERT INTO tj1 VALUES (1, 1);
|
||||
INSERT INTO tj1 VALUES (2, 2);
|
||||
INSERT INTO tj2 VALUES (2, 3);
|
||||
INSERT INTO tj3 VALUES (1, 4);
|
||||
|
||||
--echo #
|
||||
--echo # Basic test
|
||||
--echo #
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # Compare marked with literal
|
||||
--echo #
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND tj2.d(+) > 4;
|
||||
explain extended
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND tj2.d(+) > 4;
|
||||
|
||||
--echo #
|
||||
--echo # Use both marked and unmarked field in the same condition
|
||||
--echo #
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND tj2.d = 3;
|
||||
|
||||
--echo #
|
||||
--echo # Use both marked and unmarked field in OR condition
|
||||
--echo #
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
SELECT * FROM tj2,tj1 WHERE tj1.a = tj2.c(+) OR tj2.d=4;
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj3.e(+) AND (tj1.a = tj2.c(+) OR tj2.d=4);
|
||||
|
||||
--echo #
|
||||
--echo # Use unmarked fields in OR condition
|
||||
--echo #
|
||||
SELECT * FROM tj2,tj1 WHERE tj1.a = tj2.c(+) AND (tj2.d=3 OR tj2.d * 2=3);
|
||||
|
||||
--echo #
|
||||
--echo # Use marked fields in OR condition when all fields are marked
|
||||
--echo #
|
||||
SELECT * FROM tj1,tj2 WHERE tj1.a = tj2.c(+) AND (tj2.d(+)=3 OR tj2.c(+)=1);
|
||||
|
||||
--echo #
|
||||
--echo # Use more than one marked table per condition
|
||||
--echo #
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_ONE_TABLE
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) + tj3.e(+);
|
||||
|
||||
--echo #
|
||||
--echo # Use different tables per `AND` operand
|
||||
--echo #
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) AND tj1.a = tj3.e(+);
|
||||
|
||||
--echo #
|
||||
--echo # Ensure table dependencies are properly resolved
|
||||
--echo #
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj3.e AND tj1.a + 1 = tj2.c(+);
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) AND tj2.c = tj3.e(+) + 1;
|
||||
SELECT * FROM tj1, tj2, tj3 WHERE tj1.a + tj3.e = tj2.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # Cyclic dependency of tables
|
||||
--echo # ORA-01416 two tables cannot be outer-joined to each other
|
||||
--echo #
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
SELECT * FROM tj1,tj2,tj3 WHERE tj1.a = tj2.c(+) AND tj2.c = tj3.e(+) + 1 AND tj3.e = tj1.a(+);
|
||||
|
||||
--echo #
|
||||
--echo # Table not referenced in where condition (must be cross-joined)
|
||||
--echo #
|
||||
SELECT * FROM tj1, tj2, tj3 WHERE tj1.a + 1 = tj2.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # Alias
|
||||
--echo #
|
||||
SELECT * FROM tj1, tj2 b WHERE tj1.a + 1 = b.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # Subselect
|
||||
--echo #
|
||||
SELECT * FROM tj1, (SELECT * from tj2) b WHERE tj1.a + 1 = b.c(+);
|
||||
SELECT * FROM tj1, (SELECT * FROM tj1, tj2 d WHERE tj1.a = d.c(+)) b WHERE tj1.a + 1 = b.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # Single table
|
||||
--echo #
|
||||
# --error ER_INVALID_USE_OF_ORA_JOIN
|
||||
# it is legal, Oracle just ignore the operator if it is applied to all tabes
|
||||
|
||||
# The WARN_ORA_JOIN_IGNORED is emitted only on PREPARE:
|
||||
--disable_ps_protocol
|
||||
SELECT * FROM tj1 WHERE tj1.a(+) = 1;
|
||||
--enable_ps_protocol
|
||||
|
||||
--echo #
|
||||
--echo # Self outer join
|
||||
--echo #
|
||||
SELECT * FROM tj1 a, tj1 b WHERE a.a + 1 = b.a(+);
|
||||
|
||||
--echo #
|
||||
--echo # Self outer join without alias
|
||||
--echo #
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a + 1 = tj1.a(+);
|
||||
|
||||
--echo #
|
||||
--echo # Outer join condition is independent of other tables
|
||||
--echo # In this case we need to restrict the marked table(s) to appear
|
||||
--echo # after the unmarked table(s) during topological sort. This test
|
||||
--echo # ensures that the topological sort is working correctly.
|
||||
--echo #
|
||||
--echo # correct result in is empty result set (tj2.c = 1 filters all out)
|
||||
|
||||
# The WARN_ORA_JOIN_IGNORED is emitted only on PREPARE:
|
||||
--disable_ps_protocol
|
||||
SELECT * FROM tj1, tj2 WHERE tj2.c(+) = 1;
|
||||
--echo # one row (there is tj1.a = 1)
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a(+) = 1;
|
||||
--enable_ps_protocol
|
||||
|
||||
--echo #
|
||||
--echo # Outer join in 'IN' condition
|
||||
--echo # ORA-01719
|
||||
--echo #
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a IN (tj2.c(+), tj2.d(+));
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a NOT IN (tj2.c(+), tj2.d(+));
|
||||
|
||||
--echo #
|
||||
--echo # Outer join in 'IN' condition with a single expression
|
||||
--echo # This is also allowed in oracle since the expression is
|
||||
--echo # can be simplified to 'equal' or 'not equal' condition
|
||||
--echo #
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a IN (tj2.c(+));
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a NOT IN (tj2.c(+));
|
||||
|
||||
--echo #
|
||||
--echo # Oracle outer join not in WHERE clause
|
||||
--echo #
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c GROUP BY tj2.c(+);
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c GROUP BY tj2.c HAVING tj2.c(+) > 1;
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c ORDER BY tj2.c(+);
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT tj2.c(+) FROM tj2;
|
||||
|
||||
--echo #
|
||||
--echo # Mix ANSI and Oracle outer join
|
||||
--echo # ORA-25156
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
SELECT * FROM tj1 LEFT JOIN tj2 ON tj2.c = 1 WHERE tj1.a = tj2.c(+);
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
SELECT * FROM tj1 INNER JOIN tj2 ON tj2.c = 1 WHERE tj1.a = tj2.c(+);
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
SELECT * FROM tj1 NATURAL JOIN tj2 WHERE tj1.a = tj2.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # View with oracle outer join
|
||||
--echo #
|
||||
CREATE VIEW v1 AS SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c(+);
|
||||
SELECT * FROM v1;
|
||||
|
||||
--echo #
|
||||
--echo # Cursor with oracle outer join
|
||||
--echo #
|
||||
DELIMITER $$;
|
||||
DECLARE
|
||||
CURSOR c1 IS SELECT * FROM tj1, tj2 WHERE tj1.a = tj2.c(+);
|
||||
BEGIN
|
||||
FOR r1 IN c1 LOOP
|
||||
SELECT r1.a || ' ' || r1.c;
|
||||
END LOOP;
|
||||
END
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo #
|
||||
--echo # Marking ROW type
|
||||
--echo #
|
||||
DELIMITER $$;
|
||||
--error ER_PARSE_ERROR
|
||||
DECLARE
|
||||
v1 ROW (a INT, b INT);
|
||||
BEGIN
|
||||
SELECT * FROM tj1 WHERE tj1.a = v1.a(+);
|
||||
END
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo #
|
||||
--echo # Unspecified table used in WHERE clause that contains (+)
|
||||
--echo #
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = tj3.c(+);
|
||||
|
||||
--echo #
|
||||
--echo # '.' prefixed table name
|
||||
--echo #
|
||||
SELECT * FROM tj1, tj2 WHERE tj1.a = .tj2.c(+);
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE tj1(a int, b int);
|
||||
INSERT INTO tj1 VALUES (3, 3);
|
||||
INSERT INTO tj1 VALUES (4, 4);
|
||||
|
||||
--echo #
|
||||
--echo # DB qualifed ident with oracle outer join (aliased)
|
||||
--echo #
|
||||
SELECT * FROM test.tj2 a, tj1 WHERE a.c(+) = tj1.a - 1;
|
||||
|
||||
--echo #
|
||||
--echo # DB qualifed ident with oracle outer join (non-aliased)
|
||||
--echo #
|
||||
SELECT * FROM test.tj2, tj1 WHERE test.tj2.c(+) = tj1.a - 1;
|
||||
|
||||
--echo #
|
||||
--echo # DB qualifed ident with oracle outer join (aliased but use table name)
|
||||
--echo #
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
SELECT * FROM test.tj2 a, tj1 WHERE test.tj2.c(+) = tj1.a - 1;
|
||||
|
||||
USE test;
|
||||
|
||||
--echo #
|
||||
--echo # UPDATE with oracle outer join
|
||||
--echo #
|
||||
UPDATE tj1, tj2 SET tj1.a = tj2.c WHERE tj1.a = tj2.c(+);
|
||||
SELECT * FROM tj1;
|
||||
|
||||
--echo #
|
||||
--echo # DELETE with oracle outer join
|
||||
--echo #
|
||||
DELETE tj1 FROM tj1, tj2 WHERE tj1.b(+) = tj2.c;
|
||||
SELECT * FROM tj1;
|
||||
|
||||
DROP DATABASE db1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE tj4;
|
||||
DROP TABLE tj3;
|
||||
DROP TABLE tj2;
|
||||
DROP TABLE tj1;
|
||||
|
||||
--echo #
|
||||
--echo # End of iqbal-rsec tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Test from the MDEV comments
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create table t3 (c int, e int);
|
||||
insert into t3 values (3,2),(10,3),(2,20);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (3),(1),(20);
|
||||
select t1.a, t4.d, t2.b, t3.c from t1, t2, t3, t4 where t1.a = t2.b(+) and t1.a = t3.c(+) and t4.d = t2.b(+) and t4.d = t3.c(+);
|
||||
select t1.a, t4.d, t2.b, t3.c from t1, t2, t3, t4 where t1.a + t3.c = t2.b(+) and t1.a = t3.c(+) and t4.d = t2.b(+) and t4.d = t3.c(+);
|
||||
select t1.a, t4.d, t2.b, t3.c from t1, t2, t3, t4 where (t2.b(+) in (t1.a, t1.a+1)) and t1.a = t3.c(+) and t4.d = t2.b(+) and t4.d = t3.c(+);
|
||||
|
||||
drop tables t1, t2, t3, t4;
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
create table t3 (c int, f int);
|
||||
insert into t3 values (3,2),(10,3),(2,20);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (3),(1),(20);
|
||||
create table t5 (e int);
|
||||
insert into t5 values (3),(2),(20);
|
||||
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, t2, t3, t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and t3.c=t5.e(+);
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, t2, t3, t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and 1=t5.e(+);
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, t2, t3, t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and 3=t5.e(+);
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
select t1.a, t2.b, t3.c, t4.d, t5.e from t1, (t2, t3), t4, t5 where t1.a = t2.b(+) and t2.b = t3.c(+) and t1.a = t4.d(+) and t4.d=t5.e(+) and 3=t5.e(+);
|
||||
|
||||
drop tables t1, t2, t3, t4, t5;
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
|
||||
# The WARN_ORA_JOIN_IGNORED is emitted only on PREPARE:
|
||||
--disable_ps_protocol
|
||||
select t1.a, t2.b from t1, t2 where 1 = t2.b(+);
|
||||
select t1.a, t2.b from t2, t1 where 1 = t2.b(+);
|
||||
select t1.a,t2.b from t2,t1 where t2.b(+) in (1,2);
|
||||
select t2.b from t2 where 1 = t2.b(+);
|
||||
--enable_ps_protocol
|
||||
|
||||
drop tables t1, t2;
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(4),(5),(20),(21),(23);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (1),(4),(6),(7),(8),(23);
|
||||
create table t3 (c int);
|
||||
insert into t3 values (4),(7),(9),(4),(6),(10),(11),(1);
|
||||
create table t4 (d int);
|
||||
insert into t4 values (1),(4),(10),(12),(20),(21),(23);
|
||||
|
||||
SELECT * FROM t1,t2,t3,t4 WHERE t1.a = t2.b(+) AND t1.a = t3.c(+) AND t2.b=t4.d(+) AND t3.c=t4.d(+);
|
||||
select * from t1, t2, t3 where (t1.a + t2.b = t3.c(+));
|
||||
|
||||
--echo # no tables mentioned
|
||||
select * from t2, t3 where b = c(+);
|
||||
--echo # should be the same as above
|
||||
select * from t2, t3 where t2.b = t3.c(+);
|
||||
|
||||
drop tables t1, t2, t3, t4;
|
||||
|
||||
--echo #
|
||||
--echo # View creation and usage
|
||||
--echo #
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
|
||||
create view v1 as
|
||||
select t1.a, t2.b from t1, t2 where t1.a = t2.b(+);
|
||||
show create view v1;
|
||||
select * from v1;
|
||||
select t1.a, t2.b from t1, t2 where t1.a = t2.b(+);
|
||||
|
||||
--echo usage without oracle sql mode
|
||||
set SQL_MODE= '';
|
||||
select * from v1;
|
||||
--error ER_PARSE_ERROR
|
||||
select t1.a, t2.b from t1, t2 where t1.a = t2.b(+);
|
||||
set SQL_MODE= oracle;
|
||||
|
||||
drop view v1;
|
||||
drop table t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36830: Oracle outer join syntax (+): outer join not converted to inner
|
||||
--echo #
|
||||
--source include/have_sequence.inc
|
||||
|
||||
create table t1 (
|
||||
a int not null,
|
||||
b int not null
|
||||
);
|
||||
insert into t1 select seq,seq from seq_1_to_10;
|
||||
|
||||
create table t2 (
|
||||
a int not null,
|
||||
b int not null
|
||||
);
|
||||
insert into t2 select seq,seq from seq_1_to_3;
|
||||
|
||||
--echo # Must be converted to inner join:
|
||||
explain extended
|
||||
select * from t1, t2
|
||||
where
|
||||
t1.a=1 and
|
||||
t1.b=t2.b(+) and
|
||||
t2.b=1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36838: Oracle outer join syntax (+): server crash on derived tables
|
||||
--echo #
|
||||
|
||||
select a.a
|
||||
from (select 1 as a) a,
|
||||
(select 2 as b) b
|
||||
where a.a=b.b(+);
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36866: Oracle outer join syntax (+): query with checking for
|
||||
--echo # null of non-null column uses wrong query plan and returns wrong
|
||||
--echo # result
|
||||
--echo #
|
||||
|
||||
create table t1 (a int default NULL);
|
||||
create table t2 (a int not null);
|
||||
insert into t1 values (1), (2), (3), (4), (5), (6), (NULL);
|
||||
insert into t2 values (1), (4), (5), (6), (7);
|
||||
|
||||
select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
|
||||
explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
|
||||
|
||||
select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
|
||||
explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
|
||||
|
||||
select t1.*,t2.* from t1,t2 where t1.a=t2.a(+) and isnull(t2.a)=1;
|
||||
explain extended select t1.*,t2.* from t1,t2 where t1.a=t2.a(+) and isnull(t2.a)=1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # Correct nullability test
|
||||
--echo #
|
||||
|
||||
create table t1 (a int not null, s varchar(10) not null);
|
||||
create table t2 (a int not null, s varchar(10) not null);
|
||||
insert into t1 values (1, 'one');
|
||||
insert into t1 values (2, 'two');
|
||||
insert into t2 values (2, 'two');
|
||||
insert into t2 values (3, 'three');
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t2.a);
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t1.a+t2.a);
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(coalesce(t2.s, 'null'));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(ifnull(t2.s, 'null'));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(coalesce(t2.s, null));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(ifnull(t2.s, null));
|
||||
|
||||
--echo # Our optimizer does not optimize out never-null-subselects under
|
||||
--echo # isnull() so we do not test it. The following test is to make
|
||||
--echo # sure that nullable one stay in the WHERE.
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t2.a in (select a from t1));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t2.a in (1, 2, 3));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(t1.a in (1, 2, 3));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(isnull(t2.a));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(field(t2.a, 2, 23));
|
||||
|
||||
explain extended
|
||||
select * from t1,t2 where t1.a = t2.a (+) and
|
||||
isnull(benchmark(10, t2.a));
|
||||
|
||||
|
||||
drop table t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36895: Oracle outer join syntax (+): some NULLs missing from
|
||||
--echo # result of the query with derived tables and limit
|
||||
--echo #
|
||||
|
||||
create table t2 (b int);
|
||||
insert into t2 values (3),(7),(1);
|
||||
create table t3 (c int);
|
||||
insert into t3 values (3),(1);
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(7),(1);
|
||||
|
||||
select * from
|
||||
(
|
||||
select * from
|
||||
(select 'Z' as z, t1.a from t1) dt1
|
||||
left join
|
||||
(select 'Y' as y, t2.b from t2) dt2
|
||||
left join
|
||||
(select 'X' as x, t3.c from t3) dt3
|
||||
on dt2.b=dt3.c
|
||||
on dt1.a=dt2.b
|
||||
order by z, a, y, b, x, c
|
||||
limit 9
|
||||
) dt;
|
||||
|
||||
|
||||
select * from
|
||||
(
|
||||
select * from
|
||||
(select 'Z' as z, t1.a from t1) dt1
|
||||
,(select * from
|
||||
(select 'Y' as y, t2.b from t2) dt2
|
||||
,
|
||||
(select 'X' as x, t3.c from t3) dt3
|
||||
where dt2.b=dt3.c(+)
|
||||
) tdt2
|
||||
where dt1.a=tdt2.b(+)
|
||||
order by z, a, y, b, x, c
|
||||
limit 9
|
||||
) dt;
|
||||
|
||||
drop table t1, t2, t3;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-37337: Oracle outer join syntax (+): IN equal to = allow (+) on right side
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
|
||||
set SQL_MODE= oracle;
|
||||
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a = t2.b(+);
|
||||
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
explain extended
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+), 29);
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (b int);
|
||||
insert into t2 values (2),(1),(20);
|
||||
|
||||
set SQL_MODE= oracle;
|
||||
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a = t2.b(+);
|
||||
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
|
||||
explain extended
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+));
|
||||
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
select t1.a, t2.b
|
||||
from t1, t2
|
||||
where
|
||||
t1.a IN (t2.b(+), 29);
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo # End of 12.1 tests
|
||||
138
mysql-test/suite/compat/oracle/t/ora_outer_join_err.test
Normal file
138
mysql-test/suite/compat/oracle/t/ora_outer_join_err.test
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
--echo #
|
||||
--echo # Cycles
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 (b int);
|
||||
create table t3 (c int);
|
||||
|
||||
--echo # b - cyrcle
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
select * from t1, t2, t3
|
||||
where t1.a = t2.b(+) AND t2.b = t3.c(+) AND
|
||||
t3.c = t2.b(+);
|
||||
--echo # O - cyrcle
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
select * from t1, t2, t3
|
||||
where t1.a = t2.b(+) AND t2.b = t3.c(+) AND
|
||||
t3.c = t1.a(+);
|
||||
--echo # self-reference cyrcle
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
select * from t1, t2, t3
|
||||
where t1.a = t2.b(+) AND t2.b = t3.c(+) AND
|
||||
t3.c = t3.c(+);
|
||||
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 (b int);
|
||||
create table t3 (c int);
|
||||
create table t4 (d int);
|
||||
create table t5 (e int);
|
||||
|
||||
--echo # complex case
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
select * from t1, t2, t3, t4, t5
|
||||
where
|
||||
t3.c = t4.d(+) AND t4.d = t3.c(+) AND
|
||||
t1.a = t5.e(+) AND t2.b = t5.e(+) AND
|
||||
t2.b = t3.c(+)
|
||||
;
|
||||
|
||||
DROP TABLE t1,t2,t3,t4,t5;
|
||||
|
||||
--echo #
|
||||
--echo # mix with other join operatirs
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
create table t3 (a int);
|
||||
|
||||
--echo # mixing with left join
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
select * from t1, t2 left join t3 on (t2.a = t3.a)
|
||||
where t1.a = t2.a(+);
|
||||
|
||||
--echo # mixing with right join
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
select * from t1, t2 right join t3 on (t2.a = t3.a)
|
||||
where t1.a = t2.a(+);
|
||||
|
||||
--echo # mixing with natural join
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
select * from t1, t2 natural join t3
|
||||
where t1.a = t2.a(+);
|
||||
|
||||
--echo # mixing with nested join
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
select * from t1, t2 join t3
|
||||
where t1.a = t2.a(+);
|
||||
|
||||
--echo # mixing with nested join
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
select * from t1, (t2, t3)
|
||||
where t1.a = t2.a(+);
|
||||
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # misplaced usage of (+)
|
||||
--echo #
|
||||
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
|
||||
--error ER_PARSE_ERROR
|
||||
select t1.a(+), t2.a from t1,t2;
|
||||
--error ER_PARSE_ERROR
|
||||
select t1.a, t2.a from t1,t2 HAVING t1.a(+) = t2.a;
|
||||
--error ER_PARSE_ERROR
|
||||
select t1.a, t2.a from t1 join t2 on (t1.a(+) = t2.a);
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # outer reference
|
||||
--echo #
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_OUTER_REF
|
||||
select u2.a, (select t1.a, t2.a from t1,t2 where u1.a(+) = t2.a)
|
||||
from t1 as u1, t2 as u2 where u1.a(+) = u2.a;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36883: Oracle outer join syntax (+): operator (+) is not
|
||||
--echo # processed in condition like "(t2.b(+) , t1.b) in (select ...)"
|
||||
--echo #
|
||||
create table t1 ( c int, b char(1));
|
||||
insert into t1 values (1,'b');
|
||||
|
||||
create table t2 ( a int , b char(1));
|
||||
insert into t2 values (1,'a');
|
||||
|
||||
create table t3 (c1 char(1), c2 char(2));
|
||||
insert into t3 values ('c','d');
|
||||
insert into t3 values ('c','d');
|
||||
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
SELECT t2.b
|
||||
FROM t1, t2 WHERE t1.c = t2.a(+) AND (t2.b(+), t1.b) IN (SELECT * from t3);
|
||||
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
SELECT t2.b
|
||||
FROM t1, t2 WHERE t1.c = t2.a(+) AND (t2.b(+), t1.b) IN (('a','a'),('b','b'));
|
||||
|
||||
--error ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
SELECT t2.b
|
||||
FROM t1, t2 WHERE t1.c = t2.a(+) AND (t2.b(+), t1.b) = (SELECT * from t3
|
||||
ORDER BY a LIMIT 1);
|
||||
|
||||
drop tables t1,t2,t3;
|
||||
@@ -132,6 +132,7 @@ SET (SQL_SOURCE
|
||||
sql_error.cc sql_handler.cc sql_get_diagnostics.cc
|
||||
sql_help.cc sql_insert.cc sql_lex.cc
|
||||
sql_list.cc sql_load.cc sql_manager.cc
|
||||
sql_oracle_outer_join.cc
|
||||
sql_parse.cc sql_bootstrap.cc
|
||||
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
|
||||
debug_sync.cc debug.cc
|
||||
|
||||
159
sql/item.cc
159
sql/item.cc
@@ -3512,6 +3512,11 @@ void Item_ident::print(String *str, enum_query_type query_type)
|
||||
str->append('.');
|
||||
}
|
||||
append_identifier(thd, str, &field_name);
|
||||
|
||||
if (with_ora_join())
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" (+)"));
|
||||
}
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -6332,6 +6337,22 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Item_field::check_ora_join(Item **reference, bool outer_ref_fixed)
|
||||
{
|
||||
if(with_ora_join())
|
||||
{
|
||||
if (outer_ref_fixed) // Oracle join operator is local
|
||||
{
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_OUTER_REF, MYF(0), name.str);
|
||||
return TRUE;
|
||||
}
|
||||
// Keep flag about oracle join if view fied was resolved
|
||||
if (reference[0] != this) // resolved to a new field
|
||||
reference[0]->copy_flags(this, item_with_t::ORA_JOIN);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resolve the name of a column reference.
|
||||
@@ -6466,7 +6487,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||
set_max_sum_func_level(thd, select);
|
||||
set_field(new_field);
|
||||
depended_from= (*((Item_field**)res))->depended_from;
|
||||
return 0;
|
||||
return check_ora_join(reference, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6493,7 +6514,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||
its arguments are not defined.
|
||||
*/
|
||||
set_max_sum_func_level(thd, select);
|
||||
return FALSE;
|
||||
return check_ora_join(reference, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6548,7 +6569,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||
Also we suppose that view can't be changed during PS/SP life.
|
||||
*/
|
||||
if (from_field == view_ref_found)
|
||||
return FALSE;
|
||||
return check_ora_join(reference, outer_fixed);
|
||||
|
||||
set_field(from_field);
|
||||
}
|
||||
@@ -6596,6 +6617,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||
}
|
||||
#endif
|
||||
base_flags|= item_base_t::FIXED;
|
||||
if (check_ora_join(reference, outer_fixed))
|
||||
goto error;
|
||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
|
||||
!outer_fixed && !thd->lex->in_sum_func &&
|
||||
select &&
|
||||
@@ -6644,7 +6667,7 @@ mark_non_agg_field:
|
||||
select_lex->set_non_agg_field_used(true);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return check_ora_join(reference, outer_fixed);
|
||||
|
||||
error:
|
||||
context->process_error(thd);
|
||||
@@ -7806,6 +7829,17 @@ bool Item_null::send(Protocol *protocol, st_value *buffer)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a List<Item> consisting of one element -
|
||||
a single Item_join_operator_plus instance.
|
||||
*/
|
||||
List<Item> *Item_join_operator_plus::make_as_item_list(THD *thd)
|
||||
{
|
||||
Item *item= new (thd->mem_root) Item_join_operator_plus(thd);
|
||||
return item ? List<Item>::make(thd->mem_root, item) : nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if an item is a constant one and can be cached.
|
||||
|
||||
@@ -9666,6 +9700,14 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool Item_direct_view_ref::add_maybe_null_after_ora_join_processor(void *arg)
|
||||
{
|
||||
if (!maybe_null() && view->table && view->table->maybe_null)
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Prepare referenced outer field then call usual Item_direct_ref::fix_fields
|
||||
|
||||
@@ -10175,6 +10217,115 @@ bool Item_default_value::val_native_result(THD *thd, Native *to)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We're processing an expression with a (+) operator somewhere.
|
||||
We encounter reference to 'table.column' (with the(+) or not).
|
||||
Add table to the oracle outer join structure we're building
|
||||
*/
|
||||
|
||||
bool Item_ident::ora_join_add_table_ref(ora_join_processor_param *arg,
|
||||
TABLE_LIST *table)
|
||||
{
|
||||
DBUG_ASSERT(fixed());
|
||||
TABLE_LIST *err_table= NULL;
|
||||
|
||||
if (with_ora_join())
|
||||
{
|
||||
// This an item with (+) operator, the referred table is INNER.
|
||||
if (arg->inner == NULL)
|
||||
{
|
||||
arg->inner= table;
|
||||
// Make sure this table is not also in the list of OUTER tables.
|
||||
List_iterator_fast<TABLE_LIST> it(arg->outer);
|
||||
TABLE_LIST *t;
|
||||
while ((t= it++))
|
||||
{
|
||||
if (t == table)
|
||||
{
|
||||
err_table= t;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cannot have two INNER tables, like t1.col=t2.col(+) + t3.col(+)
|
||||
if (arg->inner != table)
|
||||
{
|
||||
err_table= arg->inner;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No (+) operator, this is an outer table.
|
||||
List_iterator_fast<TABLE_LIST> it(arg->outer);
|
||||
TABLE_LIST *t;
|
||||
|
||||
// Check if this table is already in the list of outer tables
|
||||
while ((t= it++))
|
||||
{
|
||||
if (t == table)
|
||||
break;
|
||||
}
|
||||
if (t == NULL)
|
||||
{
|
||||
// Check that this table is also used as INNER by this condition
|
||||
if (table == arg->inner)
|
||||
{
|
||||
err_table= arg->inner;
|
||||
goto err;
|
||||
}
|
||||
arg->outer.push_back(table);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
err:
|
||||
// it is not marked all tables as outer or several inner or outer tables
|
||||
if (table == err_table)
|
||||
{
|
||||
// self reference (simple case of cyclic reference)
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_CYCLE, MYF(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_ONE_TABLE, MYF(0),
|
||||
err_table->alias.str,
|
||||
table->alias.str,
|
||||
(with_ora_join()?"INNER":"OUTER"));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
bool Item_field::ora_join_processor(void *arg)
|
||||
{
|
||||
DBUG_ASSERT(field->table->pos_in_table_list);
|
||||
return Item_ident::ora_join_add_table_ref((ora_join_processor_param *)arg,
|
||||
field->table->pos_in_table_list);
|
||||
}
|
||||
|
||||
|
||||
bool Item_direct_view_ref::ora_join_processor(void *arg)
|
||||
{
|
||||
DBUG_ASSERT(view);
|
||||
return Item_ident::ora_join_add_table_ref((ora_join_processor_param *)arg,
|
||||
view);
|
||||
}
|
||||
|
||||
|
||||
bool Item_ref::ora_join_processor(void *arg)
|
||||
{
|
||||
if (with_ora_join())
|
||||
{
|
||||
// It should not happened
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
table_map Item_default_value::used_tables() const
|
||||
{
|
||||
if (!field || !field->default_value)
|
||||
|
||||
115
sql/item.h
115
sql/item.h
@@ -97,6 +97,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
struct ora_join_processor_param
|
||||
{
|
||||
TABLE_LIST *inner;
|
||||
List<TABLE_LIST> outer;
|
||||
/* TRUE means Oracle join operator was used inside some OR clause */
|
||||
bool or_present;
|
||||
};
|
||||
|
||||
|
||||
#ifdef DBUG_OFF
|
||||
static inline const char *dbug_print_item(Item *item) { return NULL; }
|
||||
#else
|
||||
@@ -709,7 +718,7 @@ struct subselect_table_finder_param
|
||||
|
||||
/* Base flags (including IN) for an item */
|
||||
|
||||
typedef uint8 item_flags_t;
|
||||
typedef uint16 item_flags_t;
|
||||
|
||||
enum class item_base_t : item_flags_t
|
||||
{
|
||||
@@ -742,8 +751,9 @@ enum class item_with_t : item_flags_t
|
||||
SUBQUERY= (1<<4), // If item contains a subquery
|
||||
ROWNUM_FUNC= (1<<5), // If ROWNUM function was used
|
||||
PARAM= (1<<6), // If user parameter was used
|
||||
COMPLEX_DATA_TYPE= (1<<7) // If the expression is of a complex data type which
|
||||
COMPLEX_DATA_TYPE= (1<<7),// If the expression is of a complex data type which
|
||||
// requires special handling on destruction
|
||||
ORA_JOIN= (1<<8), // If Oracle join syntax was used
|
||||
};
|
||||
|
||||
|
||||
@@ -809,6 +819,7 @@ static inline item_with_t operator~(const item_with_t a)
|
||||
typedef uint8 item_walk_flags;
|
||||
const item_walk_flags WALK_SUBQUERY= 1;
|
||||
const item_walk_flags WALK_NO_CACHE_PROCESS= (1<<1);
|
||||
const item_walk_flags WALK_NO_REF= (1<<2);
|
||||
|
||||
|
||||
class Item :public Value_source,
|
||||
@@ -1070,6 +1081,8 @@ public:
|
||||
{ return (bool) (with_flags & item_with_t::PARAM); }
|
||||
inline bool with_complex_data_types() const
|
||||
{ return (bool) (with_flags & item_with_t::COMPLEX_DATA_TYPE); }
|
||||
inline bool with_ora_join() const
|
||||
{ return (bool) (with_flags & item_with_t::ORA_JOIN); }
|
||||
inline void copy_flags(const Item *org, item_base_t mask)
|
||||
{
|
||||
base_flags= (item_base_t) (((item_flags_t) base_flags &
|
||||
@@ -2283,6 +2296,19 @@ public:
|
||||
is_expensive_cache= (int8)(-1);
|
||||
return 0;
|
||||
}
|
||||
virtual bool ora_join_processor(void *arg) { return 0; }
|
||||
/*
|
||||
This marks the item as nullable. Note that if we'd want a method that
|
||||
marks the item as not nullable (maybe_null=false) we'd need to process
|
||||
carefully functions (e.g. json*) that can always return null even with
|
||||
non-null arguments
|
||||
*/
|
||||
virtual bool add_maybe_null_after_ora_join_processor(void *arg) { return 0; }
|
||||
virtual bool remove_ora_join_processor(void *arg)
|
||||
{
|
||||
with_flags&= ~item_with_t::ORA_JOIN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool set_extraction_flag_processor(void *arg)
|
||||
{
|
||||
@@ -2892,6 +2918,24 @@ protected:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_any_arg_maybe_null()
|
||||
{
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
{
|
||||
if (args[i]->maybe_null())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_all_arg_maybe_null()
|
||||
{
|
||||
for (uint i= 0; i < arg_count; i++)
|
||||
{
|
||||
if (!args[i]->maybe_null())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
|
||||
void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
|
||||
bool excl_dep_on_table(table_map tab_map)
|
||||
@@ -3701,6 +3745,10 @@ public:
|
||||
Collect outer references
|
||||
*/
|
||||
bool collect_outer_ref_processor(void *arg) override;
|
||||
|
||||
bool ora_join_add_table_ref(ora_join_processor_param *arg,
|
||||
TABLE_LIST *table);
|
||||
|
||||
friend bool insert_fields(THD *thd, Name_resolution_context *context,
|
||||
const LEX_CSTRING &db_name,
|
||||
const LEX_CSTRING &table_name,
|
||||
@@ -3933,6 +3981,20 @@ public:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool ora_join_processor(void *arg) override;
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
/*
|
||||
Before this operation field nullability can not be removed
|
||||
(only can be set).
|
||||
maybe_null() store the old nullability state, and
|
||||
field->maybe_null() is the current state.
|
||||
*/
|
||||
DBUG_ASSERT(!maybe_null() || field->maybe_null());
|
||||
set_maybe_null(field->maybe_null());
|
||||
return 0;
|
||||
}
|
||||
bool check_ora_join(Item **reference, bool outer_ref_fixed);
|
||||
void cleanup() override;
|
||||
Item_equal *get_item_equal() override { return item_equal; }
|
||||
void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; }
|
||||
@@ -4064,6 +4126,27 @@ public:
|
||||
Item *do_build_clone(THD *thd) const override { return get_copy(thd); }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A pseudo-Item to parse Oracle style outer join operator:
|
||||
WHERE t1.a = t2.b (+);
|
||||
*/
|
||||
class Item_join_operator_plus: public Item_null
|
||||
{
|
||||
public:
|
||||
using Item_null::Item_null;
|
||||
/*
|
||||
Need to override as least one method to have an unique vtable,
|
||||
to make dynamic_cast work.
|
||||
*/
|
||||
void print(String *str, enum_query_type) override
|
||||
{
|
||||
str->append("(+)"_LEX_CSTRING);
|
||||
}
|
||||
static List<Item> *make_as_item_list(THD *thd);
|
||||
};
|
||||
|
||||
|
||||
class Item_null_result :public Item_null
|
||||
{
|
||||
public:
|
||||
@@ -5853,6 +5936,13 @@ public:
|
||||
return true;
|
||||
return (this->*processor)(arg);
|
||||
}
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
// see Item::add_maybe_null_after_ora_join_processor
|
||||
if (!maybe_null() && is_any_arg_maybe_null())
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
Built-in schema, e.g. mariadb_schema, oracle_schema, maxdb_schema
|
||||
*/
|
||||
@@ -6074,6 +6164,8 @@ public:
|
||||
bool walk(Item_processor processor, void *arg,
|
||||
item_walk_flags flags) override
|
||||
{
|
||||
if (flags & WALK_NO_REF)
|
||||
return (this->*processor)(arg);
|
||||
if (ref && *ref)
|
||||
return (*ref)->walk(processor, arg, flags) ||
|
||||
(this->*processor)(arg);
|
||||
@@ -6179,6 +6271,13 @@ public:
|
||||
return 0;
|
||||
return cleanup_processor(arg);
|
||||
}
|
||||
bool ora_join_processor(void *arg) override;
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
if ((*ref)->maybe_null())
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg) override
|
||||
{ return (*ref)->field_transformer_for_having_pushdown(thd, arg); }
|
||||
};
|
||||
@@ -6397,6 +6496,12 @@ public:
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_cache_wrapper>(thd, this); }
|
||||
Item *do_build_clone(THD *) const override { return nullptr; }
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
if (orig_item->maybe_null())
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6473,6 +6578,8 @@ public:
|
||||
bool walk(Item_processor processor, void *arg,
|
||||
item_walk_flags flags) override
|
||||
{
|
||||
if (flags & WALK_NO_REF)
|
||||
return (this->*processor)(arg);
|
||||
return (*ref)->walk(processor, arg, flags) ||
|
||||
(this->*processor)(arg);
|
||||
}
|
||||
@@ -6483,6 +6590,7 @@ public:
|
||||
view_arg->view_used_tables|= (*ref)->used_tables();
|
||||
return 0;
|
||||
}
|
||||
bool ora_join_processor(void *arg) override;
|
||||
bool excl_dep_on_table(table_map tab_map) override;
|
||||
bool excl_dep_on_grouping_fields(st_select_lex *sel) override;
|
||||
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) override;
|
||||
@@ -6627,6 +6735,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
void print(String *str, enum_query_type query_type) override;
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -8417,6 +8526,8 @@ public:
|
||||
bool walk(Item_processor processor, void *arg,
|
||||
item_walk_flags flags) override
|
||||
{
|
||||
if (flags & WALK_NO_REF)
|
||||
return (this->*processor)(arg);
|
||||
return m_item->walk(processor, arg, flags) ||
|
||||
(this->*processor)(arg);
|
||||
}
|
||||
|
||||
@@ -5034,6 +5034,33 @@ void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_in::ora_join_processor(void *arg)
|
||||
{
|
||||
if (with_ora_join())
|
||||
{
|
||||
if (args[0]->cols() > 1 && args[0]->with_ora_join())
|
||||
{
|
||||
// used in ROW operaton
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
uint n= argument_count();
|
||||
DBUG_ASSERT(n >= 2);
|
||||
// first argument (0) is right part of IN where oracle joins are allowed
|
||||
for (uint i= 1; i < n; i++)
|
||||
{
|
||||
if (args[i]->with_ora_join())
|
||||
{
|
||||
// used in right part of IN
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC, MYF(0));
|
||||
return TRUE ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
class Func_handler_bit_or_int_to_ulonglong:
|
||||
public Item_handled_func::Handler_ulonglong
|
||||
{
|
||||
|
||||
@@ -279,6 +279,9 @@ public:
|
||||
{
|
||||
return negated_item(thd);
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
|
||||
protected:
|
||||
Item_func_truth(THD *thd, Item *a, bool a_value, bool a_affirmative):
|
||||
@@ -887,6 +890,9 @@ public:
|
||||
}
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_equal>(thd, this); }
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1191,6 +1197,9 @@ public:
|
||||
}
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_interval>(thd, this); }
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1217,6 +1226,12 @@ public:
|
||||
fix_attributes(args, arg_count);
|
||||
return FALSE;
|
||||
}
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
if (!maybe_null() && is_all_arg_maybe_null())
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("coalesce") };
|
||||
@@ -1309,6 +1324,12 @@ public:
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
if (!maybe_null() && is_all_arg_maybe_null())
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
{
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("ifnull") };
|
||||
@@ -2745,6 +2766,7 @@ public:
|
||||
Item* varchar_upper_cmp_transformer(THD *thd, uchar *arg) override;
|
||||
|
||||
Item* vcol_subst_transformer(THD *thd, uchar *arg) override;
|
||||
bool ora_join_processor(void *arg) override;
|
||||
};
|
||||
|
||||
class cmp_item_row :public cmp_item
|
||||
@@ -2827,6 +2849,9 @@ public:
|
||||
base_flags&= ~item_base_t::MAYBE_NULL;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
bool count_sargable_conds(void *arg) override;
|
||||
|
||||
Item* vcol_subst_transformer(THD *thd, uchar *arg) override;
|
||||
@@ -3321,7 +3346,7 @@ public:
|
||||
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
List<Item> &fields, uint flags) override;
|
||||
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
COND **conds);
|
||||
COND **conds, List<Item> *all_fields);
|
||||
void copy_andor_arguments(THD *thd, Item_cond *item);
|
||||
bool walk(Item_processor processor, void *arg,
|
||||
item_walk_flags flags) override;
|
||||
@@ -3742,6 +3767,15 @@ public:
|
||||
table_map not_null_tables() const override { return and_tables_cache; }
|
||||
Item *copy_andor_structure(THD *thd) override;
|
||||
Item *neg_transformer(THD *thd) override;
|
||||
bool ora_join_processor(void *arg) override
|
||||
{
|
||||
if (with_ora_join())
|
||||
{
|
||||
// Oracle join operator is used in this OR clause.
|
||||
((ora_join_processor_param *) arg)->or_present= true;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_cond_or>(thd, this); }
|
||||
};
|
||||
|
||||
@@ -2624,6 +2624,9 @@ public:
|
||||
return name;
|
||||
}
|
||||
bool fix_length_and_dec(THD *thd) override;
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
bool eval_not_null_tables(void *) override
|
||||
{
|
||||
not_null_tables_cache= 0;
|
||||
@@ -2696,6 +2699,9 @@ public:
|
||||
bool fix_length_and_dec(THD *thd) override;
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_field>(thd, this); }
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -2941,6 +2947,9 @@ public:
|
||||
base_flags&= ~item_base_t::MAYBE_NULL;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
void print(String *str, enum_query_type query_type) override;
|
||||
bool check_vcol_func_processor(void *arg) override
|
||||
{
|
||||
@@ -3980,6 +3989,9 @@ public:
|
||||
base_flags&= ~item_base_t::MAYBE_NULL;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
bool check_vcol_func_processor(void *arg) override
|
||||
{
|
||||
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
|
||||
@@ -4288,6 +4300,9 @@ public:
|
||||
base_flags&= ~item_base_t::MAYBE_NULL;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
bool check_vcol_func_processor(void *arg) override
|
||||
{
|
||||
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
|
||||
@@ -4345,6 +4360,9 @@ public:
|
||||
max_length= 11;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_sqlcode>(thd, this); }
|
||||
};
|
||||
|
||||
@@ -122,6 +122,17 @@ public:
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_row>(thd, this); }
|
||||
Item *do_build_clone(THD *thd) const override;
|
||||
|
||||
bool ora_join_processor(void *arg) override
|
||||
{
|
||||
if (with_ora_join())
|
||||
{
|
||||
// Oracle join operator is used inside rows.
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC, MYF(0));
|
||||
return(TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ITEM_ROW_INCLUDED */
|
||||
|
||||
@@ -1223,6 +1223,9 @@ public:
|
||||
base_flags&= ~item_base_t::MAYBE_NULL;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_sqlerrm>(thd, this); }
|
||||
};
|
||||
@@ -1344,6 +1347,9 @@ public:
|
||||
}
|
||||
Item *do_get_copy(THD *thd) const override
|
||||
{ return get_item_copy<Item_func_current_role>(thd, this); }
|
||||
// null do not depend on nullability of the argument
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -2058,6 +2064,9 @@ public:
|
||||
base_flags&= ~item_base_t::MAYBE_NULL;
|
||||
return FALSE;
|
||||
};
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
table_map not_null_tables() const override { return 0; }
|
||||
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
|
||||
override
|
||||
|
||||
@@ -3614,11 +3614,13 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
|
||||
}
|
||||
}
|
||||
|
||||
if (left_expr && left_expr->fix_fields_if_needed(thd_arg, &left_expr))
|
||||
if (!left_expr || left_expr->fix_fields_if_needed(thd_arg, &left_expr))
|
||||
goto err;
|
||||
else
|
||||
if (Item_subselect::fix_fields(thd_arg, ref))
|
||||
goto err;
|
||||
if (left_expr->with_ora_join())
|
||||
copy_flags(left_expr, item_with_t::ORA_JOIN);
|
||||
base_flags|= item_base_t::FIXED;
|
||||
thd->where= save_where;
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
@@ -791,6 +791,22 @@ public:
|
||||
Subq_materialization_tracker *get_materialization_tracker() const
|
||||
{ return materialization_tracker; }
|
||||
|
||||
bool ora_join_processor(void *arg) override
|
||||
{
|
||||
if (left_expr->with_ora_join() && left_expr->cols() > 1)
|
||||
{
|
||||
// used in ROW operaton
|
||||
my_error(ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{
|
||||
if (!maybe_null() && left_expr->maybe_null())
|
||||
set_maybe_null();
|
||||
return 0;
|
||||
}
|
||||
friend class Item_ref_null_helper;
|
||||
friend class Item_is_not_null_test;
|
||||
friend class Item_in_optimizer;
|
||||
|
||||
@@ -807,6 +807,9 @@ public:
|
||||
null_value=0;
|
||||
return false;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1271,6 +1274,9 @@ public:
|
||||
null_value= 0;
|
||||
return FALSE;
|
||||
}
|
||||
// block standard processor for never null
|
||||
bool add_maybe_null_after_ora_join_processor(void *arg) override
|
||||
{ return 0; }
|
||||
void cleanup() override
|
||||
{
|
||||
bits= reset_bits;
|
||||
|
||||
@@ -12338,3 +12338,17 @@ ER_NULL_FOR_ASSOC_ARRAY_INDEX
|
||||
eng "NULL key used for associative array '%s'"
|
||||
ER_NEED_NAMED_ASSOCIATION
|
||||
eng "Initializing %s requires named association"
|
||||
ER_INVALID_USE_OF_ORA_JOIN
|
||||
eng "Invalid usage of (+) operator"
|
||||
ER_INVALID_USE_OF_ORA_JOIN_CYCLE
|
||||
eng "Invalid usage of (+) operator: cycle dependencies"
|
||||
ER_INVALID_USE_OF_ORA_JOIN_OUTER_REF
|
||||
eng "Invalid usage of (+) operator with outer reference %s"
|
||||
ER_INVALID_USE_OF_ORA_JOIN_ONE_TABLE
|
||||
eng "Invalid usage of (+) operator: both tables %s and %s are of %s type in the relation"
|
||||
ER_INVALID_USE_OF_ORA_JOIN_WRONG_FUNC
|
||||
eng "Invalid usage of (+) operator: used in OR, IN or ROW operation"
|
||||
ER_INVALID_USE_OF_ORA_JOIN_MIX
|
||||
eng "Invalid usage of (+) operator: mixed with other type of join"
|
||||
WARN_ORA_JOIN_IGNORED
|
||||
eng "Oracle outer join operator (+) ignored in '%-.100s'"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
/* Basic functions needed by many modules */
|
||||
|
||||
#include "lex_ident_sys.h"
|
||||
#include "mariadb.h"
|
||||
#include "sql_base.h" // setup_table_map
|
||||
#include "sql_list.h"
|
||||
@@ -8903,6 +8904,7 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Fix all conditions and outer join expressions.
|
||||
|
||||
@@ -8912,6 +8914,7 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
|
||||
tables list of tables for name resolving (select_lex->table_list)
|
||||
leaves list of leaves of join table tree (select_lex->leaf_tables)
|
||||
conds WHERE clause
|
||||
all_fields SELECT list + hidden fields
|
||||
|
||||
DESCRIPTION
|
||||
TODO
|
||||
@@ -8922,7 +8925,7 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
|
||||
*/
|
||||
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
|
||||
COND **conds)
|
||||
COND **conds, List<Item> *all_fields)
|
||||
{
|
||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||
TABLE_LIST *table= NULL; // For HP compilers
|
||||
@@ -8975,6 +8978,10 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
|
||||
(*conds)->mark_as_condition_AND_part(NO_JOIN_NEST);
|
||||
if ((*conds)->fix_fields_if_needed_for_bool(thd, conds))
|
||||
goto err_no_arena;
|
||||
|
||||
if (setup_oracle_join(thd, conds, tables, select_lex->table_list,
|
||||
&select_lex->top_join_list, all_fields))
|
||||
goto err_no_arena;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -247,7 +247,7 @@ void update_non_unique_table_error(TABLE_LIST *update,
|
||||
const char *operation,
|
||||
TABLE_LIST *duplicate);
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
|
||||
COND **conds);
|
||||
COND **conds, List<Item> *all_fields);
|
||||
void wrap_ident(THD *thd, Item **conds);
|
||||
int setup_ftfuncs(SELECT_LEX* select);
|
||||
void cleanup_ftfuncs(SELECT_LEX *select_lex);
|
||||
@@ -694,4 +694,11 @@ private:
|
||||
int m_unhandled_errors;
|
||||
uint first_error;
|
||||
};
|
||||
|
||||
bool setup_oracle_join(THD *thd, Item **conds,
|
||||
TABLE_LIST *tables,
|
||||
SQL_I_List<TABLE_LIST> &select_table_list,
|
||||
List<TABLE_LIST> *select_join_list,
|
||||
List<Item> *all_fields);
|
||||
|
||||
#endif /* SQL_BASE_INCLUDED */
|
||||
|
||||
@@ -9092,6 +9092,34 @@ Item *LEX::create_item_ident_trigger_specific(THD *thd,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@detail
|
||||
This is called when we've parsed Oracle's outer join syntax, that is
|
||||
|
||||
[[db_name.]table_name.]column_name(+)
|
||||
|
||||
Check if the parse context allows it, if yes, mark the Item_field with
|
||||
ORA_JOIN flag and return it.
|
||||
*/
|
||||
|
||||
bool LEX::mark_item_ident_for_ora_join(THD *thd, Item *item)
|
||||
{
|
||||
Item_field *item_field;
|
||||
DBUG_ASSERT(item);
|
||||
|
||||
if ((thd->variables.sql_mode & MODE_ORACLE) &&
|
||||
current_select && current_select->parsing_place == IN_WHERE &&
|
||||
(item_field= dynamic_cast<Item_field*>(item)))
|
||||
{
|
||||
item_field->with_flags|= item_with_t::ORA_JOIN;
|
||||
return false;
|
||||
}
|
||||
|
||||
thd->parse_error(ER_SYNTAX_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Item *LEX::create_item_limit(THD *thd, const Lex_ident_cli_st *ca)
|
||||
{
|
||||
DBUG_ASSERT(thd->m_parser_state->m_lip.get_buf() <= ca->pos());
|
||||
@@ -10566,6 +10594,15 @@ Item *LEX::make_item_func_call_generic(THD *thd,
|
||||
const Lex_ident_cli_st *cname,
|
||||
List<Item> *args)
|
||||
{
|
||||
if (args && args->elements == 1 &&
|
||||
dynamic_cast<Item_join_operator_plus*>(args->head()))
|
||||
{
|
||||
Item *item= create_item_ident(thd, cdb, cname);
|
||||
if (!item || mark_item_ident_for_ora_join(thd, item))
|
||||
return nullptr;
|
||||
return item;
|
||||
}
|
||||
|
||||
Lex_ident_sys db(thd, cdb), name(thd, cname);
|
||||
if (db.is_null() || name.is_null())
|
||||
return NULL; // EOM
|
||||
@@ -10661,6 +10698,15 @@ Item *LEX::make_item_func_call_generic(THD *thd,
|
||||
Lex_ident_cli_st *cfunc,
|
||||
List<Item> *args)
|
||||
{
|
||||
if (args && args->elements == 1 &&
|
||||
dynamic_cast<Item_join_operator_plus*>(args->head()))
|
||||
{
|
||||
Item *item= create_item_ident(thd, cdb, cpkg, cfunc);
|
||||
if (!item || mark_item_ident_for_ora_join(thd, item))
|
||||
return nullptr;
|
||||
return item;
|
||||
}
|
||||
|
||||
Lex_ident_sys db(thd, cdb), pkg(thd, cpkg), func(thd, cfunc);
|
||||
Identifier_chain2 q_pkg_func(pkg, func);
|
||||
sp_name *qname;
|
||||
|
||||
@@ -4061,13 +4061,13 @@ public:
|
||||
const Lex_ident_sys_st &db,
|
||||
const Lex_ident_sys_st &table,
|
||||
const Lex_ident_sys_st &name);
|
||||
Item *create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name)
|
||||
Item *create_item_ident_nosp(THD *thd, const Lex_ident_sys_st *name)
|
||||
{
|
||||
return create_item_ident_field(thd, Lex_ident_sys(), Lex_ident_sys(), *name);
|
||||
}
|
||||
Item *create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
|
||||
const char *start, const char *end);
|
||||
Item *create_item_ident(THD *thd, Lex_ident_cli_st *cname)
|
||||
Item *create_item_ident(THD *thd, const Lex_ident_cli_st *cname)
|
||||
{
|
||||
Lex_ident_sys name(thd, cname);
|
||||
if (name.is_null())
|
||||
@@ -4195,6 +4195,8 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool mark_item_ident_for_ora_join(THD *thd, Item *item);
|
||||
|
||||
/*
|
||||
Create items of this kind:
|
||||
SELECT name(args); -- e.g. spvar_assoc_array('key')
|
||||
|
||||
1147
sql/sql_oracle_outer_join.cc
Normal file
1147
sql/sql_oracle_outer_join.cc
Normal file
File diff suppressed because it is too large
Load Diff
@@ -954,7 +954,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
DBUG_ENTER("setup_without_group");
|
||||
|
||||
thd->lex->allow_sum_func.clear_bit(select->nest_level);
|
||||
res= setup_conds(thd, tables, leaves, conds);
|
||||
res= setup_conds(thd, tables, leaves, conds, &all_fields);
|
||||
|
||||
/* it's not wrong to have non-aggregated columns in a WHERE */
|
||||
select->set_non_agg_field_used(saved_non_agg_field_used);
|
||||
|
||||
@@ -1594,6 +1594,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
%type <item_list>
|
||||
expr_list opt_udf_expr_list udf_expr_list when_list when_list_opt_else
|
||||
ident_list ident_list_arg opt_expr_list
|
||||
opt_udf_expr_list_or_join_operator
|
||||
opt_expr_list_or_join_operator
|
||||
execute_using
|
||||
execute_params
|
||||
opt_sp_cparam_list
|
||||
@@ -11015,10 +11017,13 @@ function_call_generic:
|
||||
#ifdef HAVE_DLOPEN
|
||||
udf_func *udf= 0;
|
||||
LEX *lex= Lex;
|
||||
Lex_ident_sys ident(thd, &$1);
|
||||
|
||||
if (using_udf_functions &&
|
||||
(udf= find_udf(ident.str, ident.length)) &&
|
||||
if (using_udf_functions)
|
||||
{
|
||||
// find_udf expectes a 0-terminated string
|
||||
const Lex_ident_sys sysname(thd, &$1);
|
||||
if (sysname.is_null())
|
||||
MYSQL_YYABORT; // EOM
|
||||
if ((udf= find_udf(sysname.str, sysname.length)) &&
|
||||
udf->type == UDFTYPE_AGGREGATE)
|
||||
{
|
||||
if (unlikely(lex->current_select->inc_in_sum_expr()))
|
||||
@@ -11027,11 +11032,13 @@ function_call_generic:
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Temporary placing the result of find_udf in $3 */
|
||||
$<udf>$= udf;
|
||||
#endif
|
||||
}
|
||||
opt_udf_expr_list ')' opt_object_member_access
|
||||
|
||||
opt_udf_expr_list_or_join_operator ')' opt_object_member_access
|
||||
{
|
||||
const Type_handler *h;
|
||||
Create_func *builder;
|
||||
@@ -11055,9 +11062,19 @@ function_call_generic:
|
||||
|
||||
This will be revised with WL#2128 (SQL PATH)
|
||||
*/
|
||||
builder= Schema::find_implied(thd)->
|
||||
find_native_function_builder(thd, ident);
|
||||
if (builder)
|
||||
if ($4 && $4->elements == 1 &&
|
||||
dynamic_cast<Item_join_operator_plus*>($4->head()))
|
||||
{
|
||||
if ($6.str)
|
||||
{
|
||||
thd->parse_error();
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
item= Lex->create_item_ident(thd, &$1);
|
||||
if (!item || Lex->mark_item_ident_for_ora_join(thd, item))
|
||||
MYSQL_YYABORT;
|
||||
} else if ((builder= Schema::find_implied(thd)->
|
||||
find_native_function_builder(thd, ident)))
|
||||
{
|
||||
item= builder->create_func(thd, &ident, $4);
|
||||
}
|
||||
@@ -11139,7 +11156,7 @@ function_call_generic:
|
||||
$1, $3)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ident_cli '.' ident_cli '(' opt_expr_list ')'
|
||||
| ident_cli '.' ident_cli '(' opt_expr_list_or_join_operator ')'
|
||||
{
|
||||
const Lex_ident_cli pos($1.pos(), $6.pos() - $1.pos() + 1);
|
||||
if (unlikely(!($$= Lex->make_item_func_or_method_call(thd, $1,
|
||||
@@ -11147,7 +11164,21 @@ function_call_generic:
|
||||
pos))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list ')'
|
||||
| '.' ident_cli '.' ident_cli '(' '+' ')'
|
||||
{
|
||||
/*
|
||||
This grammar branch is needed for symmetry with simple_ident,
|
||||
to handle Oracle style outer join:
|
||||
WHERE t1.a = .t2.a(+)
|
||||
*/
|
||||
Lex_ident_cli empty($2.pos(), 0);
|
||||
List<Item> *list= Item_join_operator_plus::make_as_item_list(thd);
|
||||
if (unlikely(
|
||||
!list ||
|
||||
!($$= Lex->make_item_func_call_generic(thd, &empty, &$2, &$4, list))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list_or_join_operator ')'
|
||||
{
|
||||
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7))))
|
||||
MYSQL_YYABORT;
|
||||
@@ -11221,6 +11252,19 @@ opt_udf_expr_list:
|
||||
%endif
|
||||
;
|
||||
|
||||
opt_udf_expr_list_or_join_operator:
|
||||
opt_udf_expr_list
|
||||
| remember_name '+' remember_end
|
||||
{
|
||||
/*
|
||||
remember_name and remember_end are needed here
|
||||
to avoid a shift/reduce conflict with the rule udf_expr.
|
||||
*/
|
||||
if (!($$= Item_join_operator_plus::make_as_item_list(thd)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
udf_expr_list:
|
||||
udf_expr
|
||||
{
|
||||
@@ -11865,6 +11909,15 @@ opt_expr_list:
|
||||
| expr_list { $$= $1;}
|
||||
;
|
||||
|
||||
opt_expr_list_or_join_operator:
|
||||
opt_expr_list
|
||||
| '+'
|
||||
{
|
||||
if (!($$= Item_join_operator_plus::make_as_item_list(thd)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
expr_list:
|
||||
expr
|
||||
{
|
||||
@@ -16006,7 +16059,6 @@ order_ident:
|
||||
expr { $$=$1; }
|
||||
;
|
||||
|
||||
|
||||
simple_ident:
|
||||
ident_cli
|
||||
{
|
||||
|
||||
@@ -10643,7 +10643,7 @@ bool TR_table::query(ulonglong trx_id)
|
||||
Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_TRX_ID]);
|
||||
Item *value= newx Item_int(thd, trx_id);
|
||||
COND *conds= newx Item_func_eq(thd, field, value);
|
||||
if (unlikely((error= setup_conds(thd, this, dummy, &conds))))
|
||||
if (unlikely((error= setup_conds(thd, this, dummy, &conds, NULL))))
|
||||
return false;
|
||||
select= make_select(table, 0, 0, conds, NULL, 0, &error);
|
||||
if (unlikely(error || !select))
|
||||
@@ -10682,7 +10682,7 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards)
|
||||
conds= newx Item_func_ge(thd, field, value);
|
||||
else
|
||||
conds= newx Item_func_le(thd, field, value);
|
||||
if (unlikely((error= setup_conds(thd, this, dummy, &conds))))
|
||||
if (unlikely((error= setup_conds(thd, this, dummy, &conds, NULL))))
|
||||
return false;
|
||||
// FIXME: (performance) force index 'commit_timestamp'
|
||||
select= make_select(table, 0, 0, conds, NULL, 0, &error);
|
||||
|
||||
@@ -2608,6 +2608,7 @@ struct TABLE_LIST
|
||||
Item_in_subselect *jtbm_subselect;
|
||||
/* TODO: check if this can be joined with tablenr_exec */
|
||||
uint jtbm_table_no;
|
||||
uint ora_join_table_no;
|
||||
|
||||
SJ_MATERIALIZATION_INFO *sj_mat_info;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user