revision-id: 4a9686a91a7459a7476e36195fab0de8852e43b6 (mariadb-10.3.7-101-g4a9686a91a7) parent(s): 0c745c743c65ceb6533babdf21556b633e81566c author: Anel Husakovic committer: Vicențiu Ciorbaru timestamp: 2018-08-06 15:18:22 +0300 message: Prevent reporting an error when performing table discovery When performing table creation we check if a table exists. If storage engines that support table discovery are loaded, we also perform table discovery with those. Normally when a table is not found, my_error is called to signal this. However for this case a "table doesn't exist error" is not an actual problem so the error is caught and silenced. Avoid this entire juggling of errors by preventing a my_error call in the first place, with an additional flag when attempting to fetch the table share. --- sql/handler.cc | 78 ++++++++++++++-------------------------------------------- sql/table.cc | 12 ++++----- sql/table.h | 3 ++- 3 files changed, 26 insertions(+), 67 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 4f152cfd99c..a8e6b08cf42 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5113,22 +5113,19 @@ static my_bool discover_handlerton(THD *thd, plugin_ref plugin, int ha_discover_table(THD *thd, TABLE_SHARE *share) { DBUG_ENTER("ha_discover_table"); - int found; - DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR); // share is not OK yet + int found = 0; - if (!engines_with_discover) - found= FALSE; - else if (share->db_plugin) - found= discover_handlerton(thd, share->db_plugin, share); - else - found= plugin_foreach(thd, discover_handlerton, - MYSQL_STORAGE_ENGINE_PLUGIN, share); - - if (!found) - open_table_error(share, OPEN_FRM_OPEN_ERROR, ENOENT); // not found + if (engines_with_discover) + { + if (share->db_plugin) + found = discover_handlerton(thd, share->db_plugin, share); + else + found = plugin_foreach(thd, discover_handlerton, + MYSQL_STORAGE_ENGINE_PLUGIN, share); + } - DBUG_RETURN(share->error != OPEN_FRM_OK); + DBUG_RETURN(found); } static my_bool file_ext_exists(char *path, size_t path_len, const char *ext) @@ -5163,43 +5160,6 @@ static my_bool discover_existence(THD *thd, plugin_ref plugin, return ht->discover_table_existence(ht, args->db, args->table_name); } -class Table_exists_error_handler : public Internal_error_handler -{ -public: - Table_exists_error_handler() - : m_handled_errors(0), m_unhandled_errors(0) - {} - - bool handle_condition(THD *thd, - uint sql_errno, - const char* sqlstate, - Sql_condition::enum_warning_level *level, - const char* msg, - Sql_condition ** cond_hdl) - { - *cond_hdl= NULL; - if (sql_errno == ER_NO_SUCH_TABLE || - sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE || - sql_errno == ER_WRONG_OBJECT) - { - m_handled_errors++; - return TRUE; - } - - if (*level == Sql_condition::WARN_LEVEL_ERROR) - m_unhandled_errors++; - return FALSE; - } - - bool safely_trapped_errors() - { - return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); - } - -private: - int m_handled_errors; - int m_unhandled_errors; -}; /** Check if a given table exists, without doing a full discover, if possible @@ -5298,24 +5258,24 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_n if (need_full_discover_for_existence) { TABLE_LIST table; - uint flags = GTS_TABLE | GTS_VIEW; + uint flags = GTS_TABLE | GTS_VIEW | GTS_NO_ERROR_IF_MISSING; if (!hton) flags|= GTS_NOLOCK; - Table_exists_error_handler no_such_table_handler; - thd->push_internal_handler(&no_such_table_handler); table.init_one_table(db, table_name, 0, TL_READ); TABLE_SHARE *share= tdc_acquire_share(thd, &table, flags); - thd->pop_internal_handler(); - if (hton && share) + // Share returned, table exists. + if (share) { - *hton= share->db_type(); + if (hton) + *hton= share->db_type(); tdc_release_share(share); + DBUG_RETURN(TRUE); } - - // the table doesn't exist if we've caught ER_NO_SUCH_TABLE and nothing else - DBUG_RETURN(!no_such_table_handler.safely_trapped_errors()); + // No share, if errors have been reported, we assume the table exists. + if (thd->is_error()) + DBUG_RETURN(TRUE); } DBUG_RETURN(FALSE); diff --git a/sql/table.cc b/sql/table.cc index 8dedb926141..3c11ea6d918 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -573,7 +573,6 @@ inline bool is_system_table_name(const char *name, size_t length) enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) { - bool error_given= false; File file; uchar *buf; uchar head[FRM_HEADER_SIZE]; @@ -602,8 +601,9 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) { if ((flags & GTS_TABLE) && (flags & GTS_USE_DISCOVERY)) { - ha_discover_table(thd, share); - error_given= true; + if (!ha_discover_table(thd, share) && !(flags & GTS_NO_ERROR_IF_MISSING)) + open_table_error(share, OPEN_FRM_OPEN_ERROR, ENOENT); + DBUG_RETURN(share->error); } goto err_not_open; } @@ -668,16 +668,14 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags) frmlen= read_length + sizeof(head); share->init_from_binary_frm_image(thd, false, buf, frmlen); - error_given= true; // init_from_binary_frm_image has already called my_error() my_free(buf); - - goto err_not_open; + DBUG_RETURN(share->error); err: mysql_file_close(file, MYF(MY_WME)); err_not_open: - if (unlikely(share->error && !error_given)) + if (unlikely(share->error)) { share->open_errno= my_errno; open_table_error(share, share->error, share->open_errno); diff --git a/sql/table.h b/sql/table.h index 80f5e1283a3..df97b9ffbde 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2876,7 +2876,8 @@ enum get_table_share_flags { GTS_VIEW = 2, GTS_NOLOCK = 4, GTS_USE_DISCOVERY = 8, - GTS_FORCE_DISCOVERY = 16 + GTS_FORCE_DISCOVERY = 16, + GTS_NO_ERROR_IF_MISSING = 32, }; size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data);