github-actions[bot] commented on code in PR #67725:
URL: https://github.com/apache/doris/pull/67725#discussion_r4347480480


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CollectRelation.java:
##########
@@ -351,4 +382,70 @@ private void registerRowBinlogTtl(TableIf table, 
UnboundRelation relation,
             }
         }
     }
+
+    private boolean isUnderInitialFilter(
+            CascadesContext cascadesContext, Plan plan, UnboundRelation 
relation) {
+        return initialScanPredicate(cascadesContext, plan, 
relation).isPresent();
+    }
+
+    private Optional<Expression> initialScanPredicate(CascadesContext context, 
Plan plan, UnboundRelation relation) {
+        List<Expression> predicates = new ArrayList<>();
+        collectInitialScanPredicates(context, plan, relation, predicates);
+        return predicates.isEmpty() ? Optional.empty() : 
Optional.of(ExpressionUtils.and(predicates));
+    }
+
+    private void collectInitialScanPredicates(CascadesContext context, Plan 
plan, UnboundRelation relation,
+            List<Expression> predicates) {
+        if (plan instanceof LogicalFilter && 
isTransparentFilterChild(plan.child(0), relation)) {
+            ExpressionRewriteContext rewriteContext = new 
ExpressionRewriteContext(plan, context);
+            for (Expression conjunct : ((LogicalFilter<?>) 
plan).getConjuncts()) {
+                Expression folded = FoldConstantRule.evaluate(conjunct, 
rewriteContext);

Review Comment:
   [P1] Keep pre-coercion folds out of the partition predicate
   
   With decimal conversion and ordinary FE constant folding enabled, consider a 
Hive `p DECIMAL(2,1)` containing `p=0.0` and `p=0.5`:
   
   ```text
   Filter(h.p = CAST(1.0 / 2.0 AS DECIMAL(2,1)))
     CrossJoin(internal_i, HiveScan(h))
   ```
   
   `FoldConstantRule.evaluate` here runs before 
`ExpressionAnalyzer.visitDivide` applies `TypeCoercionUtils.processDivide`. 
`NumericArithmetic.divideDecimalV3` assumes that coercion has widened the 
dividend: on the raw `(2,1)` operands it instead uses result scale `1-1=0` and 
folds the division to `0`. The explicit cast produces `0.0`, which passes 
`compatibleInitialPartitionTypes`, so the pre-lock pass selects only `p=0.0`. 
Normal analysis of the original predicate produces `0.5`, but 
`PruneFileScanPartition` reuses the recorded subset and prunes it to empty, 
losing the matching `p=0.5` rows. Use this early fold only for shape/tautology 
detection, or defer selective filtering until binding and coercion have 
established the expression's value; add this mixed internal/Hive case.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/CollectRelation.java:
##########
@@ -351,4 +382,70 @@ private void registerRowBinlogTtl(TableIf table, 
UnboundRelation relation,
             }
         }
     }
+
+    private boolean isUnderInitialFilter(
+            CascadesContext cascadesContext, Plan plan, UnboundRelation 
relation) {
+        return initialScanPredicate(cascadesContext, plan, 
relation).isPresent();
+    }
+
+    private Optional<Expression> initialScanPredicate(CascadesContext context, 
Plan plan, UnboundRelation relation) {
+        List<Expression> predicates = new ArrayList<>();
+        collectInitialScanPredicates(context, plan, relation, predicates);
+        return predicates.isEmpty() ? Optional.empty() : 
Optional.of(ExpressionUtils.and(predicates));
+    }
+
+    private void collectInitialScanPredicates(CascadesContext context, Plan 
plan, UnboundRelation relation,
+            List<Expression> predicates) {
+        if (plan instanceof LogicalFilter && 
isTransparentFilterChild(plan.child(0), relation)) {
+            ExpressionRewriteContext rewriteContext = new 
ExpressionRewriteContext(plan, context);
+            for (Expression conjunct : ((LogicalFilter<?>) 
plan).getConjuncts()) {
+                Expression folded = FoldConstantRule.evaluate(conjunct, 
rewriteContext);
+                if (!BooleanLiteral.TRUE.equals(folded) && 
!folded.getInputSlots().isEmpty()
+                        && folded.getInputSlots().stream().allMatch(slot -> 
slot instanceof UnboundSlot
+                                && belongsToRelation((UnboundSlot) slot, 
plan.child(0), relation))) {
+                    predicates.add(folded);
+                }
+            }
+        }
+        for (Plan child : plan.children()) {
+            collectInitialScanPredicates(context, child, relation, predicates);
+        }
+    }
+
+    /** Only descend through shapes where pushing a relation-only WHERE 
predicate preserves rows. */
+    private boolean isTransparentFilterChild(Plan plan, UnboundRelation 
relation) {
+        if (plan == relation) {
+            return true;
+        }
+        if (plan instanceof LogicalCheckPolicy || plan instanceof 
LogicalSubQueryAlias

Review Comment:
   [P1] Preserve column-mask semantics before prefiltering partitions
   
   `LogicalCheckPolicy` can introduce a projection that changes 
partition-column values, so this wrapper cannot be assumed transparent. For a 
user with a deterministic mask `p + 1 AS p`, a Hive INT partition `p=1`, and a 
nonempty internal table, the valid query `SELECT h.p FROM internal_i i CROSS 
JOIN hive_h h WHERE h.p=2` eventually has this reduced plan:
   
   ```text
   Filter(h.p = 2)
     CrossJoin(internal_i,
       Project(raw_p + 1 AS h.p)
         HiveScan(raw_p = 1))
   ```
   
   Collection crosses the still-unexpanded policy and preloads the raw 
predicate `p=2`, obtaining an authoritative empty view. `CheckPolicy` later 
installs the mask project, and `PushDownFilterThroughProject` substitutes 
`raw_p+1=2`, but `PruneFileScanPartition` still reuses that relation's empty 
raw-`p=2` view. The matching `p=1` rows are therefore omitted. Treat the policy 
wrapper as a barrier unless raw-value preservation is established, or derive 
the selective predicate after mask expansion; cover a nonidentity mask on a 
partition column in a mixed internal/Hive query.



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