diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/CascadesContext.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/CascadesContext.java index 88472e30bc4a12..c2cfa5d22700c1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/CascadesContext.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/CascadesContext.java @@ -211,11 +211,19 @@ public void toMemo() { } public Analyzer newAnalyzer() { - return new Analyzer(this); + return newAnalyzer(false); + } + + public Analyzer newAnalyzer(boolean analyzeView) { + return new Analyzer(this, analyzeView); + } + + public Analyzer newAnalyzer(boolean analyzeView, Optional customTableResolver) { + return new Analyzer(this, analyzeView, customTableResolver); } public Analyzer newAnalyzer(Optional customTableResolver) { - return new Analyzer(this, customTableResolver); + return newAnalyzer(false, customTableResolver); } @Override 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 7f579f35336464..c88cf1c432f2d7 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 @@ -56,6 +56,7 @@ public class Analyzer extends AbstractBatchJobExecutor { public static final List DEFAULT_ANALYZE_JOBS = buildAnalyzeJobs(Optional.empty()); + public static final List DEFAULT_ANALYZE_VIEW_JOBS = buildAnalyzeViewJobs(Optional.empty()); private final List jobs; @@ -64,13 +65,37 @@ public class Analyzer extends AbstractBatchJobExecutor { * @param cascadesContext planner context for execute job */ public Analyzer(CascadesContext cascadesContext) { - this(cascadesContext, Optional.empty()); + this(cascadesContext, false); } - public Analyzer(CascadesContext cascadesContext, Optional customTableResolver) { + public Analyzer(CascadesContext cascadesContext, boolean analyzeView) { + this(cascadesContext, analyzeView, Optional.empty()); + } + + /** + * constructor of Analyzer. For view, we only do bind relation since other analyze step will do by outer Analyzer. + * + * @param cascadesContext current context for analyzer + * @param analyzeView analyze view or user sql. If true, analyzer is used for view. + * @param customTableResolver custom resolver for outer catalog. + */ + public Analyzer(CascadesContext cascadesContext, boolean analyzeView, + Optional customTableResolver) { super(cascadesContext); Objects.requireNonNull(customTableResolver, "customTableResolver cannot be null"); - this.jobs = !customTableResolver.isPresent() ? DEFAULT_ANALYZE_JOBS : buildAnalyzeJobs(customTableResolver); + if (analyzeView) { + if (customTableResolver.isPresent()) { + this.jobs = buildAnalyzeViewJobs(customTableResolver); + } else { + this.jobs = DEFAULT_ANALYZE_VIEW_JOBS; + } + } else { + if (customTableResolver.isPresent()) { + this.jobs = buildAnalyzeJobs(customTableResolver); + } else { + this.jobs = DEFAULT_ANALYZE_JOBS; + } + } } @Override @@ -85,6 +110,18 @@ public void analyze() { execute(); } + private static List buildAnalyzeViewJobs(Optional customTableResolver) { + return jobs( + topDown(new AnalyzeCTE()), + topDown(new EliminateLogicalSelectHint()), + bottomUp( + new BindRelation(customTableResolver), + new CheckPolicy(), + new UserAuthentication() + ) + ); + } + private static List buildAnalyzeJobs(Optional customTableResolver) { return jobs( // we should eliminate hint before "Subquery unnesting". @@ -93,9 +130,9 @@ private static List buildAnalyzeJobs(Optional c bottomUp( new BindRelation(customTableResolver), new CheckPolicy(), - new UserAuthentication(), - new BindExpression() + new UserAuthentication() ), + bottomUp(new BindExpression()), topDown(new BindSink()), bottomUp(new CheckAfterBind()), bottomUp( diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java index 78cde515fc4d85..ef51de8ddc3a82 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindRelation.java @@ -47,6 +47,7 @@ import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.PreAggStatus; +import org.apache.doris.nereids.trees.plans.algebra.Relation; import org.apache.doris.nereids.trees.plans.logical.LogicalCTEConsumer; import org.apache.doris.nereids.trees.plans.logical.LogicalEsScan; import org.apache.doris.nereids.trees.plans.logical.LogicalFileScan; @@ -89,7 +90,7 @@ public BindRelation(Optional customTableResolver) { public Rule build() { return unboundRelation().thenApply(ctx -> { Plan plan = doBindRelation(ctx); - if (!(plan instanceof Unbound)) { + if (!(plan instanceof Unbound) && plan instanceof Relation) { // init output and allocate slot id immediately, so that the slot id increase // in the order in which the table appears. LogicalProperties logicalProperties = plan.getLogicalProperties(); @@ -268,7 +269,7 @@ private Plan parseAndAnalyzeView(String ddlSql, CascadesContext parentContext) { } CascadesContext viewContext = CascadesContext.initContext( parentContext.getStatementContext(), parsedViewPlan, PhysicalProperties.ANY); - viewContext.newAnalyzer().analyze(); + viewContext.newAnalyzer(true, customTableResolver).analyze(); // we should remove all group expression of the plan which in other memo, so the groupId would not conflict return viewContext.getRewritePlan(); } diff --git a/regression-test/data/nereids_rules_p0/bind_relation/bind_view.out b/regression-test/data/nereids_rules_p0/bind_relation/bind_view.out new file mode 100644 index 00000000000000..3084841a79c4f2 --- /dev/null +++ b/regression-test/data/nereids_rules_p0/bind_relation/bind_view.out @@ -0,0 +1,5 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !select_view -- +20231214 1 A 2 1 120.000000000000 70.000000000000 3.0 11.1110000000 +20231214 1 B 9 8 290.000000000000 260.000000000000 10.615384615384615 12.6151153846 + diff --git a/regression-test/suites/nereids_rules_p0/bind_relation/bind_view.groovy b/regression-test/suites/nereids_rules_p0/bind_relation/bind_view.groovy new file mode 100644 index 00000000000000..f3f7641b732dd6 --- /dev/null +++ b/regression-test/suites/nereids_rules_p0/bind_relation/bind_view.groovy @@ -0,0 +1,97 @@ +// 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. + +suite("test_bind_view") { + sql "SET enable_nereids_planner=true" + sql "SET enable_fallback_to_original_planner=false" + + def table_name = "base_table" + def view_name = "decimal_view" + + sql """ + DROP TABLE IF EXISTS ${table_name}; + """ + sql """ + DROP VIEW IF EXISTS ${view_name}; + """ + + sql """ + CREATE TABLE IF NOT EXISTS ${table_name} + ( + `c1` varchar(255), + `c2` TINYINT, + `c3` varchar(65533), + `c4` varchar(255), + `c5` varchar(255), + `c6` DECIMAL(26,8), + `c7` varchar(255), + `c8` DECIMAL(35,8) + ) + DUPLICATE KEY(`c1`) + DISTRIBUTED BY HASH(`c1`) BUCKETS 1 + PROPERTIES ( + "replication_allocation" = "tag.location.default: 1" + ); + """ + + try { + + sql """ + create view ${view_name} AS + SELECT + substr(c1,1,8) c1 + ,c2 c2 + ,c3 c3 + ,count(c4) c4 + ,count(CASE WHEN c5='PA' THEN c4 end) c5 + ,sum(c6 / 100) c6 + ,sum(CASE WHEN c5='PA' THEN c6/100 end) c7 + ,sum(CASE WHEN c5 = 'PA' THEN c6 * c7 END) / sum(CASE WHEN c5 = 'PA' THEN c6 end) c8 + ,sum(CASE WHEN c5 = 'PA' THEN c6 * c8 END) / sum(CASE WHEN c5 = 'PA' THEN c6 END) c9 + FROM ${table_name} + GROUP BY 1,2,3 + ORDER BY 1,2,3; + """ + + sql """ + INSERT INTO ${table_name} values + ('20231214142039',1,'B','12312872384723','PA',3000,'12',11.111) + ,('20231214132039',1,'B','12312872384723','PA',4000,'12',12.222) + ,('20231214142239',1,'B','12312872384723','PA',3000,'12',13.333) + ,('20231214162339',1,'B','12312872384723','PA',4000,'3',11.111) + ,('20231214152139',1,'B','12312872384723','RJ',3000,'12',11.111) + ,('20231214152339',1,'A','12312872384723','RJ',5000,'3',11.111) + ,('20231214162139',1,'B','12312872384723','PA',5000,'12',13.444) + ,('20231214132439',1,'B','12312872384723','PA',3000,'12',12.111) + ,('20231214162039',1,'A','12312872384723','PA',7000,'3',11.111) + ,('20231214142039',1,'B','12312872384723','PA',1000,'12',11.111) + ,('20231214142039',1,'B','12312872384723','PA',3000,'12',15.555); + """ + + order_qt_select_view """ + select * from ${view_name} + """ + } finally { + sql """ + DROP VIEW IF EXISTS ${view_name}; + """ + sql """ + DROP TABLE IF EXISTS ${table_name}; + """ + + } +}