pingcap / pingcap/tidb

TiDB truncates LONGTEXT in a flat UNION when a DOUBLE branch is present

Open
#70,633 4 comments 0 reactions 0 assignees View on GitHub
affects-25.10 affects-26.3 affects-7.5 affects-8.1 affects-8.5 contribution severity/critical sig/planner type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

PleaTiDB truncates a `LONGTEXT` value to 255 characters in a flat heterogeneous
`UNION ALL`. Parenthesizing the first three branches as a UNION prefix (the
shape produced by VECT's materialization cut) returns the complete value
instead. The two queries contain the same rows and expressions; only the
relational boundary/parenthesization changes.

This is the stable mismatch from VECT round 4, pair 800. Unlike the other
round-4 mismatches, this case has no window expression and repeated executions
produce the same result.
se answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

The following query is self-contained and returns one non-empty row. The
other branches are empty but retain their expression types for UNION type
resolution:

```sql
SELECT FALSE AS x, CAST('q' AS CHAR(255)) AS y
WHERE FALSE
UNION ALL
SELECT CAST(367.93 AS DECIMAL(10,2)), REPEAT('z', 1592)
UNION ALL
SELECT SUM(CAST(NULL AS DOUBLE)),
CAST(10 AS DOUBLE) * CAST(10 AS DOUBLE)
FROM (SELECT 1 AS g) AS s
WHERE FALSE
GROUP BY g
UNION ALL
SELECT DISTINCT VARIANCE(CAST(NULL AS DOUBLE)), CAST('' AS CHAR(1))
FROM (SELECT 1 AS g) AS s
WHERE FALSE
GROUP BY g;
```

The second column is exposed as a string/blob with a 1020-byte maximum and the
non-empty row is truncated:

```text
367.93 | 255 characters (the first 255 z's)
```

Now parenthesize the first three branches before appending the empty fourth
branch:

```sql
(((
SELECT FALSE AS x, CAST('q' AS CHAR(255)) AS y WHERE FALSE
)
UNION ALL
SELECT CAST(367.93 AS DECIMAL(10,2)), REPEAT('z', 1592))
UNION ALL
SELECT SUM(CAST(NULL AS DOUBLE)),
CAST(10 AS DOUBLE) * CAST(10 AS DOUBLE)
FROM (SELECT 1 AS g) AS s
WHERE FALSE
GROUP BY g)
UNION ALL
SELECT DISTINCT VARIANCE(CAST(NULL AS DOUBLE)), CAST('' AS CHAR(1))
FROM (SELECT 1 AS g) AS s
WHERE FALSE
GROUP BY g;
```

The same row now contains all 1592 characters. TiDB reports a LONGTEXT-sized
second column (maximum `4294967292` bytes) instead of 1020 bytes.

### 2. What did you expect to see? (Required)

The flat and parenthesized forms should return the same complete LONGTEXT
value. A numeric `DOUBLE` branch must not cause a text branch to be narrowed
to 255 characters.

### 3. What did you see instead (Required)

### 4. What is your TiDB version? (Required)

```text
DBMS: 8.0.11-TiDB-v8.5.7
Endpoint: 127.0.0.1:4000
Test date: 2026-08-24
TiDB version (SELECT tidb_version()):
Release Version: v8.5.7
Edition: Community
Git Commit Hash: 202b7f47286a1109b5c957401d34c9358d130ae0
Git Branch: HEAD
UTC Build Time: 2026-07-15 02:06:00
GoVersion: go1.25.10
Race Enabled: false
Check Table Before Drop: false
Store: unistore
```

Contributor guide

Open the contributing guide

Research direction

Start by running the two self-contained UNION ALL queries in the issue on TiDB v8.5.7 and compare the second column's length and reported maximum. Investigate the UNION type-resolution path responsible for LONGTEXT and DOUBLE interaction; done means the flat and parenthesized forms return the same complete 1592-character value without narrowing the text column.

Written by the indexing model from the issue text.

Assessment

Tech stack
sql
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.