diff options
author | Igor Babaev <igor@askmonty.org> | 2012-02-24 16:50:22 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-02-24 16:50:22 -0800 |
commit | 841a74a4d6ebdaa2760ce615e7fc18f57100ee19 (patch) | |
tree | f3a656b6c3262d7a6b0847b0820848ad685480b0 /mysql-test/r/subselect_mat.result | |
parent | 567d871ff0c9cbdcaa4f9daa6810760edc901e14 (diff) | |
download | mariadb-git-841a74a4d6ebdaa2760ce615e7fc18f57100ee19.tar.gz |
Fixed LP bug #939009.
The result of materialization of the right part of an IN subquery predicate
is placed into a temporary table. Each row of the materialized table is
distinct. A unique key over all fields of the temporary table is defined and
created. It allows to perform key look-ups into the table.
The table created for a materialized subquery can be accessed by key as
any other table. The function best_access-path search for the best access
to join a table to a given partial join. With some where conditions this
function considers a possibility of a ref_or_null access. If such access
employs the unique key on the temporary table then when estimating
the cost this access the function tries to use the array rec_per_key. Yet,
such array is not built for this unique key. This causes a crash of the server.
Rows returned by the subquery that contain nulls don't have to be placed
into temporary table, as they cannot be match any row produced by the
left part of the subquery predicate. So all fields of the temporary table
can be defined as non-nullable. In this case any ref_or_null access
to the temporary table does not make any sense and it does not make sense
to estimate such an access.
The fix makes sure that the temporary table for a materialized IN subquery
is defined with columns that are all non-nullable. The also ensures that
any row with nulls returned by the subquery is not placed into the
temporary table.
Diffstat (limited to 'mysql-test/r/subselect_mat.result')
-rw-r--r-- | mysql-test/r/subselect_mat.result | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index 4d02e5012e2..baf7e379882 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -1473,7 +1473,7 @@ SET @@optimizer_switch='semijoin=on,materialization=on'; EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 -1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t2 range PRIMARY PRIMARY 4 NULL 2 Using index condition; Rowid-ordered scan SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); pk @@ -1861,6 +1861,39 @@ WHERE 'condition'='impossible' MIN(a) NULL DROP TABLE t1; +# +# BUG#939009: Crash with aggregate function in IN subquery +# +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='materialization=on,semijoin=on'; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (7,1), (4,2), (7,7); +CREATE TABLE t2 ( c INT ); +INSERT INTO t2 VALUES (4), (7), (6); +EXPLAIN EXTENDED +SELECT * FROM t1 +WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where ((`test`.`t1`.`a` = `<subquery2>`.`MAX(c)`) and (`test`.`t1`.`b` = 7) and (isnull(`<subquery2>`.`MAX(c)`) or (`<subquery2>`.`MAX(c)` = 7))) +SELECT * FROM t1 +WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); +a b +EXPLAIN +SELECT * FROM t1 +WHERE a IN (SELECT MAX(c) FROM t2 WHERE c < 4) AND b=7 AND (a IS NULL OR a=b); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where +SELECT * FROM t1 +WHERE a IN (SELECT MAX(c) FROM t2 WHERE c < 4) AND b=7 AND (a IS NULL OR a=b); +a b +SET optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t2; # This must be at the end: set optimizer_switch=@subselect_sj_mat_tmp; set join_cache_level=@save_join_cache_level; @@ -1983,7 +2016,7 @@ SET @@optimizer_switch='default,semijoin=on,materialization=on'; EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 -1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t2 range PRIMARY PRIMARY 4 NULL 2 Using index condition SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0); pk |