Commit 99f28694 authored by Oleg Smirnov's avatar Oleg Smirnov

MDEV-34860 Implement MAX_EXECUTION_TIME hint

It places a limit N (a timeout value in milliseconds) on how long
a statement is permitted to execute before the server terminates it.

Syntax:
SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ...

Only top-level SELECT statements support the hint.
parent 824c20ae
#
# MAX_EXECUTION_TIME hint testing
#
CREATE TABLE t1 (a INT, b VARCHAR(300));
INSERT INTO t1 VALUES (1, 'string');
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
# Correct hint usage
SELECT /*+ MAX_EXECUTION_TIME(10) */* FROM t1 a, t1 b;
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
EXPLAIN EXTENDED SELECT /*+ MAX_EXECUTION_TIME(000149) */* FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 512 100.00
Warnings:
Note 1003 select /*+ MAX_EXECUTION_TIME(000149) */ `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`
SELECT /*+ MAX_EXECUTION_TIME(20) */ *, SLEEP(1) FROM t1 UNION SELECT 1, 2, 3;
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
(SELECT /*+ MAX_EXECUTION_TIME(30) */ *, SLEEP(1) FROM t1) UNION (SELECT 1, 2, 3);
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
((SELECT /*+ MAX_EXECUTION_TIME(50) */ *, SLEEP(1) FROM t1));
ERROR 70100: Query execution was interrupted (max_statement_time exceeded)
# Hint duplication
SELECT /*+ MAX_EXECUTION_TIME(10) MAX_EXECUTION_TIME(100) */ count(*) FROM t1;
count(*)
512
Warnings:
Warning 4202 Hint MAX_EXECUTION_TIME(100) is ignored as conflicting/duplicated
# Wrong values
SELECT /*+ MAX_EXECUTION_TIME(0) */ count(*) FROM t1;
count(*)
512
Warnings:
Warning 1912 Incorrect value '0' for option 'MAX_EXECUTION_TIME'
SELECT /*+ MAX_EXECUTION_TIME(-1) */ count(*) FROM t1;
count(*)
512
Warnings:
Warning 1064 Optimizer hint syntax error near '-1) */ count(*) FROM t1' at line 1
SELECT /*+ MAX_EXECUTION_TIME(4294967296) */ count(*) FROM t1;
count(*)
512
Warnings:
Warning 1912 Incorrect value '4294967296' for option 'MAX_EXECUTION_TIME'
# Conflicting max_statement_time and hint (must issue a warning)
SET STATEMENT max_statement_time=1 FOR
SELECT /*+ MAX_EXECUTION_TIME(500) */ count(*) FROM t1 a;
count(*)
512
Warnings:
Warning 4202 Hint MAX_EXECUTION_TIME(500) is ignored as conflicting/duplicated
# only SELECT statements supports the MAX_EXECUTION_TIME hint (warning):
CREATE TABLE t2 (i INT);
INSERT /*+ MAX_EXECUTION_TIME(10) */ INTO t2 SELECT 1;
Warnings:
Warning 4172 'MAX_EXECUTION_TIME(10)' is not allowed in this context
REPLACE /*+ MAX_EXECUTION_TIME(15) */ INTO t2 SELECT 1;
Warnings:
Warning 4172 'MAX_EXECUTION_TIME(15)' is not allowed in this context
UPDATE /*+ MAX_EXECUTION_TIME(23) */ t2 SET i = 1;
Warnings:
Warning 4172 'MAX_EXECUTION_TIME(23)' is not allowed in this context
DELETE /*+ MAX_EXECUTION_TIME(5000) */ FROM t2 WHERE i = 1;
Warnings:
Warning 4172 'MAX_EXECUTION_TIME(5000)' is not allowed in this context
# Not supported inside stored procedures/functions
CREATE PROCEDURE p1() BEGIN SELECT /*+ MAX_EXECUTION_TIME(10) */ count(*) FROM t1 a, t1 b
INTO @a; END|
CALL p1();
Warnings:
Warning 4172 'MAX_EXECUTION_TIME(10)' is not allowed in this context
DROP PROCEDURE p1;
# Hint in a subquery is not allowed (warning):
SELECT 1 FROM (SELECT /*+ MAX_EXECUTION_TIME(10) */ 1) a;
1
1
Warnings:
Warning 4172 'MAX_EXECUTION_TIME(10)' is not allowed in this context
DROP TABLE t1, t2;
--echo #
--echo # MAX_EXECUTION_TIME hint testing
--echo #
CREATE TABLE t1 (a INT, b VARCHAR(300));
INSERT INTO t1 VALUES (1, 'string');
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
-- disable_query_log
-- disable_result_log
analyze table t1;
-- enable_result_log
-- enable_query_log
--echo # Correct hint usage
--error ER_STATEMENT_TIMEOUT
SELECT /*+ MAX_EXECUTION_TIME(10) */* FROM t1 a, t1 b;
EXPLAIN EXTENDED SELECT /*+ MAX_EXECUTION_TIME(000149) */* FROM t1;
--error ER_STATEMENT_TIMEOUT
SELECT /*+ MAX_EXECUTION_TIME(20) */ *, SLEEP(1) FROM t1 UNION SELECT 1, 2, 3;
--error ER_STATEMENT_TIMEOUT
(SELECT /*+ MAX_EXECUTION_TIME(30) */ *, SLEEP(1) FROM t1) UNION (SELECT 1, 2, 3);
--error ER_STATEMENT_TIMEOUT
((SELECT /*+ MAX_EXECUTION_TIME(50) */ *, SLEEP(1) FROM t1));
--echo # Hint duplication
SELECT /*+ MAX_EXECUTION_TIME(10) MAX_EXECUTION_TIME(100) */ count(*) FROM t1;
--echo # Wrong values
SELECT /*+ MAX_EXECUTION_TIME(0) */ count(*) FROM t1;
SELECT /*+ MAX_EXECUTION_TIME(-1) */ count(*) FROM t1;
SELECT /*+ MAX_EXECUTION_TIME(4294967296) */ count(*) FROM t1;
--echo # Conflicting max_statement_time and hint (must issue a warning)
SET STATEMENT max_statement_time=1 FOR
SELECT /*+ MAX_EXECUTION_TIME(500) */ count(*) FROM t1 a;
--echo
--echo # only SELECT statements supports the MAX_EXECUTION_TIME hint (warning):
--echo
CREATE TABLE t2 (i INT);
INSERT /*+ MAX_EXECUTION_TIME(10) */ INTO t2 SELECT 1;
REPLACE /*+ MAX_EXECUTION_TIME(15) */ INTO t2 SELECT 1;
UPDATE /*+ MAX_EXECUTION_TIME(23) */ t2 SET i = 1;
DELETE /*+ MAX_EXECUTION_TIME(5000) */ FROM t2 WHERE i = 1;
--echo # Not supported inside stored procedures/functions
DELIMITER |;
CREATE PROCEDURE p1() BEGIN SELECT /*+ MAX_EXECUTION_TIME(10) */ count(*) FROM t1 a, t1 b
INTO @a; END|
DELIMITER ;|
CALL p1();
DROP PROCEDURE p1;
--echo # Hint in a subquery is not allowed (warning):
SELECT 1 FROM (SELECT /*+ MAX_EXECUTION_TIME(10) */ 1) a;
DROP TABLE t1, t2;
...@@ -1799,6 +1799,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -1799,6 +1799,14 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings: Warnings:
Note 1003 select /*+ QB_NAME(`a Note 1003 select /*+ QB_NAME(`a
b`) */ 1 AS `1` b`) */ 1 AS `1`
# Identifiers starting with digits must be supported:
CREATE OR REPLACE TABLE 0a (8a INT, KEY 6a(8a));
EXPLAIN EXTENDED SELECT /*+ NO_MRR(0a 6a) BKA(0a)*/ 8a FROM 0a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE 0a system NULL NULL NULL NULL 0 0.00 Const row not found
Warnings:
Note 1003 select /*+ BKA(`0a`@`select#1`) NO_MRR(`0a`@`select#1` `6a`) */ NULL AS `8a` from `test`.`0a`
DROP TABLE 0a;
# hint syntax error: empty quoted identifier # hint syntax error: empty quoted identifier
EXPLAIN EXTENDED SELECT /*+ QB_NAME(``) */ 1; EXPLAIN EXTENDED SELECT /*+ QB_NAME(``) */ 1;
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
...@@ -1876,7 +1884,7 @@ SELECT /*+ NO_ICP(10) */ 1; ...@@ -1876,7 +1884,7 @@ SELECT /*+ NO_ICP(10) */ 1;
1 1
1 1
Warnings: Warnings:
Warning 4204 Unresolved table name `10`@`select#1` for NO_ICP hint Warning 1064 Optimizer hint syntax error near '10) */ 1' at line 1
SELECT /*+ NO_ICP( */ 1; SELECT /*+ NO_ICP( */ 1;
1 1
1 1
......
...@@ -914,6 +914,11 @@ EXPLAIN EXTENDED SELECT /*+ QB_NAME(`*b`) */ 1; ...@@ -914,6 +914,11 @@ EXPLAIN EXTENDED SELECT /*+ QB_NAME(`*b`) */ 1;
EXPLAIN EXTENDED SELECT /*+ QB_NAME(`a EXPLAIN EXTENDED SELECT /*+ QB_NAME(`a
b`) */ 1; b`) */ 1;
--echo # Identifiers starting with digits must be supported:
CREATE OR REPLACE TABLE 0a (8a INT, KEY 6a(8a));
EXPLAIN EXTENDED SELECT /*+ NO_MRR(0a 6a) BKA(0a)*/ 8a FROM 0a;
DROP TABLE 0a;
--echo # hint syntax error: empty quoted identifier --echo # hint syntax error: empty quoted identifier
EXPLAIN EXTENDED SELECT /*+ QB_NAME(``) */ 1; EXPLAIN EXTENDED SELECT /*+ QB_NAME(``) */ 1;
......
...@@ -4804,7 +4804,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) ...@@ -4804,7 +4804,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
set/reset the slave thread's timer; a Rows_log_event update needs to set set/reset the slave thread's timer; a Rows_log_event update needs to set
the timer itself the timer itself
*/ */
thd->set_query_timer(); thd->set_query_timer_if_needed();
/* /*
If there are no tables open, this must be the first row event seen If there are no tables open, this must be the first row event seen
......
This diff is collapsed.
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
#include "sql_bitmap.h" #include "sql_bitmap.h"
#include "sql_show.h" #include "sql_show.h"
#include "mysqld_error.h" #include "mysqld_error.h"
#include "opt_hints_parser.h"
struct LEX; struct LEX;
struct TABLE; struct TABLE;
...@@ -91,6 +91,7 @@ enum opt_hints_enum ...@@ -91,6 +91,7 @@ enum opt_hints_enum
MRR_HINT_ENUM, MRR_HINT_ENUM,
NO_RANGE_HINT_ENUM, NO_RANGE_HINT_ENUM,
QB_NAME_HINT_ENUM, QB_NAME_HINT_ENUM,
MAX_EXEC_TIME_HINT_ENUM,
MAX_HINT_ENUM MAX_HINT_ENUM
}; };
...@@ -304,6 +305,13 @@ class Opt_hints : public Sql_alloc ...@@ -304,6 +305,13 @@ class Opt_hints : public Sql_alloc
void check_unresolved(THD *thd); void check_unresolved(THD *thd);
virtual void append_name(THD *thd, String *str)= 0; virtual void append_name(THD *thd, String *str)= 0;
/**
Append additional hint arguments to the printed string if they exist.
For example, SEMIJOIN and SUBQUERY hints may have a list of strategies
as additional arguments
*/
virtual void append_args(THD *thd, String *str) const {}
virtual ~Opt_hints() {} virtual ~Opt_hints() {}
private: private:
...@@ -336,13 +344,29 @@ class Opt_hints : public Sql_alloc ...@@ -336,13 +344,29 @@ class Opt_hints : public Sql_alloc
class Opt_hints_global : public Opt_hints class Opt_hints_global : public Opt_hints
{ {
public: public:
const Optimizer_hint_parser::Max_execution_time_hint *max_exec_time_hint= nullptr;
/*
If MAX_EXECUTION_TIME() hint was provided, this pointer is set to
the SELECT_LEX which the hint is attached to.
NULL if MAX_EXECUTION_TIME() hint is missing.
*/
st_select_lex *max_exec_time_select_lex= nullptr;
Opt_hints_global(MEM_ROOT *mem_root_arg) Opt_hints_global(MEM_ROOT *mem_root_arg)
: Opt_hints(Lex_ident_sys(), NULL, mem_root_arg) : Opt_hints(Lex_ident_sys(), NULL, mem_root_arg)
{} {}
virtual void append_name(THD *thd, String *str) override {} virtual void append_name(THD *thd, String *str) override {}
virtual void append_args(THD *thd, String *str) const override
{
if (max_exec_time_hint)
max_exec_time_hint->append_args(thd, str);
}
bool resolve(THD *thd);
}; };
......
...@@ -57,11 +57,30 @@ Optimizer_hint_tokenizer::find_keyword(const LEX_CSTRING &str) ...@@ -57,11 +57,30 @@ Optimizer_hint_tokenizer::find_keyword(const LEX_CSTRING &str)
return TokenID::keyword_QB_NAME; return TokenID::keyword_QB_NAME;
break; break;
case 18:
if ("MAX_EXECUTION_TIME"_Lex_ident_column.streq(str))
return TokenID::keyword_MAX_EXECUTION_TIME;
break;
case 21: case 21:
if ("NO_RANGE_OPTIMIZATION"_Lex_ident_column.streq(str)) if ("NO_RANGE_OPTIMIZATION"_Lex_ident_column.streq(str))
return TokenID::keyword_NO_RANGE_OPTIMIZATION; return TokenID::keyword_NO_RANGE_OPTIMIZATION;
break; break;
} }
if (str.length > 0 && (str.str[0] >= '0' && str.str[0] <= '9'))
{
/*
If all characters are digits, qualify the token as a number,
otherwise as an identifier
*/
for(size_t i = 1; i < str.length; i++)
{
if (str.str[i] < '0' || str.str[i] > '9')
return TokenID::tIDENT;
}
return TokenID::tUNSIGNED_NUMBER;
}
return TokenID::tIDENT; return TokenID::tIDENT;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "simple_tokenizer.h" #include "simple_tokenizer.h"
#include "sql_list.h" #include "sql_list.h"
#include "sql_string.h" #include "sql_string.h"
#include "sql_type_int.h"
#include "simple_parser.h" #include "simple_parser.h"
class st_select_lex; class st_select_lex;
...@@ -72,9 +73,11 @@ class Optimizer_hint_tokenizer: public Extended_string_tokenizer ...@@ -72,9 +73,11 @@ class Optimizer_hint_tokenizer: public Extended_string_tokenizer
keyword_NO_RANGE_OPTIMIZATION, keyword_NO_RANGE_OPTIMIZATION,
keyword_MRR, keyword_MRR,
keyword_QB_NAME, keyword_QB_NAME,
keyword_MAX_EXECUTION_TIME,
// Other token types // Other token types
tIDENT tIDENT,
tUNSIGNED_NUMBER
}; };
class Token: public Lex_cstring class Token: public Lex_cstring
...@@ -240,6 +243,13 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer, ...@@ -240,6 +243,13 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
using TOKEN::TOKEN; using TOKEN::TOKEN;
}; };
class Keyword_MAX_EXECUTION_TIME:
public TOKEN<Parser, TokenID::keyword_MAX_EXECUTION_TIME>
{
public:
using TOKEN::TOKEN;
};
class Identifier: public TOKEN<Parser, TokenID::tIDENT> class Identifier: public TOKEN<Parser, TokenID::tIDENT>
{ {
public: public:
...@@ -258,6 +268,28 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer, ...@@ -258,6 +268,28 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
} }
}; };
class Unsigned_Number: public TOKEN<Parser, TokenID::tUNSIGNED_NUMBER>
{
public:
using TOKEN::TOKEN;
/*
Converts token string to a non-negative number ( >=0 ).
Returns the converted number if the conversion succeeds.
Returns non-NULL ULonglong_null value on successful string conversion and
NULL ULonglong_null if the conversion failed or the number is negative
*/
ULonglong_null get_ulonglong() const
{
int error;
char *end= const_cast<char *>(str + length);
longlong n= my_strtoll10(str, &end, &error);
if (error != 0 || end != str + length || n < 0)
return ULonglong_null(0, true);
return ULonglong_null(n, false);
}
};
class LParen: public TOKEN<Parser, TokenID::tLPAREN> class LParen: public TOKEN<Parser, TokenID::tLPAREN>
{ {
public: public:
...@@ -554,21 +586,40 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer, ...@@ -554,21 +586,40 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
}; };
public:
// max_execution_time_hint ::= MAX_EXECUTION_TIME ( milliseconds )
class Max_execution_time_hint: public AND4<Parser,
Keyword_MAX_EXECUTION_TIME,
LParen,
Unsigned_Number,
RParen>
{
public:
using AND4::AND4;
bool resolve(Parse_context *pc) const;
void append_args(THD *thd, String *str) const;
ulong get_milliseconds() const;
};
/* /*
hint ::= index_level_hint hint ::= index_level_hint
| table_level_hint | table_level_hint
| qb_name_hint | qb_name_hint
| statement_level_hint
*/ */
class Hint: public OR3<Parser, class Hint: public OR4<Parser,
Index_level_hint, Index_level_hint,
Table_level_hint, Table_level_hint,
Qb_name_hint> Qb_name_hint,
Max_execution_time_hint>
{ {
public: public:
using OR3::OR3; using OR4::OR4;
}; };
private:
// hint_list ::= hint [ hint... ] // hint_list ::= hint [ hint... ]
class Hint_list_container: public List<Hint> class Hint_list_container: public List<Hint>
{ {
......
...@@ -12292,3 +12292,7 @@ ER_UNRESOLVED_INDEX_HINT_NAME ...@@ -12292,3 +12292,7 @@ ER_UNRESOLVED_INDEX_HINT_NAME
eng "Unresolved index name %s for %s hint" eng "Unresolved index name %s for %s hint"
ER_HINTS_INSIDE_VIEWS_NOT_SUPPORTED ER_HINTS_INSIDE_VIEWS_NOT_SUPPORTED
eng "Optimizer hints are not supported inside view definitions" eng "Optimizer hints are not supported inside view definitions"
ER_WARN_BAD_MAX_EXECUTION_TIME
eng "Unsupported MAX_EXECUTION_TIME"
ER_WARN_UNSUPPORTED_MAX_EXECUTION_TIME
eng "MAX_EXECUTION_TIME hint is supported by top-level standalone SELECT statements only"
...@@ -380,7 +380,7 @@ class Parser_templates ...@@ -380,7 +380,7 @@ class Parser_templates
/* /*
A rule consisting of a choice of thee rules: A rule consisting of a choice of three rules:
rule ::= rule1 | rule2 | rule3 rule ::= rule1 | rule2 | rule3
For the case when the three branches have incompatible storage For the case when the three branches have incompatible storage
...@@ -478,7 +478,50 @@ class Parser_templates ...@@ -478,7 +478,50 @@ class Parser_templates
/* /*
A list with at least MIN_COUNT elements (typlically 0 or 1), A rule consisting of a choice of four rules:
rule ::= rule1 | rule2 | rule3 | rule4
For the case when the three branches have incompatible storage
*/
template<class PARSER, class A, class B, class C, class D>
class OR4: public A, public B, public C, public D
{
public:
OR4()
{ }
OR4(OR4 &&rhs)
:A(std::move(static_cast<A&&>(rhs))),
B(std::move(static_cast<B&&>(rhs))),
C(std::move(static_cast<C&&>(rhs))),
D(std::move(static_cast<D&&>(rhs)))
{ }
OR4 & operator=(OR4 &&rhs)
{
A::operator=(std::move(static_cast<A&&>(rhs)));
B::operator=(std::move(static_cast<B&&>(rhs)));
C::operator=(std::move(static_cast<C&&>(rhs)));
D::operator=(std::move(static_cast<D&&>(rhs)));
return *this;
}
OR4(PARSER *p)
:A(p),
B(A::operator bool() ? B() : B(p)),
C(A::operator bool() || B::operator bool() ? C() : C(p)),
D(A::operator bool() || B::operator bool() || C::operator bool() ?
D() : D(p))
{
DBUG_ASSERT(!operator bool() || !p->is_error());
}
operator bool() const
{
return A::operator bool() || B::operator bool() || C::operator bool() ||
D::operator bool();
}
};
/*
A list with at least MIN_COUNT elements (typically 0 or 1),
with or without a token separator between elements: with or without a token separator between elements:
list ::= element [ {, element }... ] // with a separator list ::= element [ {, element }... ] // with a separator
......
...@@ -8431,6 +8431,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context, ...@@ -8431,6 +8431,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
if (setup_natural_join_row_types(thd, from_clause, context)) if (setup_natural_join_row_types(thd, from_clause, context))
DBUG_RETURN(1); DBUG_RETURN(1);
if (thd->lex->opt_hints_global && select_lex->select_number == 1)
thd->lex->opt_hints_global->resolve(thd);
if (qb_hints) if (qb_hints)
qb_hints->check_unresolved(thd); qb_hints->check_unresolved(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -5826,7 +5826,7 @@ class THD: public THD_count, /* this must be first */ ...@@ -5826,7 +5826,7 @@ class THD: public THD_count, /* this must be first */
thr_timer_t query_timer; thr_timer_t query_timer;
public: public:
void set_query_timer() void set_query_timer_if_needed()
{ {
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
/* /*
...@@ -5845,9 +5845,13 @@ class THD: public THD_count, /* this must be first */ ...@@ -5845,9 +5845,13 @@ class THD: public THD_count, /* this must be first */
*/ */
if (!timeout_val || spcont || in_sub_stmt || query_timer.expired == 0) if (!timeout_val || spcont || in_sub_stmt || query_timer.expired == 0)
return; return;
thr_timer_settime(&query_timer, timeout_val); set_query_timer_force(timeout_val);
#endif #endif
} }
void set_query_timer_force(ulonglong timeout_val)
{
thr_timer_settime(&query_timer, timeout_val);
}
void reset_query_timer() void reset_query_timer()
{ {
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
......
...@@ -3822,7 +3822,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) ...@@ -3822,7 +3822,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
thd->query_plan_flags|= QPLAN_ADMIN; thd->query_plan_flags|= QPLAN_ADMIN;
/* Start timeouts */ /* Start timeouts */
thd->set_query_timer(); thd->set_query_timer_if_needed();
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* Check wsrep_mode rules before command execution. */ /* Check wsrep_mode rules before command execution. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment