Bug #37896 | Assertion on entry of Item_in_subselect::exec on subquery with AND NOT | ||
---|---|---|---|
Submitted: | 5 Jul 2008 21:32 | Modified: | 20 Nov 2010 23:10 |
Reporter: | Philip Stoev | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S1 (Critical) |
Version: | 6.0 | OS: | Any |
Assigned to: | Timour Katchaounov | CPU Architecture: | Any |
Tags: | regression |
[5 Jul 2008 21:32]
Philip Stoev
[6 Jul 2008 6:16]
Philip Stoev
Here is a simplifed test case: CREATE TABLE t1 ( `pk` int(11) NOT NULL AUTO_INCREMENT, `date_key` date DEFAULT NULL, `varchar_key` varchar(5) DEFAULT NULL, PRIMARY KEY (`pk`), KEY `date_key` (`date_key`), KEY `varchar_key` (`varchar_key`) ); INSERT INTO t1 VALUES (1,'0000-00-00','ompky'); CREATE TABLE t2 ( `pk` int(11) NOT NULL AUTO_INCREMENT, `time_nokey` time DEFAULT NULL, PRIMARY KEY (`pk`) ); SELECT MIN(OUTR . `date_key` ) FROM t1 AS OUTR WHERE '0:17:31' IN ( SELECT INNR . `time_nokey` AS Y FROM t2 AS INNR ) OR ( OUTR . `varchar_key` < 'ifh' AND NOT OUTR . `varchar_key` <> 'o' );
[9 Jul 2008 16:11]
Philip Stoev
Setting to Open so that the bug verification team can check previous releases.
[21 Aug 2008 16:55]
Sergey Petrunya
The subquery in provided testcase cannot be run with semi-join. The problem is somewhere in materialization strategy code.
[13 Oct 2008 11:39]
Timour Katchaounov
The regression occurred between 6.0.3 and 6.0.4. The bug is not reproducible in 6.0.3, reproducible in 6.0.4.
[13 Oct 2008 11:41]
Timour Katchaounov
-- Simplified test case: set @@optimizer_switch='no_semijoin'; SELECT MIN(OUTR.date_key ) FROM t1 AS OUTR WHERE '0:17:31' IN (SELECT INNR.time_nokey AS Y FROM t2 AS INNR);
[13 Oct 2008 11:58]
Timour Katchaounov
Analysis: -------------------------------------------------------------------------------- (See code outline at the end of the explanation) The cause of the assertion failure is in the call of JOIN::optimize call to opt_sum_query. In this case opt_sum_query returns "1", which tells JOIN::optimize that the query can be computed without access to any table. Therefore JOIN::optimize sets tables_list == 0. There is a shortcut in JOIN::optimize that exits early in the optimization phase if all tables have been optimizer away. As a result, JOIN::optimize never calls setup_subquery_materialization() which actually creates/initializes a subselect_hash_sj_engine object for materialized subquery execution. At the same time, JOIN::execute still calls conds->val_int(), which in turn calls Item_in_subselect::exec() where we get the assertion failure because the "engine" for this item has never been changed to a subselect_hash_sj_engine. TODO: * What remains to be done is to fully analyze opt_sum_query(), and to * decide whether it legally returns "1" for this query, or not. If opt_sum_query is fine, then we need to add one extra early call to setup_subquery_materialization(). Otherwise fix opt_sum_query. This is an outline of the related code: JOIN::optimize { ..... conds = optimize_cond(conds, ...) * reduces the where clause to Item_in_optimizer(Item_in_subselect( '0:17:31' IN (SELECT INNR.time_nokey AS Y FROM t2 AS INNR)) ) * but doesn't detect that IN is FALSE because it is marked as expensive ..... // Since there is a MIN() function, we call: res= opt_sum_query(), res == 1 ...... table_list= 0 <<<=== set the list of FROM tables to empty ..... if (table_list == 0) return 0; <<<=== RETURN PREMATURELY ..... setup_subquery_materialization() <<<=== never called ..... } JOIN::exec() { ....... if (!tables_list && (tables || !select_lex->with_sum_func)) { ..... /* We have to test for 'conds' here as the WHERE may not be constant even if we don't have any tables for prepared statements or if conds uses something like 'rand()'. */ if (cond_value != Item::COND_FALSE && (!conds || conds->val_int()) && <<<=== Indirect call to (!having || having->val_int())) Item_in_subselect::exec ..... DBUG_VOID_RETURN; } }
[15 Oct 2008 13:50]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/56272 2694 Timour Katchaounov 2008-10-15 BUG#37896 Assertion on entry of Item_in_subselect::exec on subquery with AND NOT Problem: The assertion failure is due to a shortcut in JOIN::optimize where if opt_sum_query detects that: a) a MIN/MAX function can be computed and substituted by an index lookup, and b) the WHERE clause doesn't reference any table in the FROM clause, then it does constant substitution, sets JOIN::tables_list = 0, and returns. As a result JOIN::optimize never calls setup_subquery_materialization, and never creates the correct subselect_engine. JOIN::exec still needs to execute the table-independent WHERE clause to check whether there is any result at all. This is when the assertion detects this inconsistent state. Solution: Call setup_subquery_materialization after the call to opt_sum_query detected that (a) and (b) above hold true. Note: This fix makes the behavior the same as that of subquery execution via the IN=>EXISTS transformation, thus the same as that of 5.x. However, as BUG#40037 explains, this behavior is incorrect because MIN/MAX should return NULL, if the query result is empty. This problem is filed as a separate bug since it is not related to materialization and is present in older versions.
[17 Oct 2008 12:32]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/56466 2694 Timour Katchaounov 2008-10-17 BUG#37896 Assertion on entry of Item_in_subselect::exec on subquery with AND NOT Problem: The assertion failure is due to a shortcut in JOIN::optimize where if opt_sum_query detects that: a) a MIN/MAX function can be computed and substituted by an index lookup, and b) the WHERE clause doesn't reference any table in the FROM clause, then it does constant substitution, sets JOIN::tables_list = 0, and returns. As a result JOIN::optimize never calls setup_subquery_materialization, and never creates the correct subselect_engine. JOIN::exec still needs to execute the table-independent WHERE clause to check whether there is any result at all. This is when the assertion detects this inconsistent state. Solution: Call setup_subquery_materialization after the call to opt_sum_query detected that (a) and (b) above hold true. Note: This fix makes the behavior the same as that of subquery execution via the IN=>EXISTS transformation, thus the same as that of 5.x. However, as BUG#40037 explains, this behavior is incorrect because MIN/MAX should return NULL, if the query result is empty. This problem is filed as a separate bug since it is not related to materialization and is present in older versions.
[19 Nov 2008 12:56]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/59217 2700 Timour Katchaounov 2008-11-19 [merge] BUG#37896: Assertion on entry of Item_in_subselect::exec on subquery with AND NOT Merge with mysql-6.0-opt branch.
[29 Dec 2008 15:39]
Bugs System
Pushed into 6.0.10-alpha (revid:sergefp@mysql.com-20081229085854-ui755edl9x4xomen) (version source revid:sergefp@mysql.com-20081126143611-sh4x9pv9vmbnm00v) (merge vers: 6.0.9-alpha) (pib:6)
[7 Jan 2009 8:54]
Timour Katchaounov
Short comment for the ChangeLog: "Fixed a problem where an initialization procedure for materialized subquery execution wasn't called due to an early optimization of MIN/MAX queries." I hope the above is clear and compact.
[7 Jan 2009 20:02]
Paul DuBois
Noted in 6.0.10 changelog. An initialization procedure for materialized subquery execution was not called due to an early optimization of MIN()/MAX() queries.
[16 Aug 2010 6:40]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100816062819-bluwgdq8q4xysmlg) (version source revid:alik@sun.com-20100816062612-enatdwnv809iw3s9) (pib:20)
[13 Nov 2010 16:09]
Bugs System
Pushed into mysql-trunk 5.6.99-m5 (revid:alexander.nozdrin@oracle.com-20101113155825-czmva9kg4n31anmu) (version source revid:vasil.dimov@oracle.com-20100629074804-359l9m9gniauxr94) (merge vers: 5.6.99-m4) (pib:21)
[20 Nov 2010 23:10]
Paul DuBois
Noted in 5.6.1 changelog.
[23 Nov 2010 2:09]
Paul DuBois
Correction: No 5.6.1 changelog entry. Bug does not appear in any released 5.6.x version.