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]


Reply via email to