Merge 10.2 into 10.3
This commit is contained in:
commit
ddbc612692
@ -74,7 +74,8 @@ my %debuggers = (
|
||||
options => '-f -o {log} {exe} {args}',
|
||||
},
|
||||
rr => {
|
||||
options => 'record -o {log} {exe} {args}',
|
||||
options => '_RR_TRACE_DIR={log} rr record {exe} {args}',
|
||||
run => 'env',
|
||||
pre => sub {
|
||||
::mtr_error('rr requires kernel.perf_event_paranoid <= 1')
|
||||
if ::mtr_grab_file('/proc/sys/kernel/perf_event_paranoid') > 1;
|
||||
|
@ -5479,5 +5479,22 @@ EXISTS(SELECT 1 FROM t1 GROUP BY a IN (select a from t1))
|
||||
0
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement
|
||||
#
|
||||
CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY);
|
||||
PREPARE stmt FROM 'EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b';
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE a system NULL NULL NULL NULL 0 Const row not found
|
||||
1 SIMPLE b system NULL NULL NULL NULL 0 Const row not found
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INT);
|
||||
PREPARE stmt FROM 'EXPLAIN DELETE FROM t1.* USING t1';
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 system NULL NULL NULL NULL 0 Const row not found
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
|
@ -4949,6 +4949,20 @@ EXECUTE stmt;
|
||||
EXECUTE stmt;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY);
|
||||
PREPARE stmt FROM 'EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b';
|
||||
EXECUTE stmt;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INT);
|
||||
PREPARE stmt FROM 'EXPLAIN DELETE FROM t1.* USING t1';
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
@ -1217,3 +1217,28 @@ set @rnd=1;
|
||||
select @rnd;
|
||||
@rnd
|
||||
0
|
||||
#
|
||||
# MDEV-24860: Incorrect behaviour of SET STATEMENT in case
|
||||
# it is executed as a prepared statement
|
||||
#
|
||||
PREPARE stmt FROM "SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1";
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
# Show definition of the table t1 created using Prepared Statement
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(3) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
# Create the table t1 with the same definition as it used before
|
||||
# using regular statement execution mode.
|
||||
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1;
|
||||
# Show that the table has the same definition as it is in case the table
|
||||
# created in prepared statement mode.
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` varchar(3) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
|
@ -1136,3 +1136,26 @@ while ($1)
|
||||
--enable_query_log
|
||||
--echo # @rnd should be 0
|
||||
select @rnd;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24860: Incorrect behaviour of SET STATEMENT in case
|
||||
--echo # it is executed as a prepared statement
|
||||
--echo #
|
||||
PREPARE stmt FROM "SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1";
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
--echo # Show definition of the table t1 created using Prepared Statement
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # Create the table t1 with the same definition as it used before
|
||||
--echo # using regular statement execution mode.
|
||||
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1;
|
||||
|
||||
--echo # Show that the table has the same definition as it is in case the table
|
||||
--echo # created in prepared statement mode.
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
@ -5099,7 +5099,7 @@ sub mysqld_start ($$) {
|
||||
$ENV{'MYSQLD_LAST_CMD'}= "$exe @$args";
|
||||
|
||||
My::Debugger::setup_args(\$args, \$exe, $mysqld->name());
|
||||
$ENV{'VALGRIND_TEST'}= $opt_valgrind = int($exe && $exe eq 'valgrind');
|
||||
$ENV{'VALGRIND_TEST'}= $opt_valgrind = int(($exe || '') eq 'valgrind');
|
||||
|
||||
# Remove the old pidfile if any
|
||||
unlink($mysqld->value('pid-file'));
|
||||
|
@ -57,3 +57,14 @@ disconnect dml;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
DROP TABLE child, parent;
|
||||
#
|
||||
# MDEV-24532 Table corruption ER_NO_SUCH_TABLE_IN_ENGINE or
|
||||
# ER_CRASHED_ON_USAGE after ALTER on table with foreign key
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)) ENGINE=InnoDB;
|
||||
ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES t1 (a) ON UPDATE CASCADE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
TRUNCATE TABLE t1;
|
||||
ALTER TABLE t1 ADD c INT;
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
|
@ -67,3 +67,16 @@ connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
|
||||
DROP TABLE child, parent;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24532 Table corruption ER_NO_SUCH_TABLE_IN_ENGINE or
|
||||
--echo # ER_CRASHED_ON_USAGE after ALTER on table with foreign key
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)) ENGINE=InnoDB;
|
||||
ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES t1 (a) ON UPDATE CASCADE;
|
||||
LOCK TABLE t1 WRITE;
|
||||
TRUNCATE TABLE t1;
|
||||
ALTER TABLE t1 ADD c INT;
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define HANDLER_INCLUDED
|
||||
/*
|
||||
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2020, MariaDB
|
||||
Copyright (c) 2009, 2021, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@ -1671,6 +1671,12 @@ handlerton *ha_default_tmp_handlerton(THD *thd);
|
||||
// Engine needs to access the main connect string in partitions
|
||||
#define HTON_CAN_READ_CONNECT_STRING_IN_PARTITION (1 <<12)
|
||||
|
||||
/*
|
||||
Table requires and close and reopen after truncate
|
||||
If the handler has HTON_CAN_RECREATE, this flag is not used
|
||||
*/
|
||||
#define HTON_REQUIRES_CLOSE_AFTER_TRUNCATE (1 << 18)
|
||||
|
||||
class Ha_trx_info;
|
||||
|
||||
struct THD_TRANS
|
||||
|
270
sql/sql_parse.cc
270
sql/sql_parse.cc
@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2020, MariaDB
|
||||
Copyright (c) 2008, 2021, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -3270,6 +3270,146 @@ bool Sql_cmd_call::execute(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether the SQL statement being processed is prepended by
|
||||
SET STATEMENT clause and handle variables assignment if it is.
|
||||
|
||||
@param thd thread handle
|
||||
@param lex current lex
|
||||
|
||||
@return false in case of success, true in case of error.
|
||||
*/
|
||||
|
||||
bool run_set_statement_if_requested(THD *thd, LEX *lex)
|
||||
{
|
||||
if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
|
||||
{
|
||||
Query_arena backup;
|
||||
DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
|
||||
|
||||
lex->old_var_list.empty();
|
||||
List_iterator_fast<set_var_base> it(lex->stmt_var_list);
|
||||
set_var_base *var;
|
||||
|
||||
if (lex->set_arena_for_set_stmt(&backup))
|
||||
return true;
|
||||
|
||||
MEM_ROOT *mem_root= thd->mem_root;
|
||||
while ((var= it++))
|
||||
{
|
||||
DBUG_ASSERT(var->is_system());
|
||||
set_var *o= NULL, *v= (set_var*)var;
|
||||
if (!v->var->is_set_stmt_ok())
|
||||
{
|
||||
my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
|
||||
lex->reset_arena_for_set_stmt(&backup);
|
||||
lex->old_var_list.empty();
|
||||
lex->free_arena_for_set_stmt();
|
||||
return true;
|
||||
}
|
||||
if (v->var->session_is_default(thd))
|
||||
o= new set_var(thd,v->type, v->var, &v->base, NULL);
|
||||
else
|
||||
{
|
||||
switch (v->var->option.var_type & GET_TYPE_MASK)
|
||||
{
|
||||
case GET_BOOL:
|
||||
case GET_INT:
|
||||
case GET_LONG:
|
||||
case GET_LL:
|
||||
{
|
||||
bool null_value;
|
||||
longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
(null_value ?
|
||||
(Item *) new (mem_root) Item_null(thd) :
|
||||
(Item *) new (mem_root) Item_int(thd, val)));
|
||||
}
|
||||
break;
|
||||
case GET_UINT:
|
||||
case GET_ULONG:
|
||||
case GET_ULL:
|
||||
{
|
||||
bool null_value;
|
||||
ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
(null_value ?
|
||||
(Item *) new (mem_root) Item_null(thd) :
|
||||
(Item *) new (mem_root) Item_uint(thd, val)));
|
||||
}
|
||||
break;
|
||||
case GET_DOUBLE:
|
||||
{
|
||||
bool null_value;
|
||||
double val= v->var->val_real(&null_value, thd, v->type, &v->base);
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
(null_value ?
|
||||
(Item *) new (mem_root) Item_null(thd) :
|
||||
(Item *) new (mem_root) Item_float(thd, val, 1)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case GET_NO_ARG:
|
||||
case GET_DISABLED:
|
||||
DBUG_ASSERT(0);
|
||||
/* fall through */
|
||||
case 0:
|
||||
case GET_FLAGSET:
|
||||
case GET_ENUM:
|
||||
case GET_SET:
|
||||
case GET_STR:
|
||||
case GET_STR_ALLOC:
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
|
||||
val= v->var->val_str(&tmp, thd, v->type, &v->base);
|
||||
if (val)
|
||||
{
|
||||
Item_string *str=
|
||||
new (mem_root) Item_string(thd, v->var->charset(thd),
|
||||
val->ptr(), val->length());
|
||||
o= new set_var(thd, v->type, v->var, &v->base, str);
|
||||
}
|
||||
else
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
new (mem_root) Item_null(thd));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(o);
|
||||
lex->old_var_list.push_back(o, thd->mem_root);
|
||||
}
|
||||
lex->reset_arena_for_set_stmt(&backup);
|
||||
|
||||
if (lex->old_var_list.is_empty())
|
||||
lex->free_arena_for_set_stmt();
|
||||
|
||||
if (thd->is_error() ||
|
||||
sql_set_variables(thd, &lex->stmt_var_list, false))
|
||||
{
|
||||
if (!thd->is_error())
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
|
||||
lex->restore_set_statement_var();
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
The value of last_insert_id is remembered in THD to be written to binlog
|
||||
when it's used *the first time* in the statement. But SET STATEMENT
|
||||
must read the old value of last_insert_id to be able to restore it at
|
||||
the end. This should not count at "reading of last_insert_id" and
|
||||
should not remember last_insert_id for binlog. That is, it should clear
|
||||
stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
|
||||
*/
|
||||
if (!thd->in_sub_stmt)
|
||||
{
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Execute command saved in thd and lex->sql_command.
|
||||
|
||||
@ -3540,127 +3680,13 @@ mysql_execute_command(THD *thd)
|
||||
thd->get_binlog_format(&orig_binlog_format,
|
||||
&orig_current_stmt_binlog_format);
|
||||
|
||||
if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
|
||||
{
|
||||
Query_arena backup;
|
||||
DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
|
||||
|
||||
lex->old_var_list.empty();
|
||||
List_iterator_fast<set_var_base> it(lex->stmt_var_list);
|
||||
set_var_base *var;
|
||||
|
||||
if (lex->set_arena_for_set_stmt(&backup))
|
||||
goto error;
|
||||
|
||||
MEM_ROOT *mem_root= thd->mem_root;
|
||||
while ((var= it++))
|
||||
{
|
||||
DBUG_ASSERT(var->is_system());
|
||||
set_var *o= NULL, *v= (set_var*)var;
|
||||
if (!v->var->is_set_stmt_ok())
|
||||
{
|
||||
my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
|
||||
lex->reset_arena_for_set_stmt(&backup);
|
||||
lex->old_var_list.empty();
|
||||
lex->free_arena_for_set_stmt();
|
||||
goto error;
|
||||
}
|
||||
if (v->var->session_is_default(thd))
|
||||
o= new set_var(thd,v->type, v->var, &v->base, NULL);
|
||||
else
|
||||
{
|
||||
switch (v->var->option.var_type & GET_TYPE_MASK)
|
||||
{
|
||||
case GET_BOOL:
|
||||
case GET_INT:
|
||||
case GET_LONG:
|
||||
case GET_LL:
|
||||
{
|
||||
bool null_value;
|
||||
longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
(null_value ?
|
||||
(Item *) new (mem_root) Item_null(thd) :
|
||||
(Item *) new (mem_root) Item_int(thd, val)));
|
||||
}
|
||||
break;
|
||||
case GET_UINT:
|
||||
case GET_ULONG:
|
||||
case GET_ULL:
|
||||
{
|
||||
bool null_value;
|
||||
ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
(null_value ?
|
||||
(Item *) new (mem_root) Item_null(thd) :
|
||||
(Item *) new (mem_root) Item_uint(thd, val)));
|
||||
}
|
||||
break;
|
||||
case GET_DOUBLE:
|
||||
{
|
||||
bool null_value;
|
||||
double val= v->var->val_real(&null_value, thd, v->type, &v->base);
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
(null_value ?
|
||||
(Item *) new (mem_root) Item_null(thd) :
|
||||
(Item *) new (mem_root) Item_float(thd, val, 1)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case GET_NO_ARG:
|
||||
case GET_DISABLED:
|
||||
DBUG_ASSERT(0);
|
||||
/* fall through */
|
||||
case 0:
|
||||
case GET_FLAGSET:
|
||||
case GET_ENUM:
|
||||
case GET_SET:
|
||||
case GET_STR:
|
||||
case GET_STR_ALLOC:
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
|
||||
val= v->var->val_str(&tmp, thd, v->type, &v->base);
|
||||
if (val)
|
||||
{
|
||||
Item_string *str= new (mem_root) Item_string(thd, v->var->charset(thd),
|
||||
val->ptr(), val->length());
|
||||
o= new set_var(thd, v->type, v->var, &v->base, str);
|
||||
}
|
||||
else
|
||||
o= new set_var(thd, v->type, v->var, &v->base,
|
||||
new (mem_root) Item_null(thd));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(o);
|
||||
lex->old_var_list.push_back(o, thd->mem_root);
|
||||
}
|
||||
lex->reset_arena_for_set_stmt(&backup);
|
||||
if (lex->old_var_list.is_empty())
|
||||
lex->free_arena_for_set_stmt();
|
||||
if (thd->is_error() ||
|
||||
(res= sql_set_variables(thd, &lex->stmt_var_list, false)))
|
||||
{
|
||||
if (!thd->is_error())
|
||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
|
||||
lex->restore_set_statement_var();
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
The value of last_insert_id is remembered in THD to be written to binlog
|
||||
when it's used *the first time* in the statement. But SET STATEMENT
|
||||
must read the old value of last_insert_id to be able to restore it at
|
||||
the end. This should not count at "reading of last_insert_id" and
|
||||
should not remember last_insert_id for binlog. That is, it should clear
|
||||
stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
|
||||
*/
|
||||
if (!thd->in_sub_stmt)
|
||||
{
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
Assign system variables with values specified by the clause
|
||||
SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement>
|
||||
if they are any.
|
||||
*/
|
||||
if (run_set_statement_if_requested(thd, lex))
|
||||
goto error;
|
||||
|
||||
if (thd->lex->mi.connection_name.str == NULL)
|
||||
thd->lex->mi.connection_name= thd->variables.default_master_connection;
|
||||
|
@ -100,6 +100,7 @@ void mysql_init_multi_delete(LEX *lex);
|
||||
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
|
||||
void create_table_set_open_action_and_adjust_tables(LEX *lex);
|
||||
pthread_handler_t handle_bootstrap(void *arg);
|
||||
bool run_set_statement_if_requested(THD *thd, LEX *lex);
|
||||
int mysql_execute_command(THD *thd);
|
||||
bool do_command(THD *thd);
|
||||
void do_handle_bootstrap(THD *thd);
|
||||
|
@ -4218,6 +4218,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||
*/
|
||||
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
|
||||
|
||||
/*
|
||||
Set variables specified by
|
||||
SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement>
|
||||
clause for duration of prepare phase. Original values of variable
|
||||
listed in the SET STATEMENT clause is restored right after return
|
||||
from the function check_prepared_statement()
|
||||
*/
|
||||
if (likely(error == 0))
|
||||
error= run_set_statement_if_requested(thd, lex);
|
||||
|
||||
/*
|
||||
The only case where we should have items in the thd->free_list is
|
||||
after stmt->set_params_from_vars(), which may in some cases create
|
||||
@ -4236,6 +4246,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
|
||||
}
|
||||
|
||||
/*
|
||||
Restore original values of variables modified on handling
|
||||
SET STATEMENT clause.
|
||||
*/
|
||||
thd->lex->restore_set_statement_var();
|
||||
|
||||
/* The order is important */
|
||||
lex->unit.cleanup();
|
||||
|
||||
|
@ -4288,6 +4288,9 @@ mysql_select(THD *thd,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (thd->lex->describe)
|
||||
select_options|= SELECT_DESCRIBE;
|
||||
|
||||
/*
|
||||
When in EXPLAIN, delay deleting the joins so that they are still
|
||||
available when we're producing EXPLAIN EXTENDED warning text.
|
||||
|
@ -443,6 +443,15 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
|
||||
*/
|
||||
error= handler_truncate(thd, table_ref, FALSE);
|
||||
|
||||
if (error == TRUNCATE_OK && thd->locked_tables_mode &&
|
||||
(table_ref->table->file->ht->flags &
|
||||
HTON_REQUIRES_CLOSE_AFTER_TRUNCATE))
|
||||
{
|
||||
thd->locked_tables_list.mark_table_for_reopen(thd, table_ref->table);
|
||||
if (unlikely(thd->locked_tables_list.reopen_tables(thd, true)))
|
||||
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
All effects of a TRUNCATE TABLE operation are committed even if
|
||||
truncation fails in the case of non transactional tables. Thus, the
|
||||
|
@ -4121,8 +4121,9 @@ static int innodb_init(void* p)
|
||||
innobase_hton->flush_logs = innobase_flush_logs;
|
||||
innobase_hton->show_status = innobase_show_status;
|
||||
innobase_hton->flags =
|
||||
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS
|
||||
| HTON_NATIVE_SYS_VERSIONING;
|
||||
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS |
|
||||
HTON_NATIVE_SYS_VERSIONING |
|
||||
HTON_REQUIRES_CLOSE_AFTER_TRUNCATE;
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
innobase_hton->abort_transaction=wsrep_abort_transaction;
|
||||
|
Loading…
x
Reference in New Issue
Block a user