From 9c86cad4eccf65f83ab83e5aab453e019693675d Mon Sep 17 00:00:00 2001 From: yiguolei <676222867@qq.com> Date: Fri, 19 May 2023 12:42:47 +0800 Subject: [PATCH] [improvement](session variable) add max execution time session variabe like mysql and add setter attributes in variables (#19759) 1. add session variable max_execution_time to an alias of query timeout, if user set max_execution_time, the query timeout will be modified too. 2. add a setter attribute to session variable, so that we could add some logic in setter method instead of field reflection. --- .../org/apache/doris/qe/SessionVariable.java | 23 +++++ .../java/org/apache/doris/qe/VariableMgr.java | 99 +++++++++++-------- .../test_set_session_default_val.groovy | 15 +++ 3 files changed, 94 insertions(+), 43 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java index 00d4bf82c9..7018bcaa67 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java @@ -65,6 +65,7 @@ public class SessionVariable implements Serializable, Writable { public static final String EXEC_MEM_LIMIT = "exec_mem_limit"; public static final String SCAN_QUEUE_MEM_LIMIT = "scan_queue_mem_limit"; public static final String QUERY_TIMEOUT = "query_timeout"; + public static final String MAX_EXECUTION_TIME = "max_execution_time"; public static final String INSERT_TIMEOUT = "insert_timeout"; public static final String ENABLE_PROFILE = "enable_profile"; public static final String SQL_MODE = "sql_mode"; @@ -367,6 +368,14 @@ public class SessionVariable implements Serializable, Writable { @VariableMgr.VarAttr(name = QUERY_TIMEOUT) public int queryTimeoutS = 300; + // The global max_execution_time value provides the default for the session value for new connections. + // The session value applies to SELECT executions executed within the session that include + // no MAX_EXECUTION_TIME(N) optimizer hint or for which N is 0. + // https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html + // So that it is == query timeout in doris + @VariableMgr.VarAttr(name = MAX_EXECUTION_TIME, fuzzy = true, setter = "setMaxExecutionTimeMS") + public int maxExecutionTimeMS = -1; + @VariableMgr.VarAttr(name = INSERT_TIMEOUT) public int insertTimeoutS = 14400; @@ -1051,6 +1060,10 @@ public class SessionVariable implements Serializable, Writable { return queryTimeoutS; } + public int getMaxExecutionTimeMS() { + return maxExecutionTimeMS; + } + public int getInsertTimeoutS() { return insertTimeoutS; } @@ -1210,6 +1223,16 @@ public class SessionVariable implements Serializable, Writable { this.queryTimeoutS = queryTimeoutS; } + public void setMaxExecutionTimeMS(int maxExecutionTimeMS) { + this.maxExecutionTimeMS = maxExecutionTimeMS; + this.queryTimeoutS = this.maxExecutionTimeMS / 1000; + } + + public void setMaxExecutionTimeMS(String maxExecutionTimeMS) { + this.maxExecutionTimeMS = Integer.valueOf(maxExecutionTimeMS); + this.queryTimeoutS = this.maxExecutionTimeMS / 1000; + } + public String getResourceGroup() { return resourceGroup; } 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 f714bb2d8b..1d58c07f54 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 @@ -159,50 +159,60 @@ public class VariableMgr { ErrorReport.reportDdlException(ErrorCode.ERR_INVALID_VALUE, attr.name(), value, e.getMessage()); } } - try { - switch (field.getType().getSimpleName()) { - case "boolean": - if (value.equalsIgnoreCase("ON") - || value.equalsIgnoreCase("TRUE") - || value.equalsIgnoreCase("1")) { - field.setBoolean(obj, true); - } else if (value.equalsIgnoreCase("OFF") - || value.equalsIgnoreCase("FALSE") - || value.equalsIgnoreCase("0")) { - field.setBoolean(obj, false); - } else { - throw new IllegalAccessException(); - } - break; - case "byte": - field.setByte(obj, Byte.valueOf(value)); - break; - case "short": - field.setShort(obj, Short.valueOf(value)); - break; - case "int": - field.setInt(obj, Integer.valueOf(value)); - break; - case "long": - field.setLong(obj, Long.valueOf(value)); - break; - case "float": - field.setFloat(obj, Float.valueOf(value)); - break; - case "double": - field.setDouble(obj, Double.valueOf(value)); - break; - case "String": - field.set(obj, value); - break; - default: - // Unsupported type variable. - ErrorReport.reportDdlException(ErrorCode.ERR_WRONG_TYPE_FOR_VAR, attr.name()); + // If the session variable has specified the setter, then not use reflect + if (!attr.setter().equals("")) { + Preconditions.checkArgument(obj instanceof SessionVariable); + try { + SessionVariable.class.getDeclaredMethod(attr.setter(), String.class).invoke(obj, value); + } catch (Exception e) { + ErrorReport.reportDdlException(ErrorCode.ERR_INVALID_VALUE, attr.name(), value, e.getMessage()); + } + } else { + try { + switch (field.getType().getSimpleName()) { + case "boolean": + if (value.equalsIgnoreCase("ON") + || value.equalsIgnoreCase("TRUE") + || value.equalsIgnoreCase("1")) { + field.setBoolean(obj, true); + } else if (value.equalsIgnoreCase("OFF") + || value.equalsIgnoreCase("FALSE") + || value.equalsIgnoreCase("0")) { + field.setBoolean(obj, false); + } else { + throw new IllegalAccessException(); + } + break; + case "byte": + field.setByte(obj, Byte.valueOf(value)); + break; + case "short": + field.setShort(obj, Short.valueOf(value)); + break; + case "int": + field.setInt(obj, Integer.valueOf(value)); + break; + case "long": + field.setLong(obj, Long.valueOf(value)); + break; + case "float": + field.setFloat(obj, Float.valueOf(value)); + break; + case "double": + field.setDouble(obj, Double.valueOf(value)); + break; + case "String": + field.set(obj, value); + break; + default: + // Unsupported type variable. + ErrorReport.reportDdlException(ErrorCode.ERR_WRONG_TYPE_FOR_VAR, attr.name()); + } + } catch (NumberFormatException e) { + ErrorReport.reportDdlException(ErrorCode.ERR_WRONG_TYPE_FOR_VAR, attr.name()); + } catch (IllegalAccessException e) { + ErrorReport.reportDdlException(ErrorCode.ERR_WRONG_VALUE_FOR_VAR, attr.name(), value); } - } catch (NumberFormatException e) { - ErrorReport.reportDdlException(ErrorCode.ERR_WRONG_TYPE_FOR_VAR, attr.name()); - } catch (IllegalAccessException e) { - ErrorReport.reportDdlException(ErrorCode.ERR_WRONG_VALUE_FOR_VAR, attr.name(), value); } if (VariableVarCallbacks.hasCallback(attr.name())) { @@ -652,6 +662,9 @@ public class VariableMgr { // the checker function should be: public void checker(String value), value is the input string. String checker() default ""; + // could specify the setter method for a variable, not depend on reflect mechanism + String setter() default ""; + // Set to true if the variables need to be forwarded along with forward statement. boolean needForward() default false; diff --git a/regression-test/suites/correctness/test_set_session_default_val.groovy b/regression-test/suites/correctness/test_set_session_default_val.groovy index 26a2aec639..6cf3923fa8 100644 --- a/regression-test/suites/correctness/test_set_session_default_val.groovy +++ b/regression-test/suites/correctness/test_set_session_default_val.groovy @@ -21,4 +21,19 @@ suite("test_set_session_default_val") { sql """set session insert_timeout=${default_timeout[0][1]};""" def session_timeout = sql """show variables where variable_name = 'insert_timeout';""" assertEquals(default_timeout, session_timeout) + + def default_query_timeout = sql """show variables where variable_name = 'query_timeout';""" + def default_max_execute_timeout = sql """show variables where variable_name = 'max_execution_time';""" + + sql """set query_timeout=2;""" + def query_timeout = sql """show variables where variable_name = 'query_timeout';""" + def max_execute_timeout = sql """show variables where variable_name = 'max_execution_time';""" + assertEquals(query_timeout[0][1], "2") + assertEquals(max_execute_timeout[0][1], default_max_execute_timeout[0][1]) + + sql """set max_execution_time=3000;""" + def query_timeout2 = sql """show variables where variable_name = 'query_timeout';""" + def max_execute_timeout2 = sql """show variables where variable_name = 'max_execution_time';""" + assertEquals(query_timeout2[0][1], "3") + assertEquals(max_execute_timeout2[0][1], "3000") }