summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc432
1 files changed, 227 insertions, 205 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index e0018a66400..75c3a64bc27 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -25,8 +25,6 @@
#include "mysql_priv.h"
#include "rpl_filter.h"
-
-
#include <myisampack.h>
#include <errno.h>
@@ -64,7 +62,7 @@ static const LEX_STRING sys_table_aliases[]=
};
const char *ha_row_type[] = {
- "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "?","?","?"
+ "", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
};
const char *tx_isolation_names[] =
@@ -77,6 +75,15 @@ static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
uint known_extensions_id= 0;
+
+static plugin_ref ha_default_plugin(THD *thd)
+{
+ if (thd->variables.table_plugin)
+ return thd->variables.table_plugin;
+ return my_plugin_lock(thd, &global_system_variables.table_plugin);
+}
+
+
/** @brief
Return the default storage engine handlerton for thread
@@ -89,10 +96,11 @@ uint known_extensions_id= 0;
*/
handlerton *ha_default_handlerton(THD *thd)
{
- return (thd->variables.table_type != NULL) ?
- thd->variables.table_type :
- (global_system_variables.table_type != NULL ?
- global_system_variables.table_type : myisam_hton);
+ plugin_ref plugin= ha_default_plugin(thd);
+ DBUG_ASSERT(plugin);
+ handlerton *hton= plugin_data(plugin, handlerton*);
+ DBUG_ASSERT(hton);
+ return hton;
}
@@ -105,26 +113,30 @@ handlerton *ha_default_handlerton(THD *thd)
name name of storage engine
RETURN
- pointer to handlerton
+ pointer to storage engine plugin handle
*/
-handlerton *ha_resolve_by_name(THD *thd, const LEX_STRING *name)
+plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
{
const LEX_STRING *table_alias;
- st_plugin_int *plugin;
+ plugin_ref plugin;
redo:
/* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
(const uchar *)name->str, name->length,
(const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
- return ha_default_handlerton(thd);
+ return ha_default_plugin(thd);
- if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN)))
+ if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN)))
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
- return hton;
- plugin_unlock(plugin);
+ return plugin;
+
+ /*
+ unlocking plugin immediately after locking is relatively low cost.
+ */
+ plugin_unlock(thd, plugin);
}
/*
@@ -145,19 +157,19 @@ redo:
}
-const char *ha_get_storage_engine(enum legacy_db_type db_type)
+plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
{
- switch (db_type) {
- case DB_TYPE_DEFAULT:
- return "DEFAULT";
- default:
- if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
- installed_htons[db_type])
- return hton2plugin[installed_htons[db_type]->slot]->name.str;
- /* fall through */
- case DB_TYPE_UNKNOWN:
- return "UNKNOWN";
+ if (hton)
+ {
+ st_plugin_int **plugin= hton2plugin + hton->slot;
+
+#ifdef DBUG_OFF
+ return my_plugin_lock(thd, plugin);
+#else
+ return my_plugin_lock(thd, &plugin);
+#endif
}
+ return NULL;
}
@@ -172,14 +184,16 @@ static handler *create_default(TABLE_SHARE *table, MEM_ROOT *mem_root)
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
{
+ plugin_ref plugin;
switch (db_type) {
case DB_TYPE_DEFAULT:
return ha_default_handlerton(thd);
- case DB_TYPE_UNKNOWN:
- return NULL;
default:
- if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT)
- return installed_htons[db_type];
+ if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
+ (plugin= ha_lock_engine(thd, installed_htons[db_type])))
+ return plugin_data(plugin, handlerton*);
+ /* fall through */
+ case DB_TYPE_UNKNOWN:
return NULL;
}
}
@@ -199,7 +213,7 @@ handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
{
if (report_error)
{
- const char *engine_name= ha_get_storage_engine(database_type);
+ const char *engine_name= ha_resolve_storage_engine_name(hton);
my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
}
return NULL;
@@ -238,8 +252,7 @@ handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
Here the call to current_thd() is ok as we call this function a lot of
times but we enter this branch very seldom.
*/
- DBUG_RETURN(get_new_handler(share, alloc,
- current_thd->variables.table_type));
+ DBUG_RETURN(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
}
@@ -353,7 +366,7 @@ static int ha_finish_errors(void)
/* Allocate a pointer array for the error message strings. */
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
return 1;
- my_free((gptr) errmsgs, MYF(0));
+ my_free((uchar*) errmsgs, MYF(0));
return 0;
}
@@ -391,7 +404,7 @@ int ha_finalize_handlerton(st_plugin_int *plugin)
}
}
- my_free((gptr)hton, MYF(0));
+ my_free((uchar*)hton, MYF(0));
DBUG_RETURN(0);
}
@@ -401,6 +414,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
{
handlerton *hton;
DBUG_ENTER("ha_initialize_handlerton");
+ DBUG_PRINT("plugin", ("initialize plugin: '%s'", plugin->name.str));
hton= (handlerton *)my_malloc(sizeof(handlerton),
MYF(MY_WME | MY_ZEROFILL));
@@ -522,10 +536,10 @@ int ha_end()
DBUG_RETURN(error);
}
-static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin,
+static my_bool dropdb_handlerton(THD *unused1, plugin_ref plugin,
void *path)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->drop_database)
hton->drop_database(hton, (char *)path);
return FALSE;
@@ -538,16 +552,16 @@ void ha_drop_database(char* path)
}
-static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool closecon_handlerton(THD *thd, plugin_ref plugin,
void *unused)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
/*
there's no need to rollback here as all transactions must
be rolled back already
*/
if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
- thd->ha_data[hton->slot])
+ thd_get_ha_data(thd, hton))
hton->close_connection(hton, thd);
return FALSE;
}
@@ -623,7 +637,7 @@ int ha_prepare(THD *thd)
for (; *ht; ht++)
{
int err;
- statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_prepare_count);
if ((*ht)->prepare)
{
if ((err= (*(*ht)->prepare)(*ht, thd, all)))
@@ -638,7 +652,7 @@ int ha_prepare(THD *thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
- hton2plugin[(*ht)->slot]->name.str);
+ ha_resolve_storage_engine_name(*ht));
}
}
}
@@ -718,7 +732,7 @@ int ha_commit_trans(THD *thd, bool all)
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
error= 1;
}
- statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_prepare_count);
}
DBUG_EXECUTE_IF("crash_commit_after_prepare", abort(););
if (error || (is_real_trans && xid &&
@@ -765,7 +779,7 @@ int ha_commit_one_phase(THD *thd, bool all)
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
error=1;
}
- statistic_increment(thd->status_var.ha_commit_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_commit_count);
*ht= 0;
}
trans->nht=0;
@@ -821,7 +835,7 @@ int ha_rollback_trans(THD *thd, bool all)
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
}
- statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_rollback_count);
*ht= 0;
}
trans->nht=0;
@@ -835,6 +849,9 @@ int ha_rollback_trans(THD *thd, bool all)
}
}
#endif /* USING_TRANSACTIONS */
+ if (all)
+ thd->transaction_rollback_request= FALSE;
+
/*
If a non-transactional table was updated, warn; don't warn if this is a
slave thread (because when a slave thread executes a ROLLBACK, it has
@@ -844,7 +861,7 @@ int ha_rollback_trans(THD *thd, bool all)
the error log; but we don't want users to wonder why they have this
message in the error log, so we don't send it.
*/
- if (is_real_trans && thd->no_trans_update.all &&
+ if (is_real_trans && thd->transaction.all.modified_non_trans_table &&
!thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARNING_NOT_COMPLETE_ROLLBACK,
@@ -871,6 +888,8 @@ int ha_autocommit_or_rollback(THD *thd, int error)
if (ha_commit_stmt(thd))
error=1;
}
+ else if (thd->transaction_rollback_request && !thd->in_sub_stmt)
+ (void) ha_rollback(thd);
else
(void) ha_rollback_stmt(thd);
@@ -886,10 +905,10 @@ struct xahton_st {
int result;
};
-static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin,
+static my_bool xacommit_handlerton(THD *unused1, plugin_ref plugin,
void *arg)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->recover)
{
hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
@@ -898,10 +917,10 @@ static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin,
return FALSE;
}
-static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin,
+static my_bool xarollback_handlerton(THD *unused1, plugin_ref plugin,
void *arg)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->recover)
{
hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
@@ -1004,10 +1023,10 @@ struct xarecover_st
bool dry_run;
};
-static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin,
+static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
void *arg)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
struct xarecover_st *info= (struct xarecover_st *) arg;
int got;
@@ -1016,7 +1035,7 @@ static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin,
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
{
sql_print_information("Found %d prepared transaction(s) in %s",
- got, hton2plugin[hton->slot]->name.str);
+ got, ha_resolve_storage_engine_name(hton));
for (int i=0; i < got; i ++)
{
my_xid x=info->list[i].get_my_xid();
@@ -1037,7 +1056,7 @@ static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin,
}
// recovery mode
if (info->commit_list ?
- hash_search(info->commit_list, (byte *)&x, sizeof(x)) != 0 :
+ hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
{
#ifndef DBUG_OFF
@@ -1107,7 +1126,7 @@ int ha_recover(HASH *commit_list)
plugin_foreach(NULL, xarecover_handlerton,
MYSQL_STORAGE_ENGINE_PLUGIN, &info);
- my_free((gptr)info.list, MYF(0));
+ my_free((uchar*)info.list, MYF(0));
if (info.found_foreign_xids)
sql_print_warning("Found %d prepared XA transactions",
info.found_foreign_xids);
@@ -1192,10 +1211,10 @@ bool mysql_xa_recover(THD *thd)
thd: the thread handle of the current connection
return value: always 0
*/
-static my_bool release_temporary_latches(THD *thd, st_plugin_int *plugin,
+static my_bool release_temporary_latches(THD *thd, plugin_ref plugin,
void *unused)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
hton->release_temporary_latches(hton, thd);
@@ -1231,13 +1250,12 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
{
int err;
DBUG_ASSERT((*ht)->savepoint_set != 0);
- if ((err= (*(*ht)->savepoint_rollback)(*ht, thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
+ if ((err= (*(*ht)->savepoint_rollback)(*ht, thd, (uchar *)(sv+1)+(*ht)->savepoint_offset)))
{ // cannot happen
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
}
- statistic_increment(thd->status_var.ha_savepoint_rollback_count,
- &LOCK_status);
+ status_var_increment(thd->status_var.ha_savepoint_rollback_count);
trans->no_2pc|=(*ht)->prepare == 0;
}
/*
@@ -1252,7 +1270,7 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
}
- statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_rollback_count);
*ht=0; // keep it conveniently zero-filled
}
DBUG_RETURN(error);
@@ -1280,12 +1298,12 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv)
error=1;
break;
}
- if ((err= (*(*ht)->savepoint_set)(*ht, thd, (byte *)(sv+1)+(*ht)->savepoint_offset)))
+ if ((err= (*(*ht)->savepoint_set)(*ht, thd, (uchar *)(sv+1)+(*ht)->savepoint_offset)))
{ // cannot happen
my_error(ER_GET_ERRNO, MYF(0), err);
error=1;
}
- statistic_increment(thd->status_var.ha_savepoint_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_savepoint_count);
}
sv->nht=trans->nht;
#endif /* USING_TRANSACTIONS */
@@ -1307,7 +1325,7 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
if (!(*ht)->savepoint_release)
continue;
if ((err= (*(*ht)->savepoint_release)(*ht, thd,
- (byte *)(sv+1)+
+ (uchar *)(sv+1)+
(*ht)->savepoint_offset)))
{ // cannot happen
my_error(ER_GET_ERRNO, MYF(0), err);
@@ -1318,10 +1336,10 @@ int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
}
-static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool snapshot_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES &&
hton->start_consistent_snapshot)
{
@@ -1349,10 +1367,10 @@ int ha_start_consistent_snapshot(THD *thd)
}
-static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool flush_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
hton->flush_logs(hton))
return TRUE;
@@ -1377,6 +1395,25 @@ bool ha_flush_logs(handlerton *db_type)
return FALSE;
}
+static const char *check_lowercase_names(handler *file, const char *path,
+ char *tmp_path)
+{
+ if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
+ return path;
+
+ /* Ensure that table handler get path in lower case */
+ if (tmp_path != path)
+ strmov(tmp_path, path);
+
+ /*
+ we only should turn into lowercase database/table part
+ so start the process after homedirectory
+ */
+ my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
+ return tmp_path;
+}
+
+
/** @brief
This should return ENOENT if the file doesn't exists.
The .frm file will be deleted only if we return 0 or ENOENT
@@ -1397,16 +1434,10 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
/* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
if (table_type == NULL ||
- ! (file=get_new_handler(&dummy_share, thd->mem_root, table_type)))
+ ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
DBUG_RETURN(ENOENT);
- if (lower_case_table_names == 2 && !(file->ha_table_flags() & HA_FILE_BASED))
- {
- /* Ensure that table handler get path in lower case */
- strmov(tmp_path, path);
- my_casedn_str(files_charset_info, tmp_path);
- path= tmp_path;
- }
+ path= check_lowercase_names(file, path, tmp_path);
if ((error= file->delete_table(path)) && generate_warning)
{
/*
@@ -1425,7 +1456,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
strmake(buff, thd->net.last_error, sizeof(buff)-1);
thd->query_error= 0;
- thd->spcont= 0;
+ thd->spcont= NULL;
thd->lex->current_select= 0;
thd->net.last_error[0]= 0;
@@ -1438,6 +1469,8 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
dummy_share.table_name.length= strlen(alias);
dummy_table.alias= alias;
+ file->table_share= &dummy_share;
+ file->table= &dummy_table;
file->print_error(error, 0);
strmake(new_error, thd->net.last_error, sizeof(buff)-1);
@@ -1458,7 +1491,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
****************************************************************************/
handler *handler::clone(MEM_ROOT *mem_root)
{
- handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type);
+ handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
if (new_handler && !new_handler->ha_open(table,
table->s->normalized_path.str,
table->db_stat,
@@ -1471,38 +1504,21 @@ handler *handler::clone(MEM_ROOT *mem_root)
void handler::ha_statistic_increment(ulong SSV::*offset) const
{
- statistic_increment(table->in_use->status_var.*offset, &LOCK_status);
+ status_var_increment(table->in_use->status_var.*offset);
}
+void **handler::ha_data(THD *thd) const
+{
+ return thd_ha_data(thd, ht);
+}
-bool handler::check_if_log_table_locking_is_allowed(uint sql_command,
- ulong type, TABLE *table)
+THD *handler::ha_thd(void) const
{
- /*
- Deny locking of the log tables, which is incompatible with
- concurrent insert. The routine is not called if the table is
- being locked from a logger THD (general_log_thd or slow_log_thd)
- or from a privileged thread (see log.cc for details)
- */
- if (table->s->log_table &&
- sql_command != SQLCOM_TRUNCATE &&
- sql_command != SQLCOM_ALTER_TABLE &&
- !(sql_command == SQLCOM_FLUSH &&
- type & REFRESH_LOG) &&
- (table->reginfo.lock_type >= TL_READ_NO_INSERT))
- {
- /*
- The check >= TL_READ_NO_INSERT denies all write locks
- plus the only read lock (TL_READ_NO_INSERT itself)
- */
- table->reginfo.lock_type == TL_READ_NO_INSERT ?
- my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0)) :
- my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0));
- return FALSE;
- }
- return TRUE;
+ DBUG_ASSERT(!table || !table->in_use || table->in_use == current_thd);
+ return (table && table->in_use) ? table->in_use : current_thd;
}
+
/** @brief
Open database-handler.
@@ -1544,7 +1560,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
table->db_stat|=HA_READ_ONLY;
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
- if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2)))
+ if (!(ref= (uchar*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2)))
{
close();
error=HA_ERR_OUT_OF_MEM;
@@ -1562,13 +1578,12 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
This is never called for InnoDB tables, as these table types
has the HA_STATS_RECORDS_IS_EXACT set.
*/
-int handler::read_first_row(byte * buf, uint primary_key)
+int handler::read_first_row(uchar * buf, uint primary_key)
{
register int error;
DBUG_ENTER("handler::read_first_row");
- statistic_increment(table->in_use->status_var.ha_read_first_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_first_count);
/*
If there is very few deleted rows in the table, find the first row by
@@ -1972,13 +1987,13 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
}
else
{
- byte key[MAX_KEY_LENGTH];
+ uchar key[MAX_KEY_LENGTH];
key_copy(key, table->record[0],
table->key_info + table->s->next_number_index,
table->s->next_number_key_offset);
- error= index_read(table->record[1], key,
- make_prev_keypart_map(table->s->next_number_keypart),
- HA_READ_PREFIX_LAST);
+ error= index_read_map(table->record[1], key,
+ make_prev_keypart_map(table->s->next_number_keypart),
+ HA_READ_PREFIX_LAST);
/*
MySQL needs to call us for next row: assume we are inserting ("a",null)
here, we return 3, and next this statement will want to insert
@@ -2026,8 +2041,7 @@ void handler::print_keydup_error(uint key_nr, const char *msg)
{
/* Key is unknown */
str.copy("", 0, system_charset_info);
- my_printf_error(ER_DUP_ENTRY_WITH_KEY_NAME, msg,
- MYF(0), str.c_ptr(), "*UNKNOWN*");
+ my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
}
else
{
@@ -2039,7 +2053,7 @@ void handler::print_keydup_error(uint key_nr, const char *msg)
str.length(max_length-4);
str.append(STRING_WITH_LEN("..."));
}
- my_printf_error(ER_DUP_ENTRY_WITH_KEY_NAME, msg,
+ my_printf_error(ER_DUP_ENTRY, msg,
MYF(0), str.c_ptr(), table->key_info[key_nr].name);
}
}
@@ -2316,7 +2330,13 @@ static bool update_frm_version(TABLE *table)
int result= 1;
DBUG_ENTER("update_frm_version");
- if (table->s->mysql_version != MYSQL_VERSION_ID)
+ /*
+ No need to update frm version in case table was created or checked
+ by server with the same version. This also ensures that we do not
+ update frm version for temporary tables as this code doesn't support
+ temporary tables.
+ */
+ if (table->s->mysql_version == MYSQL_VERSION_ID)
DBUG_RETURN(0);
strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
@@ -2331,12 +2351,12 @@ static bool update_frm_version(TABLE *table)
int4store(version, MYSQL_VERSION_ID);
- if ((result= my_pwrite(file,(byte*) version,4,51L,MYF_RW)))
+ if ((result= my_pwrite(file,(uchar*) version,4,51L,MYF_RW)))
goto err;
- for (entry=(TABLE*) hash_first(&open_cache,(byte*) key,key_length, &state);
+ for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
entry;
- entry= (TABLE*) hash_next(&open_cache,(byte*) key,key_length, &state))
+ entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
entry->s->mysql_version= MYSQL_VERSION_ID;
}
err:
@@ -2499,7 +2519,7 @@ int ha_enable_transaction(THD *thd, bool on)
DBUG_RETURN(error);
}
-int handler::index_next_same(byte *buf, const byte *key, uint keylen)
+int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
{
int error;
if (!(error=index_next(buf)))
@@ -2571,15 +2591,7 @@ int ha_create_table(THD *thd, const char *path,
if (update_create_info)
update_create_info_from_table(create_info, &table);
- name= share.path.str;
- if (lower_case_table_names == 2 &&
- !(table.file->ha_table_flags() & HA_FILE_BASED))
- {
- /* Ensure that handler gets name in lower case */
- strmov(name_buff, name);
- my_casedn_str(files_charset_info, name_buff);
- name= name_buff;
- }
+ name= check_lowercase_names(table.file, share.path.str, name_buff);
error= table.file->create(name, &table, create_info);
VOID(closefrm(&table, 0));
@@ -2608,8 +2620,8 @@ err:
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
{
int error;
- const void *frmblob;
- uint frmlen;
+ uchar *frmblob;
+ size_t frmlen;
char path[FN_REFLEN];
HA_CREATE_INFO create_info;
TABLE table;
@@ -2617,7 +2629,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
DBUG_ENTER("ha_create_table_from_engine");
DBUG_PRINT("enter", ("name '%s'.'%s'", db, name));
- bzero((char*) &create_info,sizeof(create_info));
+ bzero((uchar*) &create_info,sizeof(create_info));
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
{
/* Table could not be discovered and thus not created */
@@ -2629,10 +2641,11 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
frmblob and frmlen are set, write the frm to disk
*/
- (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,"/",db,"/",name,NullS);
+ (void)strxnmov(path,FN_REFLEN-1,mysql_data_home,FN_ROOTDIR,
+ db,FN_ROOTDIR,name,NullS);
// Save the frm file
error= writefrm(path, frmblob, frmlen);
- my_free((char*) frmblob, MYF(0));
+ my_free(frmblob, MYF(0));
if (error)
DBUG_RETURN(2);
@@ -2650,12 +2663,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
update_create_info_from_table(&create_info, &table);
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
- if (lower_case_table_names == 2 &&
- !(table.file->ha_table_flags() & HA_FILE_BASED))
- {
- /* Ensure that handler gets name in lower case */
- my_casedn_str(files_charset_info, path);
- }
+ check_lowercase_names(table.file, path, path);
error=table.file->create(path,&table,&create_info);
VOID(closefrm(&table, 1));
@@ -2689,8 +2697,8 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
if (!key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
- long tmp_buff_size= (long) key_cache->param_buff_size;
- long tmp_block_size= (long) key_cache->param_block_size;
+ ulong tmp_buff_size= (ulong) key_cache->param_buff_size;
+ uint tmp_block_size= (uint) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold;
pthread_mutex_unlock(&LOCK_global_system_variables);
@@ -2774,15 +2782,15 @@ struct st_discover_args
{
const char *db;
const char *name;
- const void** frmblob;
- uint* frmlen;
+ uchar **frmblob;
+ size_t *frmlen;
};
-static my_bool discover_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
st_discover_args *vargs= (st_discover_args *)arg;
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->discover &&
(!(hton->discover(hton, thd, vargs->db, vargs->name,
vargs->frmblob,
@@ -2793,7 +2801,7 @@ static my_bool discover_handlerton(THD *thd, st_plugin_int *plugin,
}
int ha_discover(THD *thd, const char *db, const char *name,
- const void **frmblob, uint *frmlen)
+ uchar **frmblob, size_t *frmlen)
{
int error= -1; // Table does not exist in any handler
DBUG_ENTER("ha_discover");
@@ -2808,7 +2816,7 @@ int ha_discover(THD *thd, const char *db, const char *name,
error= 0;
if (!error)
- statistic_increment(thd->status_var.ha_discover_count,&LOCK_status);
+ status_var_increment(thd->status_var.ha_discover_count);
DBUG_RETURN(error);
}
@@ -2824,14 +2832,14 @@ struct st_find_files_args
const char *path;
const char *wild;
bool dir;
- List<char> *files;
+ List<LEX_STRING> *files;
};
-static my_bool find_files_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool find_files_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
st_find_files_args *vargs= (st_find_files_args *)arg;
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->find_files)
@@ -2844,7 +2852,7 @@ static my_bool find_files_handlerton(THD *thd, st_plugin_int *plugin,
int
ha_find_files(THD *thd,const char *db,const char *path,
- const char *wild, bool dir, List<char> *files)
+ const char *wild, bool dir, List<LEX_STRING> *files)
{
int error= 0;
DBUG_ENTER("ha_find_files");
@@ -2858,45 +2866,50 @@ ha_find_files(THD *thd,const char *db,const char *path,
DBUG_RETURN(error);
}
-
-/** @brief
+/*
Ask handler if the table exists in engine
RETURN
- 0 Table does not exist
- 1 Table exists
- # Error code
+ HA_ERR_NO_SUCH_TABLE Table does not exist
+ HA_ERR_TABLE_EXIST Table exists
+ # Error code
+
+ */
-*/
struct st_table_exists_in_engine_args
{
const char *db;
const char *name;
+ int err;
};
-static my_bool table_exists_in_engine_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
+
+ int err= HA_ERR_NO_SUCH_TABLE;
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
- if ((hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name)) == 1)
- return TRUE;
+ err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
+
+ vargs->err = err;
+ if (vargs->err == HA_ERR_TABLE_EXIST)
+ return TRUE;
return FALSE;
}
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
{
- int error= 0;
DBUG_ENTER("ha_table_exists_in_engine");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
- st_table_exists_in_engine_args args= {db, name};
- error= plugin_foreach(thd, table_exists_in_engine_handlerton,
+ st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
+ plugin_foreach(thd, table_exists_in_engine_handlerton,
MYSQL_STORAGE_ENGINE_PLUGIN, &args);
- DBUG_PRINT("exit", ("error: %d", error));
- DBUG_RETURN(error);
+ DBUG_PRINT("exit", ("error: %d", args.err));
+ DBUG_RETURN(args.err);
}
#ifdef HAVE_NDB_BINLOG
@@ -2922,10 +2935,10 @@ struct binlog_func_st
/** @brief
Listing handlertons first to avoid recursive calls and deadlock
*/
-static my_bool binlog_func_list(THD *thd, st_plugin_int *plugin, void *arg)
+static my_bool binlog_func_list(THD *thd, plugin_ref plugin, void *arg)
{
hton_list_st *hton_list= (hton_list_st *)arg;
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->binlog_func)
{
uint sz= hton_list->sz;
@@ -3012,10 +3025,10 @@ static my_bool binlog_log_query_handlerton2(THD *thd,
}
static my_bool binlog_log_query_handlerton(THD *thd,
- st_plugin_int *plugin,
+ plugin_ref plugin,
void *args)
{
- return binlog_log_query_handlerton2(thd, (handlerton *)plugin->data, args);
+ return binlog_log_query_handlerton2(thd, plugin_data(plugin, handlerton *), args);
}
void ha_binlog_log_query(THD *thd, handlerton *hton,
@@ -3171,7 +3184,8 @@ int handler::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
read_range_first()
start_key Start key. Is 0 if no min range
end_key End key. Is 0 if no max range
- eq_range_arg Set to 1 if start_key == end_key
+ eq_range_arg Set to 1 if start_key == end_key and the range endpoints
+ will not change during query execution.
sorted Set to 1 if result should be sorted per key
NOTES
@@ -3203,10 +3217,10 @@ int handler::read_range_first(const key_range *start_key,
if (!start_key) // Read first record
result= index_first(table->record[0]);
else
- result= index_read(table->record[0],
- start_key->key,
- start_key->keypart_map,
- start_key->flag);
+ result= index_read_map(table->record[0],
+ start_key->key,
+ start_key->keypart_map,
+ start_key->flag);
if (result)
DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
? HA_ERR_END_OF_FILE
@@ -3278,15 +3292,15 @@ int handler::compare_key(key_range *range)
}
-int handler::index_read_idx(byte * buf, uint index, const byte * key,
- key_part_map keypart_map,
- enum ha_rkey_function find_flag)
+int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
int error, error1;
error= index_init(index, 0);
if (!error)
{
- error= index_read(buf, key, keypart_map, find_flag);
+ error= index_read_map(buf, key, keypart_map, find_flag);
error1= index_end();
}
return error ? error : error1;
@@ -3307,11 +3321,11 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key,
RETURN VALUE
pointer pointer to TYPELIB structure
*/
-static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin,
+static my_bool exts_handlerton(THD *unused, plugin_ref plugin,
void *arg)
{
List<char> *found_exts= (List<char> *) arg;
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
handler *file;
if (hton->state == SHOW_OPTION_YES && hton->create &&
(file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
@@ -3344,8 +3358,8 @@ TYPELIB *ha_known_exts(void)
const char **ext, *old_ext;
known_extensions_id= mysys_usage_id;
- found_exts.push_back((char*) triggers_file_ext);
- found_exts.push_back((char*) trigname_file_ext);
+ found_exts.push_back((char*) TRG_EXT);
+ found_exts.push_back((char*) TRN_EXT);
plugin_foreach(NULL, exts_handlerton,
MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
@@ -3382,11 +3396,11 @@ static bool stat_print(THD *thd, const char *type, uint type_len,
}
-static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin,
+static my_bool showstat_handlerton(THD *thd, plugin_ref plugin,
void *arg)
{
enum ha_stat_type stat= *(enum ha_stat_type *) arg;
- handlerton *hton= (handlerton *)plugin->data;
+ handlerton *hton= plugin_data(plugin, handlerton *);
if (hton->state == SHOW_OPTION_YES && hton->show_status &&
hton->show_status(hton, thd, stat_print, stat))
return TRUE;
@@ -3452,8 +3466,7 @@ namespace {
if (table->s->cached_row_logging_check == -1)
{
int const check(table->s->tmp_table == NO_TMP_TABLE &&
- binlog_filter->db_ok(table->s->db.str) &&
- !table->no_replicate);
+ binlog_filter->db_ok(table->s->db.str));
table->s->cached_row_logging_check= check;
}
@@ -3461,9 +3474,9 @@ namespace {
table->s->cached_row_logging_check == 1);
return (thd->current_stmt_binlog_row_based &&
+ table->s->cached_row_logging_check &&
(thd->options & OPTION_BIN_LOG) &&
- mysql_bin_log.is_open() &&
- table->s->cached_row_logging_check);
+ mysql_bin_log.is_open());
}
}
@@ -3538,10 +3551,10 @@ namespace
template<class RowsEventT> int
binlog_log_row(TABLE* table,
- const byte *before_record,
- const byte *after_record)
+ const uchar *before_record,
+ const uchar *after_record)
{
- if (table->file->ha_table_flags() & HA_HAS_OWN_BINLOGGING)
+ if (table->no_replicate)
return 0;
bool error= 0;
THD *const thd= table->in_use;
@@ -3588,13 +3601,13 @@ namespace
*/
template int
- binlog_log_row<Write_rows_log_event>(TABLE *, const byte *, const byte *);
+ binlog_log_row<Write_rows_log_event>(TABLE *, const uchar *, const uchar *);
template int
- binlog_log_row<Delete_rows_log_event>(TABLE *, const byte *, const byte *);
+ binlog_log_row<Delete_rows_log_event>(TABLE *, const uchar *, const uchar *);
template int
- binlog_log_row<Update_rows_log_event>(TABLE *, const byte *, const byte *);
+ binlog_log_row<Update_rows_log_event>(TABLE *, const uchar *, const uchar *);
}
@@ -3607,7 +3620,15 @@ int handler::ha_external_lock(THD *thd, int lock_type)
taken a table lock), ha_release_auto_increment() was too.
*/
DBUG_ASSERT(next_insert_id == 0);
- DBUG_RETURN(external_lock(thd, lock_type));
+
+ /*
+ We cache the table flags if the locking succeeded. Otherwise, we
+ keep them as they were when they were fetched in ha_open().
+ */
+ int error= external_lock(thd, lock_type);
+ if (error == 0)
+ cached_table_flags= table_flags();
+ DBUG_RETURN(error);
}
@@ -3618,9 +3639,9 @@ int handler::ha_reset()
{
DBUG_ENTER("ha_reset");
/* Check that we have called all proper deallocation functions */
- DBUG_ASSERT((byte*) table->def_read_set.bitmap +
+ DBUG_ASSERT((uchar*) table->def_read_set.bitmap +
table->s->column_bitmap_size ==
- (byte*) table->def_write_set.bitmap);
+ (uchar*) table->def_write_set.bitmap);
DBUG_ASSERT(bitmap_is_set_all(&table->s->all_set));
DBUG_ASSERT(table->key_read == 0);
/* ensure that ha_index_end / ha_rnd_end has been called */
@@ -3631,7 +3652,7 @@ int handler::ha_reset()
}
-int handler::ha_write_row(byte *buf)
+int handler::ha_write_row(uchar *buf)
{
int error;
if (unlikely(error= write_row(buf)))
@@ -3641,7 +3662,8 @@ int handler::ha_write_row(byte *buf)
return 0;
}
-int handler::ha_update_row(const byte *old_data, byte *new_data)
+
+int handler::ha_update_row(const uchar *old_data, uchar *new_data)
{
int error;
@@ -3658,7 +3680,7 @@ int handler::ha_update_row(const byte *old_data, byte *new_data)
return 0;
}
-int handler::ha_delete_row(const byte *buf)
+int handler::ha_delete_row(const uchar *buf)
{
int error;
if (unlikely(error= delete_row(buf)))
@@ -3781,7 +3803,7 @@ int fl_log_iterator_next(struct handler_iterator *iterator,
void fl_log_iterator_destroy(struct handler_iterator *iterator)
{
- my_free((gptr)iterator->buffer, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((uchar*)iterator->buffer, MYF(MY_ALLOW_ZERO_PTR));
}
@@ -3794,7 +3816,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator)
MY_DIR *dirp;
struct fl_buff *buff;
char *name_ptr;
- byte *ptr;
+ uchar *ptr;
FILEINFO *file;
uint32 i;
@@ -3805,7 +3827,7 @@ fl_log_iterator_buffer_init(struct handler_iterator *iterator)
{
return HA_ITERATOR_ERROR;
}
- if ((ptr= (byte*)my_malloc(ALIGN_SIZE(sizeof(fl_buff)) +
+ if ((ptr= (uchar*)my_malloc(ALIGN_SIZE(sizeof(fl_buff)) +
((ALIGN_SIZE(sizeof(LEX_STRING)) +
sizeof(enum log_status) +
+ FN_REFLEN) *