Skip to content
/ server Public
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions mysql-test/main/having_cond_pushdown.result
Original file line number Diff line number Diff line change
Expand Up @@ -6090,4 +6090,135 @@ EXPLAIN
}
}
drop table t1, t2;
#
# MDEV-38819: Logic Inconsistency between Direct HAVING Query and Derived Table Relocation
#
CREATE TABLE t0(c0 INT, c1 INT UNIQUE);
CREATE TABLE t1(c0 VARCHAR(100), c1 INT UNIQUE);
INSERT INTO t1 VALUES ('C', -1833670268);
INSERT INTO t1 VALUES ('\\', 1046230419);
INSERT INTO t0 VALUES (500, -1016012686);
SELECT t1.c1 AS g0, t0.c0 AS g1, t0.c1 AS g2
FROM t1 STRAIGHT_JOIN t0
GROUP BY t1.c1, t0.c0, t0.c1
HAVING g2 NOT IN (g0, g0 != g1);
g0 g1 g2
-1833670268 500 -1016012686
1046230419 500 -1016012686
explain format=json SELECT t1.c1 AS g0, t0.c0 AS g1, t0.c1 AS g2
FROM t1 STRAIGHT_JOIN t0
GROUP BY t1.c1, t0.c0, t0.c1
HAVING g2 NOT IN (g0, g0 != g1);
EXPLAIN
{
"query_block": {
"select_id": 1,
"filesort": {
"sort_key": "t1.c1, t0.c0, t0.c1",
"temporary_table": {
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "index",
"key": "c1",
"key_length": "5",
"used_key_parts": ["c1"],
"rows": 2,
"filtered": 100,
"using_index": true
}
},
{
"range-checked-for-each-record": {
"keys": ["c1"],
"table": {
"table_name": "t0",
"access_type": "ALL",
"possible_keys": ["c1"],
"rows": 1,
"filtered": 100
}
}
}
]
}
}
}
}
SELECT g0, g1, g2
FROM (
SELECT t1.c1 AS g0, t0.c0 AS g1, t0.c1 AS g2,
t0.c1 NOT IN (t1.c1, t1.c1 != t0.c0) AS ref1
FROM t1 STRAIGHT_JOIN t0
GROUP BY t1.c1, t0.c0, t0.c1
) AS s
WHERE ref1;
g0 g1 g2
-1833670268 500 -1016012686
1046230419 500 -1016012686
explain format=json SELECT g0, g1, g2
FROM (
SELECT t1.c1 AS g0, t0.c0 AS g1, t0.c1 AS g2,
t0.c1 NOT IN (t1.c1, t1.c1 != t0.c0) AS ref1
FROM t1 STRAIGHT_JOIN t0
GROUP BY t1.c1, t0.c0, t0.c1
) AS s
WHERE ref1;
EXPLAIN
{
"query_block": {
"select_id": 1,
"nested_loop": [
{
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"rows": 2,
"filtered": 100,
"attached_condition": "s.ref1 <> 0",
"materialized": {
"query_block": {
"select_id": 2,
"filesort": {
"sort_key": "t1.c1, t0.c0, t0.c1",
"temporary_table": {
"nested_loop": [
{
"table": {
"table_name": "t1",
"access_type": "index",
"key": "c1",
"key_length": "5",
"used_key_parts": ["c1"],
"rows": 2,
"filtered": 100,
"using_index": true
}
},
{
"block-nl-join": {
"table": {
"table_name": "t0",
"access_type": "ALL",
"rows": 1,
"filtered": 100
},
"buffer_type": "flat",
"buffer_size": "65",
"join_type": "BNL",
"attached_condition": "t0.c1 not in (t1.c1,t1.c1 <> t0.c0) <> 0"
}
}
]
}
}
}
}
}
}
]
}
}
drop table t0, t1;
# End of 10.11 tests
33 changes: 33 additions & 0 deletions mysql-test/main/having_cond_pushdown.test
Original file line number Diff line number Diff line change
Expand Up @@ -1657,4 +1657,37 @@ execute stmt;

drop table t1, t2;

--echo #
--echo # MDEV-38819: Logic Inconsistency between Direct HAVING Query and Derived Table Relocation
--echo #

CREATE TABLE t0(c0 INT, c1 INT UNIQUE);
CREATE TABLE t1(c0 VARCHAR(100), c1 INT UNIQUE);
INSERT INTO t1 VALUES ('C', -1833670268);
INSERT INTO t1 VALUES ('\\', 1046230419);
INSERT INTO t0 VALUES (500, -1016012686);

let $q=
SELECT t1.c1 AS g0, t0.c0 AS g1, t0.c1 AS g2
FROM t1 STRAIGHT_JOIN t0
GROUP BY t1.c1, t0.c0, t0.c1
HAVING g2 NOT IN (g0, g0 != g1);
eval $q;
eval explain format=json $q;

let $q=
SELECT g0, g1, g2
FROM (
SELECT t1.c1 AS g0, t0.c0 AS g1, t0.c1 AS g2,
t0.c1 NOT IN (t1.c1, t1.c1 != t0.c0) AS ref1
FROM t1 STRAIGHT_JOIN t0
GROUP BY t1.c1, t0.c0, t0.c1
) AS s
WHERE ref1;

eval $q;
eval explain format=json $q;

drop table t0, t1;

--echo # End of 10.11 tests
11 changes: 7 additions & 4 deletions sql/sql_lex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11533,7 +11533,7 @@ Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having)
list of all its conjuncts saved in attach_to_conds. Otherwise,
the condition is put into attach_to_conds as the only its element.
*/
List_iterator_fast<Item> it(attach_to_conds);
List_iterator<Item> it(attach_to_conds);
Item *item;
check_cond_extraction_for_grouping_fields(thd, having);
if (build_pushable_cond_for_having_pushdown(thd, having))
Expand Down Expand Up @@ -11593,16 +11593,19 @@ Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having)
it.rewind();
while ((item=it++))
{
item= item->transform(thd,
&Item::field_transformer_for_having_pushdown,
(uchar *)this);
Item *cloned_item= item->deep_copy_with_checks(thd);
if (!cloned_item)
cloned_item= item;
item= cloned_item->transform(
thd, &Item::field_transformer_for_having_pushdown, (uchar *) this);

if (item->walk(&Item::cleanup_excluding_immutables_processor, 0, STOP_PTR)
|| item->fix_fields(thd, NULL))
{
attach_to_conds.empty();
goto exit;
}
it.replace(item);
}

/*
Expand Down