TABLESAMPLE REGIONS(...) arguments are parsed but ignored, so a 0-row sample still returns rows
- 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)
```sql
CREATE TABLE t(a INT);
INSERT INTO t VALUES (1),(2),(3);
-- Control: REGIONS() samples one row from the single region.
SELECT COUNT(*) FROM t TABLESAMPLE REGIONS(); -- 1
EXPLAIN SELECT COUNT(*) FROM t TABLESAMPLE REGIONS(); -- plan contains TableSample
-- RED: a zero-row / zero-percent request must return zero rows.
SELECT COUNT(*) FROM t TABLESAMPLE REGIONS(0 ROWS); -- actual 1
SELECT COUNT(*) FROM t TABLESAMPLE REGIONS(0 PERCENT); -- actual 1
SELECT COUNT(*) FROM t TABLESAMPLE REGIONS(100 PERCENT); -- actual 1
SELECT a FROM t TABLESAMPLE REGIONS(0 ROWS); -- actual row 1
SHOW WARNINGS; -- empty
```
Probe output:
```text
CONTROL_REGIONS_COUNT=1
CONTROL_REGIONS_SAMPLE_OK
REGIONS_COUNT=1
ZERO_ROWS_COUNT=1
ZERO_PERCENT_COUNT=1
HUNDRED_PERCENT_COUNT=1
ZERO_ROWS_SAMPLE_ROWS=['1']
TIDB_SAMPLE_ARGUMENT_IGNORED
```
### 2. What did you expect to see? (Required)
The parser accepted a sample expression and unit, so the planner/executor must either honor them or reject the clause. In particular:
- `REGIONS(0 ROWS)` must return zero rows.
- `REGIONS(0 PERCENT)` must return zero rows.
- `REGIONS(100 PERCENT)` must not return only one row per region if a percentage is supported.
- If `REGIONS` intentionally supports no row/percent argument or repeatable seed, the statement must fail before execution.
Silently returning a row for a zero-row request is a wrong-result bug.
### 3. What did you see instead (Required)
Fixture t(a) rows (1),(2),(3). Control: SELECT COUNT(*) FROM t TABLESAMPLE REGIONS() -> 1; EXPLAIN shows TableSample. Trigger: REGIONS(0 ROWS) -> 1; REGIONS(0 PERCENT) -> 1; REGIONS(100 PERCENT) -> 1; SELECT a FROM t TABLESAMPLE REGIONS(0 ROWS) -> 1. SHOW WARNINGS is empty.
### 4. What is your TiDB version? (Required)
```text
Release Version: v8.4.0-this-is-a-placeholder
Edition: Community
Git Commit Hash: None
Git Branch: None
UTC Build Time: None
GoVersion: go1.25.12
Race Enabled: false
Check Table Before Drop: false
Store: unistore
Kernel Type: Classic
```
Built from source commit `a514a92784c9654502686e6ee6efc9e0aeda8afa` (pingcap/tidb master, 2026-09-07).
### 5. Root cause (optional)
- pkg/parser/parser.y:10415-10437 TableSampleOpt stores Expr, SampleClauseUnit, RepeatableSeed
- pkg/parser/ast/dml.go:1098-1104 TableSample fields
- pkg/planner/core/preprocess.go:419-425 only validates SampleMethod
- pkg/planner/core/logical_plan_builder.go:5316 stores the AST in TableSampleInfo
- pkg/executor/builder.go:6075-6078 only reads AstNode.SampleMethod
- pkg/executor/sample.go:77-120 tableRegionSampler has no Expr/SampleClauseUnit/RepeatableSeed field
Contributor guide
Research direction
Start with the SQL reproduction, then trace TableSampleOpt in pkg/parser/parser.y and the TableSample fields in pkg/parser/ast/dml.go. Follow validation and AST handling through pkg/planner/core/preprocess.go, pkg/planner/core/logical_plan_builder.go, pkg/executor/builder.go, and pkg/executor/sample.go. Done means the zero-row and zero-percent cases no longer return rows, 100 percent has defined behavior, or unsupported arguments are rejected before execution.
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
- 55/100