morrySnow commented on code in PR #16980:
URL: https://github.com/apache/doris/pull/16980#discussion_r1120101267


##########
fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4:
##########
@@ -50,7 +50,7 @@ explain
 planType
     : PARSED
     | ANALYZED
-    | REWRITTEN | LOGICAL  // same type
+    | REWRITTEN | CACHED | LOGICAL  // same type

Review Comment:
   cached and rewritten should not be same type, so cached should in new line



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rewrite/rules/SimplifyRange.java:
##########
@@ -96,7 +96,8 @@ private ValueDesc buildRange(ComparisonPredicate predicate) {
             Expression rewrite = ExpressionRuleExecutor.normalize(predicate);
             Expression right = rewrite.child(1);
             // only handle `NumericType`
-            if (right.isLiteral() && right.getDataType().isNumericType()) {
+            if (right.isLiteral()
+                    && right.getDataType().isRangeType()) {

Review Comment:
   useless wrap



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java:
##########
@@ -173,6 +179,14 @@ public Plan plan(LogicalPlan plan, PhysicalProperties 
requireProperties, Explain
                 }
             }
 
+            cache();

Review Comment:
   why add a new stage rather than put it into rewrite stage?



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/CacheContext.java:
##########
@@ -0,0 +1,189 @@
+// 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;
+
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.catalog.Partition;
+import org.apache.doris.catalog.PartitionType;
+import org.apache.doris.common.Config;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.plans.algebra.OlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.qe.cache.Cache;
+import org.apache.doris.qe.cache.PartitionRange;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Context used in cache.
+ */
+public class CacheContext {
+    private OlapTable lastOlapTable;
+
+    private Partition lastPartition;
+
+    private String cacheKey;
+
+    private PartitionRange range;
+
+    private Cache.HitRange hitRange;
+
+    private InternalService.PFetchCacheResult cacheResult;
+
+    private int countNewTable;
+
+    public CacheContext() {
+        countNewTable = 0;
+        hitRange = Cache.HitRange.None;
+    }
+
+    public OlapTable getLastOlapTable() {
+        return lastOlapTable;
+    }
+
+    public Partition getLastPartition() {
+        return lastPartition;
+    }
+
+    public String getCacheKey() {
+        return cacheKey;
+    }
+
+    public PartitionRange getRange() {
+        return range;
+    }
+
+    public Cache.HitRange getHitRange() {
+        return hitRange;
+    }
+
+    public InternalService.PFetchCacheResult getCacheResult() {
+        return cacheResult;
+    }
+
+    public void setLastOlapTable(OlapTable lastOlapTable) {
+        this.lastOlapTable = lastOlapTable;
+    }
+
+    public void setLastPartition(Partition lastPartition) {
+        this.lastPartition = lastPartition;
+    }
+
+    public void setCacheKey(String cacheKey) {
+        this.cacheKey = cacheKey;
+    }
+
+    public void setRange(PartitionRange range) {
+        this.range = range;
+    }
+
+    public void setHitRange(Cache.HitRange hitRange) {
+        this.hitRange = hitRange;
+    }
+
+    public void setCacheResult(InternalService.PFetchCacheResult cacheResult) {
+        this.cacheResult = cacheResult;
+    }
+
+    /**
+     * Check the last version time of olapScans.
+     */
+    public boolean checkOlapScans(Set<OlapScan> olapScans) {
+        long now = System.currentTimeMillis();
+        long interval = Config.cache_last_version_interval_second * 1000L;
+        countNewTable = 0;
+        for (OlapScan olapScan : olapScans) {
+            OlapTable olapTable = olapScan.getTable();
+            Optional<Partition> partition = 
olapTable.getAllPartitions().stream().max(

Review Comment:
   in the legacy planner, we only check selected partitions



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java:
##########
@@ -203,6 +217,33 @@ private void analyze() {
         cascadesContext.newAnalyzer().analyze();
     }
 
+    private void cache() {
+        ConnectContext connectContext = cascadesContext.getConnectContext();
+        CacheContext cacheContext = 
cascadesContext.getStatementContext().getCacheContext();
+        boolean isEnableSqlCache = Config.cache_enable_sql_mode
+                    && connectContext.getSessionVariable().isEnableSqlCache();
+        boolean isEnablePartitionCache = Config.cache_enable_partition_mode
+                    && 
connectContext.getSessionVariable().isEnablePartitionCache();
+        Plan plan = cascadesContext.getRewritePlan();
+        if (!isEnableSqlCache && !isEnablePartitionCache) {
+            return;
+        }
+        if 
(!cacheContext.checkOlapScans(plan.collect(OlapScan.class::isInstance))) {
+            return;
+        }
+        if (isEnableSqlCache && cacheContext.isEnableSqlCache()) {
+            cacheContext.setCacheKey(plan.treeString());

Review Comment:
   does plan.treeString() enough to distingush between differenct sql?



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/CacheContext.java:
##########
@@ -0,0 +1,189 @@
+// 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;
+
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.catalog.Partition;
+import org.apache.doris.catalog.PartitionType;
+import org.apache.doris.common.Config;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.plans.algebra.OlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.qe.cache.Cache;
+import org.apache.doris.qe.cache.PartitionRange;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Context used in cache.
+ */
+public class CacheContext {
+    private OlapTable lastOlapTable;
+
+    private Partition lastPartition;
+
+    private String cacheKey;
+
+    private PartitionRange range;
+
+    private Cache.HitRange hitRange;
+
+    private InternalService.PFetchCacheResult cacheResult;
+
+    private int countNewTable;
+
+    public CacheContext() {
+        countNewTable = 0;
+        hitRange = Cache.HitRange.None;
+    }
+
+    public OlapTable getLastOlapTable() {
+        return lastOlapTable;
+    }
+
+    public Partition getLastPartition() {
+        return lastPartition;
+    }
+
+    public String getCacheKey() {
+        return cacheKey;
+    }
+
+    public PartitionRange getRange() {
+        return range;
+    }
+
+    public Cache.HitRange getHitRange() {
+        return hitRange;
+    }
+
+    public InternalService.PFetchCacheResult getCacheResult() {
+        return cacheResult;
+    }
+
+    public void setLastOlapTable(OlapTable lastOlapTable) {
+        this.lastOlapTable = lastOlapTable;
+    }
+
+    public void setLastPartition(Partition lastPartition) {
+        this.lastPartition = lastPartition;
+    }
+
+    public void setCacheKey(String cacheKey) {
+        this.cacheKey = cacheKey;
+    }
+
+    public void setRange(PartitionRange range) {
+        this.range = range;
+    }
+
+    public void setHitRange(Cache.HitRange hitRange) {
+        this.hitRange = hitRange;
+    }
+
+    public void setCacheResult(InternalService.PFetchCacheResult cacheResult) {
+        this.cacheResult = cacheResult;
+    }
+
+    /**
+     * Check the last version time of olapScans.
+     */
+    public boolean checkOlapScans(Set<OlapScan> olapScans) {

Review Comment:
   there are some other restrict in legacy planner, such as
   ```java
               if (enablePartitionCache() && ((OlapScanNode) 
node).getSelectedPartitionNum() > 1
                       && selectStmt.hasGroupByClause()) {
                   LOG.debug("more than one partition scanned when qeury has 
agg, partition cache cannot use, queryid {}",
                           DebugUtil.printId(queryId));
                   return CacheMode.None;
               }
   ```



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java:
##########
@@ -203,6 +217,33 @@ private void analyze() {
         cascadesContext.newAnalyzer().analyze();
     }
 
+    private void cache() {
+        ConnectContext connectContext = cascadesContext.getConnectContext();
+        CacheContext cacheContext = 
cascadesContext.getStatementContext().getCacheContext();
+        boolean isEnableSqlCache = Config.cache_enable_sql_mode
+                    && connectContext.getSessionVariable().isEnableSqlCache();
+        boolean isEnablePartitionCache = Config.cache_enable_partition_mode
+                    && 
connectContext.getSessionVariable().isEnablePartitionCache();
+        Plan plan = cascadesContext.getRewritePlan();
+        if (!isEnableSqlCache && !isEnablePartitionCache) {
+            return;
+        }
+        if 
(!cacheContext.checkOlapScans(plan.collect(OlapScan.class::isInstance))) {
+            return;
+        }
+        if (isEnableSqlCache && cacheContext.isEnableSqlCache()) {
+            cacheContext.setCacheKey(plan.treeString());
+            SqlCache.getCacheDataForNereids(cacheContext);
+            return;
+        }
+        if 
(!cacheContext.checkAggs(plan.collect(LogicalAggregate.class::isInstance))) {

Review Comment:
   if we cannot hit sql cache, in the legacy planner, we should check whether 
the partition cache is enable



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/CacheContext.java:
##########
@@ -0,0 +1,189 @@
+// 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;
+
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.catalog.Partition;
+import org.apache.doris.catalog.PartitionType;
+import org.apache.doris.common.Config;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.plans.algebra.OlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.qe.cache.Cache;
+import org.apache.doris.qe.cache.PartitionRange;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Context used in cache.
+ */
+public class CacheContext {
+    private OlapTable lastOlapTable;
+
+    private Partition lastPartition;
+
+    private String cacheKey;
+
+    private PartitionRange range;
+
+    private Cache.HitRange hitRange;
+
+    private InternalService.PFetchCacheResult cacheResult;
+
+    private int countNewTable;
+
+    public CacheContext() {
+        countNewTable = 0;
+        hitRange = Cache.HitRange.None;
+    }
+
+    public OlapTable getLastOlapTable() {
+        return lastOlapTable;
+    }
+
+    public Partition getLastPartition() {
+        return lastPartition;
+    }
+
+    public String getCacheKey() {
+        return cacheKey;
+    }
+
+    public PartitionRange getRange() {
+        return range;
+    }
+
+    public Cache.HitRange getHitRange() {
+        return hitRange;
+    }
+
+    public InternalService.PFetchCacheResult getCacheResult() {
+        return cacheResult;
+    }
+
+    public void setLastOlapTable(OlapTable lastOlapTable) {
+        this.lastOlapTable = lastOlapTable;
+    }
+
+    public void setLastPartition(Partition lastPartition) {
+        this.lastPartition = lastPartition;
+    }
+
+    public void setCacheKey(String cacheKey) {
+        this.cacheKey = cacheKey;
+    }
+
+    public void setRange(PartitionRange range) {
+        this.range = range;
+    }
+
+    public void setHitRange(Cache.HitRange hitRange) {
+        this.hitRange = hitRange;
+    }
+
+    public void setCacheResult(InternalService.PFetchCacheResult cacheResult) {
+        this.cacheResult = cacheResult;
+    }
+
+    /**
+     * Check the last version time of olapScans.
+     */
+    public boolean checkOlapScans(Set<OlapScan> olapScans) {

Review Comment:
   we should not use cache if scans include other table other than OlapScan



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SplitConjuncts.java:
##########
@@ -0,0 +1,83 @@
+// 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.rules.rewrite.logical;
+
+import org.apache.doris.nereids.CacheContext;
+import org.apache.doris.nereids.rules.Rule;
+import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.GreaterThan;
+import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
+import org.apache.doris.nereids.trees.expressions.LessThan;
+import org.apache.doris.nereids.trees.expressions.LessThanEqual;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalCache;
+import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Split Conjuncts for partition cache
+ */
+public class SplitConjuncts implements RewriteRuleFactory {
+
+    @Override
+    public List<Rule> buildRules() {
+        return ImmutableList.of(
+            RuleType.PARTITION_CACHE_REWRITE.build(
+                logicalFilter().thenApply(ctx -> {
+                    CacheContext cacheContext = 
ctx.statementContext.getCacheContext();
+                    final LogicalFilter<Plan> filter = ctx.root;
+                    String columnName = cacheContext.getPartColumn().getName();
+
+                    Map<Boolean, List<Expression>> splitConjunts = 
filter.getConjuncts().stream().collect(
+                            Collectors.partitioningBy(expr -> {
+                                if (expr instanceof LessThan
+                                        || expr instanceof LessThanEqual
+                                        || expr instanceof GreaterThan
+                                        || expr instanceof GreaterThanEqual) {
+
+                                    List<Slot> slots = ((ImmutableSet) 
expr.getInputSlots()).asList();
+                                    return slots.size() == 1 && 
slots.get(0).getName().equals(columnName);

Review Comment:
   we cannot use name to do this, because slot'name may be same in different 
relation



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/CacheContext.java:
##########
@@ -0,0 +1,189 @@
+// 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;
+
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.catalog.Partition;
+import org.apache.doris.catalog.PartitionType;
+import org.apache.doris.common.Config;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.plans.algebra.OlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
+import org.apache.doris.proto.InternalService;
+import org.apache.doris.qe.cache.Cache;
+import org.apache.doris.qe.cache.PartitionRange;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Context used in cache.
+ */
+public class CacheContext {
+    private OlapTable lastOlapTable;
+
+    private Partition lastPartition;
+
+    private String cacheKey;
+
+    private PartitionRange range;
+
+    private Cache.HitRange hitRange;
+
+    private InternalService.PFetchCacheResult cacheResult;
+
+    private int countNewTable;
+
+    public CacheContext() {
+        countNewTable = 0;
+        hitRange = Cache.HitRange.None;
+    }
+
+    public OlapTable getLastOlapTable() {
+        return lastOlapTable;
+    }
+
+    public Partition getLastPartition() {
+        return lastPartition;
+    }
+
+    public String getCacheKey() {
+        return cacheKey;
+    }
+
+    public PartitionRange getRange() {
+        return range;
+    }
+
+    public Cache.HitRange getHitRange() {
+        return hitRange;
+    }
+
+    public InternalService.PFetchCacheResult getCacheResult() {
+        return cacheResult;
+    }
+
+    public void setLastOlapTable(OlapTable lastOlapTable) {
+        this.lastOlapTable = lastOlapTable;
+    }
+
+    public void setLastPartition(Partition lastPartition) {
+        this.lastPartition = lastPartition;
+    }
+
+    public void setCacheKey(String cacheKey) {
+        this.cacheKey = cacheKey;
+    }
+
+    public void setRange(PartitionRange range) {
+        this.range = range;
+    }
+
+    public void setHitRange(Cache.HitRange hitRange) {
+        this.hitRange = hitRange;
+    }
+
+    public void setCacheResult(InternalService.PFetchCacheResult cacheResult) {
+        this.cacheResult = cacheResult;
+    }
+
+    /**
+     * Check the last version time of olapScans.
+     */
+    public boolean checkOlapScans(Set<OlapScan> olapScans) {
+        long now = System.currentTimeMillis();
+        long interval = Config.cache_last_version_interval_second * 1000L;
+        countNewTable = 0;
+        for (OlapScan olapScan : olapScans) {
+            OlapTable olapTable = olapScan.getTable();
+            Optional<Partition> partition = 
olapTable.getAllPartitions().stream().max(
+                    Comparator.comparing(i -> i.getVisibleVersionTime())
+            );
+            if (!partition.isPresent()) {
+                continue;
+            }
+            if ((now - partition.get().getVisibleVersionTime()) < interval) {
+                ++countNewTable;
+            }
+            if (lastPartition == null
+                    || partition.get().getVisibleVersionTime() > 
lastPartition.getVisibleVersionTime()) {
+                lastOlapTable = olapTable;
+                lastPartition = partition.get();
+            }
+        }
+        return isEnableCache();
+    }
+
+    /**
+     * Check if agg expr contain partition column.
+     */
+    public boolean checkAggs(Set<LogicalAggregate> aggs) {
+        String columnName = getPartColumn().getName();
+        return !aggs.isEmpty() && aggs.stream().allMatch(agg -> {
+            boolean noneMatchColumn = 
agg.getGroupByExpressions().stream().noneMatch(expr ->
+                    expr instanceof SlotReference
+                            && ((SlotReference) 
expr).getName().equals(columnName));

Review Comment:
   i don't think it is good enough to check whether agg's group by exprs 
contains partition columns. because we could use alias wrap a real column, 
after that the slot refence's name is alias name, but it refer to partition 
column. such as
   ```sql
   select ca from (select c1 as ca from t) t2 group by ca 
   ```



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/NereidsRewriter.java:
##########
@@ -198,6 +198,7 @@ public class NereidsRewriter extends BatchRewriteJob {
             // this rule batch must keep at the end of rewrite to do some plan 
check
             topic("Final rewrite and check", bottomUp(
                 new AdjustNullable(),
+                new ExpressionOptimization(),

Review Comment:
   why add this after adjust nullable?



##########
fe/fe-core/src/main/java/org/apache/doris/qe/cache/CacheAnalyzer.java:
##########
@@ -108,6 +110,26 @@ public CacheAnalyzer(ConnectContext context, StatementBase 
parsedStmt, Planner p
         checkCacheConfig();
     }
 
+    public CacheAnalyzer(ConnectContext context, StatementBase parsedStmt, 
NereidsPlanner planner) {

Review Comment:
   add comment `constructor for Nereids`



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/SplitConjuncts.java:
##########
@@ -0,0 +1,83 @@
+// 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.rules.rewrite.logical;
+
+import org.apache.doris.nereids.CacheContext;
+import org.apache.doris.nereids.rules.Rule;
+import org.apache.doris.nereids.rules.RuleType;
+import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.GreaterThan;
+import org.apache.doris.nereids.trees.expressions.GreaterThanEqual;
+import org.apache.doris.nereids.trees.expressions.LessThan;
+import org.apache.doris.nereids.trees.expressions.LessThanEqual;
+import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalCache;
+import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Split Conjuncts for partition cache
+ */
+public class SplitConjuncts implements RewriteRuleFactory {
+
+    @Override
+    public List<Rule> buildRules() {
+        return ImmutableList.of(
+            RuleType.PARTITION_CACHE_REWRITE.build(
+                logicalFilter().thenApply(ctx -> {
+                    CacheContext cacheContext = 
ctx.statementContext.getCacheContext();
+                    final LogicalFilter<Plan> filter = ctx.root;
+                    String columnName = cacheContext.getPartColumn().getName();
+
+                    Map<Boolean, List<Expression>> splitConjunts = 
filter.getConjuncts().stream().collect(
+                            Collectors.partitioningBy(expr -> {
+                                if (expr instanceof LessThan
+                                        || expr instanceof LessThanEqual
+                                        || expr instanceof GreaterThan
+                                        || expr instanceof GreaterThanEqual) {
+
+                                    List<Slot> slots = ((ImmutableSet) 
expr.getInputSlots()).asList();
+                                    return slots.size() == 1 && 
slots.get(0).getName().equals(columnName);
+                                }
+                                return false;
+                            })
+                    );
+                    Set<Expression> cachedConjuncts = 
Sets.newHashSet(splitConjunts.get(true));
+                    Set<Expression> remainConjuncts = 
Sets.newHashSet(splitConjunts.get(false));
+                    if (cachedConjuncts.size() == 2) {

Review Comment:
   need to explain what's mean about the magic number `2`



##########
fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java:
##########
@@ -1096,25 +1097,25 @@ private boolean sendCachedValues(MysqlChannel channel, 
List<InternalService.PCac
     /**
      * Handle the SelectStmt via Cache.
      */
-    private void handleCacheStmt(CacheAnalyzer cacheAnalyzer, MysqlChannel 
channel, SelectStmt selectStmt)
+    private void handleCacheStmt(CacheAnalyzer cacheAnalyzer, MysqlChannel 
channel)
             throws Exception {
         InternalService.PFetchCacheResult cacheResult = 
cacheAnalyzer.getCacheData();
         CacheMode mode = cacheAnalyzer.getCacheMode();
-        SelectStmt newSelectStmt = selectStmt;
+        Queriable queryStmt = (Queriable) parsedStmt;
         boolean isSendFields = false;
         if (cacheResult != null) {
             isCached = true;
             if (cacheAnalyzer.getHitRange() == Cache.HitRange.Full) {
-                sendCachedValues(channel, cacheResult.getValuesList(), 
newSelectStmt, isSendFields, true);
+                sendCachedValues(channel, cacheResult.getValuesList(), 
queryStmt, isSendFields, true);
                 return;
             }
             // rewrite sql
             if (mode == CacheMode.Partition) {
                 if (cacheAnalyzer.getHitRange() == Cache.HitRange.Left) {
                     isSendFields = sendCachedValues(channel, 
cacheResult.getValuesList(),
-                            newSelectStmt, isSendFields, false);
+                        queryStmt, isSendFields, false);

Review Comment:
   indent should `last line + 8`



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