This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new 0f0b0e9b37c [Feat](nereids) Support date_trunc function in partition 
prune (#38025) (#38849)
0f0b0e9b37c is described below

commit 0f0b0e9b37c50cc9550edf884af6acb41167f2dc
Author: feiniaofeiafei <53502832+feiniaofeia...@users.noreply.github.com>
AuthorDate: Mon Aug 5 18:29:10 2024 +0800

    [Feat](nereids) Support date_trunc function in partition prune (#38025) 
(#38849)
    
    cherry-pick #38025 to branch-2.1
---
 .../rules/expression/rules/ColumnRange.java        |   8 +
 .../rules/OneRangePartitionEvaluator.java          | 315 +++++++++++++--------
 .../rules/expression/rules/PartitionSlotInput.java |   5 +-
 .../trees/expressions/functions/Monotonic.java     |  36 +++
 .../expressions/functions/scalar/DateTrunc.java    |  19 +-
 .../partition_prune/test_date_trunc_prune.groovy   | 296 +++++++++++++++++++
 6 files changed, 560 insertions(+), 119 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
index 3fcce02cde0..e932d4f2364 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ColumnRange.java
@@ -138,4 +138,12 @@ public class ColumnRange {
     public static ColumnRange range(Literal lower, BoundType lowerType, 
Literal upper, BoundType upperType) {
         return new ColumnRange(ColumnBound.range(lower, lowerType, upper, 
upperType));
     }
+
+    public ColumnRange withLowerBound(Literal lower) {
+        return this.intersect(atLeast(lower));
+    }
+
+    public ColumnRange withUpperBound(Literal upper) {
+        return this.intersect(atMost(upper));
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
index 8b01d2b8c67..446faffe0f5 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/OneRangePartitionEvaluator.java
@@ -42,16 +42,18 @@ import org.apache.doris.nereids.trees.expressions.Not;
 import org.apache.doris.nereids.trees.expressions.NullSafeEqual;
 import org.apache.doris.nereids.trees.expressions.Or;
 import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.functions.Monotonic;
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Date;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.DateTrunc;
 import org.apache.doris.nereids.trees.expressions.literal.BooleanLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.Literal;
-import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.BooleanType;
 import org.apache.doris.nereids.types.DataType;
 import org.apache.doris.nereids.util.ExpressionUtils;
 import org.apache.doris.nereids.util.Utils;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.BoundType;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -62,6 +64,7 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Range;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -87,8 +90,9 @@ public class OneRangePartitionEvaluator
     private final List<Literal> lowers;
     private final List<Literal> uppers;
     private final List<List<Expression>> inputs;
-    private final Map<Slot, Boolean> partitionSlotContainsNull;
+    private final Map<Expression, Boolean> partitionSlotContainsNull;
     private final Map<Slot, PartitionSlotType> slotToType;
+    private final Map<Expression, ColumnRange> rangeMap = new HashMap<>();
 
     /** OneRangePartitionEvaluator */
     public OneRangePartitionEvaluator(long partitionId, List<Slot> 
partitionSlots,
@@ -109,8 +113,8 @@ public class OneRangePartitionEvaluator
             // fast path
             Slot partSlot = partitionSlots.get(0);
             this.slotToType = ImmutableMap.of(partSlot, 
partitionSlotTypes.get(0));
-            this.partitionSlotContainsNull
-                    = ImmutableMap.of(partSlot, 
range.lowerEndpoint().getKeys().get(0).isMinValue());
+            this.partitionSlotContainsNull = new HashMap<>();
+            partitionSlotContainsNull.put(partSlot, 
range.lowerEndpoint().getKeys().get(0).isMinValue());
         } else {
             // slow path
             this.slotToType = Maps.newHashMap();
@@ -169,9 +173,9 @@ public class OneRangePartitionEvaluator
 
     @Override
     public Expression evaluate(Expression expression, Map<Slot, 
PartitionSlotInput> currentInputs) {
-        Map<Slot, ColumnRange> defaultColumnRanges = 
currentInputs.values().iterator().next().columnRanges;
-        EvaluateRangeResult result = expression.accept(
-                this, new EvaluateRangeInput(defaultColumnRanges, 
currentInputs));
+        Map<Expression, ColumnRange> defaultColumnRanges = 
currentInputs.values().iterator().next().columnRanges;
+        rangeMap.putAll(defaultColumnRanges);
+        EvaluateRangeResult result = expression.accept(this, new 
EvaluateRangeInput(currentInputs));
         return result.result;
     }
 
@@ -194,22 +198,14 @@ public class OneRangePartitionEvaluator
         return result;
     }
 
-    @Override
-    public EvaluateRangeResult visitNullLiteral(NullLiteral nullLiteral, 
EvaluateRangeInput context) {
-        Map<Slot, ColumnRange> emptyRanges = Maps.newHashMap();
-        for (Slot key : context.defaultColumnRanges.keySet()) {
-            emptyRanges.put(key, new ColumnRange());
-        }
-        return new EvaluateRangeResult(nullLiteral, emptyRanges, 
ImmutableList.of());
-    }
-
     @Override
     public EvaluateRangeResult visitSlot(Slot slot, EvaluateRangeInput 
context) {
         // try to replace partition slot to literal
         PartitionSlotInput slotResult = context.slotToInput.get(slot);
-        return slotResult == null
-                ? new EvaluateRangeResult(slot, context.defaultColumnRanges, 
ImmutableList.of())
-                : new EvaluateRangeResult(slotResult.result, 
slotResult.columnRanges, ImmutableList.of());
+        Preconditions.checkState(slotResult != null);
+        Preconditions.checkState(slotResult.columnRanges.containsKey(slot));
+        return new EvaluateRangeResult(slotResult.result, 
ImmutableMap.of(slot, slotResult.columnRanges.get(slot)),
+                ImmutableList.of());
     }
 
     @Override
@@ -219,19 +215,19 @@ public class OneRangePartitionEvaluator
             return result;
         }
         greaterThan = (GreaterThan) result.result;
-        if (greaterThan.left() instanceof Slot && greaterThan.right() 
instanceof Literal) {
-            Slot slot = (Slot) greaterThan.left();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+        if (!(greaterThan.left() instanceof Literal) && greaterThan.right() 
instanceof Literal) {
+            Expression expr = greaterThan.left();
+            Map<Expression, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+            if (leftColumnRanges.containsKey(expr)) {
                 ColumnRange greaterThenRange = 
ColumnRange.greaterThan((Literal) greaterThan.right());
-                result = intersectSlotRange(result, leftColumnRanges, slot, 
greaterThenRange);
+                result = intersectSlotRange(result, leftColumnRanges, expr, 
greaterThenRange);
             }
-        } else if (greaterThan.left() instanceof Literal && 
greaterThan.right() instanceof Slot) {
-            Slot slot = (Slot) greaterThan.right();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+        } else if (greaterThan.left() instanceof Literal && 
!(greaterThan.right() instanceof Literal)) {
+            Expression expr = greaterThan.right();
+            Map<Expression, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+            if (rightColumnRanges.containsKey(expr)) {
                 ColumnRange lessThenRange = ColumnRange.lessThen((Literal) 
greaterThan.left());
-                result = intersectSlotRange(result, rightColumnRanges, slot, 
lessThenRange);
+                result = intersectSlotRange(result, rightColumnRanges, expr, 
lessThenRange);
             }
         }
         return result;
@@ -244,19 +240,19 @@ public class OneRangePartitionEvaluator
             return result;
         }
         greaterThanEqual = (GreaterThanEqual) result.result;
-        if (greaterThanEqual.left() instanceof Slot && 
greaterThanEqual.right() instanceof Literal) {
-            Slot slot = (Slot) greaterThanEqual.left();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+        if (!(greaterThanEqual.left() instanceof Literal) && 
greaterThanEqual.right() instanceof Literal) {
+            Expression expr = greaterThanEqual.left();
+            Map<Expression, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+            if (leftColumnRanges.containsKey(expr)) {
                 ColumnRange atLeastRange = ColumnRange.atLeast((Literal) 
greaterThanEqual.right());
-                result = intersectSlotRange(result, leftColumnRanges, slot, 
atLeastRange);
+                result = intersectSlotRange(result, leftColumnRanges, expr, 
atLeastRange);
             }
-        } else if (greaterThanEqual.left() instanceof Literal && 
greaterThanEqual.right() instanceof Slot) {
-            Slot slot = (Slot) greaterThanEqual.right();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+        } else if (greaterThanEqual.left() instanceof Literal && 
!(greaterThanEqual.right() instanceof Literal)) {
+            Expression expr = greaterThanEqual.right();
+            Map<Expression, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+            if (rightColumnRanges.containsKey(expr)) {
                 ColumnRange atMostRange = ColumnRange.atMost((Literal) 
greaterThanEqual.left());
-                result = intersectSlotRange(result, rightColumnRanges, slot, 
atMostRange);
+                result = intersectSlotRange(result, rightColumnRanges, expr, 
atMostRange);
             }
         }
         return result;
@@ -269,19 +265,19 @@ public class OneRangePartitionEvaluator
             return result;
         }
         lessThan = (LessThan) result.result;
-        if (lessThan.left() instanceof Slot && lessThan.right() instanceof 
Literal) {
-            Slot slot = (Slot) lessThan.left();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+        if (!(lessThan.left() instanceof Literal) && lessThan.right() 
instanceof Literal) {
+            Expression expr = lessThan.left();
+            Map<Expression, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+            if (leftColumnRanges.containsKey(expr)) {
                 ColumnRange greaterThenRange = ColumnRange.lessThen((Literal) 
lessThan.right());
-                result = intersectSlotRange(result, leftColumnRanges, slot, 
greaterThenRange);
+                result = intersectSlotRange(result, leftColumnRanges, expr, 
greaterThenRange);
             }
-        } else if (lessThan.left() instanceof Literal && lessThan.right() 
instanceof Slot) {
-            Slot slot = (Slot) lessThan.right();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+        } else if (lessThan.left() instanceof Literal && !(lessThan.right() 
instanceof Literal)) {
+            Expression expr = lessThan.right();
+            Map<Expression, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+            if (rightColumnRanges.containsKey(expr)) {
                 ColumnRange lessThenRange = ColumnRange.greaterThan((Literal) 
lessThan.left());
-                result = intersectSlotRange(result, rightColumnRanges, slot, 
lessThenRange);
+                result = intersectSlotRange(result, rightColumnRanges, expr, 
lessThenRange);
             }
         }
         return result;
@@ -294,19 +290,19 @@ public class OneRangePartitionEvaluator
             return result;
         }
         lessThanEqual = (LessThanEqual) result.result;
-        if (lessThanEqual.left() instanceof Slot && lessThanEqual.right() 
instanceof Literal) {
-            Slot slot = (Slot) lessThanEqual.left();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+        if (!(lessThanEqual.left() instanceof Literal) && 
lessThanEqual.right() instanceof Literal) {
+            Expression expr = lessThanEqual.left();
+            Map<Expression, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+            if (leftColumnRanges.containsKey(expr)) {
                 ColumnRange atLeastRange = ColumnRange.atMost((Literal) 
lessThanEqual.right());
-                result = intersectSlotRange(result, leftColumnRanges, slot, 
atLeastRange);
+                result = intersectSlotRange(result, leftColumnRanges, expr, 
atLeastRange);
             }
-        } else if (lessThanEqual.left() instanceof Literal && 
lessThanEqual.right() instanceof Slot) {
-            Slot slot = (Slot) lessThanEqual.right();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+        } else if (lessThanEqual.left() instanceof Literal && 
!(lessThanEqual.right() instanceof Literal)) {
+            Expression expr = lessThanEqual.right();
+            Map<Expression, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+            if (rightColumnRanges.containsKey(expr)) {
                 ColumnRange atMostRange = ColumnRange.atLeast((Literal) 
lessThanEqual.left());
-                result = intersectSlotRange(result, rightColumnRanges, slot, 
atMostRange);
+                result = intersectSlotRange(result, rightColumnRanges, expr, 
atMostRange);
             }
         }
         return result;
@@ -319,23 +315,23 @@ public class OneRangePartitionEvaluator
             return result;
         }
         boolean isRejectNot = false;
-        if (equalTo.left() instanceof Slot && equalTo.right() instanceof 
Literal) {
-            Slot slot = (Slot) equalTo.left();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+        if (!(equalTo.left() instanceof Literal) && equalTo.right() instanceof 
Literal) {
+            Expression expr = equalTo.left();
+            Map<Expression, ColumnRange> leftColumnRanges = 
result.childrenResult.get(0).columnRanges;
+            if (leftColumnRanges.containsKey(expr)) {
                 ColumnRange atLeastRange = ColumnRange.singleton((Literal) 
equalTo.right());
-                result = intersectSlotRange(result, leftColumnRanges, slot, 
atLeastRange);
-                if (leftColumnRanges.get(slot).isSingleton()) {
+                result = intersectSlotRange(result, leftColumnRanges, expr, 
atLeastRange);
+                if (leftColumnRanges.get(expr).isSingleton()) {
                     isRejectNot = true;
                 }
             }
-        } else if (equalTo.left() instanceof Literal && equalTo.right() 
instanceof Slot) {
-            Slot slot = (Slot) equalTo.right();
-            if (isPartitionSlot(slot)) {
-                Map<Slot, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+        } else if (equalTo.left() instanceof Literal && !(equalTo.right() 
instanceof Literal)) {
+            Expression expr = equalTo.right();
+            Map<Expression, ColumnRange> rightColumnRanges = 
result.childrenResult.get(1).columnRanges;
+            if (rightColumnRanges.containsKey(expr)) {
                 ColumnRange atMostRange = ColumnRange.singleton((Literal) 
equalTo.left());
-                result = intersectSlotRange(result, rightColumnRanges, slot, 
atMostRange);
-                if (rightColumnRanges.get(slot).isSingleton()) {
+                result = intersectSlotRange(result, rightColumnRanges, expr, 
atMostRange);
+                if (rightColumnRanges.get(expr).isSingleton()) {
                     isRejectNot = true;
                 }
             }
@@ -356,11 +352,11 @@ public class OneRangePartitionEvaluator
         }
         // "A <=> null" has been convert to "A is null" or false by 
NullSafeEqualToEqual rule
         // so we don't consider "A <=> null" here
-        if (nullSafeEqual.left() instanceof Slot && nullSafeEqual.right() 
instanceof Literal) {
+        if (!(nullSafeEqual.left() instanceof Literal) && 
nullSafeEqual.right() instanceof Literal) {
             // A <=> literal -> A = literal and A is not null
             return visit(ExpressionUtils.and(new EqualTo(nullSafeEqual.left(), 
nullSafeEqual.right()),
                     new Not(new IsNull(nullSafeEqual.left()))), context);
-        } else if (nullSafeEqual.left() instanceof Literal && 
nullSafeEqual.right() instanceof Slot) {
+        } else if (nullSafeEqual.left() instanceof Literal && 
!(nullSafeEqual.right() instanceof Slot)) {
             // literal <=> A -> literal = A and A is not null
             return visit(ExpressionUtils.and(new EqualTo(nullSafeEqual.left(), 
nullSafeEqual.right()),
                     new Not(new IsNull(nullSafeEqual.right()))), context);
@@ -376,17 +372,17 @@ public class OneRangePartitionEvaluator
             return result;
         }
         inPredicate = (InPredicate) result.result;
-        if (inPredicate.getCompareExpr() instanceof Slot
+        Map<Expression, ColumnRange> exprRanges = 
result.childrenResult.get(0).columnRanges;
+        if (exprRanges.containsKey(inPredicate.getCompareExpr())
                 && 
inPredicate.getOptions().stream().allMatch(Literal.class::isInstance)) {
-            Slot slot = (Slot) inPredicate.getCompareExpr();
+            Expression compareExpr = inPredicate.getCompareExpr();
             ColumnRange unionLiteralRange = ColumnRange.empty();
-            ColumnRange slotRange = 
result.childrenResult.get(0).columnRanges.get(slot);
+            ColumnRange compareExprRange = 
result.childrenResult.get(0).columnRanges.get(compareExpr);
             for (Expression expr : inPredicate.getOptions()) {
                 unionLiteralRange = unionLiteralRange.union(
-                        slotRange.intersect(ColumnRange.singleton((Literal) 
expr)));
+                        
compareExprRange.intersect(ColumnRange.singleton((Literal) expr)));
             }
-            Map<Slot, ColumnRange> slotRanges = 
result.childrenResult.get(0).columnRanges;
-            result = intersectSlotRange(result, slotRanges, slot, 
unionLiteralRange);
+            result = intersectSlotRange(result, exprRanges, compareExpr, 
unionLiteralRange);
         }
         result = result.withRejectNot(false);
         return result;
@@ -400,11 +396,10 @@ public class OneRangePartitionEvaluator
         }
         result = result.withRejectNot(false);
         Expression child = isNull.child();
-        if (!(child instanceof Slot) || !isPartitionSlot((Slot) child)) {
+        if (!partitionSlotContainsNull.containsKey(child)) {
             return result;
         }
-
-        if (!partitionSlotContainsNull.get((Slot) child)) {
+        if (!partitionSlotContainsNull.get(child)) {
             return new EvaluateRangeResult(BooleanLiteral.FALSE,
                     result.columnRanges, result.childrenResult, false);
         }
@@ -416,7 +411,15 @@ public class OneRangePartitionEvaluator
         EvaluateRangeResult result = evaluateChildrenThenThis(and, context);
 
         result = mergeRanges(result.result, result.childrenResult.get(0), 
result.childrenResult.get(1),
-                (leftRange, rightRange) -> leftRange.intersect(rightRange));
+                (leftRange, rightRange) -> {
+                if (leftRange == null) {
+                    return rightRange;
+                }
+                if (rightRange == null) {
+                    return leftRange;
+                }
+                return leftRange.intersect(rightRange);
+            });
 
         result = returnFalseIfExistEmptyRange(result);
         if (result.result.equals(BooleanLiteral.FALSE)) {
@@ -434,20 +437,29 @@ public class OneRangePartitionEvaluator
         EvaluateRangeResult result = evaluateChildrenThenThis(or, context);
 
         result = mergeRanges(result.result, result.childrenResult.get(0), 
result.childrenResult.get(1),
-                (leftRange, rightRange) -> leftRange.union(rightRange));
-        return returnFalseIfExistEmptyRange(result);
+                (leftRange, rightRange) -> {
+                    if (leftRange == null) {
+                        return rightRange;
+                    }
+                    if (rightRange == null) {
+                        return leftRange;
+                    }
+                    return leftRange.union(rightRange);
+                });
+        return removeEmptyRange(result);
     }
 
     @Override
     public EvaluateRangeResult visitNot(Not not, EvaluateRangeInput context) {
         EvaluateRangeResult result = evaluateChildrenThenThis(not, context);
         if (result.isRejectNot() && 
!result.result.equals(BooleanLiteral.TRUE)) {
-            Map<Slot, ColumnRange> newRanges = Maps.newHashMap();
-            for (Map.Entry<Slot, ColumnRange> entry : 
result.childrenResult.get(0).columnRanges.entrySet()) {
-                Slot slot = entry.getKey();
+            Map<Expression, ColumnRange> newRanges = Maps.newHashMap();
+            for (Map.Entry<Expression, ColumnRange> entry : 
result.childrenResult.get(0).columnRanges.entrySet()) {
+                Expression expr = entry.getKey();
                 ColumnRange childRange = entry.getValue();
-                ColumnRange partitionRange = result.columnRanges.get(slot);
-                newRanges.put(slot, 
partitionRange.intersect(childRange.complete()));
+                ColumnRange partitionRange = rangeMap.containsKey(expr)
+                        ? rangeMap.get(expr) : ColumnRange.all();
+                newRanges.put(expr, 
partitionRange.intersect(childRange.complete()));
             }
             result = new EvaluateRangeResult(result.result, newRanges, 
result.childrenResult);
         }
@@ -476,7 +488,7 @@ public class OneRangePartitionEvaluator
 
         // evaluate this
         expr = FoldConstantRuleOnFE.evaluate(expr, expressionRewriteContext);
-        return new EvaluateRangeResult(expr, context.defaultColumnRanges, 
childrenResults);
+        return new EvaluateRangeResult(expr, ImmutableMap.of(), 
childrenResults);
     }
 
     private EvaluateRangeResult 
returnFalseIfExistEmptyRange(EvaluateRangeResult result) {
@@ -489,11 +501,11 @@ public class OneRangePartitionEvaluator
     }
 
     private EvaluateRangeResult intersectSlotRange(EvaluateRangeResult 
originResult,
-            Map<Slot, ColumnRange> columnRanges, Slot slot, ColumnRange 
otherRange) {
-        ColumnRange columnRange = columnRanges.get(slot);
+            Map<Expression, ColumnRange> columnRanges, Expression expr, 
ColumnRange otherRange) {
+        ColumnRange columnRange = columnRanges.get(expr);
         ColumnRange intersect = columnRange.intersect(otherRange);
 
-        Map<Slot, ColumnRange> newColumnRanges = 
replaceSlotRange(columnRanges, slot, intersect);
+        Map<Expression, ColumnRange> newColumnRanges = 
replaceExprRange(columnRanges, expr, intersect);
 
         if (intersect.isEmptyRange()) {
             return new EvaluateRangeResult(BooleanLiteral.FALSE, 
newColumnRanges, originResult.childrenResult);
@@ -513,6 +525,9 @@ public class OneRangePartitionEvaluator
         for (int i = 0; i < partitionSlotTypes.size(); i++) {
             PartitionSlotType partitionSlotType = partitionSlotTypes.get(i);
             Slot slot = partitionSlots.get(i);
+            if (!context.columnRanges.containsKey(slot)) {
+                return context;
+            }
             switch (partitionSlotType) {
                 case CONST: continue;
                 case RANGE:
@@ -547,7 +562,7 @@ public class OneRangePartitionEvaluator
             ColumnRange origin = context.columnRanges.get(qualifiedSlot);
             ColumnRange newRange = origin.intersect(qualifiedRange);
 
-            Map<Slot, ColumnRange> newRanges = 
replaceSlotRange(context.columnRanges, qualifiedSlot, newRange);
+            Map<Expression, ColumnRange> newRanges = 
replaceExprRange(context.columnRanges, qualifiedSlot, newRange);
 
             if (newRange.isEmptyRange()) {
                 return new EvaluateRangeResult(BooleanLiteral.FALSE, 
newRanges, context.childrenResult);
@@ -558,9 +573,10 @@ public class OneRangePartitionEvaluator
         return context;
     }
 
-    private Map<Slot, ColumnRange> replaceSlotRange(Map<Slot, ColumnRange> 
originRange, Slot slot, ColumnRange range) {
-        LinkedHashMap<Slot, ColumnRange> newRanges = 
Maps.newLinkedHashMap(originRange);
-        newRanges.put(slot, range);
+    private Map<Expression, ColumnRange> replaceExprRange(Map<Expression, 
ColumnRange> originRange, Expression expr,
+            ColumnRange range) {
+        LinkedHashMap<Expression, ColumnRange> newRanges = 
Maps.newLinkedHashMap(originRange);
+        newRanges.put(expr, range);
         return ImmutableMap.copyOf(newRanges);
     }
 
@@ -568,20 +584,19 @@ public class OneRangePartitionEvaluator
             Expression originResult, EvaluateRangeResult left, 
EvaluateRangeResult right,
             BiFunction<ColumnRange, ColumnRange, ColumnRange> mergeFunction) {
 
-        Map<Slot, ColumnRange> leftRanges = left.columnRanges;
-        Map<Slot, ColumnRange> rightRanges = right.columnRanges;
+        Map<Expression, ColumnRange> leftRanges = left.columnRanges;
+        Map<Expression, ColumnRange> rightRanges = right.columnRanges;
 
         if (leftRanges.equals(rightRanges)) {
             return new EvaluateRangeResult(originResult, leftRanges, 
ImmutableList.of(left, right));
         }
-
-        Set<Slot> slots = ImmutableSet.<Slot>builder()
+        Set<Expression> exprs = ImmutableSet.<Expression>builder()
                 .addAll(leftRanges.keySet())
                 .addAll(rightRanges.keySet())
                 .build();
 
-        Map<Slot, ColumnRange> mergedRange = slots.stream()
-                .map(slot -> Pair.of(slot, 
mergeFunction.apply(leftRanges.get(slot), rightRanges.get(slot))))
+        Map<Expression, ColumnRange> mergedRange = exprs.stream()
+                .map(expr -> Pair.of(expr, 
mergeFunction.apply(leftRanges.get(expr), rightRanges.get(expr))))
                 .collect(ImmutableMap.toImmutableMap(Pair::key, Pair::value));
         return new EvaluateRangeResult(originResult, mergedRange, 
ImmutableList.of(left, right));
     }
@@ -616,6 +631,19 @@ public class OneRangePartitionEvaluator
         return literals;
     }
 
+    @Override
+    public EvaluateRangeResult visitDateTrunc(DateTrunc dateTrunc, 
EvaluateRangeInput context) {
+        EvaluateRangeResult result = super.visitDateTrunc(dateTrunc, context);
+        if (!(result.result instanceof DateTrunc)) {
+            return result;
+        }
+        Expression dateTruncChild = dateTrunc.child(0);
+        if (partitionSlotContainsNull.containsKey(dateTruncChild)) {
+            partitionSlotContainsNull.put(dateTrunc, true);
+        }
+        return computeMonotonicFunctionRange(result);
+    }
+
     @Override
     public EvaluateRangeResult visitDate(Date date, EvaluateRangeInput 
context) {
         EvaluateRangeResult result = super.visitDate(date, context);
@@ -665,13 +693,13 @@ public class OneRangePartitionEvaluator
     private Map<Slot, PartitionSlotInput> fillSlotRangesToInputs(
             Map<Slot, PartitionSlotInput> inputs) {
 
-        Builder<Slot, ColumnRange> allColumnRangesBuilder =
+        Builder<Expression, ColumnRange> allColumnRangesBuilder =
                 ImmutableMap.builderWithExpectedSize(16);
         for (Entry<Slot, PartitionSlotInput> entry : inputs.entrySet()) {
             allColumnRangesBuilder.put(entry.getKey(), 
entry.getValue().columnRanges.get(entry.getKey()));
         }
 
-        Map<Slot, ColumnRange> allColumnRanges = 
allColumnRangesBuilder.build();
+        Map<Expression, ColumnRange> allColumnRanges = 
allColumnRangesBuilder.build();
 
         Builder<Slot, PartitionSlotInput> partitionSlotInputs =
                 ImmutableMap.builderWithExpectedSize(16);
@@ -683,12 +711,9 @@ public class OneRangePartitionEvaluator
 
     /** EvaluateRangeInput */
     public static class EvaluateRangeInput {
-        private Map<Slot, ColumnRange> defaultColumnRanges;
         private Map<Slot, PartitionSlotInput> slotToInput;
 
-        public EvaluateRangeInput(Map<Slot, ColumnRange> defaultColumnRanges,
-                Map<Slot, PartitionSlotInput> slotToInput) {
-            this.defaultColumnRanges = defaultColumnRanges;
+        public EvaluateRangeInput(Map<Slot, PartitionSlotInput> slotToInput) {
             this.slotToInput = slotToInput;
         }
     }
@@ -702,7 +727,8 @@ public class OneRangePartitionEvaluator
      */
     public static class EvaluateRangeResult {
         private final Expression result;
-        private final Map<Slot, ColumnRange> columnRanges;
+        private final Map<Expression, ColumnRange> columnRanges;
+        // private final Map<Slot, ColumnRange> columnRanges;
         private final List<EvaluateRangeResult> childrenResult;
 
         // rejectNot = true, if \exist e \in R, pred(e)=true, then we have 
\forAll e \in R, !pred(e)=false
@@ -717,7 +743,7 @@ public class OneRangePartitionEvaluator
         //      R=(1,10), pred: k < 11. "k<11" holds true over R, and "NOT 
k<11" dose not hold over R
         private final boolean rejectNot;
 
-        public EvaluateRangeResult(Expression result, Map<Slot, ColumnRange> 
columnRanges,
+        public EvaluateRangeResult(Expression result, Map<Expression, 
ColumnRange> columnRanges,
                                    List<EvaluateRangeResult> childrenResult, 
boolean rejectNot) {
             this.result = result;
             this.columnRanges = columnRanges;
@@ -725,7 +751,7 @@ public class OneRangePartitionEvaluator
             this.rejectNot = rejectNot;
         }
 
-        public EvaluateRangeResult(Expression result, Map<Slot, ColumnRange> 
columnRanges,
+        public EvaluateRangeResult(Expression result, Map<Expression, 
ColumnRange> columnRanges,
                 List<EvaluateRangeResult> childrenResult) {
             this(result, columnRanges, childrenResult, 
allIsRejectNot(childrenResult));
         }
@@ -757,7 +783,7 @@ public class OneRangePartitionEvaluator
         Slot partitionSlot = partitionSlots.get(0);
         Literal literal = (Literal) inputs.get(0).get(0);
         ColumnRange slotRange = ColumnRange.singleton(literal);
-        ImmutableMap<Slot, ColumnRange> slotToRange = 
ImmutableMap.of(partitionSlot, slotRange);
+        ImmutableMap<Expression, ColumnRange> slotToRange = 
ImmutableMap.of(partitionSlot, slotRange);
         Map<Slot, PartitionSlotInput> slotToInputs =
                 ImmutableMap.of(partitionSlot, new PartitionSlotInput(literal, 
slotToRange));
         return ImmutableList.of(slotToInputs);
@@ -810,7 +836,7 @@ public class OneRangePartitionEvaluator
                     previousIsLowerBoundLiteral = false;
                     previousIsUpperBoundLiteral = false;
                 }
-                ImmutableMap<Slot, ColumnRange> slotToRange = 
ImmutableMap.of(partitionSlot, slotRange);
+                ImmutableMap<Expression, ColumnRange> slotToRange = 
ImmutableMap.of(partitionSlot, slotRange);
                 slotToInputs.put(partitionSlot, new 
PartitionSlotInput(expression, slotToRange));
             }
 
@@ -819,4 +845,63 @@ public class OneRangePartitionEvaluator
         }
         return onePartitionInputs;
     }
+
+    private EvaluateRangeResult removeEmptyRange(EvaluateRangeResult result) {
+        ImmutableMap.Builder<Expression, ColumnRange> builder = 
ImmutableMap.builder();
+        for (Map.Entry<Expression, ColumnRange> entry : 
result.columnRanges.entrySet()) {
+            if (entry.getValue().isEmptyRange()) {
+                continue;
+            }
+            builder.put(entry);
+        }
+        return new EvaluateRangeResult(result.result, builder.build(), 
result.childrenResult);
+    }
+
+    private EvaluateRangeResult 
computeMonotonicFunctionRange(EvaluateRangeResult result) {
+        Monotonic func = (Monotonic) result.result;
+        if (rangeMap.containsKey(func)) {
+            return new EvaluateRangeResult((Expression) func, 
ImmutableMap.of((Expression) func,
+                    rangeMap.get(func)), result.childrenResult);
+        }
+        int childIndex = func.getMonotonicFunctionChildIndex();
+        Expression funcChild = func.child(childIndex);
+        if (!result.childrenResult.get(0).columnRanges.containsKey(funcChild)) 
{
+            return result;
+        }
+        ColumnRange childRange = 
result.childrenResult.get(0).columnRanges.get(funcChild);
+        if (childRange.isEmptyRange() || childRange.asRanges().size() != 1
+                || (!childRange.span().hasLowerBound() && 
!childRange.span().hasUpperBound())) {
+            return result;
+        }
+        Range<ColumnBound> span = childRange.span();
+        Literal lower = span.hasLowerBound() ? span.lowerEndpoint().getValue() 
: null;
+        Literal upper = span.hasUpperBound() ? span.upperEndpoint().getValue() 
: null;
+        Expression lowerValue = lower != null ? 
FoldConstantRuleOnFE.evaluate(func.withConstantArgs(lower),
+                expressionRewriteContext) : null;
+        Expression upperValue = upper != null ? 
FoldConstantRuleOnFE.evaluate(func.withConstantArgs(upper),
+                expressionRewriteContext) : null;
+        if (!func.isPositive()) {
+            Expression temp = lowerValue;
+            lowerValue = upperValue;
+            upperValue = temp;
+        }
+        LinkedHashMap<Expression, ColumnRange> newRanges = 
Maps.newLinkedHashMap();
+        ColumnRange newRange = ColumnRange.all();
+        if (lowerValue instanceof Literal && upperValue instanceof Literal && 
lowerValue.equals(upperValue)) {
+            newRange = ColumnRange.singleton((Literal) lowerValue);
+            rangeMap.put((Expression) func, newRange);
+            newRanges.put((Expression) func, newRange);
+            return new EvaluateRangeResult(lowerValue, newRanges, 
result.childrenResult);
+        } else {
+            if (lowerValue instanceof Literal) {
+                newRange = newRange.withLowerBound((Literal) lowerValue);
+            }
+            if (upperValue instanceof Literal) {
+                newRange = newRange.withUpperBound((Literal) upperValue);
+            }
+            rangeMap.put((Expression) func, newRange);
+            newRanges.put((Expression) func, newRange);
+            return new EvaluateRangeResult((Expression) func, newRanges, 
result.childrenResult);
+        }
+    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
index 44aaeade53d..994ae477eda 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/PartitionSlotInput.java
@@ -18,7 +18,6 @@
 package org.apache.doris.nereids.rules.expression.rules;
 
 import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.Slot;
 
 import com.google.common.collect.ImmutableMap;
 
@@ -116,9 +115,9 @@ public class PartitionSlotInput {
     //                          part_column1                    
IntegerLiteral(100)
     //
     // because we can't fold this predicate to BooleanLiteral.FALSE, so we 
should scan the partition.
-    public final Map<Slot, ColumnRange> columnRanges;
+    public final Map<Expression, ColumnRange> columnRanges;
 
-    public PartitionSlotInput(Expression result, Map<Slot, ColumnRange> 
columnRanges) {
+    public PartitionSlotInput(Expression result, Map<Expression, ColumnRange> 
columnRanges) {
         this.result = result;
         this.columnRanges = ImmutableMap.copyOf(columnRanges);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/Monotonic.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/Monotonic.java
new file mode 100644
index 00000000000..2fdde0e7415
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/Monotonic.java
@@ -0,0 +1,36 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.nereids.trees.expressions.functions;
+
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
+
+/** monotonicity of expressions */
+public interface Monotonic extends ExpressionTrait {
+    // true means that the function is an increasing function
+    boolean isPositive();
+
+    // return the range input child index
+    // e.g. date_trunc(dt,'xxx') return 0
+    int getMonotonicFunctionChildIndex();
+
+    // return the function with the arguments replaced by literal
+    // e.g. date_trunc(dt, 'day'), dt in range ['2020-01-01 10:00:00', 
'2020-01-03 10:00:00']
+    // return date_trunc('2020-01-01 10:00:00', 'day')
+    Expression withConstantArgs(Literal literal);
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateTrunc.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateTrunc.java
index 743976c6c1a..cbd2da5627b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateTrunc.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateTrunc.java
@@ -22,6 +22,8 @@ import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
 import 
org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
+import org.apache.doris.nereids.trees.expressions.functions.Monotonic;
+import org.apache.doris.nereids.trees.expressions.literal.Literal;
 import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral;
 import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
@@ -41,7 +43,7 @@ import java.util.List;
  * ScalarFunction 'date_trunc'. This class is generated by GenerateFunction.
  */
 public class DateTrunc extends ScalarFunction
-        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable {
+        implements BinaryExpression, ExplicitlyCastableSignature, 
AlwaysNullable, Monotonic {
 
     public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
             FunctionSignature.ret(DateTimeV2Type.SYSTEM_DEFAULT)
@@ -91,4 +93,19 @@ public class DateTrunc extends ScalarFunction
     public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
         return visitor.visitDateTrunc(this, context);
     }
+
+    @Override
+    public boolean isPositive() {
+        return true;
+    }
+
+    @Override
+    public int getMonotonicFunctionChildIndex() {
+        return 0;
+    }
+
+    @Override
+    public Expression withConstantArgs(Literal literal) {
+        return new DateTrunc(literal, child(1));
+    }
 }
diff --git 
a/regression-test/suites/nereids_rules_p0/partition_prune/test_date_trunc_prune.groovy
 
b/regression-test/suites/nereids_rules_p0/partition_prune/test_date_trunc_prune.groovy
new file mode 100644
index 00000000000..c4769b12b12
--- /dev/null
+++ 
b/regression-test/suites/nereids_rules_p0/partition_prune/test_date_trunc_prune.groovy
@@ -0,0 +1,296 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_date_trunc_prune") {
+    sql "SET enable_nereids_planner=true"
+    sql "SET enable_fallback_to_original_planner=false"
+    sql "drop table if exists mal_test_partition_range5"
+    sql"""
+        CREATE TABLE `mal_test_partition_range5` (
+          `a` INT NULL,
+          `b` datetime not NULL,
+          `c` INT NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(`a`, `b`, `c`)
+        PARTITION BY RANGE(`b`)
+        (PARTITION p1 VALUES [("2020-01-05 10:00:00"), ("2020-01-09 
10:00:00")),
+        PARTITION p2 VALUES [("2020-01-09 10:00:00"), ("2020-01-13 10:00:00")),
+        PARTITION p3 VALUES [("2020-01-13 10:00:00"), ("2020-01-19 10:00:00")))
+        DISTRIBUTED BY HASH(`a`) BUCKETS 10
+        PROPERTIES (
+        "replication_allocation" = "tag.location.default: 1"
+        );"""
+    sql """insert into mal_test_partition_range5 values(1,"2020-01-09 
09:00:00",4),(1,"2020-01-09 11:00:00",4),
+        (1,"2020-01-13 11:00:00",4),(1,"2020-01-13 09:00:00",4)"""
+    // > >= < <= = <=>
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')<="2020-01-08" """
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')<"2020-01-08" """
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
"2020-01-08">=date_trunc(b,'day')"""
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where "2020-01-08" > 
date_trunc(b,'day')"""
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')="2020-01-08" """
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where "2020-01-08" = 
date_trunc(b,'day')"""
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')>="2020-01-14" """
+        contains("partitions=1/3 (p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')>"2020-01-14" """
+        contains("partitions=1/3 (p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
"2020-01-14"<=date_trunc(b,'day')"""
+        contains("partitions=1/3 (p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where "2020-01-14" < 
date_trunc(b,'day')"""
+        contains("partitions=1/3 (p3)")
+    }
+
+    explain {
+        sql """select * from mal_test_partition_range5 where  
date_trunc(b,'day') in ("2020-01-13 00:00:00")"""
+        contains("partitions=2/3 (p2,p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where "2020-01-14" <=> 
date_trunc(b,'day')"""
+        contains("partitions=1/3 (p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where  
date_trunc(b,'day') <=>"2020-01-14" """
+        contains("partitions=1/3 (p3)")
+    }
+
+    // and or
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')>"2020-01-09"  and date_trunc(b,'day') <"2020-01-13" """
+        contains("partitions=1/3 (p2)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')>"2020-01-09"  or date_trunc(b,'day') <"2020-01-13" """
+        contains("partitions=3/3 (p1,p2,p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day')>"2020-01-14"  or date_trunc(b,'day') <"2020-01-06" """
+        contains("partitions=2/3 (p1,p3)")
+    }
+
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day') between "2020-01-09"  and "2020-01-13" """
+        contains("partitions=3/3 (p1,p2,p3)")
+
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day') between "2020-01-10"  and "2020-01-14" """
+        contains("partitions=2/3 (p2,p3)")
+
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day') between "2020-01-10"  and "2020-01-12" """
+        contains("partitions=1/3 (p2)")
+    }
+
+    // test not
+    for (int i = 0; i < 2; i++) {
+        if (i == 0) {
+            // forbid rewrite not a>1 to a<=1
+            sql "set disable_nereids_rules = 'REWRITE_FILTER_EXPRESSION'"
+        } else {
+            sql "set disable_nereids_rules = ''"
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day')<="2020-01-14" """
+            contains("partitions=1/3 (p3)")
+        }
+        explain {
+            sql """ select * from mal_test_partition_range5 where not 
date_trunc(b,'day')<"2020-01-14" """
+            contains("partitions=1/3 (p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
"2020-01-14">=date_trunc(b,'day')"""
+            contains("partitions=1/3 (p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
"2020-01-14" > date_trunc(b,'day')"""
+            contains("partitions=1/3 (p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day')="2020-01-08" """
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
"2020-01-08" = date_trunc(b,'day')"""
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day')>="2020-01-9" """
+            contains("partitions=1/3 (p1)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day')>"2020-01-9" """
+            contains("partitions=2/3 (p1,p2)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
"2020-01-9"<=date_trunc(b,'day')"""
+            contains("partitions=1/3 (p1)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
"2020-01-9" < date_trunc(b,'day')"""
+            contains("partitions=2/3 (p1,p2)")
+        }
+        explain {
+            sql """ select * from mal_test_partition_range5 where  not 
date_trunc(b,'day') in ("2020-01-13 00:00:00")"""
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """ select * from mal_test_partition_range5 where not 
"2020-01-14" <=> date_trunc(b,'day')"""
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day') <=>"2020-01-14" """
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """ select * from mal_test_partition_range5 where not  
(date_trunc(b,'day')>"2020-01-09"  and date_trunc(b,'day') <"2020-01-13") """
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """ select * from mal_test_partition_range5 where not 
(date_trunc(b,'day')>="2020-01-13"  or date_trunc(b,'day') <="2020-01-9") """
+            contains("partitions=1/3 (p2)")
+        }
+        explain {
+            sql """ select * from mal_test_partition_range5 where not 
date_trunc(b,'day')<="2020-01-14"  or date_trunc(b,'day') <"2020-01-06" """
+            contains("partitions=2/3 (p1,p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day') between "2020-01-09"  and "2020-01-13" """
+            contains("partitions=2/3 (p1,p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where not 
date_trunc(b,'day') between "2020-01-10"  and "2020-01-14" """
+            contains("partitions=3/3 (p1,p2,p3)")
+        }
+        explain {
+            sql """select * from mal_test_partition_range5 where 
date_trunc(b,'day') not between "2020-01-4"  and "2020-01-15" """
+            contains("partitions=1/3 (p3)")
+        }
+    }
+
+    // trunc(b) and b
+    explain {
+        sql """select * from mal_test_partition_range5 where (not 
date_trunc(b,'day')<="2020-01-14") or b<"2020-01-9" """
+        contains("partitions=2/3 (p1,p3)")
+    }
+    explain {
+        sql """select * from mal_test_partition_range5 where  
date_trunc(b,'day')<"2020-01-13" and  b>"2020-01-10" """
+        contains("partitions=1/3 (p2)")
+    }
+    explain {
+        sql """ select * from mal_test_partition_range5 where  
date_trunc(b,'day')<"2020-01-13" and  b>"2020-01-9" """
+        contains("partitions=2/3 (p1,p2)")
+    }
+    explain {
+        sql """ select * from mal_test_partition_range5 where ( 
date_trunc(b,'day')<="2020-01-14" and b >"2020-01-12") or b<"2020-01-9" """
+        contains("partitions=3/3 (p1,p2,p3)")
+    }
+    explain {
+        sql """ select * from mal_test_partition_range5 where ( 
date_trunc(b,'day')<="2020-01-14" and b >"2020-01-19") or b<"2020-01-9" """
+        contains("partitions=2/3 (p1,p3)")
+    }
+    explain {
+        sql """ select * from mal_test_partition_range5 where ( 
date_trunc(b,'day')<="2020-01-14" and b >"2020-01-20") or b<"2020-01-9" """
+        contains("partitions=1/3 (p1)")
+    }
+    explain {
+        sql """ select * from mal_test_partition_range5 where ( not 
date_trunc(b,'day')<="2020-01-14" or b >"2020-01-20") or b<"2020-01-9" """
+        contains("partitions=2/3 (p1,p3)")
+    }
+    explain {
+        sql """ select * from mal_test_partition_range5 where (  
date_trunc(b,'day') between "2020-01-14" and "2020-01-20") or b<"2020-01-9" """
+        contains("partitions=2/3 (p1,p3)")
+    }
+
+    // is null, can support but now not
+    sql "drop table if exists null_range_date"
+    sql """
+        create table null_range_date(
+        k0 datetime null
+        )
+        partition by range (k0)
+        (
+        PARTITION p10 values less than ('2022-01-01 10:00:00'),
+        PARTITION p100 values less than ('2022-01-04 10:00:00'),
+        PARTITION pMAX values less than (maxvalue)
+        )
+        DISTRIBUTED BY HASH(`k0`) BUCKETS 1 properties("replication_num"="1")
+    """
+    sql "insert into null_range_date values('2022-01-03 
10:00:00'),('2019-01-01 10:00:00'),('2022-01-02 10:00:00'),('2024-01-01 
10:00:00'),(null);"
+    explain {
+        sql "select * from null_range_date where date_trunc(k0,'day') is null"
+        contains("partitions=3/3 (p10,p100,pMAX)")
+    }
+    // test infinite range
+    explain {
+        sql "select * from null_range_date where date_trunc(k0,'day') 
<'2022-1-3'"
+        contains("partitions=2/3 (p10,p100)")
+    }
+    explain {
+        sql "select * from null_range_date where date_trunc(k0,'day') 
>'2022-1-3'"
+        contains("partitions=2/3 (p100,pMAX)")
+    }
+
+    sql "drop table if exists mal_test_partition_range2_two_date_int"
+    sql """CREATE TABLE `mal_test_partition_range2_two_date_int` (
+          `dt` DATETIME NULL,
+          `id` INT NULL,
+          `c` INT NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(`dt`, `id`, `c`)
+        PARTITION BY RANGE(`dt`, `id`)
+        (PARTITION p201701_1000 VALUES [('0000-01-01', "-2147483648"), 
('2017-02-01', "1000")),
+        PARTITION p201702_2000 VALUES [('2017-02-01', "1000"), ('2017-03-01', 
"2000")),
+        PARTITION p201703_all VALUES [('2017-03-01', "2000"), ('2017-04-01', 
"-2147483648")))
+        DISTRIBUTED BY HASH(`dt`) BUCKETS 10
+        PROPERTIES (
+        "replication_allocation" = "tag.location.default: 1"
+        );"""
+    sql """insert into mal_test_partition_range2_two_date_int 
values('2017-01-03 10:00:00', 3,23),('2017-02-04 10:00:00', 333,4),('2017-03-05 
10:00:00', 1222,6);"""
+    explain {
+        sql """select * from mal_test_partition_range2_two_date_int where 
date_trunc(dt,'month') = '2017-2-1 00:00:00' and id>0 ;"""
+        contains ("partitions=2/3 (p201701_1000,p201702_2000)")
+    }
+    explain {
+        sql "select * from mal_test_partition_range2_two_date_int where 
date_trunc(dt,'month') > '2017-2-1  00:00:00' and id>100;"
+        contains("partitions=2/3 (p201702_2000,p201703_all)")
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to