Fix bug lp:985667, MDEV-229
Analysis: The reason for the wrong result is the interaction between constant optimization (in this case 1-row table) and subquery optimization. - First the outer query is optimized, and 'make_join_statistics' finds that table t2 has one row, reads that row, and marks the whole table as constant. This also means that all fields of t2 are constant. - Next, we optimize the subquery in the end of the outer 'make_join_statistics'. The field 'f2' is considered constant, with value '3'. The subquery predicate is rewritten as the constant TRUE. - The outer query execution detects early that the whole query result is empty and calls 'return_zero_rows'. Since the query is with implicit grouping, we have to produce one row with special values for the aggregates (depending on each aggregate function), and NULL values for all non-aggregate fields. This function calls 'no_rows_in_result' to set each aggregate function to the default value when it aggregates over an empty result, and then calls 'send_data', which in turn evaluates each Item in the SELECT list. - When evaluation reaches the subquery predicate, it executes the subquery with field 'f2' having a constant value '3', and the subquery produces the incorrect result '7'. Solution: Implement Item::no_rows_in_result for all subquery predicates. In order to make this work, it is also needed to make all val_* methods of all subquery predicates respect the Item_subselect::forced_const flag. Otherwise subqueries are executed anyways, and override the default value set by no_rows_in_result with whatever result is produced from the subquery evaluation.
This commit is contained in:
parent
76d6549972
commit
c04786d3e3
@ -4532,7 +4532,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
|||||||
FROM t1
|
FROM t1
|
||||||
WHERE a = 230;
|
WHERE a = 230;
|
||||||
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
||||||
NULL 0
|
NULL NULL
|
||||||
DROP TABLE t1, st1, st2;
|
DROP TABLE t1, st1, st2;
|
||||||
#
|
#
|
||||||
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
||||||
@ -6004,5 +6004,46 @@ INSERT INTO t1 VALUES (1);
|
|||||||
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in
|
||||||
|
# main query and implicit grouping
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 int) engine=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (7),(8);
|
||||||
|
CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (3,'f');
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 NULL
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 1
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
drop table t1,t2;
|
||||||
# return optimizer switch changed in the beginning of this test
|
# return optimizer switch changed in the beginning of this test
|
||||||
set optimizer_switch=@subselect_tmp;
|
set optimizer_switch=@subselect_tmp;
|
||||||
|
@ -4534,7 +4534,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
|||||||
FROM t1
|
FROM t1
|
||||||
WHERE a = 230;
|
WHERE a = 230;
|
||||||
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
||||||
NULL 0
|
NULL NULL
|
||||||
DROP TABLE t1, st1, st2;
|
DROP TABLE t1, st1, st2;
|
||||||
#
|
#
|
||||||
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
||||||
@ -6003,6 +6003,47 @@ INSERT INTO t1 VALUES (1);
|
|||||||
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in
|
||||||
|
# main query and implicit grouping
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 int) engine=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (7),(8);
|
||||||
|
CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (3,'f');
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 NULL
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 1
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
drop table t1,t2;
|
||||||
# return optimizer switch changed in the beginning of this test
|
# return optimizer switch changed in the beginning of this test
|
||||||
set optimizer_switch=@subselect_tmp;
|
set optimizer_switch=@subselect_tmp;
|
||||||
set optimizer_switch=default;
|
set optimizer_switch=default;
|
||||||
|
@ -4530,7 +4530,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
|||||||
FROM t1
|
FROM t1
|
||||||
WHERE a = 230;
|
WHERE a = 230;
|
||||||
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
||||||
NULL 0
|
NULL NULL
|
||||||
DROP TABLE t1, st1, st2;
|
DROP TABLE t1, st1, st2;
|
||||||
#
|
#
|
||||||
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
||||||
@ -5999,6 +5999,47 @@ INSERT INTO t1 VALUES (1);
|
|||||||
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in
|
||||||
|
# main query and implicit grouping
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 int) engine=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (7),(8);
|
||||||
|
CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (3,'f');
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 NULL
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 1
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
drop table t1,t2;
|
||||||
# return optimizer switch changed in the beginning of this test
|
# return optimizer switch changed in the beginning of this test
|
||||||
set optimizer_switch=@subselect_tmp;
|
set optimizer_switch=@subselect_tmp;
|
||||||
set @optimizer_switch_for_subselect_test=null;
|
set @optimizer_switch_for_subselect_test=null;
|
||||||
|
@ -4538,7 +4538,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
|||||||
FROM t1
|
FROM t1
|
||||||
WHERE a = 230;
|
WHERE a = 230;
|
||||||
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
||||||
NULL 0
|
NULL NULL
|
||||||
DROP TABLE t1, st1, st2;
|
DROP TABLE t1, st1, st2;
|
||||||
#
|
#
|
||||||
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
||||||
@ -6010,6 +6010,47 @@ INSERT INTO t1 VALUES (1);
|
|||||||
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in
|
||||||
|
# main query and implicit grouping
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 int) engine=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (7),(8);
|
||||||
|
CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (3,'f');
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 NULL
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 1
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
drop table t1,t2;
|
||||||
# return optimizer switch changed in the beginning of this test
|
# return optimizer switch changed in the beginning of this test
|
||||||
set optimizer_switch=@subselect_tmp;
|
set optimizer_switch=@subselect_tmp;
|
||||||
set optimizer_switch=default;
|
set optimizer_switch=default;
|
||||||
|
@ -4530,7 +4530,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
|||||||
FROM t1
|
FROM t1
|
||||||
WHERE a = 230;
|
WHERE a = 230;
|
||||||
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b)
|
||||||
NULL 0
|
NULL NULL
|
||||||
DROP TABLE t1, st1, st2;
|
DROP TABLE t1, st1, st2;
|
||||||
#
|
#
|
||||||
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
# Bug #48709: Assertion failed in sql_select.cc:11782:
|
||||||
@ -5999,6 +5999,47 @@ INSERT INTO t1 VALUES (1);
|
|||||||
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in
|
||||||
|
# main query and implicit grouping
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (f1 int) engine=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (7),(8);
|
||||||
|
CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (3,'f');
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 NULL
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 1
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
COUNT(f1) f4
|
||||||
|
0 0
|
||||||
|
drop table t1,t2;
|
||||||
# return optimizer switch changed in the beginning of this test
|
# return optimizer switch changed in the beginning of this test
|
||||||
set optimizer_switch=@subselect_tmp;
|
set optimizer_switch=@subselect_tmp;
|
||||||
set @optimizer_switch_for_subselect_test=null;
|
set @optimizer_switch_for_subselect_test=null;
|
||||||
|
@ -5090,6 +5090,35 @@ SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 );
|
|||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in
|
||||||
|
--echo # main query and implicit grouping
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (f1 int) engine=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (7),(8);
|
||||||
|
|
||||||
|
CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (3,'f');
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
|
||||||
|
EXPLAIN
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3;
|
||||||
|
|
||||||
|
drop table t1,t2;
|
||||||
|
|
||||||
|
|
||||||
--echo # return optimizer switch changed in the beginning of this test
|
--echo # return optimizer switch changed in the beginning of this test
|
||||||
set optimizer_switch=@subselect_tmp;
|
set optimizer_switch=@subselect_tmp;
|
||||||
|
@ -889,6 +889,15 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_maxmin_subselect::no_rows_in_result()
|
||||||
|
{
|
||||||
|
value= 0;
|
||||||
|
null_value= 0;
|
||||||
|
was_values= 0;
|
||||||
|
make_const();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_singlerow_subselect::reset()
|
void Item_singlerow_subselect::reset()
|
||||||
{
|
{
|
||||||
Item_subselect::reset();
|
Item_subselect::reset();
|
||||||
@ -1084,6 +1093,8 @@ void Item_singlerow_subselect::bring_value()
|
|||||||
double Item_singlerow_subselect::val_real()
|
double Item_singlerow_subselect::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (forced_const)
|
||||||
|
return value->val_real();
|
||||||
if (!exec() && !value->null_value)
|
if (!exec() && !value->null_value)
|
||||||
{
|
{
|
||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
@ -1099,6 +1110,8 @@ double Item_singlerow_subselect::val_real()
|
|||||||
longlong Item_singlerow_subselect::val_int()
|
longlong Item_singlerow_subselect::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (forced_const)
|
||||||
|
return value->val_int();
|
||||||
if (!exec() && !value->null_value)
|
if (!exec() && !value->null_value)
|
||||||
{
|
{
|
||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
@ -1113,6 +1126,9 @@ longlong Item_singlerow_subselect::val_int()
|
|||||||
|
|
||||||
String *Item_singlerow_subselect::val_str(String *str)
|
String *Item_singlerow_subselect::val_str(String *str)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (forced_const)
|
||||||
|
return value->val_str(str);
|
||||||
if (!exec() && !value->null_value)
|
if (!exec() && !value->null_value)
|
||||||
{
|
{
|
||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
@ -1128,6 +1144,9 @@ String *Item_singlerow_subselect::val_str(String *str)
|
|||||||
|
|
||||||
my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (forced_const)
|
||||||
|
return value->val_decimal(decimal_value);
|
||||||
if (!exec() && !value->null_value)
|
if (!exec() && !value->null_value)
|
||||||
{
|
{
|
||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
@ -1143,6 +1162,9 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
|||||||
|
|
||||||
bool Item_singlerow_subselect::val_bool()
|
bool Item_singlerow_subselect::val_bool()
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
if (forced_const)
|
||||||
|
return value->val_bool();
|
||||||
if (!exec() && !value->null_value)
|
if (!exec() && !value->null_value)
|
||||||
{
|
{
|
||||||
null_value= FALSE;
|
null_value= FALSE;
|
||||||
@ -1312,10 +1334,17 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_exists_subselect::no_rows_in_result()
|
||||||
|
{
|
||||||
|
value= 0;
|
||||||
|
null_value= 0;
|
||||||
|
make_const();
|
||||||
|
}
|
||||||
|
|
||||||
double Item_exists_subselect::val_real()
|
double Item_exists_subselect::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
if (exec())
|
if (!forced_const && exec())
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
@ -1326,7 +1355,7 @@ double Item_exists_subselect::val_real()
|
|||||||
longlong Item_exists_subselect::val_int()
|
longlong Item_exists_subselect::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
if (exec())
|
if (!forced_const && exec())
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
@ -1351,7 +1380,7 @@ longlong Item_exists_subselect::val_int()
|
|||||||
String *Item_exists_subselect::val_str(String *str)
|
String *Item_exists_subselect::val_str(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
if (exec())
|
if (!forced_const && exec())
|
||||||
reset();
|
reset();
|
||||||
str->set((ulonglong)value,&my_charset_bin);
|
str->set((ulonglong)value,&my_charset_bin);
|
||||||
return str;
|
return str;
|
||||||
@ -1374,7 +1403,7 @@ String *Item_exists_subselect::val_str(String *str)
|
|||||||
my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
if (exec())
|
if (!forced_const && exec())
|
||||||
reset();
|
reset();
|
||||||
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
|
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
|
||||||
return decimal_value;
|
return decimal_value;
|
||||||
@ -1384,7 +1413,7 @@ my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
|
|||||||
bool Item_exists_subselect::val_bool()
|
bool Item_exists_subselect::val_bool()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
if (exec())
|
if (!forced_const && exec())
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
return 0;
|
return 0;
|
||||||
@ -2649,6 +2678,15 @@ void Item_allany_subselect::print(String *str, enum_query_type query_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_allany_subselect::no_rows_in_result()
|
||||||
|
{
|
||||||
|
value= 0;
|
||||||
|
null_value= 0;
|
||||||
|
was_null= 0;
|
||||||
|
make_const();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void subselect_engine::set_thd(THD *thd_arg)
|
void subselect_engine::set_thd(THD *thd_arg)
|
||||||
{
|
{
|
||||||
thd= thd_arg;
|
thd= thd_arg;
|
||||||
|
@ -146,6 +146,11 @@ public:
|
|||||||
eliminated= FALSE;
|
eliminated= FALSE;
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
Set the subquery result to the default value for the predicate when the
|
||||||
|
subquery is known to produce an empty result.
|
||||||
|
*/
|
||||||
|
void no_rows_in_result()= 0;
|
||||||
virtual bool select_transformer(JOIN *join);
|
virtual bool select_transformer(JOIN *join);
|
||||||
bool assigned() { return value_assigned; }
|
bool assigned() { return value_assigned; }
|
||||||
void assigned(bool a) { value_assigned= a; }
|
void assigned(bool a) { value_assigned= a; }
|
||||||
@ -262,6 +267,7 @@ public:
|
|||||||
subs_type substype() { return SINGLEROW_SUBS; }
|
subs_type substype() { return SINGLEROW_SUBS; }
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
void no_rows_in_result() { reset(); make_const(); }
|
||||||
bool select_transformer(JOIN *join);
|
bool select_transformer(JOIN *join);
|
||||||
void store(uint i, Item* item);
|
void store(uint i, Item* item);
|
||||||
double val_real();
|
double val_real();
|
||||||
@ -314,6 +320,7 @@ public:
|
|||||||
bool any_value() { return was_values; }
|
bool any_value() { return was_values; }
|
||||||
void register_value() { was_values= TRUE; }
|
void register_value() { was_values= TRUE; }
|
||||||
void reset_value_registration() { was_values= FALSE; }
|
void reset_value_registration() { was_values= FALSE; }
|
||||||
|
void no_rows_in_result();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* exists subselect */
|
/* exists subselect */
|
||||||
@ -335,6 +342,7 @@ public:
|
|||||||
eliminated= FALSE;
|
eliminated= FALSE;
|
||||||
value= 0;
|
value= 0;
|
||||||
}
|
}
|
||||||
|
void no_rows_in_result();
|
||||||
|
|
||||||
enum Item_result result_type() const { return INT_RESULT;}
|
enum Item_result result_type() const { return INT_RESULT;}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
@ -664,6 +672,7 @@ public:
|
|||||||
virtual void print(String *str, enum_query_type query_type);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
bool is_maxmin_applicable(JOIN *join);
|
bool is_maxmin_applicable(JOIN *join);
|
||||||
bool transform_into_max_min(JOIN *join);
|
bool transform_into_max_min(JOIN *join);
|
||||||
|
void no_rows_in_result();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -5450,8 +5450,8 @@ bool JOIN::choose_tableless_subquery_plan()
|
|||||||
/*
|
/*
|
||||||
If the optimizer determined that his query has an empty result,
|
If the optimizer determined that his query has an empty result,
|
||||||
in most cases the subquery predicate is a known constant value -
|
in most cases the subquery predicate is a known constant value -
|
||||||
either FALSE or NULL. The implementation of Item_subselect::reset()
|
either of TRUE, FALSE or NULL. The implementation of
|
||||||
determines which one.
|
Item_subselect::no_rows_in_result() determines which one.
|
||||||
*/
|
*/
|
||||||
if (zero_result_cause)
|
if (zero_result_cause)
|
||||||
{
|
{
|
||||||
@ -5459,14 +5459,13 @@ bool JOIN::choose_tableless_subquery_plan()
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Both group by queries and non-group by queries without aggregate
|
Both group by queries and non-group by queries without aggregate
|
||||||
functions produce empty subquery result.
|
functions produce empty subquery result. There is no need to further
|
||||||
|
rewrite the subquery because it will not be executed at all.
|
||||||
*/
|
*/
|
||||||
subs_predicate->reset();
|
|
||||||
subs_predicate->make_const();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO:
|
/* @todo
|
||||||
A further optimization is possible when a non-group query with
|
A further optimization is possible when a non-group query with
|
||||||
MIN/MAX/COUNT is optimized by opt_sum_query. Then, if there are
|
MIN/MAX/COUNT is optimized by opt_sum_query. Then, if there are
|
||||||
only MIN/MAX functions over an empty result set, the subquery
|
only MIN/MAX functions over an empty result set, the subquery
|
||||||
|
@ -3115,6 +3115,11 @@ bool st_select_lex::optimize_unflattened_subqueries()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool empty_union_result= true;
|
||||||
|
/*
|
||||||
|
If the subquery is a UNION, optimize all the subqueries in the UNION. If
|
||||||
|
there is no UNION, then the loop will execute once for the subquery.
|
||||||
|
*/
|
||||||
for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select())
|
for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
JOIN *inner_join= sl->join;
|
JOIN *inner_join= sl->join;
|
||||||
@ -3137,9 +3142,19 @@ bool st_select_lex::optimize_unflattened_subqueries()
|
|||||||
res= inner_join->optimize();
|
res= inner_join->optimize();
|
||||||
inner_join->select_options= save_options;
|
inner_join->select_options= save_options;
|
||||||
un->thd->lex->current_select= save_select;
|
un->thd->lex->current_select= save_select;
|
||||||
|
if (empty_union_result)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If at least one subquery in a union is non-empty, the UNION result
|
||||||
|
is non-empty. If there is no UNION, the only subquery is non-empy.
|
||||||
|
*/
|
||||||
|
empty_union_result= inner_join->empty_result();
|
||||||
|
}
|
||||||
if (res)
|
if (res)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
if (empty_union_result)
|
||||||
|
subquery_predicate->no_rows_in_result();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1322,6 +1322,7 @@ public:
|
|||||||
return (do_send_rows && implicit_grouping && !group_optimized_away &&
|
return (do_send_rows && implicit_grouping && !group_optimized_away &&
|
||||||
having_value != Item::COND_FALSE);
|
having_value != Item::COND_FALSE);
|
||||||
}
|
}
|
||||||
|
bool empty_result() { return (zero_result_cause && !implicit_grouping); }
|
||||||
bool change_result(select_result *result);
|
bool change_result(select_result *result);
|
||||||
bool is_top_level_join() const
|
bool is_top_level_join() const
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user