You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2021/11/17 03:13:20 UTC

[incubator-doris] branch master updated: [Lateral View] Multi lateral views map one TableFunctionNode (#7000)

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

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 7b71292  [Lateral View] Multi lateral views map one TableFunctionNode (#7000)
7b71292 is described below

commit 7b712925fc888f0c02310951b02ce5e80911e126
Author: EmmyMiao87 <52...@qq.com>
AuthorDate: Wed Nov 17 11:13:08 2021 +0800

    [Lateral View] Multi lateral views map one TableFunctionNode (#7000)
    
    1. Forbidden non-string column as params of explode_view.
    The first param of explode_view must be string column(VARCHAR/CHAR/STRING)
    
    2. N-1 n lateral views map one TableFunctionNode
    The TableFunctionNode include all of fnExprs which belongs to one table.
    For example:
    select pageid,mycol1, mycol2 from pageAds
        lateral view explode_string(col1) myTable1 as mycol1
        lateral view explode_string(col2) myTable2 as mycol2;
    TableFunctionNode
    |----
    |- fnExprList: explode_string(col1), explode_string(col2)
---
 .../org/apache/doris/analysis/LateralViewRef.java  |  3 ++
 .../apache/doris/planner/SingleNodePlanner.java    | 10 ++---
 .../apache/doris/planner/TableFunctionNode.java    | 44 +++++++++++++++++-----
 .../doris/planner/TableFunctionPlanTest.java       |  7 +---
 gensrc/thrift/PlanNodes.thrift                     |  2 +-
 5 files changed, 44 insertions(+), 22 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LateralViewRef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LateralViewRef.java
index e6576ec..b056b4b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LateralViewRef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LateralViewRef.java
@@ -98,6 +98,9 @@ public class LateralViewRef extends TableRef {
         if (originColumn == null) {
             throw new AnalysisException("The explode column must be a real column in table");
         }
+        if (!originColumn.getType().isStringType()) {
+           throw new AnalysisException("The explode column must be VARCHAR/CHAR/STRING type");
+        }
         // analyze lateral view
         desc = analyzer.registerTableRef(this);
         explodeSlotRef = new SlotRef(new TableName(null, viewName), columnName);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
index 31c0b3f..57b88d8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
@@ -1882,12 +1882,10 @@ public class SingleNodePlanner {
             throws UserException {
         Preconditions.checkNotNull(lateralViewRefs);
         Preconditions.checkState(lateralViewRefs.size() > 0);
-        for (LateralViewRef lateralViewRef: lateralViewRefs) {
-            TableFunctionNode tableFunctionNode = new TableFunctionNode(ctx_.getNextNodeId(), inputNode,
-                    lateralViewRef);
-            tableFunctionNode.init(analyzer);
-            inputNode = tableFunctionNode;
-        }
+        TableFunctionNode tableFunctionNode = new TableFunctionNode(ctx_.getNextNodeId(), inputNode,
+                lateralViewRefs);
+        tableFunctionNode.init(analyzer);
+        inputNode = tableFunctionNode;
         return inputNode;
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java
index 4601f8a..3bb9d8c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java
@@ -18,34 +18,41 @@
 package org.apache.doris.planner;
 
 import org.apache.doris.analysis.Analyzer;
+import org.apache.doris.analysis.Expr;
 import org.apache.doris.analysis.FunctionCallExpr;
 import org.apache.doris.analysis.LateralViewRef;
+import org.apache.doris.analysis.TupleId;
 import org.apache.doris.common.UserException;
 import org.apache.doris.thrift.TExplainLevel;
 import org.apache.doris.thrift.TPlanNode;
 import org.apache.doris.thrift.TPlanNodeType;
 import org.apache.doris.thrift.TTableFunctionNode;
 
-public class TableFunctionNode extends PlanNode {
+import java.util.List;
+import java.util.stream.Collectors;
 
-    private LateralViewRef lateralViewRef;
+public class TableFunctionNode extends PlanNode {
 
-    private FunctionCallExpr fnCallExpr;
+    private List<LateralViewRef> lateralViewRefs;
+    private List<FunctionCallExpr> fnCallExprList;
+    private List<TupleId> lateralViewTupleIds;
 
-    protected TableFunctionNode(PlanNodeId id, PlanNode inputNode, LateralViewRef lateralViewRef) {
+    protected TableFunctionNode(PlanNodeId id, PlanNode inputNode, List<LateralViewRef> lateralViewRefs) {
         super(id, "TABLE FUNCTION NODE");
         tupleIds.addAll(inputNode.getTupleIds());
         tblRefIds.addAll(inputNode.getTupleIds());
-        tupleIds.add(lateralViewRef.getDesc().getId());
-        tblRefIds.add(lateralViewRef.getDesc().getId());
+        lateralViewTupleIds = lateralViewRefs.stream().map(e -> e.getDesc().getId())
+                .collect(Collectors.toList());
+        tupleIds.addAll(lateralViewTupleIds);
+        tblRefIds.addAll(lateralViewTupleIds);
         children.add(inputNode);
-        this.lateralViewRef = lateralViewRef;
+        this.lateralViewRefs = lateralViewRefs;
     }
 
     @Override
     public void init(Analyzer analyzer) throws UserException {
         super.init(analyzer);
-        fnCallExpr = lateralViewRef.getFnExpr();
+        fnCallExprList = lateralViewRefs.stream().map(e -> e.getFnExpr()).collect(Collectors.toList());
         computeStats(analyzer);
     }
 
@@ -59,11 +66,28 @@ public class TableFunctionNode extends PlanNode {
     @Override
     public String getNodeExplainString(String prefix, TExplainLevel detailLevel) {
         StringBuilder output = new StringBuilder();
-        output.append(prefix + "table function: ").append(fnCallExpr.toSql() + "\n");
+        output.append(prefix + "table function: ");
+        for (FunctionCallExpr fnExpr : fnCallExprList) {
+            output.append(fnExpr.toSqlImpl() + " ");
+        }
+        output.append("\n");
+
+        output.append(prefix + "lateral view tuple id: ");
+        for (TupleId tupleId : lateralViewTupleIds) {
+            output.append(tupleId.asInt() + " ");
+        }
+        output.append("\n");
+
         if (detailLevel == TExplainLevel.BRIEF) {
             return output.toString();
         }
 
+        output.append(prefix + "tuple id: ");
+        for (TupleId tupleId : tupleIds) {
+            output.append(tupleId.asInt() + " ");
+        }
+        output.append("\n");
+
         if (!conjuncts.isEmpty()) {
             output.append(prefix).append("PREDICATES: ").append(
                     getExplainString(conjuncts)).append("\n");
@@ -76,6 +100,6 @@ public class TableFunctionNode extends PlanNode {
     protected void toThrift(TPlanNode msg) {
         msg.node_type = TPlanNodeType.TABLE_FUNCTION_NODE;
         msg.table_function_node = new TTableFunctionNode();
-        msg.table_function_node.setFnCallExpr(fnCallExpr.treeToThrift());
+        msg.table_function_node.setFnCallExprList(Expr.treesToThrift(fnCallExprList));
     }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
index 1d59d15..2746286 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
@@ -150,12 +150,9 @@ public class TableFunctionPlanTest {
         String sql = "desc verbose select k1, e1, e2 from db1.tbl1 lateral view explode_split(k2, \",\") tmp1 as e1"
                 + " lateral view explode_split(k2, \",\") tmp2 as e2;";
         String explainString = UtFrameUtils.getSQLPlanOrErrorMsg(ctx, sql, true);
-        Assert.assertTrue(explainString.contains("2:TABLE FUNCTION NODE"));
-        Assert.assertTrue(explainString.contains("table function: explode_split(`k2`, ',')"));
-        Assert.assertTrue(explainString.contains("tuple ids: 0 1 2"));
         Assert.assertTrue(explainString.contains("1:TABLE FUNCTION NODE"));
-        Assert.assertTrue(explainString.contains("table function: explode_split(`k2`, ',')"));
-        Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
+        Assert.assertTrue(explainString.contains("table function: explode_split(`k2`, ',') explode_split(`k2`, ',')"));
+        Assert.assertTrue(explainString.contains("lateral view tuple id: 1 2"));
         // lateral view 2 tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, tbl=tmp2, byteSize=32, materialized=true}"));
         Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e2, type=VARCHAR(*)}"));
diff --git a/gensrc/thrift/PlanNodes.thrift b/gensrc/thrift/PlanNodes.thrift
index 6a862ef..a217157 100644
--- a/gensrc/thrift/PlanNodes.thrift
+++ b/gensrc/thrift/PlanNodes.thrift
@@ -657,7 +657,7 @@ struct TOlapRewriteNode {
 }
 
 struct TTableFunctionNode {
-    1: required Exprs.TExpr fnCallExpr
+    1: required list<Exprs.TExpr> fnCallExprList
 }
 
 // This contains all of the information computed by the plan as part of the resource

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