seawinde commented on code in PR #59013:
URL: https://github.com/apache/doris/pull/59013#discussion_r2644722218


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/Predicates.java:
##########
@@ -129,167 +124,179 @@ public static Map<Expression, ExpressionInfo> 
compensateCouldNotPullUpPredicates
     }
 
     /**
-     * compensate equivalence predicates
+     * Compensate equivalence predicates based on equivalence classes.
+     * Collects uncovered equivalence predicates into uncoveredEquals for 
residual compensation.
      */
     public static Map<Expression, ExpressionInfo> 
compensateEquivalence(StructInfo queryStructInfo,
             StructInfo viewStructInfo,
             SlotMapping viewToQuerySlotMapping,
-            ComparisonResult comparisonResult) {
+            ComparisonResult comparisonResult,
+            Set<Expression> uncoveredEquals) {
         EquivalenceClass queryEquivalenceClass = 
queryStructInfo.getEquivalenceClass();
         EquivalenceClass viewEquivalenceClass = 
viewStructInfo.getEquivalenceClass();
         Map<SlotReference, SlotReference> viewToQuerySlotMap = 
viewToQuerySlotMapping.toSlotReferenceMap();
         EquivalenceClass viewEquivalenceClassQueryBased = 
viewEquivalenceClass.permute(viewToQuerySlotMap);
         if (viewEquivalenceClassQueryBased == null) {
             return null;
         }
-        final Map<Expression, ExpressionInfo> equalCompensateConjunctions = 
new HashMap<>();
         if (queryEquivalenceClass.isEmpty() && viewEquivalenceClass.isEmpty()) 
{
             return ImmutableMap.of();
         }
-        if (queryEquivalenceClass.isEmpty() && 
!viewEquivalenceClass.isEmpty()) {
-            return null;
-        }
         EquivalenceClassMapping queryToViewEquivalenceMapping =
                 EquivalenceClassMapping.generate(queryEquivalenceClass, 
viewEquivalenceClassQueryBased);
-        // can not map all target equivalence class, can not compensate
         if (queryToViewEquivalenceMapping.getEquivalenceClassSetMap().size()
                 < viewEquivalenceClass.getEquivalenceSetList().size()) {
             return null;
         }
-        // do equal compensate
+        Map<Expression, ExpressionInfo> compensations = new HashMap<>();
         Set<List<SlotReference>> mappedQueryEquivalenceSet =
                 
queryToViewEquivalenceMapping.getEquivalenceClassSetMap().keySet();
 
         for (List<SlotReference> queryEquivalenceSet : 
queryEquivalenceClass.getEquivalenceSetList()) {
-            // compensate the equivalence in query but not in view
             if (!mappedQueryEquivalenceSet.contains(queryEquivalenceSet)) {
-                Iterator<SlotReference> iterator = 
queryEquivalenceSet.iterator();
-                SlotReference first = iterator.next();
-                while (iterator.hasNext()) {
-                    Expression equals = new EqualTo(first, iterator.next());
-                    if (equals.anyMatch(AggregateFunction.class::isInstance)) {
-                        return null;
-                    }
-                    equalCompensateConjunctions.put(equals, 
ExpressionInfo.EMPTY);
+                SlotReference first = queryEquivalenceSet.get(0);
+                for (int i = 1; i < queryEquivalenceSet.size(); i++) {
+                    uncoveredEquals.add(new EqualTo(first, 
queryEquivalenceSet.get(i)));
                 }
             } else {
-                // compensate the equivalence both in query and view, but 
query has more equivalence
                 List<SlotReference> viewEquivalenceSet =
                         
queryToViewEquivalenceMapping.getEquivalenceClassSetMap().get(queryEquivalenceSet);
-                List<SlotReference> copiedQueryEquivalenceSet = new 
ArrayList<>(queryEquivalenceSet);
-                copiedQueryEquivalenceSet.removeAll(viewEquivalenceSet);
-                SlotReference first = viewEquivalenceSet.iterator().next();
-                for (SlotReference slotReference : copiedQueryEquivalenceSet) {
-                    Expression equals = new EqualTo(first, slotReference);
+                List<SlotReference> queryExtraSlots = new 
ArrayList<>(queryEquivalenceSet);
+                queryExtraSlots.removeAll(viewEquivalenceSet);
+
+                SlotReference firstViewSlot = viewEquivalenceSet.get(0);
+                for (SlotReference extraSlot : queryExtraSlots) {
+                    Expression equals = new EqualTo(firstViewSlot, extraSlot);
                     if (equals.anyMatch(AggregateFunction.class::isInstance)) {
                         return null;
                     }
-                    equalCompensateConjunctions.put(equals, 
ExpressionInfo.EMPTY);
+                    compensations.put(equals, ExpressionInfo.EMPTY);
                 }
             }
         }
-        return equalCompensateConjunctions;
+        return compensations;
     }
 
     /**
-     * compensate range predicates
+     * Compensate range predicates.
+     * Collects uncovered range predicates into uncoveredRanges for residual 
compensation.
      */
     public static Map<Expression, ExpressionInfo> 
compensateRangePredicate(StructInfo queryStructInfo,
             StructInfo viewStructInfo,
             SlotMapping viewToQuerySlotMapping,
             ComparisonResult comparisonResult,
-            CascadesContext cascadesContext) {
+            CascadesContext cascadesContext,
+            Set<Expression> uncoveredRanges) {
         SplitPredicate querySplitPredicate = 
queryStructInfo.getSplitPredicate();
         SplitPredicate viewSplitPredicate = viewStructInfo.getSplitPredicate();
 
-        Set<Expression> viewRangeQueryBasedSet = new HashSet<>();
-        for (Expression viewExpression : 
viewSplitPredicate.getRangePredicateMap().keySet()) {
-            viewRangeQueryBasedSet.add(
-                    ExpressionUtils.replace(viewExpression, 
viewToQuerySlotMapping.toSlotReferenceMap()));
-        }
-        viewRangeQueryBasedSet.remove(BooleanLiteral.TRUE);
-
-        Set<Expression> queryRangeSet = 
querySplitPredicate.getRangePredicateMap().keySet();
-        queryRangeSet.remove(BooleanLiteral.TRUE);
+        Set<Expression> viewRangeQueryBasedSet = mapExpressionsToQueryContext(
+                viewSplitPredicate.getRangePredicateMap().keySet(), 
viewToQuerySlotMapping);
+        Set<Expression> queryRangeSet = new 
HashSet<>(querySplitPredicate.getRangePredicateMap().keySet());
 
-        Set<Expression> differentExpressions = new HashSet<>();
-        Sets.difference(queryRangeSet, 
viewRangeQueryBasedSet).copyInto(differentExpressions);
-        Sets.difference(viewRangeQueryBasedSet, 
queryRangeSet).copyInto(differentExpressions);
-        // the range predicate in query and view is same, don't need to 
compensate
-        if (differentExpressions.isEmpty()) {
-            return ImmutableMap.of();
-        }
-        // try to normalize the different expressions
-        Set<Expression> normalizedExpressions =
-                normalizeExpression(ExpressionUtils.and(differentExpressions), 
cascadesContext);
-        if (!queryRangeSet.containsAll(normalizedExpressions)) {
-            // normalized expressions is not in query, can not compensate
+        Set<Expression> mvExtraRange = Sets.difference(viewRangeQueryBasedSet, 
queryRangeSet);
+        if (!mvExtraRange.isEmpty()) {

Review Comment:
   If a query uses the condition a > 3, and a materialized view uses the 
condition a > 1, the two conditions are combined with AND and then normalized. 
If, after normalization, the resulting condition is a > 3, it proves that the 
condition compensation succeeded, and this materialized view can be used for 
rewriting.



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