Skip to content

Commit 73ef86d

Browse files
committed
MDEV-29731 Assertion failure when HAVING in a correlated subquery references columns in the outer query
When resolving a column from the HAVING clause, a new Item_field object may be created inside Item_ref::fix_fields(). But the object is created with an empty name resolution context, which then leads to debug assertion failure during Item_field::fix_fields(). The solution is to pass the correct name resolution context when creating the Item_field object. Reviewer: Oleksandr Byelkin (sanja@mariadb.com)
1 parent bf5c251 commit 73ef86d

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

mysql-test/main/having.result

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,5 +904,54 @@ SELECT * FROM t HAVING f = 'foo';
904904
f
905905
DROP TABLE t;
906906
#
907+
# MDEV-29731 Crash when HAVING in a correlated subquery references
908+
# columns in the outer query
909+
#
910+
CREATE TABLE t (a INT, b INT);
911+
SELECT 1 FROM t
912+
WHERE b = (SELECT 1 FROM t GROUP BY a HAVING b = a+1);
913+
1
914+
DROP TABLE t;
915+
CREATE TABLE t (a INT, b INT, c INT);
916+
SELECT 1 FROM t
917+
WHERE (b,c) = (SELECT 1,1 FROM t GROUP BY a HAVING b = a+1 and c = a-1);
918+
1
919+
DROP TABLE t;
920+
CREATE TABLE t (a TEXT, b INT UNIQUE);
921+
SELECT 1 FROM t
922+
WHERE b IN (SELECT 1 FROM t
923+
GROUP BY '', a
924+
HAVING (CASE b WHEN 1 +'' THEN 3 ELSE a END)
925+
ORDER BY b)
926+
GROUP BY b HAVING b = 1;
927+
1
928+
Warnings:
929+
Warning 1292 Truncated incorrect DOUBLE value: ''
930+
DROP TABLE t;
931+
CREATE TABLE t (a INT, b CHAR KEY UNIQUE);
932+
CREATE VIEW v AS SELECT * FROM t WHERE a LIKE '' GROUP BY b HAVING a > a;
933+
SELECT * FROM v AS v1 NATURAL JOIN v AS v5 NATURAL JOIN v
934+
WHERE a LIKE '' AND b IN (SELECT a FROM t
935+
WHERE a LIKE ''
936+
GROUP BY a
937+
HAVING b LIKE (b < +1 OR a > 1) >= b);
938+
a b
939+
DROP VIEW v;
940+
DROP TABLE t;
941+
EXECUTE IMMEDIATE 'SELECT LEAD(c) OVER (ORDER BY c)
942+
FROM (SELECT 0 AS c) AS a NATURAL JOIN (SELECT 0 AS c) AS b;';
943+
LEAD(c) OVER (ORDER BY c)
944+
NULL
945+
CREATE TABLE t (a INT);
946+
UPDATE t SET a = ''
947+
WHERE 1 IN (SELECT * FROM
948+
(SELECT * FROM
949+
(SELECT * FROM t AS v5 NATURAL JOIN t AS v4 NATURAL JOIN t) AS v3
950+
NATURAL JOIN t
951+
GROUP BY a) AS v2
952+
WHERE (0, a) IN ((0,-1),(+1,0))
953+
ORDER BY 1+AVG(a) OVER (ORDER BY a)) ORDER BY a;
954+
DROP TABLE t;
955+
#
907956
# End of 10.4 tests
908957
#

mysql-test/main/having.test

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,53 @@ DROP TABLE t1,t2;
950950
CREATE TABLE t (f VARCHAR(512));
951951
INSERT INTO t VALUES ('a'),('b');
952952
SELECT * FROM t HAVING f = 'foo';
953+
DROP TABLE t;
954+
955+
--echo #
956+
--echo # MDEV-29731 Crash when HAVING in a correlated subquery references
957+
--echo # columns in the outer query
958+
--echo #
959+
CREATE TABLE t (a INT, b INT);
960+
SELECT 1 FROM t
961+
WHERE b = (SELECT 1 FROM t GROUP BY a HAVING b = a+1);
962+
DROP TABLE t;
963+
964+
CREATE TABLE t (a INT, b INT, c INT);
965+
SELECT 1 FROM t
966+
WHERE (b,c) = (SELECT 1,1 FROM t GROUP BY a HAVING b = a+1 and c = a-1);
967+
DROP TABLE t;
968+
969+
CREATE TABLE t (a TEXT, b INT UNIQUE);
970+
SELECT 1 FROM t
971+
WHERE b IN (SELECT 1 FROM t
972+
GROUP BY '', a
973+
HAVING (CASE b WHEN 1 +'' THEN 3 ELSE a END)
974+
ORDER BY b)
975+
GROUP BY b HAVING b = 1;
976+
DROP TABLE t;
977+
978+
CREATE TABLE t (a INT, b CHAR KEY UNIQUE);
979+
CREATE VIEW v AS SELECT * FROM t WHERE a LIKE '' GROUP BY b HAVING a > a;
980+
SELECT * FROM v AS v1 NATURAL JOIN v AS v5 NATURAL JOIN v
981+
WHERE a LIKE '' AND b IN (SELECT a FROM t
982+
WHERE a LIKE ''
983+
GROUP BY a
984+
HAVING b LIKE (b < +1 OR a > 1) >= b);
985+
DROP VIEW v;
986+
DROP TABLE t;
953987

954-
# Cleanup
988+
EXECUTE IMMEDIATE 'SELECT LEAD(c) OVER (ORDER BY c)
989+
FROM (SELECT 0 AS c) AS a NATURAL JOIN (SELECT 0 AS c) AS b;';
990+
991+
CREATE TABLE t (a INT);
992+
UPDATE t SET a = ''
993+
WHERE 1 IN (SELECT * FROM
994+
(SELECT * FROM
995+
(SELECT * FROM t AS v5 NATURAL JOIN t AS v4 NATURAL JOIN t) AS v3
996+
NATURAL JOIN t
997+
GROUP BY a) AS v2
998+
WHERE (0, a) IN ((0,-1),(+1,0))
999+
ORDER BY 1+AVG(a) OVER (ORDER BY a)) ORDER BY a;
9551000
DROP TABLE t;
9561001

9571002
--echo #

sql/item.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8041,7 +8041,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
80418041
if (from_field != not_found_field)
80428042
{
80438043
Item_field* fld;
8044-
if (!(fld= new (thd->mem_root) Item_field(thd, from_field)))
8044+
if (!(fld= new (thd->mem_root) Item_field(thd, context, from_field)))
80458045
goto error;
80468046
thd->change_item_tree(reference, fld);
80478047
mark_as_dependent(thd, last_checked_context->select_lex,

0 commit comments

Comments
 (0)