You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2023/06/06 06:35:30 UTC
[doris] branch master updated: [feature](planner)(nereids) support user defined variable (#20334)
This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new ae428c29e2 [feature](planner)(nereids) support user defined variable (#20334)
ae428c29e2 is described below
commit ae428c29e23b6df7822e943d70ad7acd291412b9
Author: Chengpeng Yan <41...@users.noreply.github.com>
AuthorDate: Tue Jun 6 14:35:16 2023 +0800
[feature](planner)(nereids) support user defined variable (#20334)
Support user-defined variables.
After this PR, we can use `set @a = xx` to define a user variable and use it in the query like `select @a`.
the changes of this PR:
1. Support the grammar for `set user variable` in the parser.
2. Add the `userVars` in `VariableMgr` to store the user-defined variables.
3. For the `set @a = xx`, we will store the variable name and its value in the `userVars` in `VariableMgr`.
4. For the `select @a`, we will get the value for the variable name in `userVars`.
---
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 2 +-
fe/fe-core/src/main/cup/sql_parser.cup | 12 ++--
.../main/java/org/apache/doris/analysis/Expr.java | 3 +-
.../apache/doris/analysis/ExpressionFunctions.java | 6 +-
.../java/org/apache/doris/analysis/SetType.java | 3 +-
.../{SetType.java => SetUserDefinedVar.java} | 49 ++++---------
.../java/org/apache/doris/analysis/SetVar.java | 37 ++++++++--
.../{SysVariableDesc.java => VariableExpr.java} | 66 ++++++++++++------
.../doris/nereids/parser/LogicalPlanBuilder.java | 3 +-
.../nereids/trees/expressions/literal/Literal.java | 7 ++
.../main/java/org/apache/doris/qe/SetExecutor.java | 3 +
.../main/java/org/apache/doris/qe/VariableMgr.java | 80 ++++++++++++++++++++--
.../apache/doris/rewrite/FoldConstantsRule.java | 14 ++--
.../java/org/apache/doris/analysis/SetVarTest.java | 2 +-
...VariableDescTest.java => VariableExprTest.java} | 6 +-
.../java/org/apache/doris/qe/VariableMgrTest.java | 4 +-
regression-test/data/nereids_p0/test_user_var.out | 16 +++++
.../data/query_p0/set/test_user_var.out | 16 +++++
.../suites/nereids_p0/test_user_var.groovy | 32 +++++++++
.../suites/query_p0/set/test_user_var.groovy | 30 ++++++++
20 files changed, 299 insertions(+), 92 deletions(-)
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 14ad9c35c4..c8035e716e 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -342,7 +342,7 @@ primaryExpression
(COMMA arguments+=expression)* (ORDER BY sortItem (COMMA sortItem)*)?)? RIGHT_PAREN
(OVER windowSpec)? #functionCall
| LEFT_PAREN query RIGHT_PAREN #subqueryExpression
- | ATSIGN identifier #userVariable
+ | ATSIGN identifierOrText #userVariable
| DOUBLEATSIGN (kind=(GLOBAL | SESSION) DOT)? identifier #systemVariable
| identifier #columnReference
| base=primaryExpression DOT fieldName=identifier #dereference
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup
index 3a85b99dd4..4f2014b001 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -4914,9 +4914,9 @@ option_value_no_option_type ::=
{:
RESULT = new SetVar(variable, expr);
:}
- | AT ident_or_text:var equal literal:expr
+ | AT ident_or_text:var equal expr:expr
{:
- RESULT = new SetVar(var, expr);
+ RESULT = new SetUserDefinedVar(var, expr);
:}
/* Ident */
| AT AT variable_name:variable equal set_expr_or_default:expr
@@ -6398,13 +6398,17 @@ exists_predicate ::=
non_pred_expr ::=
sign_chain_expr:e
{: RESULT = e; :}
+ | AT ident:l
+ {:
+ RESULT = new VariableExpr(l, SetType.USER);
+ :}
| AT AT ident:l
{:
- RESULT = new SysVariableDesc(l);
+ RESULT = new VariableExpr(l);
:}
| AT AT var_ident_type:type ident:l
{:
- RESULT = new SysVariableDesc(l, type);
+ RESULT = new VariableExpr(l, type);
:}
| literal:l
{: RESULT = l; :}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
index a6cc659794..8633b868eb 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
@@ -990,7 +990,8 @@ public abstract class Expr extends TreeNode<Expr> implements ParseNode, Cloneabl
// Hack to ensure BE never sees TYPE_NULL. If an expr makes it this far without
// being cast to a non-NULL type, the type doesn't matter and we can cast it
// arbitrarily.
- Preconditions.checkState(this instanceof NullLiteral || this instanceof SlotRef);
+ Preconditions.checkState(this instanceof NullLiteral || this instanceof SlotRef
+ || this instanceof VariableExpr);
return NullLiteral.create(ScalarType.BOOLEAN).treeToThrift();
}
TExpr result = new TExpr();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
index e7dae9617b..e39748b570 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
@@ -58,7 +58,7 @@ public enum ExpressionFunctions {
public Expr evalExpr(Expr constExpr) {
// Function's arg are all LiteralExpr.
for (Expr child : constExpr.getChildren()) {
- if (!(child instanceof LiteralExpr) && !(child instanceof SysVariableDesc)) {
+ if (!(child instanceof LiteralExpr) && !(child instanceof VariableExpr)) {
return constExpr;
}
}
@@ -115,8 +115,8 @@ public enum ExpressionFunctions {
return constExpr;
}
}
- } else if (constExpr instanceof SysVariableDesc) {
- return ((SysVariableDesc) constExpr).getLiteralExpr();
+ } else if (constExpr instanceof VariableExpr) {
+ return ((VariableExpr) constExpr).getLiteralExpr();
}
return constExpr;
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java
index 924c1f38a9..ae0fbd27bc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java
@@ -23,7 +23,8 @@ import org.apache.doris.thrift.TVarType;
public enum SetType {
DEFAULT("DEFAULT"),
GLOBAL("GLOBAL"),
- SESSION("SESSION");
+ SESSION("SESSION"),
+ USER("USER");
private String desc;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserDefinedVar.java
similarity index 53%
copy from fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java
copy to fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserDefinedVar.java
index 924c1f38a9..7b0c5d98aa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetUserDefinedVar.java
@@ -17,44 +17,23 @@
package org.apache.doris.analysis;
-import org.apache.doris.thrift.TVarType;
+import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.common.AnalysisException;
-// Set statement type.
-public enum SetType {
- DEFAULT("DEFAULT"),
- GLOBAL("GLOBAL"),
- SESSION("SESSION");
-
- private String desc;
-
- SetType(String desc) {
- this.desc = desc;
- }
-
- public TVarType toThrift() {
- switch (this) {
- case GLOBAL:
- return TVarType.GLOBAL;
- default:
- return TVarType.SESSION;
- }
- }
-
- public static SetType fromThrift(TVarType tType) {
- switch (tType) {
- case GLOBAL:
- return SetType.GLOBAL;
- default:
- return SetType.SESSION;
- }
- }
-
- public String toSql() {
- return desc;
+public class SetUserDefinedVar extends SetVar {
+ public SetUserDefinedVar(String variable, Expr value) {
+ super(SetType.USER, variable, value, SetVarType.SET_USER_DEFINED_VAR);
}
@Override
- public String toString() {
- return toSql();
+ public void analyze(Analyzer analyzer) throws AnalysisException {
+ Expr expression = getValue();
+ if (expression instanceof NullLiteral) {
+ setResult(NullLiteral.create(ScalarType.NULL));
+ } else if (expression instanceof LiteralExpr) {
+ setResult((LiteralExpr) expression);
+ } else {
+ throw new AnalysisException("Unsupported to set the non-literal for user defined variables.");
+ }
}
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java
index ccb505bbe4..8afa942dba 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java
@@ -43,7 +43,8 @@ public class SetVar {
SET_LDAP_PASS_VAR,
SET_NAMES_VAR,
SET_TRANSACTION,
- SET_USER_PROPERTY_VAR
+ SET_USER_PROPERTY_VAR,
+ SET_USER_DEFINED_VAR,
}
private String variable;
@@ -75,14 +76,36 @@ public class SetVar {
}
}
+ public SetVar(SetType setType, String variable, Expr value, SetVarType varType) {
+ this.type = setType;
+ this.varType = varType;
+ this.variable = variable;
+ this.value = value;
+ if (value instanceof LiteralExpr) {
+ this.result = (LiteralExpr) value;
+ }
+ }
+
public String getVariable() {
return variable;
}
- public LiteralExpr getValue() {
+ public Expr getValue() {
+ return value;
+ }
+
+ public void setValue(Expr value) {
+ this.value = value;
+ }
+
+ public LiteralExpr getResult() {
return result;
}
+ public void setResult(LiteralExpr result) {
+ this.result = result;
+ }
+
public SetType getType() {
return type;
}
@@ -144,7 +167,7 @@ public class SetVar {
}
if (getVariable().equalsIgnoreCase(SessionVariable.PREFER_JOIN_METHOD)) {
- String value = getValue().getStringValue();
+ String value = getResult().getStringValue();
if (!value.equalsIgnoreCase("broadcast") && !value.equalsIgnoreCase("shuffle")) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_VALUE_FOR_VAR,
SessionVariable.PREFER_JOIN_METHOD, value);
@@ -153,11 +176,11 @@ public class SetVar {
// Check variable time_zone value is valid
if (getVariable().equalsIgnoreCase(SessionVariable.TIME_ZONE)) {
- this.value = new StringLiteral(TimeUtils.checkTimeZoneValidAndStandardize(getValue().getStringValue()));
+ this.value = new StringLiteral(TimeUtils.checkTimeZoneValidAndStandardize(getResult().getStringValue()));
this.result = (LiteralExpr) this.value;
}
if (getVariable().equalsIgnoreCase(SessionVariable.PARALLEL_FRAGMENT_EXEC_INSTANCE_NUM)) {
- int instanceNum = Integer.parseInt(getValue().getStringValue());
+ int instanceNum = Integer.parseInt(getResult().getStringValue());
if (instanceNum > Config.max_instance_num) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_VALUE_FOR_VAR,
SessionVariable.PARALLEL_FRAGMENT_EXEC_INSTANCE_NUM,
@@ -165,11 +188,11 @@ public class SetVar {
}
}
if (getVariable().equalsIgnoreCase(SessionVariable.EXEC_MEM_LIMIT)) {
- this.value = new StringLiteral(Long.toString(ParseUtil.analyzeDataVolumn(getValue().getStringValue())));
+ this.value = new StringLiteral(Long.toString(ParseUtil.analyzeDataVolumn(getResult().getStringValue())));
this.result = (LiteralExpr) this.value;
}
if (getVariable().equalsIgnoreCase(SessionVariable.SCAN_QUEUE_MEM_LIMIT)) {
- this.value = new StringLiteral(Long.toString(ParseUtil.analyzeDataVolumn(getValue().getStringValue())));
+ this.value = new StringLiteral(Long.toString(ParseUtil.analyzeDataVolumn(getResult().getStringValue())));
this.result = (LiteralExpr) this.value;
}
if (getVariable().equalsIgnoreCase("is_report_success")) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SysVariableDesc.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java
similarity index 74%
rename from fe/fe-core/src/main/java/org/apache/doris/analysis/SysVariableDesc.java
rename to fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java
index 023be528e6..649bb4017f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SysVariableDesc.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java
@@ -32,33 +32,37 @@ import org.apache.doris.thrift.TStringLiteral;
import com.google.common.base.Strings;
+import java.math.BigDecimal;
import java.util.Objects;
-// System variable
+// Variable expr: including the system variable and user define variable.
// Converted to StringLiteral in analyze, if this variable is not exist, throw AnalysisException.
-public class SysVariableDesc extends Expr {
+public class VariableExpr extends Expr {
private String name;
private SetType setType;
+ private boolean isNull;
private boolean boolValue;
private long intValue;
private double floatValue;
+ private BigDecimal decimalValue;
private String strValue;
private LiteralExpr literalExpr;
- public SysVariableDesc(String name) {
+ public VariableExpr(String name) {
this(name, SetType.SESSION);
}
- public SysVariableDesc(String name, SetType setType) {
+ public VariableExpr(String name, SetType setType) {
this.name = name;
this.setType = setType;
}
- protected SysVariableDesc(SysVariableDesc other) {
+ protected VariableExpr(VariableExpr other) {
super(other);
name = other.name;
setType = other.setType;
+ isNull = other.isNull;
boolValue = other.boolValue;
intValue = other.intValue;
floatValue = other.floatValue;
@@ -67,18 +71,22 @@ public class SysVariableDesc extends Expr {
@Override
public Expr clone() {
- return new SysVariableDesc(this);
+ return new VariableExpr(this);
}
@Override
public void analyzeImpl(Analyzer analyzer) throws AnalysisException {
- VariableMgr.fillValue(analyzer.getContext().getSessionVariable(), this);
- if (!Strings.isNullOrEmpty(name) && VariableVarConverters.hasConverter(name)) {
- setType(Type.VARCHAR);
- try {
- setStringValue(VariableVarConverters.decode(name, intValue));
- } catch (DdlException e) {
- ErrorReport.reportAnalysisException(e.getMessage());
+ if (setType == SetType.USER) {
+ VariableMgr.fillValueForUserDefinedVar(this);
+ } else {
+ VariableMgr.fillValue(analyzer.getContext().getSessionVariable(), this);
+ if (!Strings.isNullOrEmpty(name) && VariableVarConverters.hasConverter(name)) {
+ setType(Type.VARCHAR);
+ try {
+ setStringValue(VariableVarConverters.decode(name, intValue));
+ } catch (DdlException e) {
+ ErrorReport.reportAnalysisException(e.getMessage());
+ }
}
}
}
@@ -91,6 +99,14 @@ public class SysVariableDesc extends Expr {
return setType;
}
+ public void setIsNull() {
+ isNull = true;
+ }
+
+ public boolean isNull() {
+ return isNull;
+ }
+
public void setBoolValue(boolean value) {
this.boolValue = value;
this.literalExpr = new BoolLiteral(value);
@@ -106,6 +122,11 @@ public class SysVariableDesc extends Expr {
this.literalExpr = new FloatLiteral(value);
}
+ public void setDecimalValue(BigDecimal value) {
+ this.decimalValue = value;
+ this.literalExpr = new DecimalLiteral(value);
+ }
+
public void setStringValue(String value) {
this.strValue = value;
this.literalExpr = new StringLiteral(value);
@@ -164,9 +185,14 @@ public class SysVariableDesc extends Expr {
@Override
public String toSqlImpl() {
- StringBuilder sb = new StringBuilder("@@");
- if (setType == SetType.GLOBAL) {
- sb.append("GLOBAL.");
+ StringBuilder sb = new StringBuilder();
+ if (setType == SetType.USER) {
+ sb.append("@");
+ } else {
+ sb.append("@@");
+ if (setType == SetType.GLOBAL) {
+ sb.append("GLOBAL.");
+ }
}
sb.append(name);
return sb.toString();
@@ -182,16 +208,16 @@ public class SysVariableDesc extends Expr {
if (this == obj) {
return true;
}
- if (!(obj instanceof SysVariableDesc)) {
+ if (!(obj instanceof VariableExpr)) {
return false;
}
- if (!name.equals(((SysVariableDesc) obj).getName())) {
+ if (!name.equals(((VariableExpr) obj).getName())) {
return false;
}
- if (!setType.equals(((SysVariableDesc) obj).getSetType())) {
+ if (!setType.equals(((VariableExpr) obj).getSetType())) {
return false;
}
- return Objects.equals(literalExpr, ((SysVariableDesc) obj).getLiteralExpr());
+ return Objects.equals(literalExpr, ((VariableExpr) obj).getLiteralExpr());
}
}
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 491b1e80f6..08f1ae00fb 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
@@ -633,7 +633,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
@Override
public Expression visitUserVariable(UserVariableContext ctx) {
- throw new ParseException("Unsupported user variable :" + ctx.getText(), ctx);
+ String name = ctx.identifierOrText().getText();
+ return VariableMgr.getLiteralForUserVar(name);
}
/**
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
index 109357499f..123aa618f4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
@@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.expressions.literal;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.catalog.Type;
+import org.apache.doris.common.Config;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.exceptions.UnboundException;
import org.apache.doris.nereids.trees.expressions.Expression;
@@ -75,6 +76,12 @@ public abstract class Literal extends Expression implements LeafExpression, Comp
return new FloatLiteral((Float) value);
} else if (value instanceof Double) {
return new DoubleLiteral((Double) value);
+ } else if (value instanceof BigDecimal) {
+ if (Config.enable_decimal_conversion) {
+ return new DecimalV3Literal((BigDecimal) value);
+ } else {
+ return new DecimalLiteral((BigDecimal) value);
+ }
} else if (value instanceof Boolean) {
return BooleanLiteral.of((Boolean) value);
} else if (value instanceof String) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SetExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/SetExecutor.java
index c88e7e3336..9dbe9ca8a9 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SetExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SetExecutor.java
@@ -22,6 +22,7 @@ import org.apache.doris.analysis.SetNamesVar;
import org.apache.doris.analysis.SetPassVar;
import org.apache.doris.analysis.SetStmt;
import org.apache.doris.analysis.SetTransaction;
+import org.apache.doris.analysis.SetUserDefinedVar;
import org.apache.doris.analysis.SetVar;
import org.apache.doris.common.DdlException;
@@ -54,6 +55,8 @@ public class SetExecutor {
} else if (var instanceof SetTransaction) {
// do nothing
return;
+ } else if (var instanceof SetUserDefinedVar) {
+ VariableMgr.setUserVar(var);
} else {
VariableMgr.setVar(ctx.getSessionVariable(), var);
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java b/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java
index 5408e74071..24b7468e77 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/VariableMgr.java
@@ -17,9 +17,16 @@
package org.apache.doris.qe;
+import org.apache.doris.analysis.BoolLiteral;
+import org.apache.doris.analysis.DecimalLiteral;
+import org.apache.doris.analysis.FloatLiteral;
+import org.apache.doris.analysis.IntLiteral;
+import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.analysis.NullLiteral;
import org.apache.doris.analysis.SetType;
import org.apache.doris.analysis.SetVar;
-import org.apache.doris.analysis.SysVariableDesc;
+import org.apache.doris.analysis.StringLiteral;
+import org.apache.doris.analysis.VariableExpr;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
@@ -52,6 +59,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
@@ -116,6 +124,8 @@ public class VariableMgr {
// its display name is "experimental_foo"
private static ImmutableMap<String, VarContext> ctxByDisplayVarName;
+ private static Map<String, LiteralExpr> userVars = new HashMap<String, LiteralExpr>();
+
// This variable is equivalent to the default value of session variables.
// Whenever a new session is established, the value in this object is copied to the session-level variable.
private static SessionVariable defaultSessionVariable;
@@ -258,6 +268,10 @@ public class VariableMgr {
}
}
+ public static void setUserVar(SetVar setVar) {
+ userVars.put(setVar.getVariable(), setVar.getResult());
+ }
+
// Entry of handling SetVarStmt
// Input:
// sessionVariable: the variable of current session
@@ -314,8 +328,8 @@ public class VariableMgr {
VarAttr attr = ctx.getField().getAnnotation(VarAttr.class);
String value;
// If value is null, this is `set variable = DEFAULT`
- if (setVar.getValue() != null) {
- value = setVar.getValue().getStringValue();
+ if (setVar.getResult() != null) {
+ value = setVar.getResult().getStringValue();
} else {
value = ctx.getDefaultValue();
if (value == null) {
@@ -416,7 +430,7 @@ public class VariableMgr {
}
// Get variable value through variable name, used to satisfy statement like `SELECT @@comment_version`
- public static void fillValue(SessionVariable var, SysVariableDesc desc) throws AnalysisException {
+ public static void fillValue(SessionVariable var, VariableExpr desc) throws AnalysisException {
VarContext ctx = ctxByVarName.get(desc.getName());
if (ctx == null) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_UNKNOWN_SYSTEM_VARIABLE, desc.getName());
@@ -434,7 +448,7 @@ public class VariableMgr {
}
}
- private static void fillValue(Object obj, Field field, SysVariableDesc desc) {
+ private static void fillValue(Object obj, Field field, VariableExpr desc) {
try {
switch (field.getType().getSimpleName()) {
case "boolean":
@@ -479,6 +493,36 @@ public class VariableMgr {
}
}
+ // Get variable value through variable name, used to satisfy statement like `SELECT @@comment_version`
+ public static void fillValueForUserDefinedVar(VariableExpr desc) {
+ String varName = desc.getName();
+ if (userVars.containsKey(varName)) {
+ LiteralExpr literalExpr = userVars.get(varName);
+ desc.setType(literalExpr.getType());
+ if (literalExpr instanceof BoolLiteral) {
+ desc.setBoolValue(((BoolLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof IntLiteral) {
+ desc.setIntValue(((IntLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof FloatLiteral) {
+ desc.setFloatValue(((FloatLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof DecimalLiteral) {
+ desc.setDecimalValue(((DecimalLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof StringLiteral) {
+ desc.setStringValue(((StringLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof NullLiteral) {
+ desc.setType(Type.NULL);
+ desc.setIsNull();
+ } else {
+ desc.setType(Type.VARCHAR);
+ desc.setStringValue("");
+ }
+ } else {
+ // If there are no such user defined var, just fill the NULL value.
+ desc.setType(Type.NULL);
+ desc.setIsNull();
+ }
+ }
+
private static String getValue(SessionVariable var, String name, SetType setType) throws AnalysisException {
VarContext ctx = ctxByVarName.get(name);
if (ctx == null) {
@@ -499,7 +543,7 @@ public class VariableMgr {
// Get variable value through variable name, used to satisfy statement like `SELECT @@comment_version`
// For test only
- public static String getValue(SessionVariable var, SysVariableDesc desc) throws AnalysisException {
+ public static String getValue(SessionVariable var, VariableExpr desc) throws AnalysisException {
return getValue(var, desc.getName(), desc.getSetType());
}
@@ -550,6 +594,30 @@ public class VariableMgr {
return Literal.of("");
}
+ public static @Nullable Literal getLiteralForUserVar(String varName) {
+ if (userVars.containsKey(varName)) {
+ LiteralExpr literalExpr = userVars.get(varName);
+ if (literalExpr instanceof BoolLiteral) {
+ return Literal.of(((BoolLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof IntLiteral) {
+ return Literal.of(((IntLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof FloatLiteral) {
+ return Literal.of(((FloatLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof DecimalLiteral) {
+ return Literal.of(((DecimalLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof StringLiteral) {
+ return Literal.of(((StringLiteral) literalExpr).getValue());
+ } else if (literalExpr instanceof NullLiteral) {
+ return Literal.of(null);
+ } else {
+ return Literal.of("");
+ }
+ } else {
+ // If there are no such user defined var, just return the NULL value.
+ return Literal.of(null);
+ }
+ }
+
private static String getValue(Object obj, Field field) {
try {
switch (field.getType().getSimpleName()) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
index a4baf0ca3e..dcc0bede70 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
@@ -29,7 +29,7 @@ import org.apache.doris.analysis.Expr;
import org.apache.doris.analysis.InformationFunction;
import org.apache.doris.analysis.LiteralExpr;
import org.apache.doris.analysis.NullLiteral;
-import org.apache.doris.analysis.SysVariableDesc;
+import org.apache.doris.analysis.VariableExpr;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.ScalarType;
@@ -216,7 +216,7 @@ public class FoldConstantsRule implements ExprRewriteRule {
return;
}
// collect sysVariableDesc expr
- if (expr.contains(Predicates.instanceOf(SysVariableDesc.class))) {
+ if (expr.contains(Predicates.instanceOf(VariableExpr.class))) {
getSysVarDescExpr(expr, sysVarMap);
return;
}
@@ -244,14 +244,14 @@ public class FoldConstantsRule implements ExprRewriteRule {
}
private void getSysVarDescExpr(Expr expr, Map<String, Expr> sysVarMap) {
- if (expr instanceof SysVariableDesc) {
- Expr literalExpr = ((SysVariableDesc) expr).getLiteralExpr();
+ if (expr instanceof VariableExpr) {
+ Expr literalExpr = ((VariableExpr) expr).getLiteralExpr();
if (literalExpr == null) {
try {
- VariableMgr.fillValue(ConnectContext.get().getSessionVariable(), (SysVariableDesc) expr);
- literalExpr = ((SysVariableDesc) expr).getLiteralExpr();
+ VariableMgr.fillValue(ConnectContext.get().getSessionVariable(), (VariableExpr) expr);
+ literalExpr = ((VariableExpr) expr).getLiteralExpr();
} catch (AnalysisException e) {
- LOG.warn("failed to get session variable value: " + ((SysVariableDesc) expr).getName());
+ LOG.warn("failed to get session variable value: " + ((VariableExpr) expr).getName());
}
}
sysVarMap.put(expr.getId().toString(), literalExpr);
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java
index 7b5360c87c..d88538a9a5 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVarTest.java
@@ -52,7 +52,7 @@ public class SetVarTest {
var.setType(SetType.GLOBAL);
Assert.assertEquals(SetType.GLOBAL, var.getType());
Assert.assertEquals("names", var.getVariable());
- Assert.assertEquals("utf-8", var.getValue().getStringValue());
+ Assert.assertEquals("utf-8", var.getResult().getStringValue());
Assert.assertEquals("GLOBAL names = 'utf-8'", var.toString());
diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SysVariableDescTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/VariableExprTest.java
similarity index 92%
rename from fe/fe-core/src/test/java/org/apache/doris/analysis/SysVariableDescTest.java
rename to fe/fe-core/src/test/java/org/apache/doris/analysis/VariableExprTest.java
index fcc8b8ddf2..28334f4102 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SysVariableDescTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/VariableExprTest.java
@@ -26,11 +26,11 @@ import org.apache.doris.thrift.TExprNodeType;
import org.junit.Assert;
import org.junit.Test;
-public class SysVariableDescTest {
+public class VariableExprTest {
@Test
public void testNormal() throws AnalysisException {
- SysVariableDesc desc = new SysVariableDesc("version_comment");
+ VariableExpr desc = new VariableExpr("version_comment");
desc.analyze(AccessTestUtil.fetchAdminAnalyzer(false));
Assert.assertEquals("@@version_comment", desc.toSql());
Assert.assertEquals("version_comment", desc.getName());
@@ -45,7 +45,7 @@ public class SysVariableDescTest {
@Test(expected = AnalysisException.class)
public void testNoVar() throws AnalysisException {
- SysVariableDesc desc = new SysVariableDesc("zcPrivate");
+ VariableExpr desc = new VariableExpr("zcPrivate");
desc.analyze(AccessTestUtil.fetchAdminAnalyzer(false));
Assert.fail("No exception throws.");
}
diff --git a/fe/fe-core/src/test/java/org/apache/doris/qe/VariableMgrTest.java b/fe/fe-core/src/test/java/org/apache/doris/qe/VariableMgrTest.java
index b8abd92d32..f1b8e7b5a7 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/VariableMgrTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/VariableMgrTest.java
@@ -22,7 +22,7 @@ import org.apache.doris.analysis.SetStmt;
import org.apache.doris.analysis.SetType;
import org.apache.doris.analysis.SetVar;
import org.apache.doris.analysis.StringLiteral;
-import org.apache.doris.analysis.SysVariableDesc;
+import org.apache.doris.analysis.VariableExpr;
import org.apache.doris.catalog.Env;
import org.apache.doris.common.Config;
import org.apache.doris.common.DdlException;
@@ -154,7 +154,7 @@ public class VariableMgrTest {
Assert.assertEquals(8L, ctx.getSessionVariable().getRuntimeFilterType());
// Get from name
- SysVariableDesc desc = new SysVariableDesc("exec_mem_limit");
+ VariableExpr desc = new VariableExpr("exec_mem_limit");
Assert.assertEquals(var.getMaxExecMemByte() + "", VariableMgr.getValue(var, desc));
}
diff --git a/regression-test/data/nereids_p0/test_user_var.out b/regression-test/data/nereids_p0/test_user_var.out
new file mode 100644
index 0000000000..41aebfe022
--- /dev/null
+++ b/regression-test/data/nereids_p0/test_user_var.out
@@ -0,0 +1,16 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !select1 --
+1 0 -1
+
+-- !select2 --
+1.1 0.0 -1.1
+
+-- !select3 --
+H
+
+-- !select4 --
+true false
+
+-- !select5 --
+\N \N
+
diff --git a/regression-test/data/query_p0/set/test_user_var.out b/regression-test/data/query_p0/set/test_user_var.out
new file mode 100644
index 0000000000..41aebfe022
--- /dev/null
+++ b/regression-test/data/query_p0/set/test_user_var.out
@@ -0,0 +1,16 @@
+-- This file is automatically generated. You should know what you did if you want to edit this
+-- !select1 --
+1 0 -1
+
+-- !select2 --
+1.1 0.0 -1.1
+
+-- !select3 --
+H
+
+-- !select4 --
+true false
+
+-- !select5 --
+\N \N
+
diff --git a/regression-test/suites/nereids_p0/test_user_var.groovy b/regression-test/suites/nereids_p0/test_user_var.groovy
new file mode 100644
index 0000000000..f54e139632
--- /dev/null
+++ b/regression-test/suites/nereids_p0/test_user_var.groovy
@@ -0,0 +1,32 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_user_var") {
+ sql "SET enable_nereids_planner=true"
+ sql "SET enable_fallback_to_original_planner=false"
+ sql "SET @a1=1, @a2=0, @a3=-1"
+ sql "SET @b1=1.1, @b2=0.0, @b3=-1.1"
+ sql "SET @c1='H', @c2=''"
+ sql "SET @d1=true, @d2=false"
+ sql "SET @f1=null"
+
+ qt_select1 'select @a1, @a2, @a3;'
+ qt_select2 'select @b1, @b2, @b3;'
+ qt_select3 'select @c1, @c2;'
+ qt_select4 'select @d1, @d2;'
+ qt_select5 'select @f1, @f2;'
+}
\ No newline at end of file
diff --git a/regression-test/suites/query_p0/set/test_user_var.groovy b/regression-test/suites/query_p0/set/test_user_var.groovy
new file mode 100644
index 0000000000..af2d2caadc
--- /dev/null
+++ b/regression-test/suites/query_p0/set/test_user_var.groovy
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_user_var") {
+ sql "SET @a1=1, @a2=0, @a3=-1"
+ sql "SET @b1=1.1, @b2=0.0, @b3=-1.1"
+ sql "SET @c1='H', @c2=''"
+ sql "SET @d1=true, @d2=false"
+ sql "SET @f1=null"
+
+ qt_select1 'select @a1, @a2, @a3;'
+ qt_select2 'select @b1, @b2, @b3;'
+ qt_select3 'select @c1, @c2;'
+ qt_select4 'select @d1, @d2;'
+ qt_select5 'select @f1, @f2;'
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org