Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.0, 13.0.1
Description
-
-
- Problem Description
When a query involves multi-table joins, derived tables, temporary tables, and sorting, the result of `TRIM(ORD(c0))` is truncated to an incorrect maximum length during materialization/sorting. In a single-table query, constant folding via the primary key evaluates the expression early and produces the correct result. In a multi-table query, the expression is evaluated at runtime, and the optimizer deduces its return type length as `VARCHAR(7)` or similar, while the actual generated string length is 8, resulting in the trailing `'0'` being truncated.
- Problem Description
-
-
-
- How to Reproduce
Execute the following SQL:
- How to Reproduce
-
```sql
DROP DATABASE IF EXISTS repro_mariadb806_db1_min6;
CREATE DATABASE repro_mariadb806_db1_min6
CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci;
USE repro_mariadb806_db1_min6;
CREATE TABLE t4 (
c0 VARCHAR(100) NOT NULL,
PRIMARY KEY (c0)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
INSERT INTO t4 VALUES ('⳾v*');
CREATE TABLE vp_mariadb_database1_937_source LIKE t4;
ALTER TABLE vp_mariadb_database1_937_source
ADD COLUMN vp_rowid BIGINT NOT NULL FIRST;
ALTER TABLE vp_mariadb_database1_937_source ENGINE=InnoDB;
INSERT INTO vp_mariadb_database1_937_source (vp_rowid, c0)
SELECT ROW_NUMBER() OVER (ORDER BY c0), c0
FROM t4;
CREATE TABLE vp_mariadb_database1_937_left (
vp_rowid BIGINT NOT NULL,
c0 VARCHAR(100)
CHARACTER SET utf8mb4 COLLATE utf8mb4_uca1400_ai_ci
) ENGINE=InnoDB;
CREATE TABLE vp_mariadb_database1_937_right (
vp_rowid BIGINT NOT NULL
) ENGINE=InnoDB;
INSERT INTO vp_mariadb_database1_937_left
SELECT vp_rowid, c0 FROM vp_mariadb_database1_937_source;
INSERT INTO vp_mariadb_database1_937_right
SELECT vp_rowid FROM vp_mariadb_database1_937_source;
SET NAMES utf8mb4 COLLATE utf8mb4_uca1400_ai_ci;
– Single-table query
SELECT *
FROM (
SELECT TRIM(ORD(c0)) AS vp_ast_col_0,
-1914373596 AS vp_ast_col_1,
c0 AS vp_ast_col_2,
c0 AS vp_ast_col_3,
'' AS vp_ast_col_4
FROM vp_mariadb_database1_937_source
) q
WHERE q.vp_ast_col_2 = '⳾v*'
ORDER BY 1, 2, 3, 4, 5;
– Multi-table rewritten query
SELECT *
FROM (
SELECT TRIM(ORD(c0)) AS vp_ast_col_0,
-1914373596 AS vp_ast_col_1,
c0 AS vp_ast_col_2,
c0 AS vp_ast_col_3,
'' AS vp_ast_col_4
FROM (
SELECT l.vp_rowid, l.c0
FROM vp_mariadb_database1_937_left l
JOIN (
SELECT vp_rowid, CONCAT('vp:', vp_rowid) AS payload
FROM vp_mariadb_database1_937_right
) p ON p.payload = CONCAT('vp:', l.vp_rowid)
JOIN vp_mariadb_database1_937_right r
ON r.vp_rowid = p.vp_rowid
) vp_rel
) q
WHERE q.vp_ast_col_2 = '⳾v*'
ORDER BY 1, 2, 3, 4, 5;
```
-
-
- Expected Behavior
Both queries should return identical results, with `vp_ast_col_0` equal to `14857150`.
- Expected Behavior
-
| Query Type | vp_ast_col_0 | vp_ast_col_1 | vp_ast_col_2 | vp_ast_col_3 | vp_ast_col_4 |
| ------------------ | -------------- | -------------- | -------------- | -------------- | -------------- |
| Single-table | 14857150 | -1914373596 | ⳾v* | ⳾v* | |
| Multi-table | 14857150 | -1914373596 | ⳾v* | ⳾v* |
-
-
- Actual Behavior
In the multi-table query, `vp_ast_col_0` loses the trailing `'0'`.
- Actual Behavior
-
| Query Type | vp_ast_col_0 | vp_ast_col_1 | vp_ast_col_2 | vp_ast_col_3 | vp_ast_col_4 |
| ------------------ | -------------- | -------------- | -------------- | -------------- | -------------- |
| Single-table | 14857150 | -1914373596 | ⳾v* | ⳾v* | |
| Multi-table | 1485715 | -1914373596 | ⳾v* | ⳾v* |
-
-
- Execution Plan Comparison
*Single-table query execution plan:*
```
1 | SIMPLE | vp_mariadb_database1_937_sourceconst PRIMARY PRIMARY 402 const 1 ```
Because `c0` is the primary key, `WHERE c0 = '⳾v*'` directly hits the primary key. The optimizer treats the entire row as a constant, and the outer `TRIM(ORD(c0))` is evaluated via constant folding, yielding the correct result `14857150`.
- Execution Plan Comparison
-
*Multi-table query execution plan:*
```
1 | SIMPLE | l
| ALL | NULL | NULL | NULL | NULL | 1 |
| Using where; Using temporary; Using filesort |
1 | SIMPLE | vp_mariadb_database1_937_right
| ALL | NULL | NULL | NULL | NULL | 1 |
| Using where; Using join buffer (flat, BNL join) |
1 | SIMPLE | r
| hash_ALL | NULL | #hash#$hj | 8 |
| ...vp_mariadb_database1_937_right.vp_rowid | 1 | ||
| Using where; Using join buffer (flat, BNLH join) ``` Here the primary key constant path is not possible. The derived table `vp_rel` is materialized or merged, `TRIM(ORD(c0))` is evaluated at runtime, and the result passes through temporary/filesort. The final output changes from `14857150` to `1485715`, dropping one `'0'`. |