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 18cb3954960 [fix] (inverted index) fix the error result in the query
when using count on index (#41375) (#41690)
18cb3954960 is described below
commit 18cb3954960c92a37567a77374bbb2013d6337ff
Author: Sun Chenyang <[email protected]>
AuthorDate: Fri Oct 11 17:15:14 2024 +0800
[fix] (inverted index) fix the error result in the query when using count
on index (#41375) (#41690)
## Proposed changes
pick from master #41375
<!--Describe your changes.-->
---
.../rules/implementation/AggregateStrategies.java | 101 +++++++++++++++------
.../inverted_index_p0/test_count_on_index_2.out | 9 ++
.../inverted_index_p0/test_count_on_index_2.groovy | 29 ++++++
3 files changed, 109 insertions(+), 30 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
index 6adbc5a1bc3..cabf6bad03b 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java
@@ -40,6 +40,7 @@ import org.apache.doris.nereids.trees.expressions.Cast;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.IsNull;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.expressions.Or;
import org.apache.doris.nereids.trees.expressions.OrderExpression;
import org.apache.doris.nereids.trees.expressions.Slot;
import org.apache.doris.nereids.trees.expressions.SlotReference;
@@ -111,42 +112,66 @@ public class AggregateStrategies implements
ImplementationRuleFactory {
logicalAggregate(
logicalFilter(
logicalOlapScan().when(this::isDupOrMowKeyTable).when(this::isInvertedIndexEnabledOnTable)
- ).when(filter -> !filter.getConjuncts().isEmpty()))
- .when(agg -> enablePushDownCountOnIndex())
- .when(agg -> agg.getGroupByExpressions().isEmpty())
- .when(agg -> {
- Set<AggregateFunction> funcs =
agg.getAggregateFunctions();
- return !funcs.isEmpty() && funcs.stream()
- .allMatch(f -> f instanceof Count &&
!f.isDistinct() && (((Count) f).isCountStar()
- || f.child(0) instanceof Slot));
- })
- .thenApply(ctx -> {
- LogicalAggregate<LogicalFilter<LogicalOlapScan>> agg =
ctx.root;
- LogicalFilter<LogicalOlapScan> filter = agg.child();
- LogicalOlapScan olapScan = filter.child();
- return pushdownCountOnIndex(agg, null, filter,
olapScan, ctx.cascadesContext);
- })
+ )
+ )
+ .when(agg -> enablePushDownCountOnIndex())
+ .when(agg -> agg.getGroupByExpressions().isEmpty())
+ .when(agg -> {
+ Set<AggregateFunction> funcs = agg.getAggregateFunctions();
+ if (funcs.isEmpty() || !funcs.stream().allMatch(f -> f
instanceof Count && !f.isDistinct()
+ && (((Count) f).isCountStar() || f.child(0)
instanceof Slot))) {
+ return false;
+ }
+ Set<Expression> conjuncts = agg.child().getConjuncts();
+ if (conjuncts.isEmpty()) {
+ return false;
+ }
+
+ Set<Slot> aggSlots = funcs.stream()
+ .flatMap(f -> f.getInputSlots().stream())
+ .collect(Collectors.toSet());
+ return conjuncts.stream().allMatch(expr ->
checkSlotInOrExpression(expr, aggSlots));
+ })
+ .thenApply(ctx -> {
+ LogicalAggregate<LogicalFilter<LogicalOlapScan>> agg =
ctx.root;
+ LogicalFilter<LogicalOlapScan> filter = agg.child();
+ LogicalOlapScan olapScan = filter.child();
+ return pushdownCountOnIndex(agg, null, filter, olapScan,
ctx.cascadesContext);
+ })
),
RuleType.COUNT_ON_INDEX.build(
logicalAggregate(
logicalProject(
logicalFilter(
logicalOlapScan().when(this::isDupOrMowKeyTable).when(this::isInvertedIndexEnabledOnTable)
- ).when(filter -> !filter.getConjuncts().isEmpty())))
- .when(agg -> enablePushDownCountOnIndex())
- .when(agg -> agg.getGroupByExpressions().isEmpty())
- .when(agg -> {
- Set<AggregateFunction> funcs =
agg.getAggregateFunctions();
- return !funcs.isEmpty() && funcs.stream().allMatch(f
-> f instanceof Count && !f.isDistinct()
- && (((Count) f).isCountStar() || f.child(0)
instanceof Slot));
- })
- .thenApply(ctx -> {
-
LogicalAggregate<LogicalProject<LogicalFilter<LogicalOlapScan>>> agg = ctx.root;
- LogicalProject<LogicalFilter<LogicalOlapScan>> project
= agg.child();
- LogicalFilter<LogicalOlapScan> filter =
project.child();
- LogicalOlapScan olapScan = filter.child();
- return pushdownCountOnIndex(agg, project, filter,
olapScan, ctx.cascadesContext);
- })
+ )
+ )
+ )
+ .when(agg -> enablePushDownCountOnIndex())
+ .when(agg -> agg.getGroupByExpressions().isEmpty())
+ .when(agg -> {
+ Set<AggregateFunction> funcs = agg.getAggregateFunctions();
+ if (funcs.isEmpty() || !funcs.stream().allMatch(f -> f
instanceof Count && !f.isDistinct()
+ && (((Count) f).isCountStar() || f.child(0)
instanceof Slot))) {
+ return false;
+ }
+ Set<Expression> conjuncts =
agg.child().child().getConjuncts();
+ if (conjuncts.isEmpty()) {
+ return false;
+ }
+
+ Set<Slot> aggSlots = funcs.stream()
+ .flatMap(f -> f.getInputSlots().stream())
+ .collect(Collectors.toSet());
+ return conjuncts.stream().allMatch(expr ->
checkSlotInOrExpression(expr, aggSlots));
+ })
+ .thenApply(ctx -> {
+
LogicalAggregate<LogicalProject<LogicalFilter<LogicalOlapScan>>> agg = ctx.root;
+ LogicalProject<LogicalFilter<LogicalOlapScan>> project =
agg.child();
+ LogicalFilter<LogicalOlapScan> filter = project.child();
+ LogicalOlapScan olapScan = filter.child();
+ return pushdownCountOnIndex(agg, project, filter,
olapScan, ctx.cascadesContext);
+ })
),
RuleType.STORAGE_LAYER_AGGREGATE_MINMAX_ON_UNIQUE_WITHOUT_PROJECT.build(
logicalAggregate(
@@ -411,6 +436,22 @@ public class AggregateStrategies implements
ImplementationRuleFactory {
return connectContext != null &&
connectContext.getSessionVariable().isEnablePushDownCountOnIndex();
}
+ private boolean checkSlotInOrExpression(Expression expr, Set<Slot>
aggSlots) {
+ if (expr instanceof Or) {
+ Set<Slot> slots = expr.getInputSlots();
+ if (!slots.stream().allMatch(aggSlots::contains)) {
+ return false;
+ }
+ } else {
+ for (Expression child : expr.children()) {
+ if (!checkSlotInOrExpression(child, aggSlots)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
private boolean isDupOrMowKeyTable(LogicalOlapScan logicalScan) {
if (logicalScan != null) {
KeysType keysType = logicalScan.getTable().getKeysType();
diff --git a/regression-test/data/inverted_index_p0/test_count_on_index_2.out
b/regression-test/data/inverted_index_p0/test_count_on_index_2.out
index 94d2a83388b..de74ba29ffe 100644
--- a/regression-test/data/inverted_index_p0/test_count_on_index_2.out
+++ b/regression-test/data/inverted_index_p0/test_count_on_index_2.out
@@ -101,3 +101,12 @@
-- !sql --
3
+-- !sql --
+1
+
+-- !sql --
+1
+
+-- !sql --
+1
+
diff --git
a/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
b/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
index 77e5de052b9..59e9904574c 100644
--- a/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
+++ b/regression-test/suites/inverted_index_p0/test_count_on_index_2.groovy
@@ -202,6 +202,35 @@ suite("test_count_on_index_2", "p0"){
qt_sql """ select count() from ${indexTbName3} where (a >= 10 and a <
20) and (b >= 5 and b < 14) and (c >= 16 and c < 25); """
qt_sql """ select count() from ${indexTbName3} where (a >= 10 and a <
20) and (b >= 5 and b < 16) and (c >= 13 and c < 25); """
+ sql """ DROP TABLE IF EXISTS tt """
+ sql """
+ CREATE TABLE `tt` (
+ `a` int NULL,
+ `b` int NULL,
+ `c` int NULL,
+ INDEX col_c (`b`) USING INVERTED,
+ INDEX col_b (`c`) USING INVERTED
+ ) ENGINE=OLAP
+ DUPLICATE KEY(`a`)
+ COMMENT 'OLAP'
+ DISTRIBUTED BY RANDOM BUCKETS 1
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1"
+ );
+ """
+
+ sql """ insert into tt values (20, 23, 30); """
+ sql """ insert into tt values (20, null, 30); """
+ qt_sql """ select count(b) from tt where b = 23 or c = 30; """
+ qt_sql """ select count(b) from tt where b = 23 and (c = 20 or c =
30); """
+ explain {
+ sql("select count(b) from tt where b = 23 and (c = 20 or c =
30);")
+ contains "COUNT_ON_INDEX"
+ }
+ explain {
+ sql("select count(b) from tt where b = 23 or b = 30;")
+ contains "COUNT_ON_INDEX"
+ }
} finally {
//try_sql("DROP TABLE IF EXISTS ${testTable}")
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]