[MySQL Compatibility 1/4][Bug] Fix bug that set sql_mode with concat() function failed (#4359)
Support `set sql_mode = concat(@@sql_mode, "STRICT_TRANS_TABLES");`
This commit is contained in:
@ -22,6 +22,8 @@ import org.apache.doris.catalog.Function;
|
||||
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 @@ public enum 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 enum ExpressionFunctions {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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.TFloatLiteral;
|
||||
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 class SysVariableDesc extends Expr {
|
||||
|
||||
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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -48,6 +48,8 @@ import org.junit.Assert;
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user