Skip to content

Grouped REPEAT over a WITH CTE returns a string; the same query on the table returns NULL #70493

Description

@wanteatfruit

Bug Report

REPEAT(name, 5592406) on VARCHAR 'abc' is 16 777 218 bytes, one past
mysql.MaxBlobWidth (16 777 216). Vectorized REPEAT
(builtin_string_vec.go) NULLs that call via len(str) > Flen/num. Scalar
REPEAT (builtin_string.go evalString) only checks max_allowed_packet
(64 MiB here) and produces the string.

On a plain table, GROUP BY name plus HAVING MAX(id) <= (SELECT COUNT(*) FROM t)
takes the vectorized path: CAST(… AS CHAR(255)) is NULL. Replace the table with
the identity CTE

1. Minimal reproduce step (Required)

CREATE TABLE t__base (id BIGINT, name VARCHAR(255));
INSERT INTO t__base VALUES (2, 'abc'), (42, '');
CREATE VIEW t AS WITH t__base_cte_1 AS (SELECT * FROM t__base) SELECT * FROM t__base_cte_1;

SELECT name,
       CAST(IF(name = name, REPEAT(name, 5592406), REGEXP_INSTR(name, '.')) AS CHAR(255)) IS NULL AS is_null,
       CHAR_LENGTH(CAST(IF(name = name, REPEAT(name, 5592406), REGEXP_INSTR(name, '.')) AS CHAR(255))) AS clen
FROM t
GROUP BY name
HAVING MAX(id) <= (SELECT COUNT(*) FROM t);
-- Expected: ('abc', 1, NULL)   
-- Actual:   ('abc', 0, 255)    -- WRONG

This is correct, selecting from a table instead of a view:

CREATE TABLE t__base (id BIGINT, name VARCHAR(255));
INSERT INTO t__base VALUES (2, 'abc'), (42, '');
CREATE TABLE t LIKE t__base;
INSERT INTO t SELECT * FROM t__base;

SELECT name,
       CAST(IF(name = name, REPEAT(name, 5592406), REGEXP_INSTR(name, '.')) AS CHAR(255)) IS NULL AS is_null,
       CHAR_LENGTH(CAST(IF(name = name, REPEAT(name, 5592406), REGEXP_INSTR(name, '.')) AS CHAR(255))) AS clen
FROM t
GROUP BY name
HAVING MAX(id) <= (SELECT COUNT(*) FROM t);
-- Expected: ('abc', 1, NULL)
-- Actual:   ('abc', 1, NULL)

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

Query Expected Actual
table, distilled IF/REPEAT/REGEXP_INSTR + HAVING NULL (IS NULL = 1) NULL
CTE view, same query NULL (same rows) 255-char string
query-level WITH t AS (SELECT * FROM t__base), same query NULL 255-char string
identity VIEW (no WITH) NULL NULL
REPEAT(name, 5592405) (3·n = 16 777 215 ≤ MaxBlobWidth) 255 on both 255 on both
IF(TRUE, REPEAT(…), REGEXP_INSTR(…)) NULL on both NULL on both
ELSE NULL NULL on both NULL on both
no HAVING 'abc' NULL and '' length 0 on both both agree

3. What did you see instead (Required)

4. What is your TiDB version? (Required)

TiDB v9.0.0-beta.2.pre @ 3bea819

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions