Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Duplicate
-
12.3.2
-
None
-
Not for Release Notes
Description
Summary
Wrong result: MAKE_SET() on inner table of LEFT JOIN wrongly rejects NULL-complemented rows
Description
MAKE_SET(1, NULL) returns a non-NULL empty string (MAKE_SET(1, NULL) IS NOT NULL is true).
A WHERE predicate MAKE_SET(1, inner_col) IS NOT NULL (or other predicates that are true for that empty string) must not null-reject outer-join NULL-complemented rows.
On MariaDB 12.3.2, placing that predicate in WHERE drops the NULL-extended LEFT JOIN row, while evaluating the same predicate in the SELECT list (or filtering it in an outer subquery) keeps the row. This is incorrect outer→inner join simplification when not_null_tables() is wrong for a function that does not return SQL NULL on NULL input.
How to repeat
CREATE TABLE t1 (a INT, b INT); |
INSERT INTO t1 VALUES (1,1),(2,3); |
|
|
-- Semantics
|
SELECT MAKE_SET(1, NULL) IS NOT NULL; -- 1 |
|
|
-- SELECT-list: NULL-extended row satisfies the predicate
|
SELECT t1.a, t2.b, MAKE_SET(1, t2.b) IS NOT NULL AS p |
FROM t1 LEFT JOIN t1 t2 ON t1.a = t2.b; |
-- 1 | 1 | 1
|
-- 2 | NULL | 1
|
|
|
-- WHERE: same predicate wrongly drops the NULL-extended row
|
SELECT COUNT(*) AS c_where |
FROM t1 LEFT JOIN t1 t2 ON t1.a = t2.b |
WHERE MAKE_SET(1, t2.b) IS NOT NULL; |
-- Actual: 1
|
-- Expected: 2
|
|
|
-- Equivalent filter outside the join (oracle)
|
SELECT COUNT(*) AS c_subq FROM ( |
SELECT t1.a, MAKE_SET(1, t2.b) IS NOT NULL AS p |
FROM t1 LEFT JOIN t1 t2 ON t1.a = t2.b |
) s WHERE p; |
-- Actual: 2
|
-- Expected: 2
|
|
|
DROP TABLE t1; |
Alternate form:
CREATE TABLE t1 (c1 INT); |
INSERT INTO t1 VALUES (1); |
|
|
SELECT ref_1.c1, |
(MAKE_SET(1, BIN(ref_1.c1), BIN(ref_1.c1)) NOT LIKE '%_6') AS w_1 |
FROM t1 AS ref_1 RIGHT JOIN t1 AS ref_2 ON FALSE; |
-- Returns 1 row: (NULL, 1)
|
|
|
SELECT ref_1.c1, |
(MAKE_SET(1, BIN(ref_1.c1), BIN(ref_1.c1)) NOT LIKE '%_6') AS w_1 |
FROM t1 AS ref_1 RIGHT JOIN t1 AS ref_2 ON FALSE |
WHERE (MAKE_SET(1, BIN(ref_1.c1), BIN(ref_1.c1)) NOT LIKE '%_6'); |
-- Actual: empty set
|
-- Expected: 1 row (NULL, 1)
|
|
|
DROP TABLE t1; |
Observed on: 12.3.2-MariaDB
Actual result
- LEFT JOIN + WHERE MAKE_SET(1, t2.b) IS NOT NULL → COUNT
= 1 - RIGHT JOIN ON FALSE + same-style WHERE → empty set
Expected result
- LEFT JOIN form → COUNT
= 2 - RIGHT JOIN ON FALSE form → 1 row (NULL, 1), matching the query without WHERE
Environment
- MariaDB 12.3.2
- InnoDB, default sql_mode
Attachments
Issue Links
- duplicates
-
MDEV-40863 CHAR() on inner table of LEFT JOIN wrongly converts outer join to inner join
-
- Confirmed
-