Commit b02f5dd8 authored by Jon Olav Hauglid's avatar Jon Olav Hauglid

Bug #56085 Embedded server tests fails with assert in

           check_if_table_exists()

This assert was triggered when the server tried to load plugins
while running in embedded server mode. In embedded server mode,
check_if_table_exists() was used to check if mysql.plugin existed
so that ER_NO_SUCH_TABLE could be silently ignored.
The problem was that this check was done without acquiring a metadata
lock on mysql.plugin first. This triggered the assert.

This patch fixes the problem by removing the call to
check_if_table_exists() from plugin_load(). Instead an error handler
which traps ER_NO_SUCH_TABLE is installed before trying to open
mysql.plugin when running in embedded server mode.

No test coverage added since this assert was triggered by 
existing tests running in embedded server mode.
parent 8f36eaa1
...@@ -59,42 +59,13 @@ ...@@ -59,42 +59,13 @@
#endif #endif
/**
This internal handler is used to trap internally
errors that can occur when executing open table
during the prelocking phase.
*/
class Prelock_error_handler : public Internal_error_handler
{
public:
Prelock_error_handler()
: m_handled_errors(0), m_unhandled_errors(0)
{}
virtual ~Prelock_error_handler() {}
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
bool safely_trapped_errors();
private:
int m_handled_errors;
int m_unhandled_errors;
};
bool bool
Prelock_error_handler::handle_condition(THD *, No_such_table_error_handler::handle_condition(THD *,
uint sql_errno, uint sql_errno,
const char*, const char*,
MYSQL_ERROR::enum_warning_level, MYSQL_ERROR::enum_warning_level,
const char*, const char*,
MYSQL_ERROR ** cond_hdl) MYSQL_ERROR ** cond_hdl)
{ {
*cond_hdl= NULL; *cond_hdl= NULL;
if (sql_errno == ER_NO_SUCH_TABLE) if (sql_errno == ER_NO_SUCH_TABLE)
...@@ -108,7 +79,7 @@ Prelock_error_handler::handle_condition(THD *, ...@@ -108,7 +79,7 @@ Prelock_error_handler::handle_condition(THD *,
} }
bool Prelock_error_handler::safely_trapped_errors() bool No_such_table_error_handler::safely_trapped_errors()
{ {
/* /*
If m_unhandled_errors != 0, something else, unanticipated, happened, If m_unhandled_errors != 0, something else, unanticipated, happened,
...@@ -4353,11 +4324,11 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, ...@@ -4353,11 +4324,11 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
The real failure will occur when/if a statement attempts to use The real failure will occur when/if a statement attempts to use
that table. that table.
*/ */
Prelock_error_handler prelock_handler; No_such_table_error_handler no_such_table_handler;
thd->push_internal_handler(& prelock_handler); thd->push_internal_handler(&no_such_table_handler);
error= open_table(thd, tables, new_frm_mem, ot_ctx); error= open_table(thd, tables, new_frm_mem, ot_ctx);
thd->pop_internal_handler(); thd->pop_internal_handler();
safe_to_ignore_table= prelock_handler.safely_trapped_errors(); safe_to_ignore_table= no_such_table_handler.safely_trapped_errors();
} }
else else
error= open_table(thd, tables, new_frm_mem, ot_ctx); error= open_table(thd, tables, new_frm_mem, ot_ctx);
......
...@@ -526,4 +526,34 @@ private: ...@@ -526,4 +526,34 @@ private:
}; };
/**
This internal handler is used to trap ER_NO_SUCH_TABLE.
*/
class No_such_table_error_handler : public Internal_error_handler
{
public:
No_such_table_error_handler()
: m_handled_errors(0), m_unhandled_errors(0)
{}
bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
/**
Returns TRUE if one or more ER_NO_SUCH_TABLE errors have been
trapped and no other errors have been seen. FALSE otherwise.
*/
bool safely_trapped_errors();
private:
int m_handled_errors;
int m_unhandled_errors;
};
#endif /* SQL_BASE_INCLUDED */ #endif /* SQL_BASE_INCLUDED */
...@@ -1393,8 +1393,9 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) ...@@ -1393,8 +1393,9 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
READ_RECORD read_record_info; READ_RECORD read_record_info;
int error; int error;
THD *new_thd= &thd; THD *new_thd= &thd;
bool result;
#ifdef EMBEDDED_LIBRARY #ifdef EMBEDDED_LIBRARY
bool table_exists; No_such_table_error_handler error_handler;
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
DBUG_ENTER("plugin_load"); DBUG_ENTER("plugin_load");
...@@ -1410,13 +1411,18 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) ...@@ -1410,13 +1411,18 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
When building an embedded library, if the mysql.plugin table When building an embedded library, if the mysql.plugin table
does not exist, we silently ignore the missing table does not exist, we silently ignore the missing table
*/ */
if (check_if_table_exists(new_thd, &tables, &table_exists)) new_thd->push_internal_handler(&error_handler);
table_exists= FALSE; #endif /* EMBEDDED_LIBRARY */
if (!table_exists)
result= open_and_lock_tables(new_thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT);
#ifdef EMBEDDED_LIBRARY
new_thd->pop_internal_handler();
if (error_handler.safely_trapped_errors())
goto end; goto end;
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
if (open_and_lock_tables(new_thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT)) if (result)
{ {
DBUG_PRINT("error",("Can't open plugin table")); DBUG_PRINT("error",("Can't open plugin table"));
sql_print_error("Can't open the mysql.plugin table. Please " sql_print_error("Can't open the mysql.plugin table. Please "
......
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