From 228cc90e4e3ace81ae4c1ead5e9dd441ae432e26 Mon Sep 17 00:00:00 2001 From: Mingyu Chen Date: Tue, 25 Apr 2023 11:05:09 +0800 Subject: [PATCH] [fix](session-var) ignore exception when setting global only var in non master FE (#18949) Introduced from #18609. When setting global variables from Non Master FE, there will be error like: `Variable 'password_history' is a GLOBAL variable and should be set with SET GLOBAL` Because when setting global variables from Non Master FE, Doris will do following step: 1. forward this SetStmt to Master FE to execute. 2. Change this SetStmt to "SESSION" level, and execute it again on this Non Master FE. But for "GLOBAL only" variable, such ash "password_history", it doesn't allow to set on SESSION level. So when doing step 2, "set password_history=xxx" without "GLOBAL" keywords will throw exception. So in this case, we should just ignore this exception and return. --- .../org/apache/doris/qe/StmtExecutor.java | 5 +-- .../java/org/apache/doris/qe/VariableMgr.java | 33 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) 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 78907a2081..cc76107f7e 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 @@ -794,8 +794,9 @@ public class StmtExecutor implements ProfileWriter { if (parsedStmt instanceof SetStmt) { SetStmt setStmt = (SetStmt) parsedStmt; setStmt.modifySetVarsForExecute(); - SetExecutor executor = new SetExecutor(context, setStmt); - executor.execute(); + for (SetVar var : setStmt.getSetVars()) { + VariableMgr.setVarForNonMasterFE(context.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 3cce372933..9d4bbb2a3a 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 @@ -251,6 +251,33 @@ public class VariableMgr { // setVar: variable information that needs to be set public static void setVar(SessionVariable sessionVariable, SetVar setVar) throws DdlException { + VarContext varCtx = setVarPreCheck(setVar); + checkUpdate(setVar, varCtx.getFlag()); + setVarInternal(sessionVariable, setVar, varCtx); + } + + // The only difference between setVar and setVarForNonMasterFE + // is that setVarForNonMasterFE will just return if "checkUpdate" throw exception. + // This is because, when setting global variables from Non Master FE, Doris will do following step: + // 1. forward this SetStmt to Master FE to execute. + // 2. Change this SetStmt to "SESSION" level, and execute it again on this Non Master FE. + // But for "GLOBAL only" variable, such ash "password_history", it doesn't allow to set on SESSION level. + // So when doing step 2, "set password_history=xxx" without "GLOBAL" keywords will throw exception. + // So in this case, we should just ignore this exception and return. + public static void setVarForNonMasterFE(SessionVariable sessionVariable, SetVar setVar) + throws DdlException { + VarContext varCtx = setVarPreCheck(setVar); + try { + checkUpdate(setVar, varCtx.getFlag()); + } catch (DdlException e) { + LOG.debug("no need to set var for non master fe: {}", setVar.getVariable(), e); + return; + } + setVarInternal(sessionVariable, setVar, varCtx); + } + + @NotNull + private static VarContext setVarPreCheck(SetVar setVar) throws DdlException { String varName = setVar.getVariable(); boolean hasExpPrefix = false; if (varName.startsWith(ExperimentalUtil.EXPERIMENTAL_PREFIX)) { @@ -265,9 +292,11 @@ public class VariableMgr { if (hasExpPrefix && ctx.getField().getAnnotation(VarAttr.class).expType() == ExperimentalType.NONE) { ErrorReport.reportDdlException(ErrorCode.ERR_UNKNOWN_SYSTEM_VARIABLE, setVar.getVariable()); } - // Check variable attribute and setVar - checkUpdate(setVar, ctx.getFlag()); + return ctx; + } + private static void setVarInternal(SessionVariable sessionVariable, SetVar setVar, VarContext ctx) + throws DdlException { // To modify to default value. VarAttr attr = ctx.getField().getAnnotation(VarAttr.class); String value;