Merge branch '10.4' into 10.5
This commit is contained in:
commit
68a925b325
@ -205,6 +205,15 @@ ENDIF()
|
|||||||
|
|
||||||
OPTION(NOT_FOR_DISTRIBUTION "Allow linking with GPLv2-incompatible system libraries. Only set it you never plan to distribute the resulting binaries" OFF)
|
OPTION(NOT_FOR_DISTRIBUTION "Allow linking with GPLv2-incompatible system libraries. Only set it you never plan to distribute the resulting binaries" OFF)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Enable protection of statement's memory root after first SP/PS execution.
|
||||||
|
# Can be switched on only for debug build.
|
||||||
|
#
|
||||||
|
OPTION(WITH_PROTECT_STATEMENT_MEMROOT "Enable protection of statement's memory root after first SP/PS execution. Turned into account only for debug build" OFF)
|
||||||
|
IF (CMAKE_BUILD_TYPE MATCHES "Debug" AND WITH_PROTECT_STATEMENT_MEMROOT)
|
||||||
|
ADD_DEFINITIONS(-DPROTECT_STATEMENT_MEMROOT)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
INCLUDE(check_compiler_flag)
|
INCLUDE(check_compiler_flag)
|
||||||
INCLUDE(check_linker_flag)
|
INCLUDE(check_linker_flag)
|
||||||
|
|
||||||
|
@ -52,6 +52,10 @@ typedef struct st_mem_root
|
|||||||
*/
|
*/
|
||||||
unsigned int first_block_usage;
|
unsigned int first_block_usage;
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
int read_only;
|
||||||
|
#endif
|
||||||
|
|
||||||
void (*error_handler)(void);
|
void (*error_handler)(void);
|
||||||
|
|
||||||
PSI_memory_key m_psi_key;
|
PSI_memory_key m_psi_key;
|
||||||
|
@ -77,6 +77,9 @@ void init_alloc_root(PSI_memory_key key, MEM_ROOT *mem_root, size_t block_size,
|
|||||||
mem_root->block_num= 4; /* We shift this with >>2 */
|
mem_root->block_num= 4; /* We shift this with >>2 */
|
||||||
mem_root->first_block_usage= 0;
|
mem_root->first_block_usage= 0;
|
||||||
mem_root->m_psi_key= key;
|
mem_root->m_psi_key= key;
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
mem_root->read_only= 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG))
|
#if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG))
|
||||||
if (pre_alloc_size)
|
if (pre_alloc_size)
|
||||||
@ -216,6 +219,10 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
|
|||||||
DBUG_PRINT("enter",("root: %p", mem_root));
|
DBUG_PRINT("enter",("root: %p", mem_root));
|
||||||
DBUG_ASSERT(alloc_root_inited(mem_root));
|
DBUG_ASSERT(alloc_root_inited(mem_root));
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
DBUG_ASSERT(mem_root->read_only == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
DBUG_EXECUTE_IF("simulate_out_of_memory",
|
||||||
{
|
{
|
||||||
/* Avoid reusing an already allocated block */
|
/* Avoid reusing an already allocated block */
|
||||||
|
@ -534,6 +534,9 @@ sp_head::sp_head(MEM_ROOT *mem_root_arg, sp_package *parent,
|
|||||||
:Query_arena(NULL, STMT_INITIALIZED_FOR_SP),
|
:Query_arena(NULL, STMT_INITIALIZED_FOR_SP),
|
||||||
Database_qualified_name(&null_clex_str, &null_clex_str),
|
Database_qualified_name(&null_clex_str, &null_clex_str),
|
||||||
main_mem_root(*mem_root_arg),
|
main_mem_root(*mem_root_arg),
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
executed_counter(0),
|
||||||
|
#endif
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_handler(sph),
|
m_handler(sph),
|
||||||
m_flags(0),
|
m_flags(0),
|
||||||
@ -791,6 +794,10 @@ sp_head::init(LEX *lex)
|
|||||||
*/
|
*/
|
||||||
lex->trg_table_fields.empty();
|
lex->trg_table_fields.empty();
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
executed_counter= 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1434,6 +1441,11 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
|
|||||||
|
|
||||||
err_status= i->execute(thd, &ip);
|
err_status= i->execute(thd, &ip);
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
if (!err_status)
|
||||||
|
i->mark_as_run();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
#ifdef HAVE_PSI_STATEMENT_INTERFACE
|
||||||
MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
|
MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
|
||||||
thd->m_statement_psi= parent_locker;
|
thd->m_statement_psi= parent_locker;
|
||||||
@ -1535,6 +1547,16 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
|
|||||||
/* Reset sp_rcontext::end_partial_result_set flag. */
|
/* Reset sp_rcontext::end_partial_result_set flag. */
|
||||||
ctx->end_partial_result_set= FALSE;
|
ctx->end_partial_result_set= FALSE;
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
if (thd->is_error())
|
||||||
|
{
|
||||||
|
// Don't count a call ended with an error as normal run
|
||||||
|
executed_counter= 0;
|
||||||
|
main_mem_root.read_only= 0;
|
||||||
|
reset_instrs_executed_counter();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} while (!err_status && likely(!thd->killed) &&
|
} while (!err_status && likely(!thd->killed) &&
|
||||||
likely(!thd->is_fatal_error) &&
|
likely(!thd->is_fatal_error) &&
|
||||||
!thd->spcont->pause_state);
|
!thd->spcont->pause_state);
|
||||||
@ -1647,6 +1669,20 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
|
|||||||
|
|
||||||
err_status|= mysql_change_db(thd, (LEX_CSTRING*)&saved_cur_db_name, TRUE) != 0;
|
err_status|= mysql_change_db(thd, (LEX_CSTRING*)&saved_cur_db_name, TRUE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
if (!err_status)
|
||||||
|
{
|
||||||
|
if (!main_mem_root.read_only &&
|
||||||
|
has_all_instrs_executed())
|
||||||
|
{
|
||||||
|
main_mem_root.read_only= 1;
|
||||||
|
}
|
||||||
|
++executed_counter;
|
||||||
|
DBUG_PRINT("info", ("execute counter: %lu", executed_counter));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
m_flags&= ~IS_INVOKED;
|
m_flags&= ~IS_INVOKED;
|
||||||
if (m_parent)
|
if (m_parent)
|
||||||
m_parent->m_invoked_subroutine_count--;
|
m_parent->m_invoked_subroutine_count--;
|
||||||
@ -3287,6 +3323,37 @@ void sp_head::add_mark_lead(uint ip, List<sp_instr> *leads)
|
|||||||
leads->push_front(i);
|
leads->push_front(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
|
||||||
|
int sp_head::has_all_instrs_executed()
|
||||||
|
{
|
||||||
|
sp_instr *ip;
|
||||||
|
uint count= 0;
|
||||||
|
|
||||||
|
for (uint i= 0; i < m_instr.elements; ++i)
|
||||||
|
{
|
||||||
|
get_dynamic(&m_instr, (uchar*)&ip, i);
|
||||||
|
if (ip->has_been_run())
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count == m_instr.elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sp_head::reset_instrs_executed_counter()
|
||||||
|
{
|
||||||
|
sp_instr *ip;
|
||||||
|
|
||||||
|
for (uint i= 0; i < m_instr.elements; ++i)
|
||||||
|
{
|
||||||
|
get_dynamic(&m_instr, (uchar*)&ip, i);
|
||||||
|
ip->mark_as_not_run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_head::opt_mark()
|
sp_head::opt_mark()
|
||||||
{
|
{
|
||||||
|
@ -140,6 +140,16 @@ class sp_head :private Query_arena,
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
MEM_ROOT main_mem_root;
|
MEM_ROOT main_mem_root;
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
/*
|
||||||
|
The following data member is wholly for debugging purpose.
|
||||||
|
It can be used for possible crash analysis to determine how many times
|
||||||
|
the stored routine was executed before the mem_root marked read_only
|
||||||
|
was requested for a memory chunk. Additionally, a value of this data
|
||||||
|
member is output to the log with DBUG_PRINT.
|
||||||
|
*/
|
||||||
|
ulong executed_counter;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
/** Possible values of m_flags */
|
/** Possible values of m_flags */
|
||||||
enum {
|
enum {
|
||||||
@ -823,6 +833,11 @@ public:
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
int has_all_instrs_executed();
|
||||||
|
void reset_instrs_executed_counter();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Add tables used by routine to the table list. */
|
/* Add tables used by routine to the table list. */
|
||||||
bool add_used_tables_to_table_list(THD *thd,
|
bool add_used_tables_to_table_list(THD *thd,
|
||||||
TABLE_LIST ***query_tables_last_ptr,
|
TABLE_LIST ***query_tables_last_ptr,
|
||||||
@ -1109,6 +1124,9 @@ public:
|
|||||||
/// Should give each a name or type code for debugging purposes?
|
/// Should give each a name or type code for debugging purposes?
|
||||||
sp_instr(uint ip, sp_pcontext *ctx)
|
sp_instr(uint ip, sp_pcontext *ctx)
|
||||||
:Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
|
:Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
, m_has_been_run(false)
|
||||||
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~sp_instr()
|
virtual ~sp_instr()
|
||||||
@ -1199,6 +1217,25 @@ public:
|
|||||||
}
|
}
|
||||||
virtual PSI_statement_info* get_psi_info() = 0;
|
virtual PSI_statement_info* get_psi_info() = 0;
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
bool has_been_run() const
|
||||||
|
{
|
||||||
|
return m_has_been_run;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_as_run()
|
||||||
|
{
|
||||||
|
m_has_been_run= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_as_not_run()
|
||||||
|
{
|
||||||
|
m_has_been_run= false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_has_been_run;
|
||||||
|
#endif
|
||||||
}; // class sp_instr : public Sql_alloc
|
}; // class sp_instr : public Sql_alloc
|
||||||
|
|
||||||
|
|
||||||
|
@ -1918,10 +1918,6 @@ retry_share:
|
|||||||
goto err_lock;
|
goto err_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open view */
|
|
||||||
if (mysql_make_view(thd, share, table_list, false))
|
|
||||||
goto err_lock;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This table is a view. Validate its metadata version: in particular,
|
This table is a view. Validate its metadata version: in particular,
|
||||||
that it was a view when the statement was prepared.
|
that it was a view when the statement was prepared.
|
||||||
@ -1929,6 +1925,10 @@ retry_share:
|
|||||||
if (check_and_update_table_version(thd, table_list, share))
|
if (check_and_update_table_version(thd, table_list, share))
|
||||||
goto err_lock;
|
goto err_lock;
|
||||||
|
|
||||||
|
/* Open view */
|
||||||
|
if (mysql_make_view(thd, share, table_list, false))
|
||||||
|
goto err_lock;
|
||||||
|
|
||||||
/* TODO: Don't free this */
|
/* TODO: Don't free this */
|
||||||
tdc_release_share(share);
|
tdc_release_share(share);
|
||||||
|
|
||||||
@ -3863,6 +3863,12 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,
|
|||||||
if (tables->open_strategy && !tables->table)
|
if (tables->open_strategy && !tables->table)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
/* Check and update metadata version of a base table. */
|
||||||
|
error= check_and_update_table_version(thd, tables, tables->table->s);
|
||||||
|
|
||||||
|
if (unlikely(error))
|
||||||
|
goto end;
|
||||||
|
|
||||||
error= extend_table_list(thd, tables, prelocking_strategy, has_prelocking_list);
|
error= extend_table_list(thd, tables, prelocking_strategy, has_prelocking_list);
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
goto end;
|
goto end;
|
||||||
@ -3870,11 +3876,6 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,
|
|||||||
/* Copy grant information from TABLE_LIST instance to TABLE one. */
|
/* Copy grant information from TABLE_LIST instance to TABLE one. */
|
||||||
tables->table->grant= tables->grant;
|
tables->table->grant= tables->grant;
|
||||||
|
|
||||||
/* Check and update metadata version of a base table. */
|
|
||||||
error= check_and_update_table_version(thd, tables, tables->table->s);
|
|
||||||
|
|
||||||
if (unlikely(error))
|
|
||||||
goto end;
|
|
||||||
/*
|
/*
|
||||||
After opening a MERGE table add the children to the query list of
|
After opening a MERGE table add the children to the query list of
|
||||||
tables, so that they are opened too.
|
tables, so that they are opened too.
|
||||||
|
@ -172,6 +172,16 @@ public:
|
|||||||
Server_side_cursor *cursor;
|
Server_side_cursor *cursor;
|
||||||
uchar *packet;
|
uchar *packet;
|
||||||
uchar *packet_end;
|
uchar *packet_end;
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
/*
|
||||||
|
The following data member is wholly for debugging purpose.
|
||||||
|
It can be used for possible crash analysis to determine how many times
|
||||||
|
the stored routine was executed before the mem_root marked read_only
|
||||||
|
was requested for a memory chunk. Additionally, a value of this data
|
||||||
|
member is output to the log with DBUG_PRINT.
|
||||||
|
*/
|
||||||
|
ulong executed_counter;
|
||||||
|
#endif
|
||||||
uint param_count;
|
uint param_count;
|
||||||
uint last_errno;
|
uint last_errno;
|
||||||
uint flags;
|
uint flags;
|
||||||
@ -4004,6 +4014,9 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
|
|||||||
cursor(0),
|
cursor(0),
|
||||||
packet(0),
|
packet(0),
|
||||||
packet_end(0),
|
packet_end(0),
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
executed_counter(0),
|
||||||
|
#endif
|
||||||
param_count(0),
|
param_count(0),
|
||||||
last_errno(0),
|
last_errno(0),
|
||||||
flags((uint) IS_IN_USE),
|
flags((uint) IS_IN_USE),
|
||||||
@ -4078,8 +4091,13 @@ void Prepared_statement::setup_set_params()
|
|||||||
Prepared_statement::~Prepared_statement()
|
Prepared_statement::~Prepared_statement()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Prepared_statement::~Prepared_statement");
|
DBUG_ENTER("Prepared_statement::~Prepared_statement");
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
DBUG_PRINT("enter",("stmt: %p cursor: %p executed_counter: %lu",
|
||||||
|
this, cursor, executed_counter));
|
||||||
|
#else
|
||||||
DBUG_PRINT("enter",("stmt: %p cursor: %p",
|
DBUG_PRINT("enter",("stmt: %p cursor: %p",
|
||||||
this, cursor));
|
this, cursor));
|
||||||
|
#endif
|
||||||
|
|
||||||
MYSQL_DESTROY_PS(m_prepared_stmt);
|
MYSQL_DESTROY_PS(m_prepared_stmt);
|
||||||
|
|
||||||
@ -4261,6 +4279,10 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||||||
}
|
}
|
||||||
lex->set_trg_event_type_for_tables();
|
lex->set_trg_event_type_for_tables();
|
||||||
|
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
executed_counter= 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
While doing context analysis of the query (in check_prepared_statement)
|
While doing context analysis of the query (in check_prepared_statement)
|
||||||
we allocate a lot of additional memory: for open tables, JOINs, derived
|
we allocate a lot of additional memory: for open tables, JOINs, derived
|
||||||
@ -4532,9 +4554,31 @@ reexecute:
|
|||||||
error= reprepare();
|
error= reprepare();
|
||||||
|
|
||||||
if (likely(!error)) /* Success */
|
if (likely(!error)) /* Success */
|
||||||
|
{
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
// There was reprepare so the counter of runs should be reset
|
||||||
|
executed_counter= 0;
|
||||||
|
mem_root->read_only= 0;
|
||||||
|
#endif
|
||||||
goto reexecute;
|
goto reexecute;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reset_stmt_params(this);
|
reset_stmt_params(this);
|
||||||
|
#ifdef PROTECT_STATEMENT_MEMROOT
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
mem_root->read_only= 1;
|
||||||
|
++executed_counter;
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("execute counter: %lu", executed_counter));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error on call shouldn't be counted as a normal run
|
||||||
|
executed_counter= 0;
|
||||||
|
mem_root->read_only= 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -735,8 +735,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
|
|||||||
ORDER *group,
|
ORDER *group,
|
||||||
List<Window_spec> &win_specs,
|
List<Window_spec> &win_specs,
|
||||||
List<Item_window_func> &win_funcs,
|
List<Item_window_func> &win_funcs,
|
||||||
bool *hidden_group_fields,
|
bool *hidden_group_fields)
|
||||||
uint *reserved)
|
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
enum_parsing_place save_place;
|
enum_parsing_place save_place;
|
||||||
@ -751,13 +750,6 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
|
|||||||
|
|
||||||
thd->lex->allow_sum_func.clear_bit(select->nest_level);
|
thd->lex->allow_sum_func.clear_bit(select->nest_level);
|
||||||
res= setup_conds(thd, tables, leaves, conds);
|
res= setup_conds(thd, tables, leaves, conds);
|
||||||
if (thd->lex->current_select->first_cond_optimization)
|
|
||||||
{
|
|
||||||
if (!res && *conds && ! thd->lex->current_select->merged_into)
|
|
||||||
(*reserved)= (*conds)->exists2in_reserved_items();
|
|
||||||
else
|
|
||||||
(*reserved)= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* it's not wrong to have non-aggregated columns in a WHERE */
|
/* it's not wrong to have non-aggregated columns in a WHERE */
|
||||||
select->set_non_agg_field_used(saved_non_agg_field_used);
|
select->set_non_agg_field_used(saved_non_agg_field_used);
|
||||||
@ -1324,6 +1316,15 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
|
|||||||
DBUG_ASSERT(select_lex->hidden_bit_fields == 0);
|
DBUG_ASSERT(select_lex->hidden_bit_fields == 0);
|
||||||
if (setup_wild(thd, tables_list, fields_list, &all_fields, select_lex, false))
|
if (setup_wild(thd, tables_list, fields_list, &all_fields, select_lex, false))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
|
if (thd->lex->current_select->first_cond_optimization)
|
||||||
|
{
|
||||||
|
if ( conds && ! thd->lex->current_select->merged_into)
|
||||||
|
select_lex->select_n_reserved= conds->exists2in_reserved_items();
|
||||||
|
else
|
||||||
|
select_lex->select_n_reserved= 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (select_lex->setup_ref_array(thd, real_og_num))
|
if (select_lex->setup_ref_array(thd, real_og_num))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
@ -1342,8 +1343,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num,
|
|||||||
all_fields, &conds, order, group_list,
|
all_fields, &conds, order, group_list,
|
||||||
select_lex->window_specs,
|
select_lex->window_specs,
|
||||||
select_lex->window_funcs,
|
select_lex->window_funcs,
|
||||||
&hidden_group_fields,
|
&hidden_group_fields))
|
||||||
&select_lex->select_n_reserved))
|
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4902,7 +4902,8 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table,
|
|||||||
open_tables function for this table
|
open_tables function for this table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int fill_schema_table_from_frm(THD *thd, TABLE *table,
|
static int fill_schema_table_from_frm(THD *thd, MEM_ROOT *mem_root,
|
||||||
|
TABLE *table,
|
||||||
ST_SCHEMA_TABLE *schema_table,
|
ST_SCHEMA_TABLE *schema_table,
|
||||||
LEX_CSTRING *db_name,
|
LEX_CSTRING *db_name,
|
||||||
LEX_CSTRING *table_name,
|
LEX_CSTRING *table_name,
|
||||||
@ -4914,6 +4915,9 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
|
|||||||
TABLE_LIST table_list;
|
TABLE_LIST table_list;
|
||||||
uint res= 0;
|
uint res= 0;
|
||||||
char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1];
|
char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1];
|
||||||
|
Query_arena i_s_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION);
|
||||||
|
Query_arena backup_arena, *old_arena;
|
||||||
|
bool i_s_arena_active= false;
|
||||||
|
|
||||||
bzero((char*) &table_list, sizeof(TABLE_LIST));
|
bzero((char*) &table_list, sizeof(TABLE_LIST));
|
||||||
bzero((char*) &tbl, sizeof(TABLE));
|
bzero((char*) &tbl, sizeof(TABLE));
|
||||||
@ -4988,6 +4992,11 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old_arena= thd->stmt_arena;
|
||||||
|
thd->stmt_arena= &i_s_arena;
|
||||||
|
thd->set_n_backup_active_arena(&i_s_arena, &backup_arena);
|
||||||
|
i_s_arena_active= true;
|
||||||
|
|
||||||
share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW);
|
share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW);
|
||||||
if (!share)
|
if (!share)
|
||||||
{
|
{
|
||||||
@ -5069,7 +5078,16 @@ end:
|
|||||||
savepoint is safe.
|
savepoint is safe.
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(thd->open_tables == NULL);
|
DBUG_ASSERT(thd->open_tables == NULL);
|
||||||
|
|
||||||
thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp);
|
thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp);
|
||||||
|
|
||||||
|
if (i_s_arena_active)
|
||||||
|
{
|
||||||
|
thd->stmt_arena= old_arena;
|
||||||
|
thd->restore_active_arena(&i_s_arena, &backup_arena);
|
||||||
|
i_s_arena.free_items();
|
||||||
|
}
|
||||||
|
|
||||||
if (!thd->is_fatal_error)
|
if (!thd->is_fatal_error)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
return res;
|
return res;
|
||||||
@ -5298,7 +5316,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||||||
if (!(table_open_method & ~OPEN_FRM_ONLY) &&
|
if (!(table_open_method & ~OPEN_FRM_ONLY) &&
|
||||||
db_name != &INFORMATION_SCHEMA_NAME)
|
db_name != &INFORMATION_SCHEMA_NAME)
|
||||||
{
|
{
|
||||||
if (!fill_schema_table_from_frm(thd, table, schema_table,
|
if (!fill_schema_table_from_frm(thd, &tmp_mem_root,
|
||||||
|
table, schema_table,
|
||||||
db_name, table_name,
|
db_name, table_name,
|
||||||
&open_tables_state_backup,
|
&open_tables_state_backup,
|
||||||
can_deadlock))
|
can_deadlock))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user