Commit 0185ac64 authored by Dave Gosselin's avatar Dave Gosselin Committed by Dave Gosselin

MDEV-30975 Wrong result with cross Join given join order

For queries with derived tables populated having some side-effect, we
will fill such a derived table more than once, but without clearing
its rows.  Consequently it will have duplicate rows.
An example query exhibiting the problem is
  SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @A := 0) x;
Since mysql_derived_fill will, for UNCACHEABLE_DEPENDENT tables, drop
all rows and repopulate, we relax the condition at line 1204: rather
than assume all uncacheable values prevent early return, we now
allow an early return for uncacheable values other than
UNCACHEABLE_DEPENDENT.  In general, we only populate derived tables
once unless they're dependent tables.
parent 85517f60
...@@ -3423,6 +3423,62 @@ SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2. ...@@ -3423,6 +3423,62 @@ SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.
COUNT(*) COUNT(*)
2 2
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
#
# MDEV-30975: Wrong result with cross Join given join order
#
CREATE TABLE `t1` (
`t1_seq` INT NOT NULL,
`c1` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`t1_seq`) USING BTREE
);
CREATE TABLE `t2` (
`t2_seq` INT NOT NULL,
`t1_seq` INT NOT NULL,
`c2` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`t2_seq`, `t1_seq`) USING BTREE
);
INSERT INTO t1 VALUES(1, 'A');
INSERT INTO t2 VALUES(1, 1, 'T2-1-1');
INSERT INTO t2 VALUES(2, 1, 'T2-1-2');
INSERT INTO t2 VALUES(3, 1, 'T2-1-3');
SELECT LPAD(@rownum := @rownum + 1, 8, 0) AS str_num
, t1.t1_seq
, t2.t2_seq
, t1.c1
, t2.c2
FROM t1
INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq)
CROSS JOIN ( SELECT @rownum := 0 ) X;
str_num t1_seq t2_seq c1 c2
00000001 1 1 A T2-1-1
00000002 1 2 A T2-1-2
00000003 1 3 A T2-1-3
SELECT STRAIGHT_JOIN LPAD(@rownum := @rownum + 1, 8, 0) AS str_num
, t1.t1_seq
, t2.t2_seq
, t1.c1
, t2.c2
FROM t1
INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq)
CROSS JOIN ( SELECT @rownum := 0 ) X;
str_num t1_seq t2_seq c1 c2
00000001 1 1 A T2-1-1
00000002 1 2 A T2-1-2
00000003 1 3 A T2-1-3
SELECT STRAIGHT_JOIN * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x;
t1_seq c1 t2_seq t1_seq c2 @a := 0
1 A 1 1 T2-1-1 0
1 A 2 1 T2-1-2 0
1 A 3 1 T2-1-3 0
SELECT * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x;
t1_seq c1 t2_seq t1_seq c2 @a := 0
1 A 1 1 T2-1-1 0
1 A 2 1 T2-1-2 0
1 A 3 1 T2-1-3 0
SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x;
c1
A
DROP TABLE t1, t2;
# End of 10.5 tests # End of 10.5 tests
# #
# MDEV-31449: Assertion s->table->opt_range_condition_rows <= s->found_records # MDEV-31449: Assertion s->table->opt_range_condition_rows <= s->found_records
......
...@@ -1838,6 +1838,52 @@ SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b; ...@@ -1838,6 +1838,52 @@ SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b;
SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b; SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b;
DROP TABLE t1, t2, t3; DROP TABLE t1, t2, t3;
--echo #
--echo # MDEV-30975: Wrong result with cross Join given join order
--echo #
CREATE TABLE `t1` (
`t1_seq` INT NOT NULL,
`c1` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`t1_seq`) USING BTREE
);
CREATE TABLE `t2` (
`t2_seq` INT NOT NULL,
`t1_seq` INT NOT NULL,
`c2` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`t2_seq`, `t1_seq`) USING BTREE
);
INSERT INTO t1 VALUES(1, 'A');
INSERT INTO t2 VALUES(1, 1, 'T2-1-1');
INSERT INTO t2 VALUES(2, 1, 'T2-1-2');
INSERT INTO t2 VALUES(3, 1, 'T2-1-3');
SELECT LPAD(@rownum := @rownum + 1, 8, 0) AS str_num
, t1.t1_seq
, t2.t2_seq
, t1.c1
, t2.c2
FROM t1
INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq)
CROSS JOIN ( SELECT @rownum := 0 ) X;
SELECT STRAIGHT_JOIN LPAD(@rownum := @rownum + 1, 8, 0) AS str_num
, t1.t1_seq
, t2.t2_seq
, t1.c1
, t2.c2
FROM t1
INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq)
CROSS JOIN ( SELECT @rownum := 0 ) X;
SELECT STRAIGHT_JOIN * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x;
SELECT * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x;
SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x;
DROP TABLE t1, t2;
--echo # End of 10.5 tests --echo # End of 10.5 tests
--echo # --echo #
......
...@@ -1201,8 +1201,12 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) ...@@ -1201,8 +1201,12 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
(derived->alias.str ? derived->alias.str : "<NULL>"), (derived->alias.str ? derived->alias.str : "<NULL>"),
derived->get_unit())); derived->get_unit()));
if (unit->executed && !unit->uncacheable && !unit->describe && /*
!derived_is_recursive) Only fill derived tables once, unless the derived table is dependent in
which case we will delete all of its rows and refill it below.
*/
if (unit->executed && !(unit->uncacheable & UNCACHEABLE_DEPENDENT) &&
!unit->describe && !derived_is_recursive)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
/*check that table creation passed without problems. */ /*check that table creation passed without problems. */
DBUG_ASSERT(derived->table && derived->table->is_created()); DBUG_ASSERT(derived->table && derived->table->is_created());
...@@ -1261,6 +1265,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) ...@@ -1261,6 +1265,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived)
} }
else else
{ {
DBUG_ASSERT(!unit->executed || (unit->uncacheable & UNCACHEABLE_DEPENDENT));
SELECT_LEX *first_select= unit->first_select(); SELECT_LEX *first_select= unit->first_select();
unit->set_limit(unit->global_parameters()); unit->set_limit(unit->global_parameters());
if (unit->lim.is_unlimited()) if (unit->lim.is_unlimited())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment