Commit c04786d3 authored by unknown's avatar unknown

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.
parent 76d65499
...@@ -4532,7 +4532,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) ...@@ -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); ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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); ...@@ -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 ); ...@@ -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) ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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() ...@@ -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() ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ class Item_subselect :public Item_result_field ...@@ -146,6 +146,11 @@ class Item_subselect :public Item_result_field
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 @@ class Item_singlerow_subselect :public Item_subselect ...@@ -262,6 +267,7 @@ class Item_singlerow_subselect :public Item_subselect
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 @@ class Item_maxmin_subselect :public Item_singlerow_subselect ...@@ -314,6 +320,7 @@ class Item_maxmin_subselect :public Item_singlerow_subselect
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 @@ class Item_exists_subselect :public Item_subselect ...@@ -335,6 +342,7 @@ class Item_exists_subselect :public Item_subselect
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 @@ class Item_allany_subselect :public Item_in_subselect ...@@ -664,6 +672,7 @@ class Item_allany_subselect :public Item_in_subselect
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() ...@@ -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() ...@@ -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() ...@@ -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() ...@@ -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 @@ class JOIN :public Sql_alloc ...@@ -1322,6 +1322,7 @@ class JOIN :public Sql_alloc
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
{ {
......
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