This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 10fd75e03d5 [fix](Nereids) fix bind having aggregate failed (#32490)
10fd75e03d5 is described below
commit 10fd75e03d5737a48e4106b1a838b56a3ea4d65b
Author: 924060929 <[email protected]>
AuthorDate: Fri Mar 22 11:53:46 2024 +0800
[fix](Nereids) fix bind having aggregate failed (#32490)
fix bind having aggregate failed, keep the behavior like mysql
---
.../org/apache/doris/catalog/FunctionRegistry.java | 41 ++++--
.../nereids/rules/analysis/BindExpression.java | 135 +++++++++++++++++--
.../functions/AggCombinerFunctionBuilder.java | 5 +
.../functions/BuiltinFunctionBuilder.java | 12 +-
.../expressions/functions/FunctionBuilder.java | 2 +
.../expressions/functions/udf/AliasUdfBuilder.java | 5 +
.../expressions/functions/udf/JavaUdafBuilder.java | 5 +
.../expressions/functions/udf/JavaUdfBuilder.java | 5 +
.../data/nereids_syntax_p0/bind_priority.out | 40 ++++++
.../suites/nereids_syntax_p0/bind_priority.groovy | 143 ++++++++++++++++++++-
10 files changed, 366 insertions(+), 27 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java
index 5552b3d1d5c..56016ad071a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionRegistry.java
@@ -53,14 +53,14 @@ public class FunctionRegistry {
// to record the global alias function and other udf.
private static final String GLOBAL_FUNCTION = "__GLOBAL_FUNCTION__";
- private final Map<String, List<FunctionBuilder>>
name2InternalBuiltinBuilders;
+ private final Map<String, List<FunctionBuilder>> name2BuiltinBuilders;
private final Map<String, Map<String, List<FunctionBuilder>>>
name2UdfBuilders;
public FunctionRegistry() {
- name2InternalBuiltinBuilders = new ConcurrentHashMap<>();
+ name2BuiltinBuilders = new ConcurrentHashMap<>();
name2UdfBuilders = new ConcurrentHashMap<>();
- registerBuiltinFunctions(name2InternalBuiltinBuilders);
- afterRegisterBuiltinFunctions(name2InternalBuiltinBuilders);
+ registerBuiltinFunctions(name2BuiltinBuilders);
+ afterRegisterBuiltinFunctions(name2BuiltinBuilders);
}
// this function is used to test.
@@ -78,12 +78,33 @@ public class FunctionRegistry {
}
public Optional<List<FunctionBuilder>> tryGetBuiltinBuilders(String name) {
- List<FunctionBuilder> builders =
name2InternalBuiltinBuilders.get(name);
- return name2InternalBuiltinBuilders.get(name) == null
+ List<FunctionBuilder> builders = name2BuiltinBuilders.get(name);
+ return name2BuiltinBuilders.get(name) == null
? Optional.empty()
: Optional.of(ImmutableList.copyOf(builders));
}
+ public boolean isAggregateFunction(String dbName, String name) {
+ name = name.toLowerCase();
+ Class<?> aggClass =
org.apache.doris.nereids.trees.expressions.functions.agg.AggregateFunction.class;
+ if (StringUtils.isEmpty(dbName)) {
+ List<FunctionBuilder> functionBuilders =
name2BuiltinBuilders.get(name);
+ for (FunctionBuilder functionBuilder : functionBuilders) {
+ if
(aggClass.isAssignableFrom(functionBuilder.functionClass())) {
+ return true;
+ }
+ }
+ }
+
+ List<FunctionBuilder> udfBuilders = findUdfBuilder(dbName, name);
+ for (FunctionBuilder udfBuilder : udfBuilders) {
+ if (aggClass.isAssignableFrom(udfBuilder.functionClass())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// currently we only find function by name and arity and args' types.
public FunctionBuilder findFunctionBuilder(String dbName, String name,
List<?> arguments) {
List<FunctionBuilder> functionBuilders = null;
@@ -92,11 +113,11 @@ public class FunctionRegistry {
if (StringUtils.isEmpty(dbName)) {
// search internal function only if dbName is empty
- functionBuilders =
name2InternalBuiltinBuilders.get(name.toLowerCase());
+ functionBuilders = name2BuiltinBuilders.get(name.toLowerCase());
if (CollectionUtils.isEmpty(functionBuilders) &&
AggCombinerFunctionBuilder.isAggStateCombinator(name)) {
String nestedName =
AggCombinerFunctionBuilder.getNestedName(name);
String combinatorSuffix =
AggCombinerFunctionBuilder.getCombinatorSuffix(name);
- functionBuilders =
name2InternalBuiltinBuilders.get(nestedName.toLowerCase());
+ functionBuilders =
name2BuiltinBuilders.get(nestedName.toLowerCase());
if (functionBuilders != null) {
List<FunctionBuilder> candidateBuilders =
Lists.newArrayListWithCapacity(functionBuilders.size());
for (FunctionBuilder functionBuilder : functionBuilders) {
@@ -199,8 +220,8 @@ public class FunctionRegistry {
}
synchronized (name2UdfBuilders) {
Map<String, List<FunctionBuilder>> builders =
name2UdfBuilders.getOrDefault(dbName, ImmutableMap.of());
- builders.getOrDefault(name, Lists.newArrayList()).removeIf(builder
-> ((UdfBuilder) builder).getArgTypes()
- .equals(argTypes));
+ builders.getOrDefault(name, Lists.newArrayList())
+ .removeIf(builder -> ((UdfBuilder)
builder).getArgTypes().equals(argTypes));
}
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
index a561507fb94..04ba599aa60 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java
@@ -19,11 +19,13 @@ package org.apache.doris.nereids.rules.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.FunctionRegistry;
+import org.apache.doris.common.Pair;
import org.apache.doris.nereids.CascadesContext;
import org.apache.doris.nereids.NereidsPlanner;
import org.apache.doris.nereids.StatementContext;
import org.apache.doris.nereids.analyzer.MappingSlot;
import org.apache.doris.nereids.analyzer.Scope;
+import org.apache.doris.nereids.analyzer.UnboundFunction;
import org.apache.doris.nereids.analyzer.UnboundOneRowRelation;
import org.apache.doris.nereids.analyzer.UnboundResultSink;
import org.apache.doris.nereids.analyzer.UnboundSlot;
@@ -351,12 +353,12 @@ public class BindExpression implements
AnalysisRuleFactory {
CascadesContext cascadesContext = ctx.cascadesContext;
// bind slot by child.output first
- Scope defaultScope = toScope(cascadesContext, childPlan.getOutput());
+ Scope childOutput = toScope(cascadesContext, childPlan.getOutput());
// then bind slot by child.children.output
- Supplier<Scope> backupScope = Suppliers.memoize(() ->
+ Supplier<Scope> childChildrenOutput = Suppliers.memoize(() ->
toScope(cascadesContext,
PlanUtils.fastGetChildrenOutputs(childPlan.children()))
);
- return bindHavingByScopes(having, cascadesContext, defaultScope,
backupScope);
+ return bindHavingByScopes(having, cascadesContext, childOutput,
childChildrenOutput);
}
private LogicalHaving<Plan> bindHavingAggregate(
@@ -365,13 +367,115 @@ public class BindExpression implements
AnalysisRuleFactory {
Aggregate<Plan> aggregate = having.child();
CascadesContext cascadesContext = ctx.cascadesContext;
- // having(aggregate) should bind slot by aggregate.child.output first
- Scope defaultScope = toScope(cascadesContext,
PlanUtils.fastGetChildrenOutputs(aggregate.children()));
- // then bind slot by aggregate.output
- Supplier<Scope> backupScope = Suppliers.memoize(() ->
- toScope(cascadesContext, aggregate.getOutput())
- );
- return bindHavingByScopes(ctx.root, ctx.cascadesContext, defaultScope,
backupScope);
+ // keep same behavior as mysql
+ Supplier<CustomSlotBinderAnalyzer> bindByAggChild =
Suppliers.memoize(() -> {
+ Scope aggChildOutputScope
+ = toScope(cascadesContext,
PlanUtils.fastGetChildrenOutputs(aggregate.children()));
+ return (analyzer, unboundSlot) ->
analyzer.bindSlotByScope(unboundSlot, aggChildOutputScope);
+ });
+
+ Scope aggOutputScope = toScope(cascadesContext, aggregate.getOutput());
+ Supplier<CustomSlotBinderAnalyzer>
bindByGroupByThenAggOutputThenAggChild = Suppliers.memoize(() -> {
+ List<Expression> groupByExprs = aggregate.getGroupByExpressions();
+ ImmutableList.Builder<Slot> groupBySlots
+ =
ImmutableList.builderWithExpectedSize(groupByExprs.size());
+ for (Expression groupBy : groupByExprs) {
+ if (groupBy instanceof Slot) {
+ groupBySlots.add((Slot) groupBy);
+ }
+ }
+ Scope groupBySlotsScope = toScope(cascadesContext,
groupBySlots.build());
+
+ Supplier<Pair<Scope, Scope>> separateAggOutputScopes =
Suppliers.memoize(() -> {
+ ImmutableList.Builder<Slot> groupByOutputs =
ImmutableList.builderWithExpectedSize(
+ aggregate.getOutputExpressions().size());
+ ImmutableList.Builder<Slot> aggFunOutputs =
ImmutableList.builderWithExpectedSize(
+ aggregate.getOutputExpressions().size());
+ for (NamedExpression outputExpression :
aggregate.getOutputExpressions()) {
+ if
(outputExpression.anyMatch(AggregateFunction.class::isInstance)) {
+ aggFunOutputs.add(outputExpression.toSlot());
+ } else {
+ groupByOutputs.add(outputExpression.toSlot());
+ }
+ }
+ Scope nonAggFunSlotsScope = toScope(cascadesContext,
groupByOutputs.build());
+ Scope aggFuncSlotsScope = toScope(cascadesContext,
aggFunOutputs.build());
+ return Pair.of(nonAggFunSlotsScope, aggFuncSlotsScope);
+ });
+
+ return (analyzer, unboundSlot) -> {
+ List<Slot> boundInGroupBy =
analyzer.bindSlotByScope(unboundSlot, groupBySlotsScope);
+ if (boundInGroupBy.size() == 1) {
+ return boundInGroupBy;
+ }
+
+ Pair<Scope, Scope> separateAggOutputScope =
separateAggOutputScopes.get();
+ List<Slot> boundInNonAggFuncs =
analyzer.bindSlotByScope(unboundSlot, separateAggOutputScope.first);
+ if (boundInNonAggFuncs.size() == 1) {
+ return boundInNonAggFuncs;
+ }
+
+ List<Slot> boundInAggFuncs =
analyzer.bindSlotByScope(unboundSlot, separateAggOutputScope.second);
+ if (boundInAggFuncs.size() == 1) {
+ return boundInAggFuncs;
+ }
+
+ return bindByAggChild.get().bindSlot(analyzer, unboundSlot);
+ };
+ });
+
+ FunctionRegistry functionRegistry =
cascadesContext.getConnectContext().getEnv().getFunctionRegistry();
+ ExpressionAnalyzer havingAnalyzer = new ExpressionAnalyzer(having,
aggOutputScope, cascadesContext,
+ false, true) {
+ private boolean currentIsInAggregateFunction;
+
+ @Override
+ public Expression visitAggregateFunction(AggregateFunction
aggregateFunction,
+ ExpressionRewriteContext context) {
+ if (!currentIsInAggregateFunction) {
+ currentIsInAggregateFunction = true;
+ try {
+ return super.visitAggregateFunction(aggregateFunction,
context);
+ } finally {
+ currentIsInAggregateFunction = false;
+ }
+ } else {
+ return super.visitAggregateFunction(aggregateFunction,
context);
+ }
+ }
+
+ @Override
+ public Expression visitUnboundFunction(UnboundFunction
unboundFunction, ExpressionRewriteContext context) {
+ if (!currentIsInAggregateFunction &&
isAggregateFunction(unboundFunction, functionRegistry)) {
+ currentIsInAggregateFunction = true;
+ try {
+ return super.visitUnboundFunction(unboundFunction,
context);
+ } finally {
+ currentIsInAggregateFunction = false;
+ }
+ } else {
+ return super.visitUnboundFunction(unboundFunction,
context);
+ }
+ }
+
+ @Override
+ protected List<? extends Expression>
bindSlotByThisScope(UnboundSlot unboundSlot) {
+ if (currentIsInAggregateFunction) {
+ return bindByAggChild.get().bindSlot(this, unboundSlot);
+ } else {
+ return
bindByGroupByThenAggOutputThenAggChild.get().bindSlot(this, unboundSlot);
+ }
+ }
+ };
+
+ Set<Expression> havingExprs = having.getConjuncts();
+ ImmutableSet.Builder<Expression> analyzedHaving =
ImmutableSet.builderWithExpectedSize(havingExprs.size());
+ ExpressionRewriteContext rewriteContext = new
ExpressionRewriteContext(cascadesContext);
+ for (Expression expression : havingExprs) {
+ analyzedHaving.add(havingAnalyzer.analyze(expression,
rewriteContext));
+ }
+
+ return new LogicalHaving<>(analyzedHaving.build(), having.child());
}
private LogicalHaving<Plan> bindHavingByScopes(
@@ -764,6 +868,11 @@ public class BindExpression implements AnalysisRuleFactory
{
}
}
+ private boolean isAggregateFunction(UnboundFunction unboundFunction,
FunctionRegistry functionRegistry) {
+ return functionRegistry.isAggregateFunction(
+ unboundFunction.getDbName(), unboundFunction.getName());
+ }
+
private <E extends Expression> E checkBoundExceptLambda(E expression, Plan
plan) {
if (expression instanceof Lambda) {
return expression;
@@ -797,6 +906,12 @@ public class BindExpression implements AnalysisRuleFactory
{
boolean enableExactMatch, boolean bindSlotInOuterScope) {
List<Slot> childrenOutputs =
PlanUtils.fastGetChildrenOutputs(children);
Scope scope = toScope(cascadesContext, childrenOutputs);
+ return buildSimpleExprAnalyzer(currentPlan, cascadesContext, scope,
enableExactMatch, bindSlotInOuterScope);
+ }
+
+ private SimpleExprAnalyzer buildSimpleExprAnalyzer(
+ Plan currentPlan, CascadesContext cascadesContext, Scope scope,
+ boolean enableExactMatch, boolean bindSlotInOuterScope) {
ExpressionRewriteContext rewriteContext = new
ExpressionRewriteContext(cascadesContext);
ExpressionAnalyzer expressionAnalyzer = new
ExpressionAnalyzer(currentPlan,
scope, cascadesContext, enableExactMatch,
bindSlotInOuterScope);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/AggCombinerFunctionBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/AggCombinerFunctionBuilder.java
index 3c514475eed..4ef642890ca 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/AggCombinerFunctionBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/AggCombinerFunctionBuilder.java
@@ -56,6 +56,11 @@ public class AggCombinerFunctionBuilder extends
FunctionBuilder {
this.nestedBuilder = Objects.requireNonNull(nestedBuilder,
"nestedBuilder can not be null");
}
+ @Override
+ public Class<? extends BoundFunction> functionClass() {
+ return nestedBuilder.functionClass();
+ }
+
@Override
public boolean canApply(List<? extends Object> arguments) {
if (combinatorSuffix.equals(STATE) ||
combinatorSuffix.equals(FOREACH)) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/BuiltinFunctionBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/BuiltinFunctionBuilder.java
index 74c4a918cf0..e2dab713332 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/BuiltinFunctionBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/BuiltinFunctionBuilder.java
@@ -42,13 +42,21 @@ public class BuiltinFunctionBuilder extends FunctionBuilder
{
// Concrete BoundFunction's constructor
private final Constructor<BoundFunction> builderMethod;
+ private final Class<? extends BoundFunction> functionClass;
- public BuiltinFunctionBuilder(Constructor<BoundFunction> builderMethod) {
+ public BuiltinFunctionBuilder(
+ Class<? extends BoundFunction> functionClass,
Constructor<BoundFunction> builderMethod) {
+ this.functionClass = Objects.requireNonNull(functionClass,
"functionClass can not be null");
this.builderMethod = Objects.requireNonNull(builderMethod,
"builderMethod can not be null");
this.arity = builderMethod.getParameterCount();
this.isVariableLength = arity > 0 &&
builderMethod.getParameterTypes()[arity - 1].isArray();
}
+ @Override
+ public Class<? extends BoundFunction> functionClass() {
+ return functionClass;
+ }
+
@Override
public boolean canApply(List<? extends Object> arguments) {
if (isVariableLength && arity > arguments.size() + 1) {
@@ -133,7 +141,7 @@ public class BuiltinFunctionBuilder extends FunctionBuilder
{
+ functionClass.getSimpleName());
return Arrays.stream(functionClass.getConstructors())
.filter(constructor ->
Modifier.isPublic(constructor.getModifiers()))
- .map(constructor -> new
BuiltinFunctionBuilder((Constructor<BoundFunction>) constructor))
+ .map(constructor -> new BuiltinFunctionBuilder(functionClass,
(Constructor<BoundFunction>) constructor))
.collect(ImmutableList.toImmutableList());
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/FunctionBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/FunctionBuilder.java
index 0b3a50a239b..d1e69d3e307 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/FunctionBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/FunctionBuilder.java
@@ -27,6 +27,8 @@ import java.util.List;
* This class used to build BoundFunction(Builtin or Combinator) by a list of
Expressions.
*/
public abstract class FunctionBuilder {
+ public abstract Class<? extends BoundFunction> functionClass();
+
/** check whether arguments can apply to the constructor */
public abstract boolean canApply(List<? extends Object> arguments);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java
index 197cb8b396d..733bd5fcae1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdfBuilder.java
@@ -50,6 +50,11 @@ public class AliasUdfBuilder extends UdfBuilder {
return aliasUdf.getArgTypes();
}
+ @Override
+ public Class<? extends BoundFunction> functionClass() {
+ return AliasUdf.class;
+ }
+
@Override
public boolean canApply(List<?> arguments) {
if (arguments.size() != aliasUdf.arity()) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java
index d0c0b067e94..89073b4eb77 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdafBuilder.java
@@ -49,6 +49,11 @@ public class JavaUdafBuilder extends UdfBuilder {
.collect(Collectors.toList())).get();
}
+ @Override
+ public Class<? extends BoundFunction> functionClass() {
+ return JavaUdaf.class;
+ }
+
@Override
public boolean canApply(List<?> arguments) {
if ((isVarArgs && arity > arguments.size() + 1) || (!isVarArgs &&
arguments.size() != arity)) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java
index efbcbf9f483..a78f8cfe4b4 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdfBuilder.java
@@ -51,6 +51,11 @@ public class JavaUdfBuilder extends UdfBuilder {
.collect(Collectors.toList())).get();
}
+ @Override
+ public Class<? extends BoundFunction> functionClass() {
+ return JavaUdf.class;
+ }
+
@Override
public boolean canApply(List<?> arguments) {
if ((isVarArgs && arity > arguments.size() + 1) || (!isVarArgs &&
arguments.size() != arity)) {
diff --git a/regression-test/data/nereids_syntax_p0/bind_priority.out
b/regression-test/data/nereids_syntax_p0/bind_priority.out
index 7cd1e3ea569..eb4002d960a 100644
--- a/regression-test/data/nereids_syntax_p0/bind_priority.out
+++ b/regression-test/data/nereids_syntax_p0/bind_priority.out
@@ -36,3 +36,43 @@ all 2
4 5
6 6
+-- !having_bind_child --
+1 10
+
+-- !having_bind_child2 --
+2 10
+
+-- !having_bind_child3 --
+2 10
+
+-- !having_bind_project --
+2 10
+
+-- !having_bind_project2 --
+
+-- !having_bind_project3 --
+
+-- !having_bind_project4 --
+2 11
+
+-- !having_bind_child4 --
+2 11
+
+-- !having_bind_child5 --
+2 11
+
+-- !having_bind_agg_fun --
+
+-- !having_bind_agg_fun --
+2 4
+3 3
+
+-- !having_bind_group_by --
+7 3
+
+-- !having_bind_group_by --
+7 3
+
+-- !having_bind_group_by --
+7 3
+
diff --git a/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
b/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
index 072587ed28e..4e1740061b6 100644
--- a/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
+++ b/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
@@ -31,7 +31,7 @@ suite("bind_priority") {
sql """
insert into bind_priority_tbl values(1, 2),(3, 4)
"""
-
+
sql "SET enable_nereids_planner=true"
sql "SET enable_fallback_to_original_planner=false"
@@ -100,17 +100,17 @@ suite("bind_priority") {
);
"""
sql "insert into bind_priority_tbl2 values(3,5),(2, 6),(1,4);"
-
+
qt_bind_order_to_project_alias """
select bind_priority_tbl.b b, bind_priority_tbl2.b
- from bind_priority_tbl join bind_priority_tbl2 on
bind_priority_tbl.a=bind_priority_tbl2.a
+ from bind_priority_tbl join bind_priority_tbl2 on
bind_priority_tbl.a=bind_priority_tbl2.a
order by b;
"""
qt_bind_order_to_project_alias """
select bind_priority_tbl.b, bind_priority_tbl2.b b
- from bind_priority_tbl join bind_priority_tbl2 on
bind_priority_tbl.a=bind_priority_tbl2.a
+ from bind_priority_tbl join bind_priority_tbl2 on
bind_priority_tbl.a=bind_priority_tbl2.a
order by b;
"""
@@ -148,11 +148,144 @@ suite("bind_priority") {
) a
), tb2 as
(
- select * from tb1
+ select * from tb1
)
select * from tb2 order by id;
""")
result([[1], [2], [3]])
}
+
+ def testBindHaving = {
+ sql "drop table if exists test_bind_having_slots"
+
+ sql """create table test_bind_having_slots
+ (id int, age int)
+ distributed by hash(id)
+ properties('replication_num'='1');
+ """
+ sql "insert into test_bind_having_slots values(1, 10), (2, 20), (3,
30);"
+
+ order_qt_having_bind_child """
+ select id, sum(age)
+ from test_bind_having_slots s
+ group by id
+ having id = 1; -- bind id from group by
+ """
+
+ order_qt_having_bind_child2 """
+ select id + 1 as id, sum(age)
+ from test_bind_having_slots s
+ group by id
+ having id = 1; -- bind id from group by
+ """
+
+ order_qt_having_bind_child3 """
+ select id + 1 as id, sum(age)
+ from test_bind_having_slots s
+ group by id
+ having id + 1 = 2; -- bind id from group by
+ """
+
+ order_qt_having_bind_project """
+ select id + 1 as id, sum(age)
+ from test_bind_having_slots s
+ group by id + 1
+ having id = 2; -- bind id from project
+ """
+
+ order_qt_having_bind_project2 """
+ select id + 1 as id, sum(age)
+ from test_bind_having_slots s
+ group by id + 1
+ having id + 1 = 2; -- bind id from project
+ """
+
+ order_qt_having_bind_project3 """
+ select id + 1 as id, sum(age + 1) as age
+ from test_bind_having_slots s
+ group by id
+ having age = 10; -- bind age from project
+ """
+
+ order_qt_having_bind_project4 """
+ select id + 1 as id, sum(age + 1) as age
+ from test_bind_having_slots s
+ group by id
+ having age = 11; -- bind age from project
+ """
+
+ order_qt_having_bind_child4 """
+ select id + 1 as id, sum(age + 1) as age
+ from test_bind_having_slots s
+ group by id
+ having sum(age) = 10; -- bind age from s
+ """
+
+ order_qt_having_bind_child5 """
+ select id + 1 as id, sum(age + 1) as age
+ from test_bind_having_slots s
+ group by id
+ having sum(age + 1) = 11 -- bind age from s
+ """
+
+
+
+
+ sql "drop table if exists test_bind_having_slots2"
+ sql """create table test_bind_having_slots2
+ (id int)
+ distributed by hash(id)
+ properties('replication_num'='1');
+ """
+ sql "insert into test_bind_having_slots2 values(1), (2), (3), (2);"
+
+ order_qt_having_bind_agg_fun """
+ select id, abs(sum(id)) as id
+ from test_bind_having_slots2
+ group by id
+ having sum(id) + id >= 7
+ """
+
+ order_qt_having_bind_agg_fun """
+ select id, abs(sum(id)) as id
+ from test_bind_having_slots2
+ group by id
+ having sum(id) + id >= 6
+ """
+
+
+
+
+
+ sql "drop table if exists test_bind_having_slots3"
+
+ sql """CREATE TABLE `test_bind_having_slots3`(pk int, pk2 int)
+ DUPLICATE KEY(`pk`)
+ DISTRIBUTED BY HASH(`pk`) BUCKETS 10
+ properties('replication_num'='1');
+ """
+ sql "insert into test_bind_having_slots3 values(1, 1), (2, 2), (2, 2),
(3, 3), (3, 3), (3, 3);"
+
+ order_qt_having_bind_group_by """
+ SELECT pk + 6 as ps, COUNT(pk ) * 3 as pk
+ FROM test_bind_having_slots3 tbl_alias1
+ GROUP by pk
+ HAVING pk = 1
+ """
+
+ order_qt_having_bind_group_by """
+ SELECT pk + 6 as pk, COUNT(pk ) * 3 as pk
+ FROM test_bind_having_slots3 tbl_alias1
+ GROUP by pk + 6
+ HAVING pk = 7
+ """
+
+ order_qt_having_bind_group_by """
+ SELECT pk + 6, COUNT(pk ) * 3 as pk
+ FROM test_bind_having_slots3 tbl_alias1
+ GROUP by pk + 6
+ HAVING pk = 3
+ """
+ }()
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]