This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit a4bf43f2d102577004b04440880a51c1494eeb5e Author: morrySnow <[email protected]> AuthorDate: Tue Aug 22 15:28:29 2023 +0800 [feature](Nereids) support handle query in fe (#23263) 1. fix select variable with alias parsed as two level alias expression. 2. support handle query in fe --- .../org/apache/doris/nereids/NereidsPlanner.java | 41 +++++++ .../doris/nereids/analyzer/UnboundVariable.java | 75 +++++++++++++ .../doris/nereids/parser/LogicalPlanBuilder.java | 37 ++----- .../doris/nereids/rules/analysis/SlotBinder.java | 45 +++++++- .../rules/expression/ExpressionNormalization.java | 2 + .../expression/rules/ReplaceVariableByLiteral.java | 36 +++++++ .../doris/nereids/trees/expressions/Variable.java | 118 +++++++++++++++++++++ .../expressions/visitor/ExpressionVisitor.java | 10 ++ .../org/apache/doris/planner/OriginalPlanner.java | 35 ++++++ .../java/org/apache/doris/planner/Planner.java | 24 +++++ .../java/org/apache/doris/qe/StmtExecutor.java | 48 +-------- 11 files changed, 399 insertions(+), 72 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java index 4bef000639..267ca0064c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java @@ -19,8 +19,10 @@ package org.apache.doris.nereids; import org.apache.doris.analysis.DescriptorTable; import org.apache.doris.analysis.ExplainOptions; +import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.StatementBase; import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.Column; import org.apache.doris.common.NereidsException; import org.apache.doris.common.Pair; import org.apache.doris.common.util.DebugUtil; @@ -40,17 +42,24 @@ import org.apache.doris.nereids.minidump.NereidsTracer; import org.apache.doris.nereids.processor.post.PlanPostProcessors; import org.apache.doris.nereids.processor.pre.PlanPreprocessors; import org.apache.doris.nereids.properties.PhysicalProperties; +import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.plans.AbstractPlan; +import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.commands.ExplainCommand.ExplainLevel; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; +import org.apache.doris.nereids.trees.plans.physical.PhysicalOneRowRelation; import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan; +import org.apache.doris.nereids.trees.plans.physical.PhysicalResultSink; import org.apache.doris.planner.PlanFragment; import org.apache.doris.planner.Planner; import org.apache.doris.planner.RuntimeFilter; import org.apache.doris.planner.ScanNode; import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.CommonResultSet; +import org.apache.doris.qe.ResultSet; +import org.apache.doris.qe.ResultSetMetaData; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; @@ -65,6 +74,7 @@ import org.json.JSONObject; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.Executors; @@ -441,6 +451,37 @@ public class NereidsPlanner extends Planner { return cascadesContext.getRuntimeFilterContext().getLegacyFilters(); } + @Override + public Optional<ResultSet> handleQueryInFe(StatementBase parsedStmt) { + if (!(parsedStmt instanceof LogicalPlanAdapter)) { + return Optional.empty(); + } + if (!(physicalPlan instanceof PhysicalResultSink)) { + return Optional.empty(); + } + if (!(((PhysicalResultSink<?>) physicalPlan).child() instanceof PhysicalOneRowRelation)) { + return Optional.empty(); + } + PhysicalOneRowRelation physicalOneRowRelation + = (PhysicalOneRowRelation) ((PhysicalResultSink<?>) physicalPlan).child(); + List<Column> columns = Lists.newArrayList(); + List<String> data = Lists.newArrayList(); + for (int i = 0; i < physicalOneRowRelation.getProjects().size(); i++) { + NamedExpression item = physicalOneRowRelation.getProjects().get(i); + Expression expr = item.child(0); + if (expr instanceof Literal) { + LiteralExpr legacyExpr = ((Literal) expr).toLegacyLiteral(); + columns.add(new Column(item.getName(), item.getDataType().toCatalogDataType())); + super.handleLiteralInFe(legacyExpr, data); + } else { + return Optional.empty(); + } + } + ResultSetMetaData metadata = new CommonResultSet.CommonResultSetMetaData(columns); + ResultSet resultSet = new CommonResultSet(metadata, Collections.singletonList(data)); + return Optional.of(resultSet); + } + @VisibleForTesting public CascadesContext getCascadesContext() { return cascadesContext; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundVariable.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundVariable.java new file mode 100644 index 0000000000..dfd4e7fd46 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundVariable.java @@ -0,0 +1,75 @@ +// 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.analyzer; + +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; + +import java.util.Objects; + +/** + * unbound variable + */ +public class UnboundVariable extends Expression implements Unbound { + + private final String name; + private final VariableType type; + + public UnboundVariable(String name, VariableType type) { + this.name = Objects.requireNonNull(name, "name should not be null"); + this.type = Objects.requireNonNull(type, "type should not be null"); + } + + public String getName() { + return name; + } + + public VariableType getType() { + return type; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitUnboundVariable(this, context); + } + + @Override + public boolean nullable() { + return false; + } + + @Override + public String toString() throws UnboundException { + if (type == VariableType.USER) { + return "@" + name; + } else { + return "@@" + name; + } + } + + /** + * variable type + */ + public enum VariableType { + GLOBAL, + SESSION, + DEFAULT, + USER, + } +} 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 0ab372afe2..cd9644e2d6 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 @@ -18,10 +18,8 @@ package org.apache.doris.nereids.parser; import org.apache.doris.analysis.ArithmeticExpr.Operator; -import org.apache.doris.analysis.SetType; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.common.Config; -import org.apache.doris.common.DdlException; import org.apache.doris.common.Pair; import org.apache.doris.nereids.DorisParser; import org.apache.doris.nereids.DorisParser.AggClauseContext; @@ -125,6 +123,8 @@ import org.apache.doris.nereids.analyzer.UnboundResultSink; import org.apache.doris.nereids.analyzer.UnboundSlot; import org.apache.doris.nereids.analyzer.UnboundStar; import org.apache.doris.nereids.analyzer.UnboundTVFRelation; +import org.apache.doris.nereids.analyzer.UnboundVariable; +import org.apache.doris.nereids.analyzer.UnboundVariable.VariableType; import org.apache.doris.nereids.exceptions.ParseException; import org.apache.doris.nereids.properties.OrderKey; import org.apache.doris.nereids.properties.SelectHint; @@ -201,14 +201,12 @@ import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DecimalLiteral; import org.apache.doris.nereids.trees.expressions.literal.DecimalV3Literal; -import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; import org.apache.doris.nereids.trees.expressions.literal.Interval; import org.apache.doris.nereids.trees.expressions.literal.LargeIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.expressions.literal.SmallIntLiteral; -import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; import org.apache.doris.nereids.trees.plans.JoinHint; @@ -249,13 +247,8 @@ import org.apache.doris.nereids.util.ExpressionUtils; import org.apache.doris.policy.FilterType; import org.apache.doris.policy.PolicyTypeEnum; import org.apache.doris.qe.ConnectContext; -import org.apache.doris.qe.SessionVariable; import org.apache.doris.qe.SqlModeHelper; -import org.apache.doris.qe.VariableMgr; -import org.apache.doris.qe.VariableVarConverters; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; @@ -665,35 +658,23 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { @Override public Expression visitSystemVariable(SystemVariableContext ctx) { - String name = ctx.identifier().getText(); - SessionVariable sessionVariable = ConnectContext.get().getSessionVariable(); - Literal literal = null; + VariableType type = null; if (ctx.kind == null) { - literal = VariableMgr.getLiteral(sessionVariable, name, SetType.DEFAULT); + type = VariableType.DEFAULT; } else if (ctx.kind.getType() == DorisParser.SESSION) { - literal = VariableMgr.getLiteral(sessionVariable, name, SetType.SESSION); + type = VariableType.SESSION; } else if (ctx.kind.getType() == DorisParser.GLOBAL) { - literal = VariableMgr.getLiteral(sessionVariable, name, SetType.GLOBAL); + type = VariableType.GLOBAL; } - if (literal == null) { + if (type == null) { throw new ParseException("Unsupported system variable: " + ctx.getText(), ctx); } - if (!Strings.isNullOrEmpty(name) && VariableVarConverters.hasConverter(name)) { - try { - Preconditions.checkArgument(literal instanceof IntegerLikeLiteral); - IntegerLikeLiteral integerLikeLiteral = (IntegerLikeLiteral) literal; - literal = new StringLiteral(VariableVarConverters.decode(name, integerLikeLiteral.getLongValue())); - } catch (DdlException e) { - throw new ParseException(e.getMessage(), ctx); - } - } - return literal.alias(ctx.getText()); + return new UnboundVariable(ctx.identifier().getText(), type); } @Override public Expression visitUserVariable(UserVariableContext ctx) { - String name = ctx.identifierOrText().getText(); - return VariableMgr.getLiteralForUserVar(name); + return new UnboundVariable(ctx.identifierOrText().getText(), VariableType.USER); } /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java index ddbea3b3f4..486ddca97d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java @@ -17,13 +17,17 @@ package org.apache.doris.nereids.rules.analysis; +import org.apache.doris.analysis.SetType; import org.apache.doris.cluster.ClusterNamespace; +import org.apache.doris.common.DdlException; import org.apache.doris.common.util.Util; import org.apache.doris.nereids.CascadesContext; import org.apache.doris.nereids.analyzer.Scope; import org.apache.doris.nereids.analyzer.UnboundAlias; import org.apache.doris.nereids.analyzer.UnboundSlot; import org.apache.doris.nereids.analyzer.UnboundStar; +import org.apache.doris.nereids.analyzer.UnboundVariable; +import org.apache.doris.nereids.analyzer.UnboundVariable.VariableType; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.expressions.Alias; import org.apache.doris.nereids.trees.expressions.BoundStar; @@ -31,7 +35,17 @@ import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.Variable; +import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral; +import org.apache.doris.nereids.trees.expressions.literal.Literal; +import org.apache.doris.nereids.trees.expressions.literal.StringLiteral; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.SessionVariable; +import org.apache.doris.qe.VariableMgr; +import org.apache.doris.qe.VariableVarConverters; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -49,7 +63,7 @@ class SlotBinder extends SubExprAnalyzer { but enabled for order by clause TODO after remove original planner, always enable exact match mode. */ - private boolean enableExactMatch; + private final boolean enableExactMatch; private final boolean bindSlotInOuterScope; public SlotBinder(Scope scope, CascadesContext cascadesContext) { @@ -67,6 +81,35 @@ class SlotBinder extends SubExprAnalyzer { return expression.accept(this, null); } + @Override + public Expression visitUnboundVariable(UnboundVariable unboundVariable, CascadesContext context) { + String name = unboundVariable.getName(); + SessionVariable sessionVariable = ConnectContext.get().getSessionVariable(); + Literal literal = null; + if (unboundVariable.getType() == VariableType.DEFAULT) { + literal = VariableMgr.getLiteral(sessionVariable, name, SetType.DEFAULT); + } else if (unboundVariable.getType() == VariableType.SESSION) { + literal = VariableMgr.getLiteral(sessionVariable, name, SetType.SESSION); + } else if (unboundVariable.getType() == VariableType.GLOBAL) { + literal = VariableMgr.getLiteral(sessionVariable, name, SetType.GLOBAL); + } else if (unboundVariable.getType() == VariableType.USER) { + literal = VariableMgr.getLiteralForUserVar(name); + } + if (literal == null) { + throw new AnalysisException("Unsupported system variable: " + unboundVariable.getName()); + } + if (!Strings.isNullOrEmpty(name) && VariableVarConverters.hasConverter(name)) { + try { + Preconditions.checkArgument(literal instanceof IntegerLikeLiteral); + IntegerLikeLiteral integerLikeLiteral = (IntegerLikeLiteral) literal; + literal = new StringLiteral(VariableVarConverters.decode(name, integerLikeLiteral.getLongValue())); + } catch (DdlException e) { + throw new AnalysisException(e.getMessage()); + } + } + return new Variable(unboundVariable.getName(), unboundVariable.getType(), literal); + } + @Override public Expression visitUnboundAlias(UnboundAlias unboundAlias, CascadesContext context) { Expression child = unboundAlias.child().accept(this, context); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java index e15228a3b0..bd234204b2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java @@ -23,6 +23,7 @@ import org.apache.doris.nereids.rules.expression.rules.FoldConstantRule; import org.apache.doris.nereids.rules.expression.rules.InPredicateDedup; import org.apache.doris.nereids.rules.expression.rules.InPredicateToEqualToRule; import org.apache.doris.nereids.rules.expression.rules.NormalizeBinaryPredicatesRule; +import org.apache.doris.nereids.rules.expression.rules.ReplaceVariableByLiteral; import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticComparisonRule; import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticRule; import org.apache.doris.nereids.rules.expression.rules.SimplifyCastRule; @@ -42,6 +43,7 @@ public class ExpressionNormalization extends ExpressionRewrite { // from_unixtime(timestamp, 'yyyyMMdd') to 'yyyyMMdd' public static final List<ExpressionRewriteRule> NORMALIZE_REWRITE_RULES = ImmutableList.of( SupportJavaDateFormatter.INSTANCE, + ReplaceVariableByLiteral.INSTANCE, NormalizeBinaryPredicatesRule.INSTANCE, InPredicateDedup.INSTANCE, InPredicateToEqualToRule.INSTANCE, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ReplaceVariableByLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ReplaceVariableByLiteral.java new file mode 100644 index 0000000000..3fd5330395 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/ReplaceVariableByLiteral.java @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.rules.expression.rules; + +import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule; +import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.Variable; + +/** + * replace varaible to real expression + */ +public class ReplaceVariableByLiteral extends AbstractExpressionRewriteRule { + + public static ReplaceVariableByLiteral INSTANCE = new ReplaceVariableByLiteral(); + + @Override + public Expression visitVariable(Variable variable, ExpressionRewriteContext context) { + return variable.getRealExpression(); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Variable.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Variable.java new file mode 100644 index 0000000000..fd16b84b18 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Variable.java @@ -0,0 +1,118 @@ +// 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.expressions; + +import org.apache.doris.nereids.analyzer.UnboundVariable.VariableType; +import org.apache.doris.nereids.exceptions.UnboundException; +import org.apache.doris.nereids.trees.expressions.shape.LeafExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DataType; + +import com.google.common.base.Preconditions; + +import java.util.List; +import java.util.Objects; + +/** + * variable for session / global / user variable + */ +public class Variable extends Expression implements LeafExpression { + + private final String name; + private final VariableType type; + private final Expression realExpression; + + public Variable(String name, VariableType type, Expression realExpression) { + this.name = Objects.requireNonNull(name, "name should not be null"); + this.type = Objects.requireNonNull(type, "type should not be null"); + this.realExpression = Objects.requireNonNull(realExpression, "realExpression should not be null"); + } + + public String getName() { + return name; + } + + public VariableType getType() { + return type; + } + + public Expression getRealExpression() { + return realExpression; + } + + @Override + public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { + return visitor.visitVariable(this, context); + } + + @Override + public boolean isConstant() { + return realExpression.isConstant(); + } + + @Override + public boolean nullable() { + return realExpression.nullable(); + } + + @Override + public DataType getDataType() throws UnboundException { + return realExpression.getDataType(); + } + + @Override + public String toString() throws UnboundException { + if (type == VariableType.USER) { + return "@" + name; + } else { + return "@@" + name; + } + } + + @Override + public String toSql() throws UnboundException { + return toString(); + } + + @Override + public Variable withChildren(List<Expression> children) { + Preconditions.checkArgument(children.isEmpty()); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + Variable variable = (Variable) o; + return Objects.equals(name, variable.name) && type == variable.type && Objects.equals( + realExpression, variable.realExpression); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), name, type, realExpression); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java index aae5e34fc4..4517f444e0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java @@ -21,6 +21,7 @@ import org.apache.doris.nereids.analyzer.UnboundAlias; import org.apache.doris.nereids.analyzer.UnboundFunction; import org.apache.doris.nereids.analyzer.UnboundSlot; import org.apache.doris.nereids.analyzer.UnboundStar; +import org.apache.doris.nereids.analyzer.UnboundVariable; import org.apache.doris.nereids.trees.expressions.Add; import org.apache.doris.nereids.trees.expressions.AggregateExpression; import org.apache.doris.nereids.trees.expressions.Alias; @@ -71,6 +72,7 @@ import org.apache.doris.nereids.trees.expressions.TVFProperties; import org.apache.doris.nereids.trees.expressions.TimestampArithmetic; import org.apache.doris.nereids.trees.expressions.UnaryArithmetic; import org.apache.doris.nereids.trees.expressions.UnaryOperator; +import org.apache.doris.nereids.trees.expressions.Variable; import org.apache.doris.nereids.trees.expressions.VariableDesc; import org.apache.doris.nereids.trees.expressions.VirtualSlotReference; import org.apache.doris.nereids.trees.expressions.WhenClause; @@ -196,6 +198,10 @@ public abstract class ExpressionVisitor<R, C> return visitNamedExpression(slot, context); } + public R visitVariable(Variable variable, C context) { + return visit(variable, context); + } + public R visitNamedExpression(NamedExpression namedExpression, C context) { return visit(namedExpression, context); } @@ -467,4 +473,8 @@ public abstract class ExpressionVisitor<R, C> public R visitUnboundStar(UnboundStar unboundStar, C context) { return visitNamedExpression(unboundStar, context); } + + public R visitUnboundVariable(UnboundVariable unboundVariable, C context) { + return visit(unboundVariable, context); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java index 7b0fa4512c..f77aba25da 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OriginalPlanner.java @@ -24,7 +24,9 @@ import org.apache.doris.analysis.Analyzer; import org.apache.doris.analysis.DescriptorTable; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.InsertStmt; +import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.QueryStmt; +import org.apache.doris.analysis.SelectListItem; import org.apache.doris.analysis.SelectStmt; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotId; @@ -40,7 +42,10 @@ import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.common.Config; import org.apache.doris.common.UserException; +import org.apache.doris.qe.CommonResultSet; import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.ResultSet; +import org.apache.doris.qe.ResultSetMetaData; import org.apache.doris.rewrite.mvrewrite.MVSelectFailedException; import org.apache.doris.statistics.query.StatsDelta; import org.apache.doris.thrift.TFetchOption; @@ -57,6 +62,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; /** @@ -636,4 +642,33 @@ public class OriginalPlanner extends Planner { LOG.info("failed to collect query stat: {}", e.getMessage()); } } + + @Override + public Optional<ResultSet> handleQueryInFe(StatementBase parsedStmt) { + if (!(parsedStmt instanceof SelectStmt)) { + return Optional.empty(); + } + SelectStmt parsedSelectStmt = (SelectStmt) parsedStmt; + if (!parsedSelectStmt.getTableRefs().isEmpty()) { + return Optional.empty(); + } + List<SelectListItem> selectItems = parsedSelectStmt.getSelectList().getItems(); + List<Column> columns = new ArrayList<>(selectItems.size()); + List<String> columnLabels = parsedSelectStmt.getColLabels(); + List<String> data = new ArrayList<>(); + for (int i = 0; i < selectItems.size(); i++) { + SelectListItem item = selectItems.get(i); + Expr expr = item.getExpr(); + String columnName = columnLabels.get(i); + if (expr instanceof LiteralExpr) { + columns.add(new Column(columnName, expr.getType())); + super.handleLiteralInFe((LiteralExpr) expr, data); + } else { + return Optional.empty(); + } + } + ResultSetMetaData metadata = new CommonResultSet.CommonResultSetMetaData(columns); + ResultSet resultSet = new CommonResultSet(metadata, Collections.singletonList(data)); + return Optional.of(resultSet); + } } 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 62f7313004..48f2ba7cbd 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 @@ -17,12 +17,19 @@ package org.apache.doris.planner; +import org.apache.doris.analysis.ArrayLiteral; +import org.apache.doris.analysis.DecimalLiteral; import org.apache.doris.analysis.DescriptorTable; import org.apache.doris.analysis.ExplainOptions; +import org.apache.doris.analysis.FloatLiteral; +import org.apache.doris.analysis.LiteralExpr; +import org.apache.doris.analysis.NullLiteral; import org.apache.doris.analysis.StatementBase; 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.LiteralUtils; +import org.apache.doris.qe.ResultSet; import org.apache.doris.thrift.TQueryOptions; import com.google.common.base.Preconditions; @@ -32,6 +39,7 @@ import org.apache.logging.log4j.Logger; import java.util.ArrayList; import java.util.List; +import java.util.Optional; public abstract class Planner { @@ -80,6 +88,20 @@ public abstract class Planner { return str.toString(); } + protected void handleLiteralInFe(LiteralExpr literalExpr, List<String> data) { + if (literalExpr instanceof NullLiteral) { + data.add(null); + } else if (literalExpr instanceof FloatLiteral) { + data.add(LiteralUtils.getStringValue((FloatLiteral) literalExpr)); + } else if (literalExpr instanceof DecimalLiteral) { + data.add(((DecimalLiteral) literalExpr).getValue().toPlainString()); + } else if (literalExpr instanceof ArrayLiteral) { + data.add(LiteralUtils.getStringValue((ArrayLiteral) literalExpr)); + } else { + data.add(literalExpr.getStringValue()); + } + } + public void appendTupleInfo(StringBuilder stringBuilder) {} public List<PlanFragment> getFragments() { @@ -94,4 +116,6 @@ public abstract class Planner { public abstract List<RuntimeFilter> getRuntimeFilters(); + public abstract Optional<ResultSet> handleQueryInFe(StatementBase parsedStmt); + } 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 6da5c07c30..626a9e24f2 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 @@ -29,7 +29,6 @@ import org.apache.doris.analysis.CreateRoutineLoadStmt; import org.apache.doris.analysis.CreateTableAsSelectStmt; import org.apache.doris.analysis.CreateTableLikeStmt; import org.apache.doris.analysis.DdlStmt; -import org.apache.doris.analysis.DecimalLiteral; import org.apache.doris.analysis.DeleteStmt; import org.apache.doris.analysis.DropPartitionClause; import org.apache.doris.analysis.DropTableStmt; @@ -37,12 +36,10 @@ import org.apache.doris.analysis.ExecuteStmt; import org.apache.doris.analysis.ExplainOptions; import org.apache.doris.analysis.ExportStmt; import org.apache.doris.analysis.Expr; -import org.apache.doris.analysis.FloatLiteral; import org.apache.doris.analysis.InsertOverwriteTableStmt; import org.apache.doris.analysis.InsertStmt; import org.apache.doris.analysis.KillStmt; import org.apache.doris.analysis.LabelName; -import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.LoadStmt; import org.apache.doris.analysis.LoadType; import org.apache.doris.analysis.LockTablesStmt; @@ -56,7 +53,6 @@ import org.apache.doris.analysis.QueryStmt; import org.apache.doris.analysis.RedirectStatus; import org.apache.doris.analysis.ReplacePartitionClause; import org.apache.doris.analysis.ReplaceTableClause; -import org.apache.doris.analysis.SelectListItem; import org.apache.doris.analysis.SelectStmt; import org.apache.doris.analysis.SetOperationStmt; import org.apache.doris.analysis.SetStmt; @@ -102,7 +98,6 @@ import org.apache.doris.common.profile.Profile; import org.apache.doris.common.profile.SummaryProfile; import org.apache.doris.common.profile.SummaryProfile.SummaryBuilder; import org.apache.doris.common.util.DebugUtil; -import org.apache.doris.common.util.LiteralUtils; import org.apache.doris.common.util.MetaLockUtils; import org.apache.doris.common.util.ProfileManager.ProfileType; import org.apache.doris.common.util.SqlParserUtils; @@ -188,6 +183,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -1285,39 +1281,6 @@ public class StmtExecutor { sendResult(false, isSendFields, queryStmt, channel, cacheAnalyzer, cacheResult); } - private boolean handleSelectRequestInFe(SelectStmt parsedSelectStmt) throws IOException { - List<SelectListItem> selectItemList = parsedSelectStmt.getSelectList().getItems(); - List<Column> columns = new ArrayList<>(selectItemList.size()); - ResultSetMetaData metadata = new CommonResultSet.CommonResultSetMetaData(columns); - - List<String> columnLabels = parsedSelectStmt.getColLabels(); - List<String> data = new ArrayList<>(); - for (int i = 0; i < selectItemList.size(); i++) { - SelectListItem item = selectItemList.get(i); - Expr expr = item.getExpr(); - String columnName = columnLabels.get(i); - if (expr instanceof LiteralExpr) { - columns.add(new Column(columnName, expr.getType())); - if (expr instanceof NullLiteral) { - data.add(null); - } else if (expr instanceof FloatLiteral) { - data.add(LiteralUtils.getStringValue((FloatLiteral) expr)); - } else if (expr instanceof DecimalLiteral) { - data.add(((DecimalLiteral) expr).getValue().toPlainString()); - } else if (expr instanceof ArrayLiteral) { - data.add(LiteralUtils.getStringValue((ArrayLiteral) expr)); - } else { - data.add(expr.getStringValue()); - } - } else { - return false; - } - } - ResultSet resultSet = new CommonResultSet(metadata, Collections.singletonList(data)); - sendResultSet(resultSet); - return true; - } - // Process a select statement. private void handleQueryStmt() throws Exception { // Every time set no send flag and clean all data in buffer @@ -1340,11 +1303,10 @@ public class StmtExecutor { } // handle selects that fe can do without be, so we can make sql tools happy, especially the setup step. - if (parsedStmt instanceof SelectStmt && ((SelectStmt) parsedStmt).getTableRefs().isEmpty()) { - SelectStmt parsedSelectStmt = (SelectStmt) parsedStmt; - if (handleSelectRequestInFe(parsedSelectStmt)) { - return; - } + Optional<ResultSet> resultSet = planner.handleQueryInFe(parsedStmt); + if (resultSet.isPresent()) { + sendResultSet(resultSet.get()); + return; } MysqlChannel channel = context.getMysqlChannel(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
