Skip to content

Commit 7158b81

Browse files
author
Dag Wanvik
committed
Bug#36079456 Assertion `having_cond->has_subquery() || !(having_cond->used_tables() & ~(1 | PSEUDO_TABLE_BITS))' failed.
Server exit not seen in production builds, although even those are not functioning correctly for this case. In transforming subqueries to derived tables (WL#12885), replacement of a subquery in a HAVING condition failed to use an Item_ref, instead using an Item_field. This leads to the assert seen cf. this quote in JOIN::add_having_as_tmp_table_cond: "Pushing parts of HAVING to an internal temporary table. Fields in HAVING condition may have been replaced with fields in an internal temporary table. This table has map=1. " For the above to work, the item replacing the subquery must be an item ref, so the slice system can do its thing: allowing the having condition to reference the temporary table, not the original derived table (which has a map entry of 4 in the simplified repro, not 1 as expected, hence the assert). The code did not correctly detect that the subquery was part of a HAVING condition. This is regression after commit ca2cd90bffb WL#9384: Prepare each DML statement once although due to another error it didn't manifest for the repro until later, in commit ca5275ff6e7 Bug#35060385 Item::update_used_tables should also update the PROP_SUBQUERY - for transforms Change-Id: Iaddce7fddd7e08ebbb6fb0e683f81fc1a00f0d89
1 parent 5c214df commit 7158b81

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

mysql-test/r/subquery_scalar_to_derived.result

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4870,4 +4870,25 @@ a MIN(f1)
48704870
NULL NULL
48714871
DROP TABLE t1;
48724872
SET SQL_MODE=default;
4873+
#
4874+
# Bug#36079456 Assertion `having_cond->has_subquery() ||
4875+
# !(having_cond->used_tables() & ~(1 | PSEUDO_TABLE_BITS))'
4876+
# failed.
4877+
CREATE TABLE t(i INT);
4878+
SELECT i FROM t
4879+
HAVING i <> ( SELECT MIN(i)
4880+
FROM t)
4881+
ORDER BY i;
4882+
i
4883+
EXPLAIN SELECT i FROM t
4884+
HAVING i <> ( SELECT MIN(i)
4885+
FROM t)
4886+
ORDER BY i;
4887+
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
4888+
1 PRIMARY t NULL ALL NULL NULL NULL NULL 1 100.00 Using temporary; Using filesort
4889+
1 PRIMARY <derived2> NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (hash join)
4890+
2 DERIVED t NULL ALL NULL NULL NULL NULL 1 100.00 NULL
4891+
Warnings:
4892+
Note 1003 /* select#1 */ select `test`.`t`.`i` AS `i` from `test`.`t` left join (/* select#2 */ select min(`test`.`t`.`i`) AS `MIN(i)` from `test`.`t`) `derived_1_2` on(true) where true having (`test`.`t`.`i` <> `derived_1_2`.`MIN(i)`) order by `test`.`t`.`i`
4893+
DROP TABLE t;
48734894
SET optimizer_switch='subquery_to_derived=default';

mysql-test/t/subquery_scalar_to_derived.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,4 +2549,21 @@ DROP TABLE t1;
25492549

25502550
SET SQL_MODE=default;
25512551

2552+
--echo #
2553+
--echo # Bug#36079456 Assertion `having_cond->has_subquery() ||
2554+
--echo # !(having_cond->used_tables() & ~(1 | PSEUDO_TABLE_BITS))'
2555+
--echo # failed.
2556+
CREATE TABLE t(i INT);
2557+
2558+
let $query=
2559+
SELECT i FROM t
2560+
HAVING i <> ( SELECT MIN(i)
2561+
FROM t)
2562+
ORDER BY i;
2563+
2564+
eval $query;
2565+
eval EXPLAIN $query;
2566+
2567+
DROP TABLE t;
2568+
25522569
SET optimizer_switch='subquery_to_derived=default';

sql/item_subselect.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3031,7 +3031,7 @@ Item *Item_singlerow_subselect::replace_scalar_subquery(uchar *arg) {
30313031
ref = info->m_outer_query_block->add_hidden_item(scalar_item);
30323032
}
30333033
Item *result;
3034-
if (query_expr()->place() == CTX_HAVING) {
3034+
if (place() == CTX_HAVING) {
30353035
result = new (mem_root)
30363036
Item_ref(&info->m_outer_query_block->context, ref, scalar_item->db_name,
30373037
scalar_item->table_name, scalar_item->field_name);

0 commit comments

Comments
 (0)