Doris-Breakwater commented on issue #66030:
URL: https://github.com/apache/doris/issues/66030#issuecomment-5076182386

   Breakwater-GitHub-Analysis-Slot: slot_4fd365c156f3
   
   ## Preliminary maintainer assessment
   
   **Verdict: confirmed FE planner/short-circuit contract bug, with a 
high-confidence code-level root cause.** The supplied DDL, query, versions, and 
stack are sufficient for triage. The issue is open with no labels, assignee, 
milestone, or linked development item; it should be routed as an FE/Nereids 
point-query bug.
   
   ### Root cause
   
   The exception is the exact invariant at 
[`PointQueryExecutor.setScanRangeLocations()` line 
120](https://github.com/apache/doris/blob/b10073ad9ca/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java#L112-L121):
 after lazy range evaluation, a point query must target exactly one tablet.
   
   The invariant is violated because a predicate required by the short-circuit 
path is removed earlier:
   
   1. `LogicalResultSinkToShortCircuitPointQuery` marks this query as 
short-circuit while both key equalities (`pk = 'abcd'` and `_id = 1`) are still 
present. The rewrite order intentionally runs this rule before 
`PruneOlapScanPartition`.
   2. For the singleton LIST partition `VALUES IN ('abcd')`, partition pruning 
proves `pk = 'abcd'` is always true inside the selected partition. In 
`b10073ad9ca`, [`PruneOlapScanPartition` calls 
`PartitionPruner.prunePredicate()`](https://github.com/apache/doris/blob/b10073ad9ca/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PruneOlapScanPartition.java#L77-L98),
 which removes that conjunct. In `aec169d2025`, removal is deferred but still 
performed by `PrunePartitionPredicate`.
   3. The translated legacy `OlapScanNode` consequently retains only `_id = 1`. 
During short-circuit execution, [`lazyEvaluateRangeLocations()` recomputes 
filters and tablet ranges from those remaining 
conjuncts](https://github.com/apache/doris/blob/b10073ad9ca/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java#L966-L983).
   4. Because the distribution is `HASH(pk, _id)`, `HashDistributionPruner` 
cannot compute the hash without the removed `pk` filter and returns every 
bucket tablet. `BUCKETS AUTO` resolved to more than one tablet in this 
reproduction, so the `size() == 1` precondition fails.
   
   This also fully explains why there is no BE log: the FE throws before 
selecting a tablet/backend or sending the lookup RPC. It is not a BE storage or 
row-store failure.
   
   The missing predicate is more than a routing problem. 
`PointQueryExecutor.addKeyTuples()` later builds the primary-key lookup tuple 
from the same scan conjuncts. Merely weakening the one-tablet assertion or 
choosing an arbitrary tablet would therefore be incorrect and could expose a 
null/missing key literal or wrong-result path.
   
   ### Recommended fix
   
   Keep partition pruning enabled, but do not remove partition predicates for a 
query already marked as short-circuit. The focused fix is to include:
   
   ```java
   ctx.statementContext.isShortCircuitQuery()
   ```
   
   in the `skipPrunePredicate` condition in `PruneOlapScanPartition`. This 
works with both affected implementations: it prevents direct removal in 
`b10073ad9ca` and prevents recording the predicate for deferred removal in 
`aec169d2025`/newer code. It also preserves all primary-key literals for both 
distribution pruning and `addKeyTuples()`.
   
   Changing `PointQueryExecutor` to accept multiple tablets is not recommended: 
the short-circuit request and retry path are designed around one tablet, and 
that would mask the lost-key-predicate defect rather than repair it.
   
   ### Regression coverage
   
   - Add a `point_query_p0` case based on the supplied DDL, but use a fixed 
multi-bucket count such as `BUCKETS 4` so the failure is deterministic.
   - With default `skip_prune_predicate = false`, verify `EXPLAIN` still 
reports `SHORT-CIRCUIT` and the query returns `('abcd', 1)`.
   - Cover both a normal statement and server-side prepare/execute, including 
repeated execution so cached short-circuit context is exercised.
   - Add a second LIST-partition case where the partition key is a primary-key 
column but is not a distribution column. That case guards key-tuple 
construction even when tablet pruning can succeed without the partition key.
   - Retain a missing-key lookup case and verify it returns an empty result 
rather than an FE exception.
   
   ### Workaround and missing information
   
   A safe session-level workaround on both reported builds is:
   
   ```sql
   SET skip_prune_predicate = true;
   ```
   
   This preserves the predicate while retaining short-circuit execution. If 
that setting is undesirable, `SET enable_short_circuit_query = false` avoids 
the failing path at the cost of point-query performance.
   
   No additional FE/BE logs or Doris profile are needed to establish the root 
cause. Two non-blocking details would help make the regression match the report 
exactly: the actual bucket count selected by `BUCKETS AUTO`, and whether step 5 
was issued through server-side prepare/execute (the stack includes 
`ExecuteCommand`). Neither affects the diagnosis.
   


-- 
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]

Reply via email to