This is an automated email from the ASF dual-hosted git repository. lingmiao 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 e82d8433be [feature](nereids) Integrate nereids into current SQL process framework (#10304) e82d8433be is described below commit e82d8433bee672fbb8162b18e1fa68b791e60386 Author: Kikyou1997 <33112463+kikyou1...@users.noreply.github.com> AuthorDate: Fri Jun 24 18:26:26 2022 +0800 [feature](nereids) Integrate nereids into current SQL process framework (#10304) To integrate the nereids optimizer with new SQLParser and Planner to existing SQL process framework, I abstract a interface which named "Planner" and let the Both planner from nereids and stale optimizer implement it, to disguish it with origin Planner, I rename the Planner to OriginalPlanner. As we don't want to impact the existing logic too much, I defined a LogicalPlanAdapter to adapt the logicalPlan that is the output of the new paser to the existing code. Besides, as the MySQL protocol supports sending multiple statements in one packet, so I add Nereids#SparseSQL method to handle this properly. --- .../apache/doris/load/update/UpdatePlanner.java | 5 +- .../nereids/{Planner.java => NereidsPlanner.java} | 49 ++- .../doris/nereids/parser/LogicalPlanBuilder.java | 14 + .../apache/doris/nereids/parser/NereidsParser.java | 108 ++++++ .../org/apache/doris/nereids/parser/SqlParser.java | 85 ----- .../nereids/properties/PhysicalProperties.java | 2 + .../java/org/apache/doris/nereids/qe/Executor.java | 59 ---- .../trees/plans/PhysicalPlanTranslator.java | 11 +- .../doris/nereids/trees/plans/PlanContext.java | 14 +- .../plans/logical/LogicalPlanAdapter.java} | 29 +- .../planner/{Planner.java => OriginalPlanner.java} | 56 +-- .../java/org/apache/doris/planner/Planner.java | 379 +-------------------- .../java/org/apache/doris/qe/ConnectProcessor.java | 14 +- .../java/org/apache/doris/qe/SessionVariable.java | 19 ++ .../java/org/apache/doris/qe/StmtExecutor.java | 25 +- .../org/apache/doris/analysis/SelectStmtTest.java | 12 +- .../java/org/apache/doris/nereids/AnalyzeTest.java | 8 +- .../doris/nereids/parser/NereidsParserTest.java | 51 +++ .../expression/rewrite/ExpressionRewriteTest.java | 8 +- .../trees/expressions/ExpressionParserTest.java | 8 +- .../doris/planner/DistributedPlannerTest.java | 12 +- .../java/org/apache/doris/planner/PlannerTest.java | 48 +-- .../java/org/apache/doris/qe/CoordinatorTest.java | 28 +- .../java/org/apache/doris/qe/StmtExecutorTest.java | 6 +- .../java/org/apache/doris/utframe/DorisAssert.java | 2 +- .../apache/doris/utframe/TestWithFeService.java | 2 +- .../org/apache/doris/utframe/UtFrameUtils.java | 2 +- 27 files changed, 403 insertions(+), 653 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java b/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java index 887e2b33e1..51a28779dd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/update/UpdatePlanner.java @@ -35,10 +35,10 @@ import org.apache.doris.common.util.VectorizedUtil; import org.apache.doris.planner.DataPartition; import org.apache.doris.planner.OlapScanNode; import org.apache.doris.planner.OlapTableSink; +import org.apache.doris.planner.OriginalPlanner; import org.apache.doris.planner.PlanFragment; import org.apache.doris.planner.PlanFragmentId; import org.apache.doris.planner.PlanNodeId; -import org.apache.doris.planner.Planner; import org.apache.doris.planner.ScanNode; import com.google.common.base.Preconditions; @@ -49,7 +49,7 @@ import java.util.List; import java.util.Map; -public class UpdatePlanner extends Planner { +public class UpdatePlanner extends OriginalPlanner { private final IdGenerator<PlanNodeId> nodeIdGenerator = PlanNodeId.createGenerator(); private final IdGenerator<PlanFragmentId> fragmentIdGenerator = @@ -65,6 +65,7 @@ public class UpdatePlanner extends Planner { public UpdatePlanner(long dbId, OlapTable targetTable, List<Expr> setExprs, TupleDescriptor srcTupleDesc, Analyzer analyzer) { + super(analyzer); this.targetDBId = dbId; this.targetTable = targetTable; this.setExprs = setExprs; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java similarity index 67% rename from fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java rename to fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java index ab9396b35e..5af438c3b7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/Planner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java @@ -17,27 +17,64 @@ package org.apache.doris.nereids; +import org.apache.doris.analysis.StatementBase; import org.apache.doris.common.AnalysisException; +import org.apache.doris.common.UserException; +import org.apache.doris.common.util.VectorizedUtil; import org.apache.doris.nereids.jobs.cascades.OptimizeGroupJob; import org.apache.doris.nereids.jobs.rewrite.RewriteBottomUpJob; import org.apache.doris.nereids.memo.Group; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.memo.Memo; import org.apache.doris.nereids.properties.PhysicalProperties; +import org.apache.doris.nereids.trees.plans.PhysicalPlanTranslator; import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.PlanContext; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlanAdapter; import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan; +import org.apache.doris.planner.PlanFragment; +import org.apache.doris.planner.Planner; +import org.apache.doris.planner.ScanNode; import org.apache.doris.qe.ConnectContext; import com.google.common.collect.Lists; +import java.util.ArrayList; import java.util.List; /** * Planner to do query plan in Nereids. */ -public class Planner { +public class NereidsPlanner extends Planner { + private PlannerContext plannerContext; + private final ConnectContext ctx; + private List<ScanNode> scanNodeList = null; + + public NereidsPlanner(ConnectContext ctx) { + this.ctx = ctx; + } + + @Override + public void plan(StatementBase queryStmt, + org.apache.doris.thrift.TQueryOptions queryOptions) throws UserException { + if (!(queryStmt instanceof LogicalPlanAdapter)) { + throw new RuntimeException("Wrong type of queryStmt, expected: <? extends LogicalPlanAdapter>"); + } + LogicalPlanAdapter logicalPlanAdapter = (LogicalPlanAdapter) queryStmt; + PhysicalPlan physicalPlan = plan(logicalPlanAdapter.getLogicalPlan(), new PhysicalProperties(), ctx); + PhysicalPlanTranslator physicalPlanTranslator = new PhysicalPlanTranslator(); + PlanContext planContext = new PlanContext(); + physicalPlanTranslator.translatePlan(physicalPlan, planContext); + fragments = new ArrayList<>(planContext.getPlanFragmentList()); + PlanFragment root = fragments.get(fragments.size() - 1); + root.setOutputExprs(queryStmt.getResultExprs()); + if (VectorizedUtil.isVectorized()) { + root.getPlanRoot().convertToVectoriezd(); + } + scanNodeList = planContext.getScanNodeList(); + } /** * Do analyze and optimize for query plan. @@ -67,6 +104,11 @@ public class Planner { return getRoot().extractPlan(); } + @Override + public List<ScanNode> getScanNodes() { + return scanNodeList; + } + public Group getRoot() { return plannerContext.getOptimizerContext().getMemo().getRoot(); } @@ -93,4 +135,9 @@ public class Planner { return physicalPlan; } + + @Override + public boolean isBlockQuery() { + return true; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 23b697ede3..6b83a63f73 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -37,6 +37,7 @@ import org.apache.doris.nereids.DorisParser.JoinCriteriaContext; import org.apache.doris.nereids.DorisParser.JoinRelationContext; import org.apache.doris.nereids.DorisParser.LogicalBinaryContext; import org.apache.doris.nereids.DorisParser.LogicalNotContext; +import org.apache.doris.nereids.DorisParser.MultiStatementsContext; import org.apache.doris.nereids.DorisParser.MultipartIdentifierContext; import org.apache.doris.nereids.DorisParser.NamedExpressionContext; import org.apache.doris.nereids.DorisParser.NamedExpressionSeqContext; @@ -52,6 +53,7 @@ import org.apache.doris.nereids.DorisParser.SelectClauseContext; import org.apache.doris.nereids.DorisParser.SingleStatementContext; import org.apache.doris.nereids.DorisParser.SortItemContext; import org.apache.doris.nereids.DorisParser.StarContext; +import org.apache.doris.nereids.DorisParser.StatementContext; import org.apache.doris.nereids.DorisParser.StringLiteralContext; import org.apache.doris.nereids.DorisParser.TableNameContext; import org.apache.doris.nereids.DorisParser.WhereClauseContext; @@ -147,6 +149,18 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { return ParserUtils.withOrigin(ctx, f); } + /** + * Visit multi-statements. + */ + public Object visitMultiStatements(MultiStatementsContext ctx) { + List<LogicalPlan> logicalPlanList = new ArrayList<>(); + for (StatementContext stmtCtx : ctx.statement()) { + LogicalPlan logicalPlan = (LogicalPlan) visit(stmtCtx); + logicalPlanList.add(logicalPlan); + } + return logicalPlanList; + } + /* ******************************************************************************************** * Plan parsing * ******************************************************************************************** */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java new file mode 100644 index 0000000000..5f294cafa4 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java @@ -0,0 +1,108 @@ +// 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.parser; + +import org.apache.doris.analysis.StatementBase; +import org.apache.doris.nereids.DorisLexer; +import org.apache.doris.nereids.DorisParser; +import org.apache.doris.nereids.exceptions.ParsingException; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlanAdapter; + +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.atn.PredictionMode; +import org.antlr.v4.runtime.misc.ParseCancellationException; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Sql parser, convert sql DSL to logical plan. + */ +public class NereidsParser { + + /** + * In MySQL protocol, client could send multi-statement in. + * a single packet. + * https://dev.mysql.com/doc/internals/en/com-set-option.html + */ + public List<StatementBase> parseSQL(String originStr) throws Exception { + List<LogicalPlan> logicalPlanList = parseMultiple(originStr); + List<StatementBase> statementBaseList = new ArrayList<>(); + for (LogicalPlan logicalPlan : logicalPlanList) { + LogicalPlanAdapter logicalPlanAdapter = new LogicalPlanAdapter(logicalPlan); + statementBaseList.add(logicalPlanAdapter); + } + return statementBaseList; + } + + /** + * parse sql DSL string. + * + * @param sql sql string + * @return logical plan + */ + public LogicalPlan parseSingle(String sql) throws Exception { + return (LogicalPlan) parse(sql, DorisParser::singleStatement); + } + + public List<LogicalPlan> parseMultiple(String sql) throws Exception { + return (List<LogicalPlan>) parse(sql, DorisParser::multiStatements); + } + + private Object parse(String sql, Function<DorisParser, ParserRuleContext> parseFunction) { + try { + ParserRuleContext tree = toAst(sql, parseFunction); + LogicalPlanBuilder logicalPlanBuilder = new LogicalPlanBuilder(); + return logicalPlanBuilder.visit(tree); + } catch (StackOverflowError e) { + throw new ParsingException(e.getMessage()); + } + } + + private ParserRuleContext toAst(String sql, Function<DorisParser, ParserRuleContext> parseFunction) { + DorisLexer lexer = new DorisLexer(new CaseInsensitiveStream(CharStreams.fromString(sql))); + CommonTokenStream tokenStream = new CommonTokenStream(lexer); + DorisParser parser = new DorisParser(tokenStream); + // parser.addParseListener(PostProcessor) + // parser.removeErrorListeners() + // parser.addErrorListener(ParseErrorListener) + ParserRuleContext tree; + try { + // first, try parsing with potentially faster SLL mode + parser.getInterpreter().setPredictionMode(PredictionMode.SLL); + tree = parseFunction.apply(parser); + } catch (ParseCancellationException ex) { + // if we fail, parse with LL mode + tokenStream.seek(0); // rewind input stream + parser.reset(); + + parser.getInterpreter().setPredictionMode(PredictionMode.LL); + tree = parseFunction.apply(parser); + } + return tree; + } + + public Expression createExpression(String expression) { + return (Expression) parse(expression, DorisParser::expression); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/SqlParser.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/SqlParser.java deleted file mode 100644 index b46633c46a..0000000000 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/SqlParser.java +++ /dev/null @@ -1,85 +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.parser; - -import org.apache.doris.nereids.DorisLexer; -import org.apache.doris.nereids.DorisParser; -import org.apache.doris.nereids.exceptions.ParsingException; -import org.apache.doris.nereids.trees.TreeNode; -import org.apache.doris.nereids.trees.expressions.Expression; -import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; - -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.atn.PredictionMode; -import org.antlr.v4.runtime.misc.ParseCancellationException; - -import java.util.function.Function; - -/** - * Sql parser, convert sql DSL to logical plan. - */ -public class SqlParser { - - /** - * parse sql DSL string. - * - * @param sql sql string - * @return logical plan - */ - public LogicalPlan parse(String sql) { - return (LogicalPlan) parse(sql, DorisParser::singleStatement); - } - - private TreeNode parse(String sql, Function<DorisParser, ParserRuleContext> parseFunction) { - try { - DorisLexer lexer = new DorisLexer(new CaseInsensitiveStream(CharStreams.fromString(sql))); - CommonTokenStream tokenStream = new CommonTokenStream(lexer); - DorisParser parser = new DorisParser(tokenStream); - - // parser.addParseListener(PostProcessor) - // parser.removeErrorListeners() - // parser.addErrorListener(ParseErrorListener) - - ParserRuleContext tree; - try { - // first, try parsing with potentially faster SLL mode - parser.getInterpreter().setPredictionMode(PredictionMode.SLL); - tree = parseFunction.apply(parser); - } catch (ParseCancellationException ex) { - // if we fail, parse with LL mode - tokenStream.seek(0); // rewind input stream - parser.reset(); - - parser.getInterpreter().setPredictionMode(PredictionMode.LL); - tree = parseFunction.apply(parser); - } - - LogicalPlanBuilder logicalPlanBuilder = new LogicalPlanBuilder(); - return (TreeNode) logicalPlanBuilder.visit(tree); - - } catch (StackOverflowError e) { - throw new ParsingException(e.getMessage()); - } - } - - public Expression createExpression(String expression) { - return (Expression) parse(expression, DorisParser::expression); - } -} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java index 88ae78aa87..50899b7f31 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java @@ -23,6 +23,8 @@ package org.apache.doris.nereids.properties; public class PhysicalProperties { private DistributionSpec distributionDesc; + public PhysicalProperties() {} + public DistributionSpec getDistributionDesc() { return distributionDesc; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/qe/Executor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/qe/Executor.java deleted file mode 100644 index 342585f932..0000000000 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/qe/Executor.java +++ /dev/null @@ -1,59 +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.qe; - -import org.apache.doris.nereids.parser.SqlParser; -import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; -import org.apache.doris.qe.ConnectContext; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * Temporary executor in Nereids. - */ -public class Executor { - private static final Logger LOG = LogManager.getLogger(Executor.class); - - private final String sql; - private final ConnectContext context; - - public Executor(String sql, ConnectContext context) { - this.sql = sql; - this.context = context; - } - - public void dryRun() throws Exception { - doExecute(false); - } - - public void execute() throws Exception { - doExecute(true); - } - - private void doExecute(boolean sendFragments) throws Exception { - LOG.info("==== input SQL: ====\n{}", sql); - System.out.println("==== input SQL: ====\n" + sql + "\n"); - - // parse phase - SqlParser parser = new SqlParser(); - LogicalPlan parsedPlan = parser.parse(sql); - LOG.info("==== parsed plan: ====\n{}", parsedPlan.treeString()); - System.out.println("==== parsed plan: ====\n" + parsedPlan.treeString() + "\n"); - } -} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java index 4544ea7bd7..cf2fb9e637 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PhysicalPlanTranslator.java @@ -77,9 +77,7 @@ public class PhysicalPlanTranslator extends PlanOperatorVisitor<PlanFragment, Pl } /** - * Translate in following steps: - * 1. - * + * Translate Agg. */ @Override public PlanFragment visitPhysicalAggregation( @@ -141,6 +139,7 @@ public class PhysicalPlanTranslator extends PlanOperatorVisitor<PlanFragment, Pl OlapTable olapTable = physicalOlapScan.getTable(); TupleDescriptor tupleDescriptor = generateTupleDesc(slotList, context, olapTable); OlapScanNode olapScanNode = new OlapScanNode(context.nextNodeId(), tupleDescriptor, olapTable.getName()); + context.addScanNode(olapScanNode); // Create PlanFragment PlanFragment planFragment = new PlanFragment(context.nextFragmentId(), olapScanNode, DataPartition.RANDOM); context.addPlanFragment(planFragment); @@ -194,6 +193,7 @@ public class PhysicalPlanTranslator extends PlanOperatorVisitor<PlanFragment, Pl childSortNode.setLimit(limit + offset); } childSortNode.setOffset(0); + context.addPlanFragment(mergeFragment); return mergeFragment; } @@ -228,6 +228,7 @@ public class PhysicalPlanTranslator extends PlanOperatorVisitor<PlanFragment, Pl rightFragment.setDestination(exchangeNode); crossJoinNode.setChild(0, leftFragment.getPlanRoot()); leftFragment.setPlanRoot(crossJoinNode); + context.addPlanFragment(leftFragment); return leftFragment; } @@ -251,7 +252,9 @@ public class PhysicalPlanTranslator extends PlanOperatorVisitor<PlanFragment, Pl hashJoinNode.setLimit(physicalHashJoin.getLimited()); leftFragment.setDestination((ExchangeNode) rightFragment.getPlanRoot()); rightFragment.setDestination((ExchangeNode) leftFragmentPlanRoot); - return new PlanFragment(context.nextFragmentId(), hashJoinNode, leftFragment.getDataPartition()); + PlanFragment result = new PlanFragment(context.nextFragmentId(), hashJoinNode, leftFragment.getDataPartition()); + context.addPlanFragment(result); + return result; } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanContext.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanContext.java index fc43e5fa30..486034ceae 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanContext.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/PlanContext.java @@ -24,19 +24,22 @@ import org.apache.doris.common.IdGenerator; import org.apache.doris.planner.PlanFragment; import org.apache.doris.planner.PlanFragmentId; import org.apache.doris.planner.PlanNodeId; +import org.apache.doris.planner.ScanNode; import com.clearspring.analytics.util.Lists; +import java.util.ArrayList; import java.util.List; /** * Context of physical plan. */ public class PlanContext { - private List<PlanFragment> planFragmentList = Lists.newArrayList(); + private final List<PlanFragment> planFragmentList = Lists.newArrayList(); - private DescriptorTable descTable = new DescriptorTable(); + private final DescriptorTable descTable = new DescriptorTable(); + private final List<ScanNode> scanNodeList = new ArrayList<>(); private final IdGenerator<PlanFragmentId> fragmentIdGenerator = PlanFragmentId.createGenerator(); @@ -70,4 +73,11 @@ public class PlanContext { this.planFragmentList.add(planFragment); } + public void addScanNode(ScanNode scanNode) { + scanNodeList.add(scanNode); + } + + public List<ScanNode> getScanNodeList() { + return scanNodeList; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlanAdapter.java similarity index 53% copy from fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java copy to fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlanAdapter.java index 88ae78aa87..419fb2ba4f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/PhysicalProperties.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalPlanAdapter.java @@ -6,7 +6,7 @@ // "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 +// 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 @@ -15,19 +15,30 @@ // specific language governing permissions and limitations // under the License. -package org.apache.doris.nereids.properties; +package org.apache.doris.nereids.trees.plans.logical; + +import org.apache.doris.analysis.RedirectStatus; +import org.apache.doris.analysis.StatementBase; /** - * Physical properties used in cascades. + * This class is used for the compatibility and code reuse in. + * @see org.apache.doris.qe.ConnectProcessor */ -public class PhysicalProperties { - private DistributionSpec distributionDesc; +public class LogicalPlanAdapter extends StatementBase { + + private final LogicalPlan logicalPlan; - public DistributionSpec getDistributionDesc() { - return distributionDesc; + public LogicalPlanAdapter(LogicalPlan logicalPlan) { + this.logicalPlan = logicalPlan; } - public void setDistributionDesc(DistributionSpec distributionDesc) { - this.distributionDesc = distributionDesc; + @Override + public RedirectStatus getRedirectStatus() { + return RedirectStatus.NO_FORWARD; } + + public LogicalPlan getLogicalPlan() { + return logicalPlan; + } + } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java similarity index 89% copy from fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java copy to fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java index c563ae126c..16066544e7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java @@ -21,7 +21,6 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Analyzer; -import org.apache.doris.analysis.ExplainOptions; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.InsertStmt; import org.apache.doris.analysis.QueryStmt; @@ -34,12 +33,9 @@ import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.ScalarType; import org.apache.doris.common.UserException; -import org.apache.doris.common.profile.PlanTreeBuilder; -import org.apache.doris.common.profile.PlanTreePrinter; import org.apache.doris.common.util.VectorizedUtil; import org.apache.doris.qe.ConnectContext; import org.apache.doris.rewrite.mvrewrite.MVSelectFailedException; -import org.apache.doris.thrift.TExplainLevel; import org.apache.doris.thrift.TQueryOptions; import org.apache.doris.thrift.TRuntimeFilterMode; @@ -56,23 +52,20 @@ import java.util.List; * The planner is responsible for turning parse trees into plan fragments that can be shipped off to backends for * execution. */ -public class Planner { - private static final Logger LOG = LogManager.getLogger(Planner.class); - - private boolean isBlockQuery = false; - - protected ArrayList<PlanFragment> fragments = Lists.newArrayList(); +public class OriginalPlanner extends Planner { + private static final Logger LOG = LogManager.getLogger(OriginalPlanner.class); private PlannerContext plannerContext; private SingleNodePlanner singleNodePlanner; private DistributedPlanner distributedPlanner; + private Analyzer analyzer; - public boolean isBlockQuery() { - return isBlockQuery; + public OriginalPlanner(Analyzer analyzer) { + this.analyzer = analyzer; } - public List<PlanFragment> getFragments() { - return fragments; + public boolean isBlockQuery() { + return isBlockQuery; } public PlannerContext getPlannerContext() { @@ -86,7 +79,7 @@ public class Planner { return singleNodePlanner.getScanNodes(); } - public void plan(StatementBase queryStmt, Analyzer analyzer, TQueryOptions queryOptions) + public void plan(StatementBase queryStmt, TQueryOptions queryOptions) throws UserException { createPlanFragments(queryStmt, analyzer, queryOptions); } @@ -123,36 +116,9 @@ public class Planner { /** * Return combined explain string for all plan fragments. */ - public String getExplainString(List<PlanFragment> fragments, ExplainOptions explainOptions) { - Preconditions.checkNotNull(explainOptions); - if (explainOptions.isGraph()) { - // print the plan graph - PlanTreeBuilder builder = new PlanTreeBuilder(fragments); - try { - builder.build(); - } catch (UserException e) { - LOG.warn("Failed to build explain plan tree", e); - return e.getMessage(); - } - return PlanTreePrinter.printPlanExplanation(builder.getTreeRoot()); - } - - // print text plan - TExplainLevel explainLevel = explainOptions.isVerbose() ? TExplainLevel.VERBOSE : TExplainLevel.NORMAL; - StringBuilder str = new StringBuilder(); - for (int i = 0; i < fragments.size(); ++i) { - PlanFragment fragment = fragments.get(i); - if (i > 0) { - // a blank line between plan fragments - str.append("\n"); - } - str.append("PLAN FRAGMENT " + i + "\n"); - str.append(fragment.getExplainString(explainLevel)); - } - if (explainLevel == TExplainLevel.VERBOSE) { - str.append(plannerContext.getRootAnalyzer().getDescTbl().getExplainString()); - } - return str.toString(); + @Override + public void appendTupleInfo(StringBuilder str) { + str.append(plannerContext.getRootAnalyzer().getDescTbl().getExplainString()); } /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java index c563ae126c..f21a988b0a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/Planner.java @@ -6,7 +6,7 @@ // "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 +// 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 @@ -14,34 +14,15 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -// This file is copied from -// https://github.com/apache/impala/blob/branch-2.9.0/fe/src/main/java/org/apache/impala/Planner.java -// and modified by Doris package org.apache.doris.planner; -import org.apache.doris.analysis.Analyzer; import org.apache.doris.analysis.ExplainOptions; -import org.apache.doris.analysis.Expr; -import org.apache.doris.analysis.InsertStmt; -import org.apache.doris.analysis.QueryStmt; -import org.apache.doris.analysis.SelectStmt; -import org.apache.doris.analysis.SlotDescriptor; -import org.apache.doris.analysis.SlotId; import org.apache.doris.analysis.StatementBase; -import org.apache.doris.analysis.StorageBackend; -import org.apache.doris.analysis.TupleDescriptor; -import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.ScalarType; import org.apache.doris.common.UserException; import org.apache.doris.common.profile.PlanTreeBuilder; import org.apache.doris.common.profile.PlanTreePrinter; -import org.apache.doris.common.util.VectorizedUtil; -import org.apache.doris.qe.ConnectContext; -import org.apache.doris.rewrite.mvrewrite.MVSelectFailedException; -import org.apache.doris.thrift.TExplainLevel; import org.apache.doris.thrift.TQueryOptions; -import org.apache.doris.thrift.TRuntimeFilterMode; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; @@ -49,81 +30,22 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -/** - * The planner is responsible for turning parse trees into plan fragments that can be shipped off to backends for - * execution. - */ -public class Planner { - private static final Logger LOG = LogManager.getLogger(Planner.class); +public abstract class Planner { - private boolean isBlockQuery = false; + private static final Logger LOG = LogManager.getLogger(Planner.class); protected ArrayList<PlanFragment> fragments = Lists.newArrayList(); - private PlannerContext plannerContext; - private SingleNodePlanner singleNodePlanner; - private DistributedPlanner distributedPlanner; - - public boolean isBlockQuery() { - return isBlockQuery; - } - - public List<PlanFragment> getFragments() { - return fragments; - } - - public PlannerContext getPlannerContext() { - return plannerContext; - } - - public List<ScanNode> getScanNodes() { - if (singleNodePlanner == null) { - return Lists.newArrayList(); - } - return singleNodePlanner.getScanNodes(); - } - - public void plan(StatementBase queryStmt, Analyzer analyzer, TQueryOptions queryOptions) - throws UserException { - createPlanFragments(queryStmt, analyzer, queryOptions); - } - - /** - */ - private void setResultExprScale(Analyzer analyzer, ArrayList<Expr> outputExprs) { - for (TupleDescriptor tupleDesc : analyzer.getDescTbl().getTupleDescs()) { - for (SlotDescriptor slotDesc : tupleDesc.getSlots()) { - for (Expr expr : outputExprs) { - List<SlotId> slotList = Lists.newArrayList(); - expr.getIds(null, slotList); - if (PrimitiveType.DECIMALV2 != expr.getType().getPrimitiveType()) { - continue; - } + protected boolean isBlockQuery = false; - if (PrimitiveType.DECIMALV2 != slotDesc.getType().getPrimitiveType()) { - continue; - } + public abstract List<ScanNode> getScanNodes(); - if (slotList.contains(slotDesc.getId()) && null != slotDesc.getColumn()) { - int outputScale = slotDesc.getColumn().getScale(); - if (outputScale >= 0) { - if (outputScale > expr.getOutputScale()) { - expr.setOutputScale(outputScale); - } - } - } - } - } - } - } + public abstract void plan(StatementBase queryStmt, + TQueryOptions queryOptions) throws UserException; - /** - * Return combined explain string for all plan fragments. - */ - public String getExplainString(List<PlanFragment> fragments, ExplainOptions explainOptions) { + public String getExplainString(ExplainOptions explainOptions) { Preconditions.checkNotNull(explainOptions); if (explainOptions.isGraph()) { // print the plan graph @@ -138,7 +60,9 @@ public class Planner { } // print text plan - TExplainLevel explainLevel = explainOptions.isVerbose() ? TExplainLevel.VERBOSE : TExplainLevel.NORMAL; + org.apache.doris.thrift.TExplainLevel + explainLevel = explainOptions.isVerbose() + ? org.apache.doris.thrift.TExplainLevel.VERBOSE : org.apache.doris.thrift.TExplainLevel.NORMAL; StringBuilder str = new StringBuilder(); for (int i = 0; i < fragments.size(); ++i) { PlanFragment fragment = fragments.get(i); @@ -149,287 +73,20 @@ public class Planner { str.append("PLAN FRAGMENT " + i + "\n"); str.append(fragment.getExplainString(explainLevel)); } - if (explainLevel == TExplainLevel.VERBOSE) { - str.append(plannerContext.getRootAnalyzer().getDescTbl().getExplainString()); + if (explainLevel == org.apache.doris.thrift.TExplainLevel.VERBOSE) { + appendTupleInfo(str); } return str.toString(); } - /** - * Create plan fragments for an analyzed statement, given a set of execution options. The fragments are returned in - * a list such that element i of that list can only consume output of the following fragments j > i. - */ - public void createPlanFragments(StatementBase statement, Analyzer analyzer, TQueryOptions queryOptions) - throws UserException { - QueryStmt queryStmt; - if (statement instanceof InsertStmt) { - queryStmt = ((InsertStmt) statement).getQueryStmt(); - } else { - queryStmt = (QueryStmt) statement; - } - - plannerContext = new PlannerContext(analyzer, queryStmt, queryOptions, statement); - singleNodePlanner = new SingleNodePlanner(plannerContext); - PlanNode singleNodePlan = singleNodePlanner.createSingleNodePlan(); - - if (VectorizedUtil.isVectorized()) { - singleNodePlan.convertToVectoriezd(); - } - - if (analyzer.getContext() != null - && analyzer.getContext().getSessionVariable().isEnableProjection() - && statement instanceof SelectStmt) { - ProjectPlanner projectPlanner = new ProjectPlanner(analyzer); - projectPlanner.projectSingleNodePlan(queryStmt.getResultExprs(), singleNodePlan); - } - - if (statement instanceof InsertStmt) { - InsertStmt insertStmt = (InsertStmt) statement; - insertStmt.prepareExpressions(); - } - - // TODO chenhao16 , no used materialization work - // compute referenced slots before calling computeMemLayout() - //analyzer.markRefdSlots(analyzer, singleNodePlan, resultExprs, null); - - setResultExprScale(analyzer, queryStmt.getResultExprs()); - - // materialized view selector - boolean selectFailed = singleNodePlanner.selectMaterializedView(queryStmt, analyzer); - if (selectFailed) { - throw new MVSelectFailedException("Failed to select materialize view"); - } - - /** - * - Under normal circumstances, computeMemLayout() will be executed - * at the end of the init function of the plan node. - * Such as : - * OlapScanNode { - * init () { - * analyzer.materializeSlots(conjuncts); - * computeTupleStatAndMemLayout(analyzer); - * computeStat(); - * } - * } - * - However Doris is currently unable to determine - * whether it is possible to cut or increase the columns in the tuple after PlanNode.init(). - * - Therefore, for the time being, computeMemLayout() can only be placed - * after the completion of the entire single node planner. - */ - analyzer.getDescTbl().computeMemLayout(); - singleNodePlan.finalize(analyzer); - - if (queryOptions.num_nodes == 1) { - // single-node execution; we're almost done - singleNodePlan = addUnassignedConjuncts(analyzer, singleNodePlan); - fragments.add(new PlanFragment(plannerContext.getNextFragmentId(), singleNodePlan, - DataPartition.UNPARTITIONED)); - } else { - // all select query are unpartitioned. - distributedPlanner = new DistributedPlanner(plannerContext); - fragments = distributedPlanner.createPlanFragments(singleNodePlan); - } - - // Optimize the transfer of query statistic when query doesn't contain limit. - PlanFragment rootFragment = fragments.get(fragments.size() - 1); - QueryStatisticsTransferOptimizer queryStatisticTransferOptimizer - = new QueryStatisticsTransferOptimizer(rootFragment); - queryStatisticTransferOptimizer.optimizeQueryStatisticsTransfer(); - - // Create runtime filters. - if (!ConnectContext.get().getSessionVariable().getRuntimeFilterMode().toUpperCase() - .equals(TRuntimeFilterMode.OFF.name())) { - RuntimeFilterGenerator.generateRuntimeFilters(analyzer, rootFragment.getPlanRoot()); - } - - if (statement instanceof InsertStmt && !analyzer.getContext().isTxnModel()) { - InsertStmt insertStmt = (InsertStmt) statement; - rootFragment = distributedPlanner.createInsertFragment(rootFragment, insertStmt, fragments); - rootFragment.setSink(insertStmt.getDataSink()); - insertStmt.complete(); - ArrayList<Expr> exprs = ((InsertStmt) statement).getResultExprs(); - List<Expr> resExprs = Expr.substituteList( - exprs, rootFragment.getPlanRoot().getOutputSmap(), analyzer, true); - rootFragment.setOutputExprs(resExprs); - } else { - List<Expr> resExprs = Expr.substituteList(queryStmt.getResultExprs(), - rootFragment.getPlanRoot().getOutputSmap(), analyzer, false); - rootFragment.setOutputExprs(resExprs); - } - LOG.debug("finalize plan fragments"); - for (PlanFragment fragment : fragments) { - fragment.finalize(queryStmt); - } - - Collections.reverse(fragments); - - pushDownResultFileSink(analyzer); - - if (queryStmt instanceof SelectStmt) { - SelectStmt selectStmt = (SelectStmt) queryStmt; - if (queryStmt.getSortInfo() != null || selectStmt.getAggInfo() != null) { - isBlockQuery = true; - LOG.debug("this is block query"); - } else { - isBlockQuery = false; - LOG.debug("this isn't block query"); - } - } - } - - /** - * If there are unassigned conjuncts, returns a SelectNode on top of root that evaluate those conjuncts; otherwise - * returns root unchanged. - */ - private PlanNode addUnassignedConjuncts(Analyzer analyzer, PlanNode root) - throws UserException { - Preconditions.checkNotNull(root); - // List<Expr> conjuncts = analyzer.getUnassignedConjuncts(root.getTupleIds()); - - List<Expr> conjuncts = analyzer.getUnassignedConjuncts(root); - if (conjuncts.isEmpty()) { - return root; - } - // evaluate conjuncts in SelectNode - SelectNode selectNode = new SelectNode(plannerContext.getNextNodeId(), root, conjuncts); - selectNode.init(analyzer); - Preconditions.checkState(selectNode.hasValidStats()); - return selectNode; - } + public void appendTupleInfo(StringBuilder stringBuilder) {} - /** - * This function is mainly used to try to push the top-level result file sink down one layer. - * The result file sink after the pushdown can realize the function of concurrently exporting the result set. - * Push down needs to meet the following conditions: - * 1. The query enables the session variable of the concurrent export result set - * 2. The top-level fragment is not a merge change node - * 3. The export method uses the s3 method - * - * After satisfying the above three conditions, - * the result file sink and the associated output expr will be pushed down to the next layer. - * The second plan fragment performs expression calculation and derives the result set. - * The top plan fragment will only summarize the status of the exported result set and return it to fe. - */ - private void pushDownResultFileSink(Analyzer analyzer) { - if (fragments.size() < 1) { - return; - } - if (!(fragments.get(0).getSink() instanceof ResultFileSink)) { - return; - } - if (!ConnectContext.get().getSessionVariable().isEnableParallelOutfile()) { - return; - } - if (!(fragments.get(0).getPlanRoot() instanceof ExchangeNode)) { - return; - } - PlanFragment topPlanFragment = fragments.get(0); - ExchangeNode topPlanNode = (ExchangeNode) topPlanFragment.getPlanRoot(); - // try to push down result file sink - if (topPlanNode.isMergingExchange()) { - return; - } - PlanFragment secondPlanFragment = fragments.get(1); - ResultFileSink resultFileSink = (ResultFileSink) topPlanFragment.getSink(); - if (resultFileSink.getStorageType() == StorageBackend.StorageType.BROKER) { - return; - } - if (secondPlanFragment.getOutputExprs() != null) { - return; - } - // create result file sink desc - TupleDescriptor fileStatusDesc = constructFileStatusTupleDesc(analyzer); - resultFileSink.resetByDataStreamSink((DataStreamSink) secondPlanFragment.getSink()); - resultFileSink.setOutputTupleId(fileStatusDesc.getId()); - secondPlanFragment.setOutputExprs(topPlanFragment.getOutputExprs()); - secondPlanFragment.resetSink(resultFileSink); - ResultSink resultSink = new ResultSink(topPlanNode.getId()); - topPlanFragment.resetSink(resultSink); - topPlanFragment.resetOutputExprs(fileStatusDesc); - topPlanFragment.getPlanRoot().resetTupleIds(Lists.newArrayList(fileStatusDesc.getId())); + public List<PlanFragment> getFragments() { + return fragments; } - /** - * Construct a tuple for file status, the tuple schema as following: - * | FileNumber | Int | - * | TotalRows | Bigint | - * | FileSize | Bigint | - * | URL | Varchar | - */ - private TupleDescriptor constructFileStatusTupleDesc(Analyzer analyzer) { - TupleDescriptor resultFileStatusTupleDesc = - analyzer.getDescTbl().createTupleDescriptor("result_file_status"); - resultFileStatusTupleDesc.setIsMaterialized(true); - SlotDescriptor fileNumber = analyzer.getDescTbl().addSlotDescriptor(resultFileStatusTupleDesc); - fileNumber.setLabel("FileNumber"); - fileNumber.setType(ScalarType.createType(PrimitiveType.INT)); - fileNumber.setIsMaterialized(true); - fileNumber.setIsNullable(false); - SlotDescriptor totalRows = analyzer.getDescTbl().addSlotDescriptor(resultFileStatusTupleDesc); - totalRows.setLabel("TotalRows"); - totalRows.setType(ScalarType.createType(PrimitiveType.BIGINT)); - totalRows.setIsMaterialized(true); - totalRows.setIsNullable(false); - SlotDescriptor fileSize = analyzer.getDescTbl().addSlotDescriptor(resultFileStatusTupleDesc); - fileSize.setLabel("FileSize"); - fileSize.setType(ScalarType.createType(PrimitiveType.BIGINT)); - fileSize.setIsMaterialized(true); - fileSize.setIsNullable(false); - SlotDescriptor url = analyzer.getDescTbl().addSlotDescriptor(resultFileStatusTupleDesc); - url.setLabel("URL"); - url.setType(ScalarType.createType(PrimitiveType.VARCHAR)); - url.setIsMaterialized(true); - url.setIsNullable(false); - resultFileStatusTupleDesc.computeStatAndMemLayout(); - return resultFileStatusTupleDesc; + public boolean isBlockQuery() { + return isBlockQuery; } - private static class QueryStatisticsTransferOptimizer { - private final PlanFragment root; - - public QueryStatisticsTransferOptimizer(PlanFragment root) { - Preconditions.checkNotNull(root); - this.root = root; - } - - public void optimizeQueryStatisticsTransfer() { - optimizeQueryStatisticsTransfer(root, null); - } - - private void optimizeQueryStatisticsTransfer(PlanFragment fragment, PlanFragment parent) { - if (parent != null && hasLimit(parent.getPlanRoot(), fragment.getPlanRoot())) { - fragment.setTransferQueryStatisticsWithEveryBatch(true); - } - for (PlanFragment child : fragment.getChildren()) { - optimizeQueryStatisticsTransfer(child, fragment); - } - } - - // Check whether leaf node contains limit. - private boolean hasLimit(PlanNode ancestor, PlanNode successor) { - final List<PlanNode> exchangeNodes = Lists.newArrayList(); - collectExchangeNode(ancestor, exchangeNodes); - for (PlanNode leaf : exchangeNodes) { - if (leaf.getChild(0) == successor - && leaf.hasLimit()) { - return true; - } - } - return false; - } - - private void collectExchangeNode(PlanNode planNode, List<PlanNode> exchangeNodes) { - if (planNode instanceof ExchangeNode) { - exchangeNodes.add(planNode); - } - - for (PlanNode child : planNode.getChildren()) { - if (child instanceof ExchangeNode) { - exchangeNodes.add(child); - } else { - collectExchangeNode(child, exchangeNodes); - } - } - } - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java index 512b8c61f3..c83f5eeb45 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java @@ -45,6 +45,7 @@ import org.apache.doris.mysql.MysqlPacket; import org.apache.doris.mysql.MysqlProto; import org.apache.doris.mysql.MysqlSerializer; import org.apache.doris.mysql.MysqlServerStatusFlag; +import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.plugin.AuditEvent.EventType; import org.apache.doris.proto.Data; import org.apache.doris.service.FrontendOptions; @@ -201,7 +202,18 @@ public class ConnectProcessor { List<Pair<StatementBase, Data.PQueryStatistics>> auditInfoList = Lists.newArrayList(); boolean alreadyAddedToAuditInfoList = false; try { - List<StatementBase> stmts = analyze(originStmt); + List<StatementBase> stmts = null; + if (ctx.getSessionVariable().isEnableNereids()) { + NereidsParser nereidsParser = new NereidsParser(); + try { + stmts = nereidsParser.parseSQL(originStmt); + } catch (Exception e) { + LOG.warn("SQL : {}, parse failed by new parser", originStmt, e); + } + } + if (stmts == null) { + stmts = analyze(originStmt); + } for (int i = 0; i < stmts.size(); ++i) { alreadyAddedToAuditInfoList = false; ctx.getState().reset(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java index 384401e5b3..e7cdfd37f9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java @@ -192,6 +192,8 @@ public class SessionVariable implements Serializable, Writable { static final String ENABLE_ARRAY_TYPE = "enable_array_type"; + public static final String ENABLE_NEREIDS = "enable_nereids"; + // session origin value public Map<Field, String> sessionOriginValue = new HashMap<Field, String>(); // check stmt is or not [select /*+ SET_VAR(...)*/ ...] @@ -471,6 +473,15 @@ public class SessionVariable implements Serializable, Writable { @VariableMgr.VarAttr(name = ENABLE_ARRAY_TYPE) private boolean enableArrayType = false; + /** + * as the new optimizer is not mature yet, use this var + * to control whether to use new optimizer, remove it when + * the new optimizer is fully developed. I hope that day + * would be coming soon. + */ + @VariableMgr.VarAttr(name = ENABLE_NEREIDS) + private boolean enableNereids = false; + public String getBlockEncryptionMode() { return blockEncryptionMode; } @@ -970,6 +981,14 @@ public class SessionVariable implements Serializable, Writable { this.enableArrayType = enableArrayType; } + public boolean isEnableNereids() { + return enableNereids; + } + + public void setEnableNereids(boolean enableNereids) { + this.enableNereids = enableNereids; + } + /** * Serialize to thrift object. * Used for rest api. diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index ba4ab0d200..edbc629be0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -84,7 +84,10 @@ import org.apache.doris.mysql.MysqlChannel; import org.apache.doris.mysql.MysqlEofPacket; import org.apache.doris.mysql.MysqlSerializer; import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.nereids.NereidsPlanner; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlanAdapter; import org.apache.doris.planner.OlapScanNode; +import org.apache.doris.planner.OriginalPlanner; import org.apache.doris.planner.Planner; import org.apache.doris.planner.ScanNode; import org.apache.doris.proto.Data; @@ -729,10 +732,14 @@ public class StmtExecutor implements ProfileWriter { } plannerProfile.setQueryAnalysisFinishTime(); - // create plan - planner = new Planner(); + if (parsedStmt instanceof LogicalPlanAdapter) { + // create plan + planner = new NereidsPlanner(context); + } else { + planner = new OriginalPlanner(analyzer); + } if (parsedStmt instanceof QueryStmt || parsedStmt instanceof InsertStmt) { - planner.plan(parsedStmt, analyzer, tQueryOptions); + planner.plan(parsedStmt, tQueryOptions); } // TODO(zc): // Preconditions.checkState(!analyzer.hasUnassignedConjuncts()); @@ -874,8 +881,12 @@ public class StmtExecutor implements ProfileWriter { newSelectStmt.reset(); analyzer = new Analyzer(context.getCatalog(), context); newSelectStmt.analyze(analyzer); - planner = new Planner(); - planner.plan(newSelectStmt, analyzer, context.getSessionVariable().toThrift()); + if (parsedStmt instanceof LogicalPlanAdapter) { + planner = new NereidsPlanner(context); + } else { + planner = new OriginalPlanner(analyzer); + } + planner.plan(newSelectStmt, context.getSessionVariable().toThrift()); } } sendResult(false, isSendFields, newSelectStmt, channel, cacheAnalyzer, cacheResult); @@ -929,7 +940,7 @@ public class StmtExecutor implements ProfileWriter { } if (queryStmt.isExplain()) { - String explainString = planner.getExplainString(planner.getFragments(), queryStmt.getExplainOptions()); + String explainString = planner.getExplainString(queryStmt.getExplainOptions()); handleExplainStmt(explainString); return; } @@ -1245,7 +1256,7 @@ public class StmtExecutor implements ProfileWriter { if (insertStmt.getQueryStmt().isExplain()) { ExplainOptions explainOptions = insertStmt.getQueryStmt().getExplainOptions(); insertStmt.setIsExplain(explainOptions); - String explainString = planner.getExplainString(planner.getFragments(), explainOptions); + String explainString = planner.getExplainString(explainOptions); handleExplainStmt(explainString); return; } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java index a1d35a5b1b..5577a566be 100755 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SelectStmtTest.java @@ -20,7 +20,7 @@ package org.apache.doris.analysis; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; import org.apache.doris.common.util.Util; -import org.apache.doris.planner.Planner; +import org.apache.doris.planner.OriginalPlanner; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.VariableMgr; import org.apache.doris.utframe.DorisAssert; @@ -562,28 +562,28 @@ public class SelectStmtTest { @Test public void testSelectHintSetVar() throws Exception { String sql = "SELECT sleep(3);"; - Planner planner = dorisAssert.query(sql).internalExecuteOneAndGetPlan(); + OriginalPlanner planner = (OriginalPlanner) dorisAssert.query(sql).internalExecuteOneAndGetPlan(); Assert.assertEquals(VariableMgr.getDefaultSessionVariable().getQueryTimeoutS(), planner.getPlannerContext().getQueryOptions().query_timeout); sql = "SELECT /*+ SET_VAR(query_timeout = 1) */ sleep(3);"; - planner = dorisAssert.query(sql).internalExecuteOneAndGetPlan(); + planner = (OriginalPlanner) dorisAssert.query(sql).internalExecuteOneAndGetPlan(); Assert.assertEquals(1, planner.getPlannerContext().getQueryOptions().query_timeout); sql = "select * from db1.partition_table where datekey=20200726"; - planner = dorisAssert.query(sql).internalExecuteOneAndGetPlan(); + planner = (OriginalPlanner) dorisAssert.query(sql).internalExecuteOneAndGetPlan(); Assert.assertEquals(VariableMgr.getDefaultSessionVariable().getMaxExecMemByte(), planner.getPlannerContext().getQueryOptions().mem_limit); sql = "select /*+ SET_VAR(exec_mem_limit = 8589934592) */ poi_id, count(*) from db1.partition_table " + "where datekey=20200726 group by 1"; - planner = dorisAssert.query(sql).internalExecuteOneAndGetPlan(); + planner = (OriginalPlanner) dorisAssert.query(sql).internalExecuteOneAndGetPlan(); Assert.assertEquals(8589934592L, planner.getPlannerContext().getQueryOptions().mem_limit); int queryTimeOut = dorisAssert.getSessionVariable().getQueryTimeoutS(); long execMemLimit = dorisAssert.getSessionVariable().getMaxExecMemByte(); sql = "select /*+ SET_VAR(exec_mem_limit = 8589934592, query_timeout = 1) */ 1 + 2;"; - planner = dorisAssert.query(sql).internalExecuteOneAndGetPlan(); + planner = (OriginalPlanner) dorisAssert.query(sql).internalExecuteOneAndGetPlan(); // session variable have been changed Assert.assertEquals(1, planner.getPlannerContext().getQueryOptions().query_timeout); Assert.assertEquals(8589934592L, planner.getPlannerContext().getQueryOptions().mem_limit); diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/AnalyzeTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/AnalyzeTest.java index 2832dfa115..f4a472fe7a 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/AnalyzeTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/AnalyzeTest.java @@ -20,7 +20,7 @@ package org.apache.doris.nereids; import org.apache.doris.nereids.analyzer.Unbound; import org.apache.doris.nereids.jobs.rewrite.RewriteBottomUpJob; import org.apache.doris.nereids.memo.Memo; -import org.apache.doris.nereids.parser.SqlParser; +import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.properties.PhysicalProperties; import org.apache.doris.nereids.rules.analysis.BindRelation; import org.apache.doris.nereids.rules.analysis.BindSlotReference; @@ -37,7 +37,7 @@ import java.util.List; public class AnalyzeTest extends TestWithFeService { - private final SqlParser parser = new SqlParser(); + private final NereidsParser parser = new NereidsParser(); @Override protected void runBeforeAll() throws Exception { @@ -67,8 +67,8 @@ public class AnalyzeTest extends TestWithFeService { Assertions.assertTrue(checkBound(analyzed)); } - private LogicalPlan analyze(String sql) { - LogicalPlan parsed = parser.parse(sql); + private LogicalPlan analyze(String sql) throws Exception { + LogicalPlan parsed = parser.parseSingle(sql); return analyze(parsed, connectContext); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java new file mode 100644 index 0000000000..f1104e97da --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/parser/NereidsParserTest.java @@ -0,0 +1,51 @@ +// 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.parser; + +import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; + +import org.junit.Assert; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; + +public class NereidsParserTest { + + @Test + public void testParseMultiple() throws Exception { + NereidsParser nereidsParser = new NereidsParser(); + String sql = "SELECT b FROM test;SELECT a FROM test;"; + List<LogicalPlan> logicalPlanList = nereidsParser.parseMultiple(sql); + Assertions.assertEquals(2, logicalPlanList.size()); + } + + @Test + public void testSingle() throws Exception { + NereidsParser nereidsParser = new NereidsParser(); + String sql = "SELECT * FROM test;"; + Exception exceptionOccurred = null; + try { + nereidsParser.parseSingle(sql); + } catch (Exception e) { + exceptionOccurred = e; + e.printStackTrace(); + } + Assert.assertNull(exceptionOccurred); + } +} diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java index 46ebcef0f3..0cb2e4c2be 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/rewrite/ExpressionRewriteTest.java @@ -17,7 +17,7 @@ package org.apache.doris.nereids.rules.expression.rewrite; -import org.apache.doris.nereids.parser.SqlParser; +import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.rules.expression.rewrite.rules.NormalizeExpressionRule; import org.apache.doris.nereids.rules.expression.rewrite.rules.SimplifyNotExprRule; import org.apache.doris.nereids.trees.expressions.Expression; @@ -29,7 +29,7 @@ import org.junit.Test; * all expr rewrite rule test case. */ public class ExpressionRewriteTest { - private final SqlParser parser = new SqlParser(); + private static final NereidsParser PARSER = new NereidsParser(); private ExpressionRuleExecutor executor; @Test @@ -57,8 +57,8 @@ public class ExpressionRewriteTest { } private void assertRewrite(String expression, String expected) { - Expression needRewriteExpression = parser.createExpression(expression); - Expression expectedExpression = parser.createExpression(expected); + Expression needRewriteExpression = PARSER.createExpression(expression); + Expression expectedExpression = PARSER.createExpression(expected); Expression rewrittenExpression = executor.rewrite(needRewriteExpression); Assert.assertEquals(expectedExpression, rewrittenExpression); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java index 987760f6bf..b868c69584 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/ExpressionParserTest.java @@ -17,16 +17,16 @@ package org.apache.doris.nereids.trees.expressions; -import org.apache.doris.nereids.parser.SqlParser; +import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.trees.TreeNode; import org.junit.Test; public class ExpressionParserTest { - private static final SqlParser PARSER = new SqlParser(); + private static final NereidsParser PARSER = new NereidsParser(); private void assertSql(String sql) throws Exception { - TreeNode treeNode = PARSER.parse(sql); + TreeNode treeNode = PARSER.parseSingle(sql); System.out.println(treeNode.toString()); } @@ -50,7 +50,7 @@ public class ExpressionParserTest { @Test public void testSqlAnd() throws Exception { String sql = "select * from test1 where a > 1 and b > 1"; - TreeNode treeNode = PARSER.parse(sql); + TreeNode treeNode = PARSER.parseSingle(sql); System.out.println(treeNode); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/DistributedPlannerTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/DistributedPlannerTest.java index c8331573e5..4f119bc4e4 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/DistributedPlannerTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/DistributedPlannerTest.java @@ -133,16 +133,14 @@ public class DistributedPlannerTest { StmtExecutor stmtExecutor = new StmtExecutor(ctx, sql); stmtExecutor.execute(); Planner planner = stmtExecutor.planner(); - List<PlanFragment> fragments = planner.getFragments(); - String plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + String plan = planner.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(BROADCAST)")); sql = "explain select * from db1.tbl1 join [SHUFFLE] db1.tbl2 on tbl1.k1 = tbl2.k3"; stmtExecutor = new StmtExecutor(ctx, sql); stmtExecutor.execute(); planner = stmtExecutor.planner(); - fragments = planner.getFragments(); - plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + plan = planner.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(PARTITIONED)")); } @@ -152,8 +150,7 @@ public class DistributedPlannerTest { StmtExecutor stmtExecutor = new StmtExecutor(ctx, sql); stmtExecutor.execute(); Planner planner = stmtExecutor.planner(); - List<PlanFragment> fragments = planner.getFragments(); - String plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + String plan = planner.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(BROADCAST)")); double originThreshold = ctx.getSessionVariable().autoBroadcastJoinThreshold; @@ -162,8 +159,7 @@ public class DistributedPlannerTest { stmtExecutor = new StmtExecutor(ctx, sql); stmtExecutor.execute(); planner = stmtExecutor.planner(); - fragments = planner.getFragments(); - plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + plan = planner.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan, "INNER JOIN(PARTITIONED)")); } finally { ctx.getSessionVariable().autoBroadcastJoinThreshold = originThreshold; diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java index 73fe9bf24b..d52314518a 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/PlannerTest.java @@ -93,8 +93,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor1 = new StmtExecutor(connectContext, sql1); stmtExecutor1.execute(); Planner planner1 = stmtExecutor1.planner(); - List<PlanFragment> fragments1 = planner1.getFragments(); - String plan1 = planner1.getExplainString(fragments1, new ExplainOptions(false, false)); + String plan1 = planner1.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan1, "UNION")); String sql2 = "explain select * from db1.tbl1 where k1='a' and k4=1\n" + "union distinct\n" @@ -118,8 +117,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor2 = new StmtExecutor(connectContext, sql2); stmtExecutor2.execute(); Planner planner2 = stmtExecutor2.planner(); - List<PlanFragment> fragments2 = planner2.getFragments(); - String plan2 = planner2.getExplainString(fragments2, new ExplainOptions(false, false)); + String plan2 = planner2.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(4, StringUtils.countMatches(plan2, "UNION")); // intersect @@ -134,8 +132,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor3 = new StmtExecutor(connectContext, sql3); stmtExecutor3.execute(); Planner planner3 = stmtExecutor3.planner(); - List<PlanFragment> fragments3 = planner3.getFragments(); - String plan3 = planner3.getExplainString(fragments3, new ExplainOptions(false, false)); + String plan3 = planner3.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan3, "INTERSECT")); String sql4 = "explain select * from db1.tbl1 where k1='a' and k4=1\n" + "intersect distinct\n" @@ -160,8 +157,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor4 = new StmtExecutor(connectContext, sql4); stmtExecutor4.execute(); Planner planner4 = stmtExecutor4.planner(); - List<PlanFragment> fragments4 = planner4.getFragments(); - String plan4 = planner4.getExplainString(fragments4, new ExplainOptions(false, false)); + String plan4 = planner4.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(3, StringUtils.countMatches(plan4, "INTERSECT")); // except @@ -176,8 +172,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor5 = new StmtExecutor(connectContext, sql5); stmtExecutor5.execute(); Planner planner5 = stmtExecutor5.planner(); - List<PlanFragment> fragments5 = planner5.getFragments(); - String plan5 = planner5.getExplainString(fragments5, new ExplainOptions(false, false)); + String plan5 = planner5.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan5, "EXCEPT")); String sql6 = "select * from db1.tbl1 where k1='a' and k4=1\n" @@ -191,8 +186,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor6 = new StmtExecutor(connectContext, sql6); stmtExecutor6.execute(); Planner planner6 = stmtExecutor6.planner(); - List<PlanFragment> fragments6 = planner6.getFragments(); - String plan6 = planner6.getExplainString(fragments6, new ExplainOptions(false, false)); + String plan6 = planner6.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan6, "EXCEPT")); String sql7 = "select * from db1.tbl1 where k1='a' and k4=1\n" @@ -206,8 +200,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor7 = new StmtExecutor(connectContext, sql7); stmtExecutor7.execute(); Planner planner7 = stmtExecutor7.planner(); - List<PlanFragment> fragments7 = planner7.getFragments(); - String plan7 = planner7.getExplainString(fragments7, new ExplainOptions(false, false)); + String plan7 = planner7.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan7, "EXCEPT")); // mixed @@ -222,8 +215,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor8 = new StmtExecutor(connectContext, sql8); stmtExecutor8.execute(); Planner planner8 = stmtExecutor8.planner(); - List<PlanFragment> fragments8 = planner8.getFragments(); - String plan8 = planner8.getExplainString(fragments8, new ExplainOptions(false, false)); + String plan8 = planner8.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(1, StringUtils.countMatches(plan8, "UNION")); Assert.assertEquals(1, StringUtils.countMatches(plan8, "INTERSECT")); Assert.assertEquals(1, StringUtils.countMatches(plan8, "EXCEPT")); @@ -251,8 +243,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor9 = new StmtExecutor(connectContext, sql9); stmtExecutor9.execute(); Planner planner9 = stmtExecutor9.planner(); - List<PlanFragment> fragments9 = planner9.getFragments(); - String plan9 = planner9.getExplainString(fragments9, new ExplainOptions(false, false)); + String plan9 = planner9.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(2, StringUtils.countMatches(plan9, "UNION")); Assert.assertEquals(3, StringUtils.countMatches(plan9, "INTERSECT")); Assert.assertEquals(2, StringUtils.countMatches(plan9, "EXCEPT")); @@ -362,8 +353,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor1 = new StmtExecutor(connectContext, sql1); stmtExecutor1.execute(); Planner planner1 = stmtExecutor1.planner(); - List<PlanFragment> fragments1 = planner1.getFragments(); - String plan1 = planner1.getExplainString(fragments1, new ExplainOptions(true, false)); + String plan1 = planner1.getExplainString(new ExplainOptions(true, false)); Assert.assertEquals(2, StringUtils.countMatches(plan1, "nullIndicatorBit=0")); } @@ -413,8 +403,7 @@ public class PlannerTest extends TestWithFeService { e.printStackTrace(); } Planner planner1 = stmtExecutor1.planner(); - List<PlanFragment> fragments1 = planner1.getFragments(); - String plan1 = planner1.getExplainString(fragments1, new ExplainOptions(false, false)); + String plan1 = planner1.getExplainString(new ExplainOptions(false, false)); StmtExecutor stmtExecutor2 = new StmtExecutor(connectContext, sql2); try { @@ -423,8 +412,7 @@ public class PlannerTest extends TestWithFeService { e.printStackTrace(); } Planner planner2 = stmtExecutor2.planner(); - List<PlanFragment> fragments2 = planner2.getFragments(); - String plan2 = planner2.getExplainString(fragments2, new ExplainOptions(false, false)); + String plan2 = planner2.getExplainString(new ExplainOptions(false, false)); Assert.assertEquals(plan1, plan2); }; @@ -459,8 +447,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor = new StmtExecutor(connectContext, sql); stmtExecutor.execute(); Planner planner = stmtExecutor.planner(); - List<PlanFragment> fragments = planner.getFragments(); - String plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + String plan = planner.getExplainString(new ExplainOptions(false, false)); Assertions.assertTrue(plan.contains("PREDICATES: `k1` = 1\n")); } @@ -471,8 +458,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor = new StmtExecutor(connectContext, sql); stmtExecutor.execute(); Planner planner = stmtExecutor.planner(); - List<PlanFragment> fragments = planner.getFragments(); - String plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + String plan = planner.getExplainString(new ExplainOptions(false, false)); Assertions.assertFalse(plan.contains("PREDICATES:")); } @@ -483,8 +469,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor = new StmtExecutor(connectContext, sql); stmtExecutor.execute(); Planner planner = stmtExecutor.planner(); - List<PlanFragment> fragments = planner.getFragments(); - String plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + String plan = planner.getExplainString(new ExplainOptions(false, false)); Assertions.assertTrue(plan.contains("PREDICATES: `k1` = 1, `k2` = 1\n")); } @@ -496,8 +481,7 @@ public class PlannerTest extends TestWithFeService { StmtExecutor stmtExecutor = new StmtExecutor(connectContext, sql); stmtExecutor.execute(); Planner planner = stmtExecutor.planner(); - List<PlanFragment> fragments = planner.getFragments(); - String plan = planner.getExplainString(fragments, new ExplainOptions(false, false)); + String plan = planner.getExplainString(new ExplainOptions(false, false)); Assertions.assertTrue(plan.contains("PREDICATES: `k1` = 1\n")); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/CoordinatorTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/CoordinatorTest.java index 8a079f6390..033f8bb766 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/qe/CoordinatorTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/qe/CoordinatorTest.java @@ -33,10 +33,10 @@ import org.apache.doris.planner.DataPartition; import org.apache.doris.planner.EmptySetNode; import org.apache.doris.planner.HashJoinNode; import org.apache.doris.planner.OlapScanNode; +import org.apache.doris.planner.OriginalPlanner; import org.apache.doris.planner.PlanFragment; import org.apache.doris.planner.PlanFragmentId; import org.apache.doris.planner.PlanNodeId; -import org.apache.doris.planner.Planner; import org.apache.doris.planner.ScanNode; import org.apache.doris.service.FrontendOptions; import org.apache.doris.system.Backend; @@ -63,13 +63,7 @@ import java.util.Map; import java.util.Set; public class CoordinatorTest extends Coordinator { - static Planner planner = new Planner(); - static ConnectContext context = new ConnectContext(null); - static { - context.setQueryId(new TUniqueId(1, 2)); - context.setQualifiedUser("root"); - } @Mocked static Catalog catalog; @@ -77,17 +71,25 @@ public class CoordinatorTest extends Coordinator { static EditLog editLog; @Mocked static FrontendOptions frontendOptions; + + static ConnectContext context = new ConnectContext(null); static Analyzer analyzer = new Analyzer(catalog, context); + static OriginalPlanner originalPlanner = new OriginalPlanner(analyzer); + + static { + context.setQueryId(new TUniqueId(1, 2)); + context.setQualifiedUser("root"); + } public CoordinatorTest() { - super(context, analyzer, planner); + super(context, analyzer, originalPlanner); } private static Coordinator coor; @Test public void testComputeColocateJoinInstanceParam() { - Coordinator coordinator = new Coordinator(context, analyzer, planner); + Coordinator coordinator = new Coordinator(context, analyzer, originalPlanner); PlanFragmentId planFragmentId = new PlanFragmentId(1); int scanNodeId = 1; @@ -279,7 +281,7 @@ public class CoordinatorTest extends Coordinator { @Test public void testColocateJoinAssignment() { - Coordinator coordinator = new Coordinator(context, analyzer, planner); + Coordinator coordinator = new Coordinator(context, analyzer, originalPlanner); PlanFragmentId planFragmentId = new PlanFragmentId(1); int scanNodeId = 1; @@ -505,7 +507,7 @@ public class CoordinatorTest extends Coordinator { @Test public void testComputeScanRangeAssignmentByScheduler() { - Coordinator coordinator = new Coordinator(context, analyzer, planner); + Coordinator coordinator = new Coordinator(context, analyzer, originalPlanner); PlanFragmentId planFragmentId = new PlanFragmentId(1); int scanNodeId = 1; Map<PlanFragmentId, Set<Integer>> fragmentIdToScanNodeIds = new HashMap<>(); @@ -589,7 +591,7 @@ public class CoordinatorTest extends Coordinator { @Test public void testGetExecHostPortForFragmentIDAndBucketSeq() { - Coordinator coordinator = new Coordinator(context, analyzer, planner); + Coordinator coordinator = new Coordinator(context, analyzer, originalPlanner); PlanFragmentId planFragmentId = new PlanFragmentId(1); // each olaptable bucket have the same TScanRangeLocations, be id is {0, 1, 2} TScanRangeLocations tScanRangeLocations = new TScanRangeLocations(); @@ -712,7 +714,7 @@ public class CoordinatorTest extends Coordinator { @Test public void testComputeScanRangeAssignment() { - Coordinator coordinator = new Coordinator(context, analyzer, planner); + Coordinator coordinator = new Coordinator(context, analyzer, originalPlanner); //TScanRangeLocations TScanRangeLocations tScanRangeLocations = new TScanRangeLocations(); diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java index 5b371995de..8be9d2433b 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/qe/StmtExecutorTest.java @@ -37,7 +37,7 @@ import org.apache.doris.common.util.RuntimeProfile; import org.apache.doris.metric.MetricRepo; import org.apache.doris.mysql.MysqlChannel; import org.apache.doris.mysql.MysqlSerializer; -import org.apache.doris.planner.Planner; +import org.apache.doris.planner.OriginalPlanner; import org.apache.doris.rewrite.ExprRewriter; import org.apache.doris.service.FrontendOptions; import org.apache.doris.thrift.TQueryOptions; @@ -174,7 +174,7 @@ public class StmtExecutorTest { @Test public void testSelect(@Mocked QueryStmt queryStmt, @Mocked SqlParser parser, - @Mocked Planner planner, + @Mocked OriginalPlanner planner, @Mocked Coordinator coordinator) throws Exception { Catalog catalog = Catalog.getCurrentCatalog(); Deencapsulation.setField(catalog, "canRead", new AtomicBoolean(true)); @@ -211,7 +211,7 @@ public class StmtExecutorTest { minTimes = 0; result = symbol; - planner.plan((QueryStmt) any, (Analyzer) any, (TQueryOptions) any); + planner.plan((QueryStmt) any, (TQueryOptions) any); minTimes = 0; // mock coordinator diff --git a/fe/fe-core/src/test/java/org/apache/doris/utframe/DorisAssert.java b/fe/fe-core/src/test/java/org/apache/doris/utframe/DorisAssert.java index 1d74e49471..398f6112ef 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/utframe/DorisAssert.java +++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/DorisAssert.java @@ -204,7 +204,7 @@ public class DorisAssert { } } Planner planner = stmtExecutor.planner(); - String explainString = planner.getExplainString(planner.getFragments(), new ExplainOptions(false, false)); + String explainString = planner.getExplainString(new ExplainOptions(false, false)); System.out.println(explainString); return explainString; } diff --git a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java index 649043e9ac..feed9b0a58 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java +++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java @@ -319,7 +319,7 @@ public abstract class TestWithFeService { stmtExecutor.execute(); if (connectContext.getState().getStateType() != QueryState.MysqlStateType.ERR) { Planner planner = stmtExecutor.planner(); - return planner.getExplainString(planner.getFragments(), new ExplainOptions(isVerbose, false)); + return planner.getExplainString(new ExplainOptions(isVerbose, false)); } else { return connectContext.getState().getErrorMessage(); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java b/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java index e822667383..4e0a49016f 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java +++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/UtFrameUtils.java @@ -282,7 +282,7 @@ public class UtFrameUtils { stmtExecutor.execute(); if (ctx.getState().getStateType() != QueryState.MysqlStateType.ERR) { Planner planner = stmtExecutor.planner(); - return planner.getExplainString(planner.getFragments(), new ExplainOptions(isVerbose, false)); + return planner.getExplainString(new ExplainOptions(isVerbose, false)); } else { return ctx.getState().getErrorMessage(); } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org