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 b19198b3052 [opt](Nereids) Support to get notdeterministic functions 
and  base tables from plan (#26120)
b19198b3052 is described below

commit b19198b3052eaa43105f15c32817da894f9f1bc3
Author: seawinde <149132972+seawi...@users.noreply.github.com>
AuthorDate: Fri Nov 3 17:37:46 2023 +0800

    [opt](Nereids) Support to get notdeterministic functions and  base tables 
from plan (#26120)
    
    Support to get notdeterministic functions and  base tables from plan.
    These are implemented by Plan Visitor
    
    **table collect useage example as following:**
    ```
    TableCollectorContext collectorContext =
        new PlanVisitors.TableCollectorContext(Sets.newHashSet(TableType.OLAP));
    physicalPlan.accept(PlanVisitors.TABLE_COLLECTOR, collectorContext);
    ```
    `collectorContext.getCollectedTables()` has the tables
    
    **nondeterministic functions collect useage example as following:**
    ```
    List<Expression> functionCollectResult = new ArrayList<>();
    plan.accept(PlanVisitors.NondeterministicCollector.INSTANCE, collectResult);
    ```
    `functionCollectResult` has the nondeterministic functions
---
 .../visitor/NondeterministicFunctionCollector.java |  47 +++++++
 .../trees/plans/visitor/TableCollector.java        |  69 ++++++++++
 .../doris/nereids/trees/plans/PlanVisitorTest.java | 145 +++++++++++++++++++++
 3 files changed, 261 insertions(+)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/NondeterministicFunctionCollector.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/NondeterministicFunctionCollector.java
new file mode 100644
index 00000000000..b17be42d383
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/NondeterministicFunctionCollector.java
@@ -0,0 +1,47 @@
+// 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.trees.plans.visitor;
+
+import org.apache.doris.nereids.trees.TreeNode;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.Nondeterministic;
+import org.apache.doris.nereids.trees.plans.Plan;
+
+import java.util.List;
+
+/**
+ * Collect the nondeterministic expr in plan, these expressions will be put 
into context
+ */
+public class NondeterministicFunctionCollector
+        extends DefaultPlanVisitor<Void, List<TreeNode<Expression>>> {
+
+    public static final NondeterministicFunctionCollector INSTANCE
+            = new NondeterministicFunctionCollector();
+
+    @Override
+    public Void visit(Plan plan, List<TreeNode<Expression>> 
collectedExpressions) {
+        List<? extends Expression> expressions = plan.getExpressions();
+        if (expressions.isEmpty()) {
+            return super.visit(plan, collectedExpressions);
+        }
+        expressions.forEach(expression -> {
+            
collectedExpressions.addAll(expression.collect(Nondeterministic.class::isInstance));
+        });
+        return super.visit(plan, collectedExpressions);
+    }
+}
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/TableCollector.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/TableCollector.java
new file mode 100644
index 00000000000..54ffab75966
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/TableCollector.java
@@ -0,0 +1,69 @@
+// 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.trees.plans.visitor;
+
+import org.apache.doris.catalog.TableIf;
+import org.apache.doris.catalog.TableIf.TableType;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.algebra.CatalogRelation;
+import 
org.apache.doris.nereids.trees.plans.visitor.TableCollector.TableCollectorContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Collect the table in plan
+ * Note: will not get table if table is eliminated by EmptyRelation in rewrite.
+ */
+public class TableCollector extends DefaultPlanVisitor<Void, 
TableCollectorContext> {
+
+    public static final TableCollector INSTANCE = new TableCollector();
+
+    @Override
+    public Void visit(Plan plan, TableCollectorContext context) {
+        if (plan instanceof CatalogRelation) {
+            TableIf table = ((CatalogRelation) plan).getTable();
+            if (context.getTargetTableTypes().contains(table.getType())) {
+                context.getCollectedTables().add(table);
+            }
+        }
+        return super.visit(plan, context);
+    }
+
+    /**
+     * The context for table collecting, it contains the target collect table 
types
+     * and the result of collect.
+     */
+    public static final class TableCollectorContext {
+        private final List<TableIf> collectedTables = new ArrayList<>();
+        private final Set<TableType> targetTableTypes;
+
+        public TableCollectorContext(Set<TableType> targetTableTypes) {
+            this.targetTableTypes = targetTableTypes;
+        }
+
+        public List<TableIf> getCollectedTables() {
+            return collectedTables;
+        }
+
+        public Set<TableType> getTargetTableTypes() {
+            return targetTableTypes;
+        }
+    }
+}
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanVisitorTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanVisitorTest.java
new file mode 100644
index 00000000000..e70470c4682
--- /dev/null
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/PlanVisitorTest.java
@@ -0,0 +1,145 @@
+// 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.trees.plans;
+
+import org.apache.doris.catalog.TableIf;
+import org.apache.doris.catalog.TableIf.TableType;
+import org.apache.doris.nereids.trees.TreeNode;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.CurrentDate;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.Now;
+import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan;
+import 
org.apache.doris.nereids.trees.plans.visitor.NondeterministicFunctionCollector;
+import org.apache.doris.nereids.trees.plans.visitor.TableCollector;
+import 
org.apache.doris.nereids.trees.plans.visitor.TableCollector.TableCollectorContext;
+import org.apache.doris.nereids.util.PlanChecker;
+import org.apache.doris.utframe.TestWithFeService;
+
+import com.google.common.collect.Sets;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Tests for plan visitors to make sure the result meets expectation.
+ */
+public class PlanVisitorTest extends TestWithFeService {
+
+    @Override
+    protected void runBeforeAll() throws Exception {
+        createDatabase("visitor_test");
+        useDatabase("visitor_test");
+
+        createTable("CREATE TABLE `table1` (\n"
+                + " `c1` varchar(20) NULL,\n"
+                + " `c2` bigint(20) NULL,\n"
+                + " `c3` int(20) not NULL,\n"
+                + " `k4` bitmap BITMAP_UNION NULL,\n"
+                + " `k5` bitmap BITMAP_UNION NULL\n"
+                + ") ENGINE=OLAP\n"
+                + "AGGREGATE KEY(`c1`, `c2`, `c3`)\n"
+                + "COMMENT 'OLAP'\n"
+                + "DISTRIBUTED BY HASH(`c2`) BUCKETS 1\n"
+                + "PROPERTIES (\n"
+                + "\"replication_num\" = \"1\" \n"
+                + ");");
+
+        createTable("CREATE TABLE `table2` (\n"
+                + " `c1` bigint(20) NULL,\n"
+                + " `c2` bigint(20) NULL,\n"
+                + " `c3` bigint(20) not NULL,\n"
+                + " `k4` bitmap BITMAP_UNION NULL,\n"
+                + " `k5` bitmap BITMAP_UNION NULL\n"
+                + ") ENGINE=OLAP\n"
+                + "AGGREGATE KEY(`c1`, `c2`, `c3`)\n"
+                + "COMMENT 'OLAP'\n"
+                + "DISTRIBUTED BY HASH(`c2`) BUCKETS 1\n"
+                + "PROPERTIES (\n"
+                + "\"replication_num\" = \"1\"\n"
+                + ");");
+
+        createView("CREATE VIEW `view1` AS SELECT t1.*, current_date() FROM\n"
+                + "`table1` t1 LEFT JOIN\n"
+                + "`table2` t2 ON t1.c1 = t2.c1;");
+    }
+
+    @Test
+    public void test1() {
+        PlanChecker.from(connectContext)
+                .checkPlannerResult("SELECT *, now() FROM table1 "
+                                + "LEFT SEMI JOIN table2 ON table1.c1 = 
table2.c1 "
+                                + "WHERE table1.c1 IN (SELECT c1 FROM table2) 
OR table1.c1 < 10",
+                        nereidsPlanner -> {
+                            PhysicalPlan physicalPlan = 
nereidsPlanner.getPhysicalPlan();
+                            List<TreeNode<Expression>> collectResult = new 
ArrayList<>();
+                            // Check nondeterministic collect
+                            
physicalPlan.accept(NondeterministicFunctionCollector.INSTANCE, collectResult);
+                            Assertions.assertEquals(1, collectResult.size());
+                            Assertions.assertTrue(collectResult.get(0) 
instanceof Now);
+                            // Check get tables
+                            TableCollectorContext collectorContext =
+                                    new 
TableCollector.TableCollectorContext(Sets.newHashSet(TableType.OLAP));
+                            physicalPlan.accept(TableCollector.INSTANCE, 
collectorContext);
+                            Assertions.assertEquals(3, 
collectorContext.getCollectedTables().size());
+                            List<String> expectedTables = new ArrayList<>();
+                            expectedTables.add("table1");
+                            expectedTables.add("table2");
+                            expectedTables.add("table2");
+                            Assertions.assertEquals(
+                                    
collectorContext.getCollectedTables().stream()
+                                            .map(TableIf::getName)
+                                            .collect(Collectors.toList()),
+                                    expectedTables);
+                        });
+    }
+
+    @Test
+    public void test2() {
+        PlanChecker.from(connectContext)
+                .checkPlannerResult("SELECT view1.*, now() FROM view1 "
+                                + "LEFT SEMI JOIN table2 ON view1.c1 = 
table2.c1 "
+                                + "WHERE view1.c1 IN (SELECT c1 FROM table2) 
OR view1.c1 < 10",
+                        nereidsPlanner -> {
+                            PhysicalPlan physicalPlan = 
nereidsPlanner.getPhysicalPlan();
+                            List<TreeNode<Expression>> collectResult = new 
ArrayList<>();
+                            // Check nondeterministic collect
+                            
physicalPlan.accept(NondeterministicFunctionCollector.INSTANCE, collectResult);
+                            Assertions.assertEquals(2, collectResult.size());
+                            Assertions.assertTrue(collectResult.get(0) 
instanceof Now);
+                            Assertions.assertTrue(collectResult.get(1) 
instanceof CurrentDate);
+                            // Check get tables
+                            TableCollectorContext collectorContext =
+                                    new 
TableCollector.TableCollectorContext(Sets.newHashSet(TableType.OLAP));
+                            physicalPlan.accept(TableCollector.INSTANCE, 
collectorContext);
+                            Assertions.assertEquals(4, 
collectorContext.getCollectedTables().size());
+                            List<String> expectedTables = new ArrayList<>();
+                            expectedTables.add("table1");
+                            expectedTables.add("table2");
+                            expectedTables.add("table2");
+                            expectedTables.add("table2");
+                            Assertions.assertEquals(
+                                    
collectorContext.getCollectedTables().stream()
+                                            .map(TableIf::getName)
+                                            .collect(Collectors.toList()),
+                                    expectedTables);
+                        });
+    }
+}


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

Reply via email to