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]