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

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

commit 9bc7902e5a0a4d8f10be1cb1e7bedbbc68b9fda6
Author: 924060929 <924060...@qq.com>
AuthorDate: Mon Apr 1 21:28:53 2024 +0800

    [fix](Nereids) fix bind group by int literal (#33117)
    
    This sql will failed because
    
        2 in the group by will bind to 1 as col2 in BindExpression
        ResolveOrdinalInOrderByAndGroupBy will replace 1 to MIN (LENGTH 
(cast(age as varchar)))
        CheckAnalysis will throw an exception because group by can not contains 
aggregate function
    
    select MIN (LENGTH (cast(age as varchar))), 1 AS col2
    from test_bind_groupby_slots
    group by 2
    
    we should move ResolveOrdinalInOrderByAndGroupBy into BindExpression
    
    (cherry picked from commit 3fab4496c3fefe95b4db01f300bf747080bfc3d8)
---
 .../doris/nereids/jobs/executor/Analyzer.java      |   2 -
 .../nereids/rules/analysis/BindExpression.java     |  33 ++++++-
 .../ResolveOrdinalInOrderByAndGroupBy.java         | 102 ---------------------
 .../data/nereids_syntax_p0/bind_priority.out       |   6 ++
 .../suites/nereids_syntax_p0/bind_priority.groovy  |  28 ++++++
 5 files changed, 63 insertions(+), 108 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
index 9ad10a30aa2..a0431e066be 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Analyzer.java
@@ -43,7 +43,6 @@ import 
org.apache.doris.nereids.rules.analysis.OneRowRelationExtractAggregate;
 import org.apache.doris.nereids.rules.analysis.ProjectToGlobalAggregate;
 import org.apache.doris.nereids.rules.analysis.ProjectWithDistinctToAggregate;
 import org.apache.doris.nereids.rules.analysis.ReplaceExpressionByChildOutput;
-import 
org.apache.doris.nereids.rules.analysis.ResolveOrdinalInOrderByAndGroupBy;
 import org.apache.doris.nereids.rules.analysis.SubqueryToApply;
 import org.apache.doris.nereids.rules.rewrite.MergeProjects;
 import org.apache.doris.nereids.rules.rewrite.SemiJoinCommute;
@@ -147,7 +146,6 @@ public class Analyzer extends AbstractBatchJobExecutor {
                 // please see rule BindSlotReference or BindFunction for 
example
                 new EliminateDistinctConstant(),
                 new ProjectWithDistinctToAggregate(),
-                new ResolveOrdinalInOrderByAndGroupBy(),
                 new ReplaceExpressionByChildOutput(),
                 new OneRowRelationExtractAggregate()
             ),
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 6211f493eaf..43f89d5b010 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
@@ -56,6 +56,7 @@ import 
org.apache.doris.nereids.trees.expressions.functions.scalar.GroupingScala
 import org.apache.doris.nereids.trees.expressions.functions.scalar.Lambda;
 import 
org.apache.doris.nereids.trees.expressions.functions.scalar.StructElement;
 import 
org.apache.doris.nereids.trees.expressions.functions.table.TableValuedFunction;
+import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.StringLiteral;
 import org.apache.doris.nereids.trees.plans.AbstractPlan;
 import org.apache.doris.nereids.trees.plans.JoinType;
@@ -486,11 +487,12 @@ public class BindExpression implements 
AnalysisRuleFactory {
         LogicalSort<LogicalSetOperation> sort = ctx.root;
         CascadesContext cascadesContext = ctx.cascadesContext;
 
+        List<Slot> childOutput = sort.child().getOutput();
         SimpleExprAnalyzer analyzer = buildSimpleExprAnalyzer(
                 sort, cascadesContext, sort.children(), true, true);
         Builder<OrderKey> boundKeys = 
ImmutableList.builderWithExpectedSize(sort.getOrderKeys().size());
         for (OrderKey orderKey : sort.getOrderKeys()) {
-            Expression boundKey = analyzer.analyze(orderKey.getExpr());
+            Expression boundKey = bindWithOrdinal(orderKey.getExpr(), 
analyzer, childOutput);
             boundKeys.add(orderKey.withExpression(boundKey));
         }
         return new LogicalSort<>(boundKeys.build(), sort.child());
@@ -699,7 +701,11 @@ public class BindExpression implements AnalysisRuleFactory 
{
                     return useOutputExpr.build();
                 });
 
-        List<Expression> boundGroupBy = analyzer.analyzeToList(groupBy);
+        ImmutableList.Builder<Expression> boundGroupByBuilder = 
ImmutableList.builderWithExpectedSize(groupBy.size());
+        for (Expression key : groupBy) {
+            boundGroupByBuilder.add(bindWithOrdinal(key, analyzer, 
boundAggOutput));
+        }
+        List<Expression> boundGroupBy = boundGroupByBuilder.build();
         checkIfOutputAliasNameDuplicatedForGroupBy(boundGroupBy, 
boundAggOutput);
         return boundGroupBy;
     }
@@ -723,6 +729,9 @@ public class BindExpression implements AnalysisRuleFactory {
     private Plan 
bindSortWithoutSetOperation(MatchingContext<LogicalSort<Plan>> ctx) {
         LogicalSort<Plan> sort = ctx.root;
         Plan input = sort.child();
+
+        List<Slot> childOutput = input.getOutput();
+
         // we should skip LogicalHaving to bind slot in LogicalSort;
         if (input instanceof LogicalHaving) {
             input = input.child(0);
@@ -744,7 +753,8 @@ public class BindExpression implements AnalysisRuleFactory {
         //        group by col1
         //        order by col1;     # order by order_col1
         //    bind order_col1 with alias_col1, then, bind it with inner_col1
-        Scope inputScope = toScope(cascadesContext, input.getOutput());
+        List<Slot> inputSlots = input.getOutput();
+        Scope inputScope = toScope(cascadesContext, inputSlots);
 
         final Plan finalInput = input;
         Supplier<Scope> inputChildrenScope = Suppliers.memoize(
@@ -766,7 +776,7 @@ public class BindExpression implements AnalysisRuleFactory {
 
         Builder<OrderKey> boundOrderKeys = 
ImmutableList.builderWithExpectedSize(sort.getOrderKeys().size());
         for (OrderKey orderKey : sort.getOrderKeys()) {
-            Expression boundKey = analyzer.analyze(orderKey.getExpr());
+            Expression boundKey = bindWithOrdinal(orderKey.getExpr(), 
analyzer, childOutput);
             boundOrderKeys.add(orderKey.withExpression(boundKey));
         }
         return new LogicalSort<>(boundOrderKeys.build(), sort.child());
@@ -858,6 +868,21 @@ public class BindExpression implements AnalysisRuleFactory 
{
                     unboundFunction.getDbName(), unboundFunction.getName());
     }
 
+    private Expression bindWithOrdinal(
+            Expression unbound, SimpleExprAnalyzer analyzer, List<? extends 
Expression> boundSelectOutput) {
+        if (unbound instanceof IntegerLikeLiteral) {
+            int ordinal = ((IntegerLikeLiteral) unbound).getIntValue();
+            if (ordinal >= 1 && ordinal <= boundSelectOutput.size()) {
+                Expression boundSelectItem = boundSelectOutput.get(ordinal - 
1);
+                return boundSelectItem instanceof Alias ? 
boundSelectItem.child(0) : boundSelectItem;
+            } else {
+                return unbound; // bound literal
+            }
+        } else {
+            return analyzer.analyze(unbound);
+        }
+    }
+
     private <E extends Expression> E checkBoundExceptLambda(E expression, Plan 
plan) {
         if (expression instanceof Lambda) {
             return expression;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
deleted file mode 100644
index 1cefd203ff7..00000000000
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ResolveOrdinalInOrderByAndGroupBy.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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.analysis;
-
-import org.apache.doris.nereids.properties.OrderKey;
-import org.apache.doris.nereids.rules.Rule;
-import org.apache.doris.nereids.rules.RuleType;
-import org.apache.doris.nereids.trees.expressions.Alias;
-import org.apache.doris.nereids.trees.expressions.Expression;
-import org.apache.doris.nereids.trees.expressions.NamedExpression;
-import org.apache.doris.nereids.trees.expressions.Slot;
-import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral;
-import org.apache.doris.nereids.trees.plans.Plan;
-import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
-import org.apache.doris.nereids.trees.plans.logical.LogicalSort;
-
-import com.google.common.collect.ImmutableList;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * SELECT col1, col2 FROM t1 ORDER BY 1 -> SELECT col1, col2 FROM t1 ORDER BY 
col1
- * SELECT col1, SUM(col2) FROM t1 GROUP BY 1 -> SELECT col1, SUM(col2) FROM t1 
GROUP BY col1
- */
-public class ResolveOrdinalInOrderByAndGroupBy implements AnalysisRuleFactory {
-
-    @Override
-    public List<Rule> buildRules() {
-        return ImmutableList.<Rule>builder()
-                .add(RuleType.RESOLVE_ORDINAL_IN_ORDER_BY.build(
-                        logicalSort().thenApply(ctx -> {
-                            LogicalSort<Plan> sort = ctx.root;
-                            List<Slot> childOutput = sort.child().getOutput();
-                            List<OrderKey> orderKeys = sort.getOrderKeys();
-                            List<OrderKey> orderKeysWithoutOrd = new 
ArrayList<>();
-                            for (OrderKey k : orderKeys) {
-                                Expression expression = k.getExpr();
-                                if (expression instanceof IntegerLikeLiteral) {
-                                    IntegerLikeLiteral i = 
(IntegerLikeLiteral) expression;
-                                    int ord = i.getIntValue();
-                                    checkOrd(ord, childOutput.size());
-                                    orderKeysWithoutOrd
-                                            .add(new 
OrderKey(childOutput.get(ord - 1), k.isAsc(), k.isNullFirst()));
-                                } else {
-                                    orderKeysWithoutOrd.add(k);
-                                }
-                            }
-                            return sort.withOrderKeys(orderKeysWithoutOrd);
-                        })
-                ))
-                .add(RuleType.RESOLVE_ORDINAL_IN_GROUP_BY.build(
-                        
logicalAggregate().whenNot(LogicalAggregate::isOrdinalIsResolved).thenApply(ctx 
-> {
-                            LogicalAggregate<Plan> agg = ctx.root;
-                            List<NamedExpression> aggOutput = 
agg.getOutputExpressions();
-                            List<Expression> groupByWithoutOrd = new 
ArrayList<>();
-                            boolean ordExists = false;
-                            for (Expression groupByExpr : 
agg.getGroupByExpressions()) {
-                                if (groupByExpr instanceof IntegerLikeLiteral) 
{
-                                    IntegerLikeLiteral i = 
(IntegerLikeLiteral) groupByExpr;
-                                    int ord = i.getIntValue();
-                                    checkOrd(ord, aggOutput.size());
-                                    Expression aggExpr = aggOutput.get(ord - 
1);
-                                    if (aggExpr instanceof Alias) {
-                                        aggExpr = ((Alias) aggExpr).child();
-                                    }
-                                    groupByWithoutOrd.add(aggExpr);
-                                    ordExists = true;
-                                } else {
-                                    groupByWithoutOrd.add(groupByExpr);
-                                }
-                            }
-                            if (ordExists) {
-                                return new 
LogicalAggregate<>(groupByWithoutOrd, agg.getOutputExpressions(),
-                                        true, agg.child());
-                            } else {
-                                return agg;
-                            }
-                        }))).build();
-    }
-
-    private void checkOrd(int ord, int childOutputSize) {
-        if (ord < 1 || ord > childOutputSize) {
-            throw new IllegalStateException(String.format("ordinal exceeds 
number of items in select list: %s", ord));
-        }
-    }
-}
diff --git a/regression-test/data/nereids_syntax_p0/bind_priority.out 
b/regression-test/data/nereids_syntax_p0/bind_priority.out
index 53432880c24..56706546bab 100644
--- a/regression-test/data/nereids_syntax_p0/bind_priority.out
+++ b/regression-test/data/nereids_syntax_p0/bind_priority.out
@@ -85,3 +85,9 @@ all   2
 -- !having_bind_group_by --
 2      1
 
+-- !sql --
+2      1
+
+-- !sql --
+2      1
+
diff --git a/regression-test/suites/nereids_syntax_p0/bind_priority.groovy 
b/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
index 84bab14eba0..769f1771982 100644
--- a/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
+++ b/regression-test/suites/nereids_syntax_p0/bind_priority.groovy
@@ -309,4 +309,32 @@ suite("bind_priority") {
                 having pk = 2;
                 """
     }()
+
+    def bindGroupBy = {
+        sql "drop table if exists test_bind_groupby_slots"
+
+        sql """create table test_bind_groupby_slots
+                (id int, age int)
+                distributed by hash(id)
+                properties('replication_num'='1');
+                """
+        sql "insert into test_bind_groupby_slots values(1, 10), (2, 20), (3, 
30);"
+
+        order_qt_sql "select MIN (LENGTH (cast(age as varchar))), 1 AS col2 
from test_bind_groupby_slots group by 2"
+    }()
+
+
+
+    def bindOrderBy = {
+        sql "drop table if exists test_bind_orderby_slots"
+
+        sql """create table test_bind_orderby_slots
+                (id int, age int)
+                distributed by hash(id)
+                properties('replication_num'='1');
+                """
+        sql "insert into test_bind_orderby_slots values(1, 10), (2, 20), (3, 
30);"
+
+        order_qt_sql "select MIN (LENGTH (cast(age as varchar))), 1 AS col2 
from test_bind_orderby_slots order by 2"
+    }()
 }


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

Reply via email to