MDEV-35510 ASAN build crashes during bootstrap
Avoid ASAN failure by collecting statistics from Result objects before cleaning them up. In related single-table cases, statistics are maintained directly by the single-table update and delete functions.
This commit is contained in:
parent
6cff704e57
commit
d3c9a2ee21
@ -20,6 +20,8 @@
|
|||||||
#ifndef SQL_CMD_INCLUDED
|
#ifndef SQL_CMD_INCLUDED
|
||||||
#define SQL_CMD_INCLUDED
|
#define SQL_CMD_INCLUDED
|
||||||
|
|
||||||
|
#include <my_base.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When a command is added here, be sure it's also added in mysqld.cc
|
When a command is added here, be sure it's also added in mysqld.cc
|
||||||
in "struct show_var_st status_vars[]= {" ...
|
in "struct show_var_st status_vars[]= {" ...
|
||||||
@ -225,6 +227,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool is_dml() const { return false; }
|
virtual bool is_dml() const { return false; }
|
||||||
|
|
||||||
|
virtual void get_dml_stat (ha_rows &found, ha_rows &changed)
|
||||||
|
{
|
||||||
|
found= changed= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Unprepare prepared statement for the command
|
@brief Unprepare prepared statement for the command
|
||||||
@param thd global context of the processed statement
|
@param thd global context of the processed statement
|
||||||
|
@ -328,7 +328,6 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd)
|
|||||||
SQL_SELECT *select= 0;
|
SQL_SELECT *select= 0;
|
||||||
SORT_INFO *file_sort= 0;
|
SORT_INFO *file_sort= 0;
|
||||||
READ_RECORD info;
|
READ_RECORD info;
|
||||||
ha_rows deleted= 0;
|
|
||||||
bool reverse= FALSE;
|
bool reverse= FALSE;
|
||||||
bool binlog_is_row;
|
bool binlog_is_row;
|
||||||
killed_state killed_status= NOT_KILLED;
|
killed_state killed_status= NOT_KILLED;
|
||||||
@ -427,6 +426,7 @@ bool Sql_cmd_delete::delete_from_single_table(THD *thd)
|
|||||||
|
|
||||||
has_triggers= table->triggers && table->triggers->has_delete_triggers();
|
has_triggers= table->triggers && table->triggers->has_delete_triggers();
|
||||||
transactional_table= table->file->has_transactions_and_rollback();
|
transactional_table= table->file->has_transactions_and_rollback();
|
||||||
|
deleted= 0;
|
||||||
|
|
||||||
if (!returning && !using_limit && const_cond_result &&
|
if (!returning && !using_limit && const_cond_result &&
|
||||||
(!thd->is_current_stmt_binlog_format_row() && !has_triggers)
|
(!thd->is_current_stmt_binlog_format_row() && !has_triggers)
|
||||||
@ -1861,6 +1861,9 @@ bool Sql_cmd_delete::execute_inner(THD *thd)
|
|||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
/* In single table case, this->deleted set by delete_from_single_table */
|
||||||
|
if (res && multitable)
|
||||||
|
deleted= ((multi_delete*)get_result())->num_deleted();
|
||||||
res= false;
|
res= false;
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ template <typename T> class SQL_I_List;
|
|||||||
class Sql_cmd_delete final : public Sql_cmd_dml
|
class Sql_cmd_delete final : public Sql_cmd_dml
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ha_rows deleted{0};
|
||||||
Sql_cmd_delete(bool multitable_arg)
|
Sql_cmd_delete(bool multitable_arg)
|
||||||
: orig_multitable(multitable_arg), multitable(multitable_arg),
|
: orig_multitable(multitable_arg), multitable(multitable_arg),
|
||||||
save_protocol(NULL)
|
save_protocol(NULL)
|
||||||
@ -66,6 +67,12 @@ public:
|
|||||||
|
|
||||||
void remove_order_by_without_limit(THD *thd);
|
void remove_order_by_without_limit(THD *thd);
|
||||||
|
|
||||||
|
void get_dml_stat (ha_rows &found, ha_rows &changed) override
|
||||||
|
{
|
||||||
|
found= 0;
|
||||||
|
changed= deleted;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@brief Perform precheck of table privileges for delete statements
|
@brief Perform precheck of table privileges for delete statements
|
||||||
|
@ -34268,39 +34268,38 @@ static void MYSQL_DML_START(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void MYSQL_DML_DONE(THD *thd, int rc)
|
static void MYSQL_DML_GET_STAT(THD * thd, ha_rows &found, ha_rows &changed)
|
||||||
{
|
{
|
||||||
switch (thd->lex->sql_command) {
|
switch (thd->lex->sql_command) {
|
||||||
|
|
||||||
case SQLCOM_UPDATE:
|
case SQLCOM_UPDATE:
|
||||||
MYSQL_UPDATE_DONE(
|
|
||||||
rc,
|
|
||||||
(rc ? 0 :
|
|
||||||
((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
|
|
||||||
->num_found()),
|
|
||||||
(rc ? 0 :
|
|
||||||
((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
|
|
||||||
->num_updated()));
|
|
||||||
break;
|
|
||||||
case SQLCOM_UPDATE_MULTI:
|
case SQLCOM_UPDATE_MULTI:
|
||||||
MYSQL_MULTI_UPDATE_DONE(
|
case SQLCOM_DELETE_MULTI:
|
||||||
rc,
|
thd->lex->m_sql_cmd->get_dml_stat(found, changed);
|
||||||
(rc ? 0 :
|
|
||||||
((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
|
|
||||||
->num_found()),
|
|
||||||
(rc ? 0 :
|
|
||||||
((multi_update*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
|
|
||||||
->num_updated()));
|
|
||||||
break;
|
break;
|
||||||
case SQLCOM_DELETE:
|
case SQLCOM_DELETE:
|
||||||
MYSQL_DELETE_DONE(rc, (rc ? 0 : (ulong) (thd->get_row_count_func())));
|
found= 0;
|
||||||
|
changed= (thd->get_row_count_func());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void MYSQL_DML_DONE(THD *thd, int rc, ha_rows found, ha_rows changed)
|
||||||
|
{
|
||||||
|
switch (thd->lex->sql_command) {
|
||||||
|
case SQLCOM_UPDATE:
|
||||||
|
MYSQL_UPDATE_DONE(rc, found, changed);
|
||||||
|
break;
|
||||||
|
case SQLCOM_UPDATE_MULTI:
|
||||||
|
MYSQL_MULTI_UPDATE_DONE(rc, found, changed);
|
||||||
|
break;
|
||||||
|
case SQLCOM_DELETE:
|
||||||
|
MYSQL_DELETE_DONE(rc, changed);
|
||||||
break;
|
break;
|
||||||
case SQLCOM_DELETE_MULTI:
|
case SQLCOM_DELETE_MULTI:
|
||||||
MYSQL_MULTI_DELETE_DONE(
|
MYSQL_MULTI_DELETE_DONE(rc, changed);
|
||||||
rc,
|
|
||||||
(rc ? 0 :
|
|
||||||
((multi_delete*)(((Sql_cmd_dml*)(thd->lex->m_sql_cmd))->get_result()))
|
|
||||||
->num_deleted()));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
@ -34389,6 +34388,7 @@ err:
|
|||||||
bool Sql_cmd_dml::execute(THD *thd)
|
bool Sql_cmd_dml::execute(THD *thd)
|
||||||
{
|
{
|
||||||
lex = thd->lex;
|
lex = thd->lex;
|
||||||
|
ha_rows found= 0, changed= 0;
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
SELECT_LEX_UNIT *unit = &lex->unit;
|
SELECT_LEX_UNIT *unit = &lex->unit;
|
||||||
@ -34439,6 +34439,8 @@ bool Sql_cmd_dml::execute(THD *thd)
|
|||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
goto err;
|
goto err;
|
||||||
|
else
|
||||||
|
MYSQL_DML_GET_STAT(thd, found, changed);
|
||||||
|
|
||||||
res= unit->cleanup();
|
res= unit->cleanup();
|
||||||
|
|
||||||
@ -34447,13 +34449,13 @@ bool Sql_cmd_dml::execute(THD *thd)
|
|||||||
|
|
||||||
THD_STAGE_INFO(thd, stage_end);
|
THD_STAGE_INFO(thd, stage_end);
|
||||||
|
|
||||||
MYSQL_DML_DONE(thd, res);
|
MYSQL_DML_DONE(thd, 0, found, changed);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
DBUG_ASSERT(thd->is_error() || thd->killed);
|
DBUG_ASSERT(thd->is_error() || thd->killed);
|
||||||
MYSQL_DML_DONE(thd, 1);
|
MYSQL_DML_DONE(thd, 1, 0, 0);
|
||||||
THD_STAGE_INFO(thd, stage_end);
|
THD_STAGE_INFO(thd, stage_end);
|
||||||
(void)unit->cleanup();
|
(void)unit->cleanup();
|
||||||
if (is_prepared())
|
if (is_prepared())
|
||||||
|
@ -366,7 +366,7 @@ bool Sql_cmd_update::update_single_table(THD *thd)
|
|||||||
ha_rows dup_key_found;
|
ha_rows dup_key_found;
|
||||||
bool need_sort= TRUE;
|
bool need_sort= TRUE;
|
||||||
bool reverse= FALSE;
|
bool reverse= FALSE;
|
||||||
ha_rows updated, updated_or_same, found;
|
ha_rows updated_or_same;
|
||||||
key_map old_covering_keys;
|
key_map old_covering_keys;
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
SQL_SELECT *select= NULL;
|
SQL_SELECT *select= NULL;
|
||||||
@ -3140,6 +3140,13 @@ bool Sql_cmd_update::execute_inner(THD *thd)
|
|||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
/* In single table case, this->updated set by update_single_table */
|
||||||
|
if (res && multitable)
|
||||||
|
{
|
||||||
|
found= ((multi_update*)get_result())->num_found();
|
||||||
|
updated= ((multi_update*)get_result())->num_updated();
|
||||||
|
}
|
||||||
|
|
||||||
res= false;
|
res= false;
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ bool compare_record(const TABLE *table);
|
|||||||
class Sql_cmd_update final : public Sql_cmd_dml
|
class Sql_cmd_update final : public Sql_cmd_dml
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ha_rows found{0}, updated{0};
|
||||||
Sql_cmd_update(bool multitable_arg)
|
Sql_cmd_update(bool multitable_arg)
|
||||||
: orig_multitable(multitable_arg), multitable(multitable_arg)
|
: orig_multitable(multitable_arg), multitable(multitable_arg)
|
||||||
{}
|
{}
|
||||||
@ -65,6 +66,13 @@ public:
|
|||||||
|
|
||||||
void set_as_multitable() { multitable= true; }
|
void set_as_multitable() { multitable= true; }
|
||||||
|
|
||||||
|
void get_dml_stat (ha_rows &found, ha_rows &changed) override
|
||||||
|
{
|
||||||
|
|
||||||
|
found= this->found;
|
||||||
|
changed= this->updated;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@brief Perform precheck of table privileges for update statements
|
@brief Perform precheck of table privileges for update statements
|
||||||
|
Loading…
x
Reference in New Issue
Block a user