hulincup opened a new pull request, #66416:
URL: https://github.com/apache/doris/pull/66416
## Motivation
Fixes #66030.
A short-circuit point query on a table with `PARTITION BY LIST` and more
than one tablet per partition threw `IllegalStateException` (msg: null):
```
java.lang.IllegalStateException
at com.google.common.base.Preconditions.checkState(Preconditions.java:499)
at
org.apache.doris.qe.PointQueryExecutor.setScanRangeLocations(PointQueryExecutor.java:120)
```
Repro (from the issue):
```sql
CREATE TABLE tbl_point_query (
pk varchar(64), _id bigint
) UNIQUE KEY(pk, _id)
PARTITION BY LIST (`pk`) (PARTITION p_abcd VALUES IN ('abcd'))
DISTRIBUTED BY HASH(pk, _id) BUCKETS AUTO
PROPERTIES
("store_row_column"="true","enable_unique_key_merge_on_write"="true","light_schema_change"="true");
INSERT INTO tbl_point_query VALUES ('abcd', 1);
SELECT * FROM tbl_point_query WHERE pk = 'abcd' AND _id = 1; --
IllegalStateException
```
## Root cause
In `OlapScanNode.computeTabletInfo`, the distribution prune flag is
`isNereids && !isPointQuery`, which forces point queries onto the legacy
`HashDistributionPruner` path. That path prunes using `columnFilters`, which is
populated by `computeColumnsFilter` from the legacy `conjuncts`. For a
nereids-planned *direct* point query the conjuncts are not in the legacy form
that feeds `columnFilters`, so the pruner returns **all tablets of the matched
partition**. `PointQueryExecutor.setScanRangeLocations` then hits
`checkState(scanTabletIds.size() == 1)` with an un-pruned list and crashes. The
bug is masked when a partition has a single tablet (e.g. `BUCKETS 1`), so it
only surfaces with `BUCKETS AUTO` / multiple buckets — which is why
LIST-partition users hit it.
## Change
Use the nereids-pruned tablet set for point queries when it has already been
pruned to a single tablet (the direct-query case, where the key literals are
known at planning time and `PhysicalPlanTranslator` populates
`nereidsPrunedTabletIds` from the nereids plan's `selectedTabletIds`). When the
pruned set still contains multiple tablets (a prepared-statement point query
whose parameter values are unknown at planning time), keep the legacy
runtime-prune path, so that path is **not** regressed.
```java
boolean useNereidsPrune = isNereids && (!isPointQuery ||
nereidsPrunedTabletIds.size() == 1);
Collection<Long> prunedTabletIds = distributionPrune(..., useNereidsPrune);
```
Behavior matrix:
- Normal (non-point) query: unchanged (`!isPointQuery` is true).
- Direct point query: `nereidsPrunedTabletIds` has 1 tablet → uses nereids
path → pruned to 1 → fixed.
- Prepared point query: `nereidsPrunedTabletIds` has multiple tablets (value
unknown at planning) → falls back to legacy runtime prune → unchanged.
## Files
- `fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java` —
the prune-flag change.
-
`regression-test/suites/point_query_p0/test_point_query_list_partition.groovy`
— new regression test reproducing the issue (LIST partition + BUCKETS 3 +
short-circuit point query).
## Verification
I could not build/run FE locally for this change; verification relies on CI.
The new regression test reproduces the original failure (it asserts the query
returns 1 row instead of throwing) and the existing `point_query_p0` suites
guard the non-regression side.
## Test plan
- [ ] CI: new `point_query_p0/test_point_query_list_partition` passes.
- [ ] CI: existing `point_query_p0/*` (incl. `test_point_query_partition`,
`test_point_query`, prepared-statement paths) pass unchanged.
- [ ] Maintainer review: please confirm the direct-vs-prepared branching is
the right cut — I could not fully verify the prepared-statement runtime-prune
path without a local cluster.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]