mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
Fix bug lp:777691
Analysis: For some of the re-executions of the correlated subquery the where clause is false. In these cases the execution of the subquery detects that it must generate a NULL row because of implicit grouping. In this case the subquery execution reaches the following code in do_select(): while ((table= li++)) mark_as_null_row(table->table); This code marks all rows in the table as complete NULL rows. In the example, when evaluating the field t2.f10 for the second row, all bits of Field::null_ptr[0] are set by the previous call to mark_as_null_row(). Then the call to Field::is_null() returns true, resulting in a NULL for the MAX function. Thus the lines above are not suitable for subquery re-execution because mark_as_null_row() changes the NULL bits of each table field, and there is no logic to restore these fields. Solution: The call to mark_as_null_row() was added by the fix for bug lp:613029. Therefore removing the fix for lp:613029 corrects this wrong result. At the same time the test for lp:613029 behaves correctly because the changes of MWL#89 result in a different execution path where: - the constant subquery is evaluated via JOIN::exec_const_cond - detecting that it has an empty result triggers the branch if (zero_result_cause) return_zero_rows() - return_zero_rows() calls mark_as_null_row().
This commit is contained in:
parent
c4097382ef
commit
53681ee5db
3 changed files with 82 additions and 8 deletions
|
@ -1190,6 +1190,54 @@ set @@optimizer_switch='materialization=off,semijoin=on';
|
|||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# LP BUG#777691 Wrong result with subqery in select list and subquery cache=off in maria-5.3
|
||||
#
|
||||
CREATE TABLE t1 ( f1 varchar(32)) ;
|
||||
INSERT INTO t1 VALUES ('b'),('x'),('c'),('x');
|
||||
CREATE TABLE t2 ( f2 int, f3 varchar(32)) ;
|
||||
INSERT INTO t2 VALUES (1,'x');
|
||||
set @save_optimizer_switch=@@optimizer_switch;
|
||||
set @@optimizer_switch='materialization=off,in_to_exists=on,subquery_cache=off';
|
||||
EXPLAIN
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
|
||||
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
f1 max_f2
|
||||
b NULL
|
||||
x 1
|
||||
c NULL
|
||||
x 1
|
||||
set @@optimizer_switch='materialization=on,in_to_exists=off,subquery_cache=off';
|
||||
EXPLAIN
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
|
||||
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
f1 max_f2
|
||||
b NULL
|
||||
x 1
|
||||
c NULL
|
||||
x 1
|
||||
set @@optimizer_switch='materialization=off,in_to_exists=on,subquery_cache=off';
|
||||
Even when t2 is not constant table, the result must be the same.
|
||||
INSERT INTO t2 VALUES (2,'y');
|
||||
EXPLAIN
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
|
||||
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
f1 max_f2
|
||||
b NULL
|
||||
x 1
|
||||
c NULL
|
||||
x 1
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# LP BUG#641203 Query returns rows where no result is expected (impossible WHERE)
|
||||
#
|
||||
CREATE TABLE t1 (c1 varchar(1) DEFAULT NULL);
|
||||
|
|
|
@ -964,6 +964,40 @@ WHERE (t2.pk = t1.pk) AND t2.pk IN (SELECT f2 FROM t1);
|
|||
-- echo set @@optimizer_switch='materialization=off,semijoin=on';
|
||||
|
||||
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
|
||||
drop table t1, t2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # LP BUG#777691 Wrong result with subqery in select list and subquery cache=off in maria-5.3
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 ( f1 varchar(32)) ;
|
||||
INSERT INTO t1 VALUES ('b'),('x'),('c'),('x');
|
||||
|
||||
CREATE TABLE t2 ( f2 int, f3 varchar(32)) ;
|
||||
INSERT INTO t2 VALUES (1,'x');
|
||||
|
||||
set @save_optimizer_switch=@@optimizer_switch;
|
||||
set @@optimizer_switch='materialization=off,in_to_exists=on,subquery_cache=off';
|
||||
|
||||
EXPLAIN
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
|
||||
set @@optimizer_switch='materialization=on,in_to_exists=off,subquery_cache=off';
|
||||
EXPLAIN
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
|
||||
set @@optimizer_switch='materialization=off,in_to_exists=on,subquery_cache=off';
|
||||
--echo Even when t2 is not constant table, the result must be the same.
|
||||
INSERT INTO t2 VALUES (2,'y');
|
||||
EXPLAIN
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
SELECT t1.f1, ( SELECT MAX( f2 ) FROM t2 WHERE t2.f3 = t1.f1 ) as max_f2 FROM t1;
|
||||
|
||||
set @@optimizer_switch=@save_optimizer_switch;
|
||||
|
||||
drop table t1, t2;
|
||||
|
|
|
@ -14651,14 +14651,6 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
|||
{
|
||||
List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
|
||||
fields);
|
||||
/*
|
||||
With implicit grouping all fields of special row produced for an
|
||||
empty result are NULL. See return_zero_rows() for the same behavior.
|
||||
*/
|
||||
TABLE_LIST *table;
|
||||
List_iterator_fast<TABLE_LIST> li(join->select_lex->leaf_tables);
|
||||
while ((table= li++))
|
||||
mark_as_null_row(table->table);
|
||||
rc= join->result->send_data(*columns_list) > 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue