Skip to content

Commit

Permalink
MDEV-26247 Re-implement spider gbh query rewrite of tables
Browse files Browse the repository at this point in the history
Spider GBH's query rewrite of table joins is overly complex and
error-prone. We replace it with something closer to what
dbug_print() (more specifically, print_join()) does, but catered to
spider.

More specifically, we replace the body of
spider_db_mbase_util::append_from_and_tables() with a call to
spider_db_mbase_util::append_join(), and remove downstream append_X
functions.

We make it handle const tables by rewriting them as (select 1). This
fixes the main issue in MDEV-26247.

We also ban semijoin from spider gbh, which fixes MDEV-31645 and
MDEV-30392, as semi-join is an "internal" join, and "semi join" does
not parse, and it is different from "join" in that it deduplicates the
right hand side

Not all queries passed to a group by handler are valid (MDEV-32273),
for example, a join on expr may refer outer fields not in the current
context. We detect this during the handler creation when walking the
join. See also gbh_outer_fields_in_join.test.

It also skips eliminated tables, which fixes MDEV-26193.
  • Loading branch information
mariadb-YuchenPei committed Nov 17, 2023
1 parent 0bacef7 commit 1783965
Show file tree
Hide file tree
Showing 29 changed files with 770 additions and 526 deletions.
@@ -0,0 +1,50 @@
#
# MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064
#
for master_1
for child2
child2_1
child2_2
child2_3
for child3
connection child2_1;
CREATE DATABASE auto_test_remote;
USE auto_test_remote;
CREATE TABLE t1 (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE t2 (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE t3 (a int) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1), (2);
INSERT INTO t3 VALUES (1), (2), (3);
connection master_1;
CREATE DATABASE auto_test_local;
USE auto_test_local;
CREATE TABLE t1 (a int) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t1"';
CREATE TABLE t2 (a int) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t2"';
CREATE TABLE t3 (a int) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t3"';
select * from t3 left join t1 on t3.a = t1.a left join t2 on t3.a = t2.a;
a a a
1 1 1
2 NULL 2
3 NULL NULL
select * from t1 left join t2 on t1.a = t2.a right join t3 on t3.a = t1.a;
a a a
1 1 1
NULL NULL 2
NULL NULL 3
select * from t3 left join (t1 left join t2 on t1.a = t2.a) on t3.a = t1.a;
a a a
1 1 1
2 NULL NULL
3 NULL NULL
drop table t1, t2, t3;
connection master_1;
DROP DATABASE IF EXISTS auto_test_local;
connection child2_1;
DROP DATABASE IF EXISTS auto_test_remote;
for master_1
for child2
child2_1
child2_2
child2_3
for child3
2 changes: 2 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result
Expand Up @@ -72,6 +72,7 @@ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
select `pkey`,`val` from `auto_test_remote`.`tbl_a`
select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1
select 1 from (select 1) t0
select `pkey`,`val` from `auto_test_remote`.`tbl_a`
select `pkey`,`val` from `auto_test_remote`.`tbl_a`
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
Expand All @@ -85,6 +86,7 @@ argument
select `pkey`,`val` from `auto_test_remote2`.`tbl_a`
select `pkey`,`val` from `auto_test_remote2`.`tbl_a`
select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 2
select 1 from (select 1) t0
select `pkey`,`val` from `auto_test_remote2`.`tbl_a`
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
SELECT pkey, val FROM tbl_a ORDER BY pkey;
Expand Down
90 changes: 90 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/r/mdev_26247.result
@@ -0,0 +1,90 @@
#
# MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064
#
for master_1
for child2
child2_1
child2_2
child2_3
for child3
connection child2_1;
CREATE DATABASE auto_test_remote;
USE auto_test_remote;
CREATE TABLE t1 (
a11 int,
primary key (a11)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE t2 (
a21 int,
a22 int,
primary key (a21, a22)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE t3 (
a31 int,
a32 int,
primary key (a31, a32)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t1 VALUES (1), (2), (3);
INSERT INTO t2 VALUES (1, 11), (2, 22), (3, 33);
INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333);
connection master_1;
CREATE DATABASE auto_test_local;
USE auto_test_local;
CREATE TABLE t1 (
a11 int,
primary key (a11)
) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t1"';
CREATE TABLE t2 (
a21 int,
a22 int,
primary key (a21, a22)
) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t2"';
CREATE TABLE t3 (
a31 int,
a32 int,
primary key (a31, a32)
) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='srv "s_2_1", table "t3"';
SELECT a22 FROM t1 LEFT JOIN t2 ON a11 = a21 WHERE a11 IN (1);
a22
11
SELECT a22 FROM t1 LEFT JOIN t2 ON a11 = a21 - a21 WHERE a11 IN (1);
a22
NULL
SELECT a22 FROM t2 RIGHT JOIN t1 ON a21 = a11 WHERE a11 IN (1);
a22
11
SELECT a22 FROM t2 RIGHT JOIN t1 ON a21 = a11 WHERE a11 IN (1,2);
a22
11
22
SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 RIGHT JOIN t3 on a21 = a31 WHERE a11 IN (1);
a22 a32
11 111
SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 - a21 RIGHT JOIN t3 on a21 = a31 - a31 WHERE a11 IN (1);
a22 a32
SELECT a22, a32 FROM t1 LEFT JOIN t2 ON a11 = a21 RIGHT JOIN t3 on a21 = a31 WHERE a11 IN (1,2);
a22 a32
11 111
22 222
SELECT a22 FROM t2 LEFT JOIN t1 ON a11 = a21 WHERE a11 IN (1);
a22
11
SELECT a22 FROM t2 LEFT JOIN t1 ON a11 = a21 - a21 WHERE a11 IN (1);
a22
SELECT a22 FROM t1 RIGHT JOIN t2 ON a21 = a11 WHERE a11 IN (1);
a22
11
SELECT a22 FROM t1 RIGHT JOIN t2 ON a21 = a11 WHERE a11 IN (1,2);
a22
11
22
connection master_1;
DROP DATABASE IF EXISTS auto_test_local;
connection child2_1;
DROP DATABASE IF EXISTS auto_test_remote;
for master_1
for child2
child2_1
child2_2
child2_3
for child3
23 changes: 23 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/r/mdev_29163.result
@@ -0,0 +1,23 @@
#
# MDEV-29163 Server crash with SIGSEGV or dynamic-stack-buffer-overflow in spider_db_mbase_util::append_table
#
for master_1
for child2
for child3
CREATE SERVER s FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (b INT);
CREATE TABLE t3 (c INT, PRIMARY KEY(c));
CREATE TABLE t1_spider (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't1'";
CREATE TABLE t2_spider (b INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't2'";
CREATE TABLE t3_spider (c INT, PRIMARY KEY(c)) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 's', table 't3'";
SELECT t1_spider.* FROM t1_spider LEFT JOIN t2_spider LEFT JOIN t3_spider ON b = c ON a = b;
a
DROP TABLE t1_spider, t2_spider, t3_spider, t1, t2, t3;
drop server s;
for master_1
for child2
for child3
#
# end of test mdev_29163
#
22 changes: 22 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/r/mdev_30392.result
@@ -0,0 +1,22 @@
#
# MDEV-30392 Syntax error upon query with subquery from Spider table
#
for master_1
for child2
for child3
CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (a INT) ENGINE=SPIDER COMMENT = "wrapper 'mysql', srv 'srv', table 't1'";
SELECT a FROM t2 WHERE a IN ( SELECT a FROM t2 );
a
1
2
DROP TABLE t1, t2;
DROP SERVER srv;
for master_1
for child2
for child3
#
# end of test mdev_30392
#
22 changes: 22 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/r/mdev_31645.result
@@ -0,0 +1,22 @@
#
# MDEV-31645 Spider doesn't recognize semi JOIN
#
for master_1
for child2
for child3
CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
CREATE TABLE t1 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a));
CREATE TABLE t2 ( a bigint(20) NOT NULL, b bigint(20) DEFAULT 0, PRIMARY KEY (a)) ENGINE=SPIDER COMMENT='srv "srv", WRAPPER "mysql", TABLE "t1"';
SELECT * FROM t2 WHERE b IN (SELECT b FROM t2 WHERE a > 10);
a b
SELECT * FROM t2
WHERE A BETWEEN 0 AND 10 AND B IN(SELECT B FROM t2 WHERE A BETWEEN 11 AND 20);
a b
drop table t1, t2;
drop server srv;
for master_1
for child2
for child3
#
# end of test mdev_31645
#
@@ -0,0 +1,23 @@
#
# Test joining a spider table with a non-spider table
#
for master_1
for child2
for child3
CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t1 (c int);
create table t2 (d int);
insert into t2 values (1), (2);
create table t3 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"';
insert into t3 values (2), (3);
select c from t3 join t2 on c = d;
c
2
drop table t1, t2, t3;
drop server srv;
for master_1
for child2
for child3
#
# end of test spider_join_with_non_spider
#
24 changes: 24 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/r/subquery.result
@@ -0,0 +1,24 @@
#
# Test spider select with subqueries
#
for master_1
for child2
for child3
CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
create table t1 (c1 int);
create table t2 (c2 int);
insert into t1 values (1), (2);
insert into t2 values (0), (1), (2);
create table t1s (c1 int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"';
create table t2s (c2 int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
select c1 from t1s, (select c2 from t2s where c2 > 0) t where c1 + 1 = c2;
c1
1
drop table t1, t2, t1s, t2s;
drop server srv;
for master_1
for child2
for child3
#
# end of test subquery
#
@@ -0,0 +1,3 @@
!include include/default_mysqld.cnf
!include ../my_1_1.cnf
!include ../my_2_1.cnf
@@ -0,0 +1,46 @@
--echo #
--echo # MDEV-26247 Spider: Valid LEFT JOIN results in ERROR 1064
--echo #

--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log

--connection child2_1
CREATE DATABASE auto_test_remote;
USE auto_test_remote;

eval CREATE TABLE t1 (a int) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
eval CREATE TABLE t2 (a int) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
eval CREATE TABLE t3 (a int) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;

INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1), (2);
INSERT INTO t3 VALUES (1), (2), (3);

--connection master_1
CREATE DATABASE auto_test_local;
USE auto_test_local;

eval CREATE TABLE t1 (a int) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t1"';
eval CREATE TABLE t2 (a int) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t2"';
eval CREATE TABLE t3 (a int) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='srv "s_2_1", table "t3"';

select * from t3 left join t1 on t3.a = t1.a left join t2 on t3.a = t2.a;
select * from t1 left join t2 on t1.a = t2.a right join t3 on t3.a = t1.a;
select * from t3 left join (t1 left join t2 on t1.a = t2.a) on t3.a = t1.a;

drop table t1, t2, t3;

--connection master_1
DROP DATABASE IF EXISTS auto_test_local;
--connection child2_1
DROP DATABASE IF EXISTS auto_test_remote;

--disable_query_log
--disable_result_log
--source ../t/test_deinit.inc
--enable_query_log
--enable_result_log
3 changes: 3 additions & 0 deletions storage/spider/mysql-test/spider/bugfix/t/mdev_26247.cnf
@@ -0,0 +1,3 @@
!include include/default_mysqld.cnf
!include ../my_1_1.cnf
!include ../my_2_1.cnf

0 comments on commit 1783965

Please sign in to comment.