Bug #121028 Cardinality Check Granularity Error in subquery_to_derived

Submitted: 29 Jul 6:09 Modified: 31 Jul 11:48
Reporter: Jacob Ding Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S2 (Serious)
Version:9.7.1 OS:MacOS
Assigned to: CPU Architecture:ARM
Tags: logical-bug

[29 Jul 6:09] Jacob Ding
Description:
-- Root cause: When a correlated scalar subquery contains GROUP BY with multiple
-- columns, decorrelate_derived_scalar_subquery_pre (D31) adds a windowed COUNT
-- cardinality check. But this check counts rows PER GROUP BY GROUP, not PER
-- CORRELATION VALUE. With multi-column GROUP BY, each group has 1 row (COUNT=1,
-- passes check), but each correlation value may match multiple groups → multiple
-- rows returned → scalar subquery constraint violated silently.
--
-- source: sql_resolver.cc:8086-8097 (setup_counts_over_partitions) +
--         sql_resolver.cc:8257-8261 (build_reject_if)

How to repeat:
CREATE TABLE t0 (id INT PRIMARY KEY, c0 INT, c1 INT);
CREATE TABLE t1 (id INT PRIMARY KEY, c0 INT, c1 INT);
INSERT INTO t0 VALUES (1, 10, 100), (2, 20, 200), (3, 30, 300);
INSERT INTO t1 VALUES (1, 10, 1000), (2, 10, 3000), (3, 20, 2000), (4, 20, 4000), (5, 30, 5000);

-- Plan A (default — correct): ERROR 1242
SET SESSION optimizer_switch = 'default';
SELECT t0.c0,
       (SELECT SUM(t1.c1) FROM t1 WHERE t1.c0 = t0.c0 GROUP BY t1.c0, t1.c1) AS sq
FROM t0;
-- ERROR 1242: Subquery returns more than 1 row  ← CORRECT: scalar subquery violated

-- Plan B (s2d=on — BUG): returns 8 rows silently, no error
SET SESSION optimizer_switch = 'subquery_to_derived=on';
SELECT t0.c0,
       (SELECT SUM(t1.c1) FROM t1 WHERE t1.c0 = t0.c0 GROUP BY t1.c0, t1.c1) AS sq
FROM t0;
-- (10, 1000), (10, 3000), (20, 2000), (20, 4000), (30, 5000), (NULL, NULL), (10, 1000), (10, 3000)
-- WRONG: 8 rows returned, no error. Should error with 1242.
--
-- EXPLAIN shows reject_if is present but checks per-group, not per-correlation-value:
-- Filter: reject_if((derived_1_2.Name_exp_5 > 1))
-- The derived table groups by (t1.c0, t1.c1), so each group has COUNT=1 → passes check.
-- But c0=10 matches 2 groups → 2 rows → scalar subquery returns 2 rows → should be 1242.
[31 Jul 11:48] Chaithra Marsur Gopala Reddy
Hi Jacob Ding,

Thank you for the test case. Verified.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.038 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.