summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/t/partition_disabled.test2
-rw-r--r--mysql-test/t/show_check.test2
-rw-r--r--sql/handler.cc120
-rw-r--r--sql/handler.h22
-rw-r--r--sql/sql_base.cc32
-rw-r--r--sql/sql_db.cc4
-rw-r--r--sql/sql_table.cc43
-rw-r--r--sql/table.cc111
-rw-r--r--sql/table.h4
-rw-r--r--storage/archive/azio.c8
-rw-r--r--storage/archive/azlib.h4
-rw-r--r--storage/archive/ha_archive.cc42
12 files changed, 219 insertions, 175 deletions
diff --git a/mysql-test/t/partition_disabled.test b/mysql-test/t/partition_disabled.test
index 320d6238502..798fb0aa59e 100644
--- a/mysql-test/t/partition_disabled.test
+++ b/mysql-test/t/partition_disabled.test
@@ -29,7 +29,9 @@ ALTER TABLE t1 ANALYZE PARTITION ALL;
ALTER TABLE t1 REBUILD PARTITION ALL;
ALTER TABLE t1 ENGINE Memory;
ALTER TABLE t1 ADD (new INT);
+--disable_warnings
DROP TABLE t1;
+--enable_warnings
--error ER_OPTION_PREVENTS_STATEMENT
CREATE TABLE t1 (
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index c2edef87d41..32bf5417a0a 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -429,7 +429,9 @@ system echo "this is a junk file for test" >> $MYSQLD_DATADIR/test/t1.frm ;
SHOW TABLE STATUS like 't1';
--error ER_NOT_FORM_FILE
show create table t1;
+--disable_warnings
drop table if exists t1;
+--enable_warnings
--error 1,0
--remove_file $MYSQLD_DATADIR/test/t1.frm
diff --git a/sql/handler.cc b/sql/handler.cc
index 32d78e78ba3..a9a2214a91d 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -491,11 +491,11 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
// if the enfine can discover a single table and it is file-based
// then it can use a default file-based table names discovery
if (!hton->discover_table_names &&
- hton->discover && hton->tablefile_extensions[0])
+ hton->discover_table && hton->tablefile_extensions[0])
hton->discover_table_names= hton_ext_based_table_discovery;
// default discover_table_existence implementation
- if (!hton->discover_table_existence && hton->discover)
+ if (!hton->discover_table_existence && hton->discover_table)
{
if (hton->tablefile_extensions[0])
hton->discover_table_existence= ext_based_existence;
@@ -4279,56 +4279,44 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache,
}
-/**
- Try to discover one table from handler(s).
-
- @retval
- -1 Table did not exists
- @retval
- 0 OK. In this case *frmblob and *frmlen are set
- @retval
- >0 error. frmblob and frmlen may not be set
-*/
-struct st_discover_args
-{
- const char *db;
- const char *name;
- uchar **frmblob;
- size_t *frmlen;
-};
-
static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
- st_discover_args *vargs= (st_discover_args *)arg;
+ TABLE_SHARE *share= (TABLE_SHARE *)arg;
handlerton *hton= plugin_data(plugin, handlerton *);
- if (hton->state == SHOW_OPTION_YES && hton->discover &&
- (!(hton->discover(hton, thd, vargs->db, vargs->name,
- vargs->frmblob,
- vargs->frmlen))))
- return TRUE;
+ if (hton->state == SHOW_OPTION_YES && hton->discover_table)
+ {
+ int error= hton->discover_table(hton, thd, share);
+ if (error != HA_ERR_NO_SUCH_TABLE)
+ {
+ if (error)
+ {
+ DBUG_ASSERT(share->error); // MUST be always set for get_cached_table_share to work
+ my_error(ER_GET_ERRNO, MYF(0), error);
+ }
+ else
+ share->error= OPEN_FRM_OK;
- return FALSE;
+ status_var_increment(thd->status_var.ha_discover_count);
+ return TRUE; // abort the search
+ }
+ }
+
+ DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR);
+ return FALSE; // continue with the next engine
}
-int ha_discover(THD *thd, const char *db, const char *name,
- uchar **frmblob, size_t *frmlen)
+int ha_discover_table(THD *thd, TABLE_SHARE *share)
{
- int error= -1; // Table does not exist in any handler
- DBUG_ENTER("ha_discover");
- DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
- st_discover_args args= {db, name, frmblob, frmlen};
+ DBUG_ENTER("ha_discover_table");
- if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
- DBUG_RETURN(error);
+ DBUG_ASSERT(share->error == OPEN_FRM_OPEN_ERROR); // share is not OK yet
- if (plugin_foreach(thd, discover_handlerton,
- MYSQL_STORAGE_ENGINE_PLUGIN, &args))
- error= 0;
+ if (!plugin_foreach(thd, discover_handlerton,
+ MYSQL_STORAGE_ENGINE_PLUGIN, share))
+ open_table_error(share, OPEN_FRM_OPEN_ERROR, ENOENT); // not found
- if (!error)
- status_var_increment(thd->status_var.ha_discover_count);
- DBUG_RETURN(error);
+ DBUG_RETURN(share->error != OPEN_FRM_OK);
}
/**
@@ -4363,6 +4351,45 @@ 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,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** 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 ||
+ sql_errno == ER_OPTION_PREVENTS_STATEMENT) // partition_disabled.test
+ {
+ m_handled_errors++;
+ return TRUE;
+ }
+
+ if (level == MYSQL_ERROR::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;
+};
+
bool ha_table_exists(THD *thd, const char *db, const char *table_name)
{
DBUG_ENTER("ha_discover_table_existence");
@@ -4371,10 +4398,13 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name)
{
TABLE_LIST table;
- DBUG_ASSERT(0);
- TABLE_SHARE *share= get_table_share(thd, db, table_name,
- GTS_TABLE | GTS_NOLOCK);
- DBUG_RETURN(share != 0);
+ Table_exists_error_handler no_such_table_handler;
+ thd->push_internal_handler(&no_such_table_handler);
+ get_table_share(thd, db, table_name, GTS_TABLE | GTS_VIEW | GTS_NOLOCK);
+ thd->pop_internal_handler();
+
+ // 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());
}
mysql_mutex_lock(&LOCK_open);
diff --git a/sql/handler.h b/sql/handler.h
index 2f899fdaa19..2093a3d1605 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1075,10 +1075,6 @@ struct handlerton
enum handler_create_iterator_result
(*create_iterator)(handlerton *hton, enum handler_iterator_type type,
struct handler_iterator *fill_this_in);
- int (*discover)(handlerton *hton, THD* thd, const char *db,
- const char *name,
- uchar **frmblob,
- size_t *frmlen);
/*
Optional clauses in the CREATE/ALTER TABLE
*/
@@ -1111,6 +1107,20 @@ struct handlerton
**********************************************************************/
/*
+ This method is required for any engine that supports automatic table
+ discovery, there is no default implementation.
+
+ Given a TABLE_SHARE discover_table() fills it in with a correct table
+ structure using one of the TABLE_SHARE::init_from_* methods.
+
+ Returns HA_ERR_NO_SUCH_TABLE if the table did not exist in the engine,
+ zero if the table was discovered successfully, or any other
+ HA_ERR_* error code as appropriate if the table existed, but the
+ discovery failed.
+ */
+ int (*discover_table)(handlerton *hton, THD* thd, TABLE_SHARE *share);
+
+ /*
The discover_table_names method tells the server
about all tables in the specified database that the engine
knows about. Tables (or file names of tables) are added to
@@ -1157,6 +1167,7 @@ struct handlerton
*/
int (*discover_table_existence)(handlerton *hton, const char *db,
const char *table_name);
+
};
@@ -3088,8 +3099,7 @@ int ha_delete_table(THD *thd, handlerton *db_type, const char *path,
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat);
/* discovery */
-int ha_discover(THD* thd, const char* dbname, const char* name,
- uchar** frmblob, size_t* frmlen);
+int ha_discover_table(THD *thd, TABLE_SHARE *share);
int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp,
handlerton::discovered_list *result);
bool ha_table_exists(THD *thd, const char *db, const char *table_name);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 03f6db3a498..d93c412dd60 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -585,24 +585,15 @@ TABLE_SHARE *get_table_share(THD *thd, const char *db, const char *table_name,
char *key, uint key_length, uint flags,
my_hash_value_type hash_value)
{
- bool open_failed;
TABLE_SHARE *share;
DBUG_ENTER("get_table_share");
- DBUG_ASSERT(!(flags & GTS_FORCE_DISCOVERY)); // FIXME not implemented
-
mysql_mutex_lock(&LOCK_open);
- /*
- To be able perform any operation on table we should own
- some kind of metadata lock on it.
- */
- DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name,
- MDL_SHARED));
-
/* Read table definition from cache */
share= (TABLE_SHARE*) my_hash_search_using_hash_value(&table_def_cache,
hash_value, (uchar*) key, key_length);
+
if (!share)
{
if (!(share= alloc_table_share(db, table_name, key, key_length)))
@@ -633,12 +624,15 @@ TABLE_SHARE *get_table_share(THD *thd, const char *db, const char *table_name,
mysql_mutex_lock(&share->LOCK_ha_data);
mysql_mutex_unlock(&LOCK_open);
- open_failed= open_table_def(thd, share, flags);
+ if (flags & GTS_FORCE_DISCOVERY)
+ ha_discover_table(thd, share); // don't read the frm at all
+ else
+ open_table_def(thd, share, flags | GTS_FORCE_DISCOVERY); // frm or discover
mysql_mutex_unlock(&share->LOCK_ha_data);
mysql_mutex_lock(&LOCK_open);
- if (open_failed)
+ if (share->error)
{
share->ref_count--;
(void) my_hash_delete(&table_def_cache, (uchar*) share);
@@ -650,6 +644,9 @@ TABLE_SHARE *get_table_share(THD *thd, const char *db, const char *table_name,
goto end;
}
+ /* cannot force discovery of a cached share */
+ DBUG_ASSERT(!(flags & GTS_FORCE_DISCOVERY));
+
/* make sure that open_table_def() for this share is not running */
mysql_mutex_lock(&share->LOCK_ha_data);
mysql_mutex_unlock(&share->LOCK_ha_data);
@@ -706,7 +703,7 @@ err:
end:
if (flags & GTS_NOLOCK)
{
- share->ref_count--;
+ release_table_share(share);
/*
if GTS_NOLOCK is requested, the returned share pointer cannot be used,
the share it points to may go away any moment.
@@ -716,6 +713,15 @@ end:
*/
share= (TABLE_SHARE*) 1;
}
+ else
+ {
+ /*
+ To be able perform any operation on table we should own
+ some kind of metadata lock on it.
+ */
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name,
+ MDL_SHARED));
+ }
mysql_mutex_unlock(&LOCK_open);
DBUG_RETURN(share);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 6dee6b4bcc5..d4f8431beec 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -832,11 +832,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
mysql_ha_rm_tables(thd, tables);
for (table= tables; table; table= table->next_local)
- {
- tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
- false);
deleted_tables++;
- }
thd->push_internal_handler(&err_handler);
if (!thd->killed &&
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b19e179f022..830c57438a3 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1928,10 +1928,6 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout,
MYSQL_OPEN_SKIP_TEMPORARY))
DBUG_RETURN(true);
- for (table= tables; table; table= table->next_local)
-
- tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
- false);
}
else
{
@@ -2222,23 +2218,9 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{
non_temp_tables_count++;
- if (thd->locked_tables_mode)
- {
- if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED,
- TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE))
- {
- error= -1;
- goto err;
- }
- close_all_tables_for_name(thd, table->table->s,
- HA_EXTRA_PREPARE_FOR_DROP);
- table->table= 0;
- }
-
- /* Check that we have an exclusive lock on the table to be dropped. */
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db,
table->table_name,
- MDL_EXCLUSIVE));
+ MDL_SHARED));
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
/* remove .frm file and engine files */
@@ -2307,6 +2289,28 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
else
{
char *end;
+
+ if (thd->locked_tables_mode)
+ {
+ if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED,
+ TDC_RT_REMOVE_NOT_OWN_AND_MARK_NOT_USABLE))
+ {
+ error= -1;
+ goto err;
+ }
+ close_all_tables_for_name(thd, table->table->s,
+ HA_EXTRA_PREPARE_FOR_DROP);
+ table->table= 0;
+ }
+ else
+ tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
+ false);
+
+ /* Check that we have an exclusive lock on the table to be dropped. */
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db,
+ table->table_name,
+ MDL_EXCLUSIVE));
+
/*
Cannot use the db_type from the table, since that might have changed
while waiting for the exclusive name lock.
@@ -2372,6 +2376,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
err:
if (wrong_tables.length())
{
+ thd->clear_error();
if (!foreign_key_error)
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
wrong_tables.c_ptr_safe());
diff --git a/sql/table.cc b/sql/table.cc
index 8a74c1c0b60..d9dab7fe170 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -316,6 +316,7 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
share->normalized_path.length= path_length;
share->table_category= get_table_category(& share->db, & share->table_name);
share->set_refresh_version();
+ share->open_errno= ENOENT;
/*
Since alloc_table_share() can be called without any locking (for
@@ -570,24 +571,21 @@ inline bool is_system_table_name(const char *name, uint length)
}
-/**
- Check if a string contains path elements
-*/
-
+/*
+ We don't try to open 5.0 unencoded name, if
+ - non-encoded name contains '@' signs,
+ because '@' can be misinterpreted.
+ It is not clear if '@' is escape character in 5.1,
+ or a normal character in 5.0.
+
+ - non-encoded db or table name contain "#mysql50#" prefix.
+ This kind of tables must have been opened only by the
+ mysql_file_open() above.
+*/
static bool has_disabled_path_chars(const char *str)
{
- for (; *str; str++)
- {
- switch (*str) {
- case FN_EXTCHAR:
- case '/':
- case '\\':
- case '~':
- case '@':
- return TRUE;
- }
- }
- return FALSE;
+ return strpbrk(str, "/\\~@.") != 0 ||
+ strncmp(str, STRING_WITH_LEN(MYSQL50_TABLE_NAME_PREFIX)) == 0;
}
@@ -626,50 +624,45 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
if ((file= mysql_file_open(key_file_frm,
path, O_RDONLY | O_SHARE, MYF(0))) < 0)
{
- /*
- We don't try to open 5.0 unencoded name, if
- - non-encoded name contains '@' signs,
- because '@' can be misinterpreted.
- It is not clear if '@' is escape character in 5.1,
- or a normal character in 5.0.
-
- - non-encoded db or table name contain "#mysql50#" prefix.
- This kind of tables must have been opened only by the
- mysql_file_open() above.
- */
- if (has_disabled_path_chars(share->table_name.str) ||
- has_disabled_path_chars(share->db.str) ||
- !strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
- MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
- !strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
- MYSQL50_TABLE_NAME_PREFIX_LENGTH))
- goto err_not_open;
-
- /* Try unencoded 5.0 name */
- uint length;
- strxnmov(path, sizeof(path)-1,
- mysql_data_home, "/", share->db.str, "/",
- share->table_name.str, reg_ext, NullS);
- length= unpack_filename(path, path) - reg_ext_length;
- /*
- The following is a safety test and should never fail
- as the old file name should never be longer than the new one.
- */
- DBUG_ASSERT(length <= share->normalized_path.length);
- /*
- If the old and the new names have the same length,
- then table name does not have tricky characters,
- so no need to check the old file name.
- */
- if (length == share->normalized_path.length ||
- ((file= mysql_file_open(key_file_frm,
- path, O_RDONLY | O_SHARE, MYF(0))) < 0))
+ if (!has_disabled_path_chars(share->table_name.str) &&
+ !has_disabled_path_chars(share->db.str))
+ {
+ /* Try unencoded 5.0 name */
+ uint length;
+ strxnmov(path, sizeof(path)-1,
+ mysql_data_home, "/", share->db.str, "/",
+ share->table_name.str, reg_ext, NullS);
+ length= unpack_filename(path, path) - reg_ext_length;
+ /*
+ The following is a safety test and should never fail
+ as the old file name should never be longer than the new one.
+ */
+ DBUG_ASSERT(length <= share->normalized_path.length);
+ /*
+ If the old and the new names have the same length,
+ then table name does not have tricky characters,
+ so no need to check the old file name.
+ */
+ if (length != share->normalized_path.length &&
+ (file= mysql_file_open(key_file_frm,
+ path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
+ {
+ /* Unencoded 5.0 table name found */
+ path[length]= '\0'; // Remove .frm extension
+ strmov(share->normalized_path.str, path);
+ share->normalized_path.length= length;
+ }
+ }
+ /* still no luck? try to discover the table */
+ if (file < 0)
+ {
+ if (flags & GTS_TABLE && flags & GTS_FORCE_DISCOVERY)
+ {
+ ha_discover_table(thd, share);
+ error_given= true;
+ }
goto err_not_open;
-
- /* Unencoded 5.0 table name found */
- path[length]= '\0'; // Remove .frm extension
- strmov(share->normalized_path.str, path);
- share->normalized_path.length= length;
+ }
}
if (mysql_file_read(file, head, sizeof(head), MYF(MY_NABP)))
diff --git a/sql/table.h b/sql/table.h
index cd967824a04..e4e5b839a85 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -2450,8 +2450,8 @@ static inline void dbug_tmp_restore_column_maps(MY_BITMAP *read_set,
enum get_table_share_flags {
GTS_TABLE = 1,
GTS_VIEW = 2,
- GTS_NOLOCK = 4, // don't increase share->ref_count
- GTS_FORCE_DISCOVERY = 8 // don't use the .frm file
+ GTS_NOLOCK = 4,
+ GTS_FORCE_DISCOVERY = 8
};
size_t max_row_length(TABLE *table, const uchar *data);
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index 92d7ad70344..43c418e516d 100644
--- a/storage/archive/azio.c
+++ b/storage/archive/azio.c
@@ -855,7 +855,7 @@ int azclose (azio_stream *s)
Though this was added to support MySQL's FRM file, anything can be
stored in this location.
*/
-int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
+int azwrite_frm(azio_stream *s, uchar *blob, unsigned int length)
{
if (s->mode == 'r')
return 1;
@@ -867,7 +867,7 @@ int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
s->frm_length= length;
s->start+= length;
- if (my_pwrite(s->file, (uchar*) blob, s->frm_length,
+ if (my_pwrite(s->file, blob, s->frm_length,
s->frm_start_pos, MYF(MY_NABP)) ||
write_header(s) ||
(my_seek(s->file, 0, MY_SEEK_END, MYF(0)) == MY_FILEPOS_ERROR))
@@ -876,9 +876,9 @@ int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
return 0;
}
-int azread_frm(azio_stream *s, char *blob)
+int azread_frm(azio_stream *s, uchar *blob)
{
- return my_pread(s->file, (uchar*) blob, s->frm_length,
+ return my_pread(s->file, blob, s->frm_length,
s->frm_start_pos, MYF(MY_NABP)) ? 1 : 0;
}
diff --git a/storage/archive/azlib.h b/storage/archive/azlib.h
index 29a6329fb0a..05fc299e581 100644
--- a/storage/archive/azlib.h
+++ b/storage/archive/azlib.h
@@ -331,8 +331,8 @@ extern int azclose(azio_stream *file);
error number (see function gzerror below).
*/
-extern int azwrite_frm (azio_stream *s, char *blob, unsigned int length);
-extern int azread_frm (azio_stream *s, char *blob);
+extern int azwrite_frm (azio_stream *s, uchar *blob, unsigned int length);
+extern int azread_frm (azio_stream *s, uchar *blob);
extern int azwrite_comment (azio_stream *s, char *blob, unsigned int length);
extern int azread_comment (azio_stream *s, char *blob);
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 57d6fc947f8..37b1273b65d 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -26,6 +26,7 @@
#include <myisam.h> // T_EXTEND
#include "ha_archive.h"
+#include "discover.h"
#include <my_dir.h>
#include <mysql/plugin.h>
@@ -120,10 +121,7 @@ extern "C" PSI_file_key arch_key_file_data;
static handler *archive_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root);
-int archive_discover(handlerton *hton, THD* thd, const char *db,
- const char *name,
- uchar **frmblob,
- size_t *frmlen);
+int archive_discover(handlerton *hton, THD* thd, TABLE_SHARE *share);
/*
Number of rows that will force a bulk insert.
@@ -220,7 +218,7 @@ int archive_db_init(void *p)
archive_hton->db_type= DB_TYPE_ARCHIVE_DB;
archive_hton->create= archive_create_handler;
archive_hton->flags= HTON_NO_FLAGS;
- archive_hton->discover= archive_discover;
+ archive_hton->discover_table= archive_discover;
archive_hton->tablefile_extensions= ha_archive_exts;
if (mysql_mutex_init(az_key_mutex_archive_mutex,
@@ -270,19 +268,17 @@ ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg)
archive_reader_open= FALSE;
}
-int archive_discover(handlerton *hton, THD* thd, const char *db,
- const char *name,
- uchar **frmblob,
- size_t *frmlen)
+int archive_discover(handlerton *hton, THD* thd, TABLE_SHARE *share)
{
DBUG_ENTER("archive_discover");
- DBUG_PRINT("archive_discover", ("db: %s, name: %s", db, name));
+ DBUG_PRINT("archive_discover", ("db: '%s' name: '%s'", share->db.str,
+ share->table_name.str));
azio_stream frm_stream;
char az_file[FN_REFLEN];
- char *frm_ptr;
+ uchar *frm_ptr;
MY_STAT file_stat;
- build_table_filename(az_file, sizeof(az_file) - 1, db, name, ARZ, 0);
+ strxmov(az_file, share->normalized_path.str, ARZ, NullS);
if (!(mysql_file_stat(/* arch_key_file_data */ 0, az_file, &file_stat, MYF(0))))
goto err;
@@ -295,19 +291,23 @@ int archive_discover(handlerton *hton, THD* thd, const char *db,
}
if (frm_stream.frm_length == 0)
- goto err;
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- frm_ptr= (char *)my_malloc(sizeof(char) * frm_stream.frm_length, MYF(0));
+ frm_ptr= (uchar *)my_malloc(sizeof(char) * frm_stream.frm_length, MYF(0));
azread_frm(&frm_stream, frm_ptr);
azclose(&frm_stream);
- *frmlen= frm_stream.frm_length;
- *frmblob= (uchar*) frm_ptr;
+ // don't go through the discovery again
+ if (writefrm(share->normalized_path.str, frm_ptr, frm_stream.frm_length))
+ DBUG_RETURN(my_errno);
+
+ share->init_from_binary_frm_image(thd, frm_ptr);
+
+ my_free(frm_ptr);
DBUG_RETURN(0);
err:
- my_errno= 0;
- DBUG_RETURN(1);
+ DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
/*
@@ -650,9 +650,9 @@ int ha_archive::close(void)
int ha_archive::frm_copy(azio_stream *src, azio_stream *dst)
{
int rc= 0;
- char *frm_ptr;
+ uchar *frm_ptr;
- if (!(frm_ptr= (char *) my_malloc(src->frm_length, MYF(0))))
+ if (!(frm_ptr= (uchar *) my_malloc(src->frm_length, MYF(0))))
return HA_ERR_OUT_OF_MEM;
/* Write file offset is set to the end of the file. */
@@ -758,7 +758,7 @@ int ha_archive::create(const char *name, TABLE *table_arg,
if (frm_ptr)
{
mysql_file_read(frm_file, frm_ptr, (size_t)file_stat.st_size, MYF(0));
- azwrite_frm(&create_stream, (char *)frm_ptr, (size_t)file_stat.st_size);
+ azwrite_frm(&create_stream, frm_ptr, (size_t)file_stat.st_size);
my_free(frm_ptr);
}
}