Assertion `0' failed in replace_where_subcondition with derived_merge and first execution of prepared statement

Bug #878753 reported by Philip Stoev
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
MariaDB
Fix Released
Undecided
Sergey Petrunia

Bug Description

This query:

SELECT *
FROM (
        SELECT *
        FROM t3
        WHERE t3.b <= 'c'
) AS alias1
RIGHT JOIN t1
ON t1.a = alias1.b
AND ( 6 ) IN (
        SELECT a
        FROM t2
)

crashes when executed with derived_merge=ON, semijoin=ON and prepared statement.

explain:

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
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables

optimizer switch: derived_merge=ON,semijoin=ON
full switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,index_condition_pushdown=off,derived_merge=on,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on

test case:

CREATE TABLE t1 ( a varchar(1)) ;

CREATE TABLE t2 ( a int(11), b int(11)) ;

CREATE TABLE t3 ( a int(11) NOT NULL , b varchar(1)) ;

SET SESSION optimizer_switch = 'derived_merge=on';
SET SESSION optimizer_switch = 'semijoin=on';

PREPARE st1 from "
SELECT *
FROM (
        SELECT *
        FROM t3
        WHERE t3.b <= 0
) AS alias1
RIGHT JOIN t1
ON t1.a = alias1.b
AND ( 6 ) IN (
        SELECT a
        FROM t2
)";
EXECUTE st1;

bzr version-info
revision-id: <email address hidden>
date: 2011-10-19 21:01:42 +0200
build-date: 2011-10-20 13:09:07 +0300
revno: 3242
branch-nick: maria-5.3

Changed in maria:
assignee: nobody → Sergey Petrunia (sergefp)
milestone: none → 5.3
Revision history for this message
Philip Stoev (pstoev-askmonty) wrote :

Also reproducible without a subquery in the ON clause. Let me know if you require such a testcase.

summary: Assertion `0' failed in replace_where_subcondition with derived_merge
- and subquery in the ON clause and prepared statement
+ and first execution of prepared statement
Revision history for this message
Philip Stoev (pstoev-askmonty) wrote :

Test case without subquery in the ON clause:

CREATE TABLE t1 ( b int(11)) ;

CREATE TABLE t2 (c int, b int, d varchar(52) NOT NULL ) ;

CREATE TABLE t3 (b int(11)) ;

SET SESSION optimizer_switch='semijoin=on,derived_merge=on';
PREPARE st1 FROM '
        SELECT * FROM t1
        JOIN (
                SELECT t2.* FROM t2
                WHERE t2.d <> "a"
                AND t2.c IN (
                        SELECT t3.b
                        FROM t3
                )
        ) AS alias2
        ON ( alias2.b = t1.b );
';
EXECUTE st1;

Changed in maria:
status: New → Confirmed
Revision history for this message
Sergey Petrunia (sergefp) wrote :

The crash happens inside convert_join_subqueries_to_semijoins(). replace_where_subcondition() throws an assert, because it was unable to locate the subquery item that it needs to replace.

Revision history for this message
Sergey Petrunia (sergefp) wrote :

The code goes like this:

    Item **tree= (in_subq->emb_on_expr_nest == NO_JOIN_NEST)?
                   &join->conds : &(in_subq->emb_on_expr_nest->on_expr);
    Item *replace_me= in_subq->original_item();
    if (replace_where_subcondition(join, tree, replace_me, substitute,
                                   do_fix_fields))
      DBUG_RETURN(TRUE);

    ...

    if (!thd->stmt_arena->is_conventional())
    {
      tree= (in_subq->emb_on_expr_nest == NO_JOIN_NEST)?
             &join->select_lex->prep_where :
             &(in_subq->emb_on_expr_nest->prep_on_expr);
      if (*tree && replace_where_subcondition(join, tree, replace_me, substitute,
                                     FALSE))
        DBUG_RETURN(TRUE);
    }

the assert happens inside the second invocation. We fail to replace Item_in_subselect in prep_on_expr, because prep_on_expr shares the "sub-item" that contains Item_in_subselect with on_expr.

First, we do [successfull] replace in on_expr, which also makes the replace in prep_on_expr.
Second, we attempt to do the replace in prep_on_expr, and that fails.

Changed in maria:
status: Confirmed → Fix Committed
Changed in maria:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.