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 ee9a6f5499c74c..88420cd7c58543 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 @@ -22,6 +22,8 @@ import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.VariableMgr; import org.apache.doris.rewrite.FEFunction; import org.apache.doris.rewrite.FEFunctions; @@ -56,18 +58,18 @@ private ExpressionFunctions() { public Expr evalExpr(Expr constExpr) { // Function's arg are all LiteralExpr. for (Expr child : constExpr.getChildren()) { - if (!(child instanceof LiteralExpr)) { + if (!(child instanceof LiteralExpr) && !(child instanceof SysVariableDesc)) { return constExpr; } } if (constExpr instanceof ArithmeticExpr - || constExpr instanceof FunctionCallExpr + || constExpr instanceof FunctionCallExpr || constExpr instanceof TimestampArithmeticExpr) { Function fn = constExpr.getFn(); - + Preconditions.checkNotNull(fn, "Expr's fn can't be null."); - + // return NullLiteral directly iff: // 1. Not UDF // 2. Not in NonNullResultWithNullParamFunctions @@ -96,6 +98,14 @@ public Expr evalExpr(Expr constExpr) { return constExpr; } } + } else if (constExpr instanceof SysVariableDesc) { + try { + VariableMgr.fillValue(ConnectContext.get().getSessionVariable(), (SysVariableDesc) constExpr); + return ((SysVariableDesc) constExpr).getLiteralExpr(); + } catch (AnalysisException e) { + LOG.warn("failed to get session variable value: " + ((SysVariableDesc) constExpr).getName()); + return constExpr; + } } return constExpr; } 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 4d3b0d61cd3b29..a62f36bda505b9 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 @@ -17,7 +17,6 @@ package org.apache.doris.analysis; -import com.google.common.base.Strings; import org.apache.doris.catalog.Catalog; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.ErrorCode; @@ -30,6 +29,8 @@ import org.apache.doris.qe.SessionVariable; import org.apache.doris.system.HeartbeatFlags; +import com.google.common.base.Strings; + // change one variable. public class SetVar { 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/SysVariableDesc.java index 3d7da4074e53f0..f8906c393e8275 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/SysVariableDesc.java @@ -17,7 +17,6 @@ package org.apache.doris.analysis; -import com.google.common.base.Strings; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.DdlException; @@ -32,6 +31,8 @@ import org.apache.doris.thrift.TIntLiteral; import org.apache.doris.thrift.TStringLiteral; +import com.google.common.base.Strings; + // System variable // Converted to StringLiteral in analyze, if this variable is not exist, throw AnalysisException. public class SysVariableDesc extends Expr { @@ -42,6 +43,8 @@ public class SysVariableDesc extends Expr { private double floatValue; private String strValue; + private LiteralExpr literalExpr; + public SysVariableDesc(String name) { this(name, SetType.SESSION); } @@ -89,18 +92,48 @@ public SetType getSetType() { public void setBoolValue(boolean value) { this.boolValue = value; + this.literalExpr = new BoolLiteral(value); } public void setIntValue(long value) { this.intValue = value; + this.literalExpr = new IntLiteral(value); } public void setFloatValue(double value) { this.floatValue = value; + this.literalExpr = new FloatLiteral(value); } public void setStringValue(String value) { this.strValue = value; + this.literalExpr = new StringLiteral(value); + } + + public Expr getLiteralExpr() { + return this.literalExpr; + } + + @Override + public Expr getResultValue() throws AnalysisException { + Expr expr = super.getResultValue(); + if (!Strings.isNullOrEmpty(name) && name.equalsIgnoreCase(SessionVariable.SQL_MODE)) { + // SQL_MODE is a special variable. Its type is int, but it is usually set using a string. + // Such as `set sql_mode = concat(@@sql_mode, "STRICT_TRANS_TABLES");` + // So we return the string type here so that it can correctly match the subsequent function signature. + // We will convert the string to int in VariableMgr. + try { + return new StringLiteral(SqlModeHelper.decode(intValue)); + } catch (DdlException e) { + throw new AnalysisException(e.getMessage()); + } + } + return expr; + } + + @Override + protected boolean isConstantImpl() { + return true; } @Override diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVariableTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVariableTest.java new file mode 100644 index 00000000000000..7cf115531338bb --- /dev/null +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SetVariableTest.java @@ -0,0 +1,63 @@ +// 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.analysis; + +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.SqlModeHelper; +import org.apache.doris.qe.StmtExecutor; +import org.apache.doris.utframe.UtFrameUtils; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.UUID; + +public class SetVariableTest { + // use a unique dir so that it won't be conflict with other unit test which + // may also start a Mocked Frontend + private static String runningDir = "fe/mocked/QueryPlanTest/" + UUID.randomUUID().toString() + "/"; + + private static ConnectContext connectContext; + + @BeforeClass + public static void beforeClass() throws Exception { + UtFrameUtils.createMinDorisCluster(runningDir); + // create connect context + connectContext = UtFrameUtils.createDefaultCtx(); + } + + @Test + public void testSqlMode() throws Exception { + String setStr = "set sql_mode = concat(@@sql_mode, 'STRICT_TRANS_TABLES');"; + connectContext.getState().reset(); + StmtExecutor stmtExecutor = new StmtExecutor(connectContext, setStr); + stmtExecutor.execute(); + Assert.assertEquals("STRICT_TRANS_TABLES", + SqlModeHelper.decode(connectContext.getSessionVariable().getSqlMode())); + } + + @Test + public void testExecMemLimit() throws Exception { + String setStr = "set exec_mem_limit = @@exec_mem_limit * 10"; + connectContext.getState().reset(); + StmtExecutor stmtExecutor = new StmtExecutor(connectContext, setStr); + stmtExecutor.execute(); + Assert.assertEquals(21474836480L, connectContext.getSessionVariable().getMaxExecMemByte()); + } +} \ No newline at end of file diff --git a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java index beb7b506de239f..492bcd57dd758d 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java @@ -17,7 +17,6 @@ package org.apache.doris.planner; -import com.google.common.collect.Lists; import org.apache.doris.analysis.CreateDbStmt; import org.apache.doris.analysis.CreateTableStmt; import org.apache.doris.analysis.DropDbStmt; @@ -47,6 +46,8 @@ import org.junit.BeforeClass; import org.junit.Test; +import com.google.common.collect.Lists; + import java.io.File; import java.util.List; import java.util.UUID;