RETURNING clause silently ignored on DELETE / UPDATE / INSERT
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
Please answer these questions before submitting your issue. Thanks!
### 1. Minimal reproduce step (Required)
```
CREATE TABLE rt(id INT PRIMARY KEY, c INT);
INSERT INTO rt VALUES (1,10),(2,20);
DELETE FROM rt WHERE id > 1 RETURNING *; -- 返回 affected=1,无结果集
UPDATE rt SET c = c * 10 WHERE id = 1 RETURNING c; -- affected=1,无结果集
INSERT INTO rt VALUES (3, 30) RETURNING id, c; -- affected=1,无结果集
INSERT INTO rt VALUES (2, 20) RETURNING *; -- affected=1,无结果集
-- PREPARE 路径同样:
PREPARE s FROM 'DELETE FROM rt WHERE id = ? RETURNING *';
EXECUTE s USING @id; -- 语句执行(行被删除),RETURNING 仍被忽略
```
### 2. What did you expect to see? (Required)
Parser accepts the clause; executor drops it. Callers expecting the affected rows get affected-rows only. REPLACE … RETURNING is rejected with 1064 — three different behaviors within one statement family.
### 3. What did you see instead (Required)
```
mysql> CREATE TABLE rt(id INT PRIMARY KEY, c INT);
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO rt VALUES (1,10),(2,20);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql>
mysql> DELETE FROM rt WHERE id > 1 RETURNING *; -- 返回 affected=1,无 结果集
Query OK, 1 row affected (0.00 sec)
mysql> UPDATE rt SET c = c * 10 WHERE id = 1 RETURNING c; -- affected=1 ,无结果集
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> INSERT INTO rt VALUES (3, 30) RETURNING id, c; -- affected=1 ,无结果集
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO rt VALUES (2, 20) RETURNING *; -- affected=1 ,无结果集
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> -- PREPARE 路径同样:
mysql> PREPARE s FROM 'DELETE FROM rt WHERE id = ? RETURNING *';
Query OK, 0 rows affected (0.00 sec)
mysql> EXECUTE s USING @id; -- 语句执行(行被删除),RETURNING 仍被忽略
Query OK, 0 rows affected, 1 warning (0.00 sec)
```
### 4. What is your TiDB version? (Required)
mysql> SELECT tidb_version()
-> ;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v9.0.0-beta.2.pre-2174-g65ac2fad58-dirty
Edition: Community
Git Commit Hash: 65ac2fad582510b92d3c4b79999e48217c989737
Git Branch: master
UTC Build Time: 2026-08-30 15:18:00
GoVersion: go1.25.12
Race Enabled: false
Check Table Before Drop: false
Store: unistore
Kernel Type: Classic |
Contributor guide
Research direction
Start by running the supplied DELETE, UPDATE, INSERT, and PREPARE/EXECUTE reproductions against TiDB. Trace how the parser and executor handle RETURNING for each DML statement, including the REPLACE case. Done means each accepted RETURNING clause produces its requested result set consistently instead of only affected-row counts, with prepared statements covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100