Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Major
-
Resolution: Unresolved
-
11.4, 11.8, 12.3, 13.1, 12.3.2
-
Operating system:
- Ubuntu 20.04.6 LTS (Focal Fossa)
- Linux kernel: 5.4.0-204-generic
- Architecture: x86_64
Hardware:
- CPU: 2 × Intel Xeon Gold 5218R @ 2.10 GHz
- 40 physical cores / 80 logical CPUs
Description
-
-
- Problem Description
With `optimizer_switch='derived_merge=off'`, a single-table query and a CTE/derived-table rewritten query return different results for the same logical condition `c1 IN (c2)`. The single-table query returns 2 rows, while the rewritten query returns only 1 row. The root cause is that the comparison between `BIT(1)` and `JSON` uses different implicit conversion/condition derivation paths in the single-table path and in the CTE-materialized derived-table path. After materialization, the original `JSON` column loses its type marker and becomes an ordinary temporary column/LONGTEXT, which changes the type aggregation rules for `c1 IN (c2)`.
- Problem Description
-
-
-
- How to Reproduce
Execute the following SQL:
- How to Reproduce
-
```sql
DROP DATABASE IF EXISTS repro_mariadb_database9_tiny;
CREATE DATABASE repro_mariadb_database9_tiny;
USE repro_mariadb_database9_tiny;
CREATE TABLE src (
id INT PRIMARY KEY,
c0 DATETIME NOT NULL,
c1 BIT(1) NOT NULL,
c2 JSON NOT NULL,
c3 DATE NULL
) ENGINE=Aria;
INSERT INTO src VALUES
(1, '0000-00-00 00:00:00', b'0', 'null', NULL),
(2, '2000-01-01 00:00:02', b'0', '
', '2000-01-03');
CREATE TABLE l (
id INT PRIMARY KEY,
c0 DATETIME NOT NULL,
c2 JSON NOT NULL
) ENGINE=Aria;
CREATE TABLE r (
id INT PRIMARY KEY,
c1 BIT(1) NOT NULL,
c3 DATE NULL,
c2 JSON NOT NULL
) ENGINE=Aria;
INSERT INTO l SELECT id, c0, c2 FROM src;
INSERT INTO r SELECT id, c1, c3, c2 FROM src;
SET SESSION optimizer_switch='derived_merge=off';
– Single-table query
SELECT
'direct' AS tag,
CAST((c0 IN (c0, (c0 < c1), c1)) AS UNSIGNED) AS v,
c3
FROM src
WHERE c1 IN (c2);
– CTE/derived rewritten query
WITH lq AS (
SELECT * FROM l
),
rq AS (
SELECT * FROM r
)
SELECT
'rewrite' AS tag,
CAST((c0 IN (c0, (c0 < c1), c1)) AS UNSIGNED) AS v,
c3
FROM (
SELECT
lq.id,
lq.c0,
rq.c1,
lq.c2,
rq.c3
FROM lq
JOIN rq ON lq.id = rq.id
) q
WHERE c1 IN (c2);
```
-
-
- Expected Behavior
The single-table query and the CTE/derived-table rewritten query should return identical results. Whether or not the derived table is materialized, the comparison semantics of `c1 IN (c2)` should remain consistent.
- Expected Behavior
-
-
-
- Actual Behavior
-
- Single-table query: returns 2 rows
- CTE/derived-table rewritten query: returns 1 row (the second row is lost)
Single-table result:
```
tag v c3
direct 1 NULL
direct 1 2000-01-03
```
Rewritten result:
```
tag v c3
rewrite 1 NULL
```