pingcap / pingcap/tidb

TABLESAMPLE REGIONS(...) arguments are parsed but ignored, so a 0-row sample still returns rows

Open
#70,986 1 comment 0 reactions 0 assignees View on GitHub
affects-25.10 affects-26.3 affects-7.5 affects-8.1 affects-8.5 affects-9.0 component/executor found-by-ai severity/major sig/execution type/bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.