summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc316
1 files changed, 138 insertions, 178 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index b9ef05a33c2..927a8eb8ed5 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -44,18 +44,19 @@
#include "ha_innodb.h"
#endif
-/* While we have legacy_db_type, we have this array to
- check for dups and to find handlerton from legacy_db_type.
- Remove when legacy_db_type is finally gone */
-static handlerton *installed_htons[128];
+/*
+ While we have legacy_db_type, we have this array to
+ check for dups and to find handlerton from legacy_db_type.
+ Remove when legacy_db_type is finally gone
+*/
-#define BITMAP_STACKBUF_SIZE (128/8)
+static handlerton *installed_htons[128];
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0} };
/* static functions defined in this file */
-static handler *create_default(TABLE_SHARE *table);
+static handler *create_default(TABLE_SHARE *table, MEM_ROOT *mem_root);
const handlerton default_hton =
{
@@ -146,8 +147,7 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name)
const char *ha_get_storage_engine(enum legacy_db_type db_type)
{
- switch (db_type)
- {
+ switch (db_type) {
case DB_TYPE_DEFAULT:
return "DEFAULT";
case DB_TYPE_UNKNOWN:
@@ -161,18 +161,17 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type)
}
-static handler *create_default(TABLE_SHARE *table)
+static handler *create_default(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
- handlerton *hton=ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT);
+ handlerton *hton= ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT);
return (hton && hton != &default_hton && hton->create) ?
- hton->create(table) : NULL;
+ hton->create(table, mem_root) : NULL;
}
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
{
- switch (db_type)
- {
+ switch (db_type) {
case DB_TYPE_DEFAULT:
return (thd->variables.table_type != NULL) ?
thd->variables.table_type :
@@ -225,36 +224,23 @@ handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
handlerton *db_type)
{
- handler *file= NULL;
- /*
- handlers are allocated with new in the handlerton create() function
- we need to set the thd mem_root for these to be allocated correctly
- */
- THD *thd= current_thd;
- MEM_ROOT *thd_save_mem_root= thd->mem_root;
- thd->mem_root= alloc;
-
- if (db_type != NULL && db_type->state == SHOW_OPTION_YES && db_type->create)
- file= db_type->create(share);
-
- thd->mem_root= thd_save_mem_root;
+ handler *file;
+ DBUG_ENTER("get_new_handler");
+ DBUG_PRINT("enter", ("alloc: 0x%lx", (long) alloc));
- if (!file)
+ if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
{
- handlerton *def= current_thd->variables.table_type;
- /* Try first with 'default table type' */
- if (db_type != def)
- return get_new_handler(share, alloc, def);
+ if ((file= db_type->create(share, alloc)))
+ file->init();
+ DBUG_RETURN(file);
}
- if (file)
- {
- if (file->ha_initialise())
- {
- delete file;
- file=0;
- }
- }
- return file;
+ /*
+ Try the default table type
+ 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));
}
@@ -265,11 +251,13 @@ handler *get_ha_partition(partition_info *part_info)
DBUG_ENTER("get_ha_partition");
if ((partition= new ha_partition(part_info)))
{
- if (partition->ha_initialise())
+ if (partition->initialise_partition(current_thd->mem_root))
{
delete partition;
partition= 0;
}
+ else
+ partition->init();
}
else
{
@@ -1379,7 +1367,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
! (file=get_new_handler(&dummy_share, thd->mem_root, table_type)))
DBUG_RETURN(ENOENT);
- if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
+ 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);
@@ -1462,6 +1450,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
table= table_arg;
DBUG_ASSERT(table->s == table_share);
+ DBUG_ASSERT(alloc_root_inited(&table->mem_root));
if ((error=open(name,mode,test_if_locked)))
{
@@ -1483,106 +1472,23 @@ 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
- DBUG_ASSERT(alloc_root_inited(&table->mem_root));
-
if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2)))
{
close();
error=HA_ERR_OUT_OF_MEM;
}
else
- dupp_ref=ref+ALIGN_SIZE(ref_length);
-
- if (ha_allocate_read_write_set(table->s->fields))
- error= 1;
+ dup_ref=ref+ALIGN_SIZE(ref_length);
+ cached_table_flags= table_flags();
}
DBUG_RETURN(error);
}
-int handler::ha_initialise()
-{
- DBUG_ENTER("ha_initialise");
- DBUG_RETURN(FALSE);
-}
-
-
-/*
- Initalize bit maps for used fields
-
- Called from open_table_from_share()
-*/
-
-int handler::ha_allocate_read_write_set(ulong no_fields)
-{
- uint bitmap_size= bitmap_buffer_size(no_fields+1);
- uint32 *read_buf, *write_buf;
- DBUG_ENTER("ha_allocate_read_write_set");
- DBUG_PRINT("enter", ("no_fields = %d", no_fields));
-
- if (!multi_alloc_root(&table->mem_root,
- &read_set, sizeof(MY_BITMAP),
- &write_set, sizeof(MY_BITMAP),
- &read_buf, bitmap_size,
- &write_buf, bitmap_size,
- NullS))
- {
- DBUG_RETURN(TRUE);
- }
- bitmap_init(read_set, read_buf, no_fields+1, FALSE);
- bitmap_init(write_set, write_buf, no_fields+1, FALSE);
- table->read_set= read_set;
- table->write_set= write_set;
- ha_clear_all_set();
- DBUG_RETURN(FALSE);
-}
-
-void handler::ha_clear_all_set()
-{
- DBUG_ENTER("ha_clear_all_set");
- bitmap_clear_all(read_set);
- bitmap_clear_all(write_set);
- bitmap_set_bit(read_set, 0);
- bitmap_set_bit(write_set, 0);
- DBUG_VOID_RETURN;
-}
-
-int handler::ha_retrieve_all_cols()
-{
- DBUG_ENTER("handler::ha_retrieve_all_cols");
- bitmap_set_all(read_set);
- DBUG_RETURN(0);
-}
-
-int handler::ha_retrieve_all_pk()
-{
- DBUG_ENTER("ha_retrieve_all_pk");
- ha_set_primary_key_in_read_set();
- DBUG_RETURN(0);
-}
-
-void handler::ha_set_primary_key_in_read_set()
-{
- ulong prim_key= table->s->primary_key;
- DBUG_ENTER("handler::ha_set_primary_key_in_read_set");
- DBUG_PRINT("info", ("Primary key = %d", prim_key));
- if (prim_key != MAX_KEY)
- {
- KEY_PART_INFO *key_part= table->key_info[prim_key].key_part;
- KEY_PART_INFO *key_part_end= key_part +
- table->key_info[prim_key].key_parts;
- for (;key_part != key_part_end; ++key_part)
- ha_set_bit_in_read_set(key_part->fieldnr);
- }
- DBUG_VOID_RETURN;
-}
-
-
-
/*
Read first row (only) from a table
This is never called for InnoDB or BDB tables, as these table types
- has the HA_NOT_EXACT_COUNT set.
+ has the HA_STATS_RECORDS_IS_EXACT set.
*/
int handler::read_first_row(byte * buf, uint primary_key)
@@ -1598,7 +1504,7 @@ int handler::read_first_row(byte * buf, uint primary_key)
scanning the table.
TODO remove the test for HA_READ_ORDER
*/
- if (deleted < 10 || primary_key >= MAX_KEY ||
+ if (stats.deleted < 10 || primary_key >= MAX_KEY ||
!(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
{
(void) ha_rnd_init(1);
@@ -1786,12 +1692,38 @@ void handler::restore_auto_increment()
}
+/*
+ MySQL signal that it changed the column bitmap
+
+ USAGE
+ This is for handlers that needs to setup their own column bitmaps.
+ Normally the handler should set up their own column bitmaps in
+ index_init() or rnd_init() and in any column_bitmaps_signal() call after
+ this.
+
+ The handler is allowd to do changes to the bitmap after a index_init or
+ rnd_init() call is made as after this, MySQL will not use the bitmap
+ for any program logic checking.
+*/
+
+void handler::column_bitmaps_signal()
+{
+ DBUG_ENTER("column_bitmaps_signal");
+ DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx", table->read_set,
+ table->write_set));
+ DBUG_VOID_RETURN;
+}
+
+
ulonglong handler::get_auto_increment()
{
ulonglong nr;
int error;
(void) extra(HA_EXTRA_KEYREAD);
+ table->mark_columns_used_by_index_no_reset(table->s->next_number_index,
+ table->read_set);
+ column_bitmaps_signal();
index_init(table->s->next_number_index, 1);
if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
@@ -1857,18 +1789,20 @@ void handler::print_error(int error, myf errflag)
uint key_nr=get_dup_key(error);
if ((int) key_nr >= 0)
{
+ uint max_length;
/* Write the duplicated key in the error message */
char key[MAX_KEY_LENGTH];
String str(key,sizeof(key),system_charset_info);
/* Table is opened and defined at this point */
key_unpack(&str,table,(uint) key_nr);
- uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
+ max_length= MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
if (str.length() >= max_length)
{
str.length(max_length-4);
str.append(STRING_WITH_LEN("..."));
}
- my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), table->key_info[key_nr].name);
+ my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(),
+ table->key_info[key_nr].name);
DBUG_VOID_RETURN;
}
textno=ER_DUP_KEY;
@@ -1879,12 +1813,14 @@ void handler::print_error(int error, myf errflag)
uint key_nr= get_dup_key(error);
if ((int) key_nr >= 0)
{
+ uint max_length;
/* Write the key in the error message */
char key[MAX_KEY_LENGTH];
String str(key,sizeof(key),system_charset_info);
/* Table is opened and defined at this point */
key_unpack(&str,table,(uint) key_nr);
- uint max_length= MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY));
+ max_length= (MYSQL_ERRMSG_SIZE-
+ (uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
if (str.length() >= max_length)
{
str.length(max_length-4);
@@ -2293,22 +2229,23 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen)
}
-void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info, uint part_id)
+void handler::get_dynamic_partition_info(PARTITION_INFO *stat_info,
+ uint part_id)
{
info(HA_STATUS_CONST | HA_STATUS_TIME | HA_STATUS_VARIABLE |
HA_STATUS_NO_LOCK);
- stat_info->records= records;
- stat_info->mean_rec_length= mean_rec_length;
- stat_info->data_file_length= data_file_length;
- stat_info->max_data_file_length= max_data_file_length;
- stat_info->index_file_length= index_file_length;
- stat_info->delete_length= delete_length;
- stat_info->create_time= create_time;
- stat_info->update_time= update_time;
- stat_info->check_time= check_time;
- stat_info->check_sum= 0;
+ stat_info->records= stats.records;
+ stat_info->mean_rec_length= stats.mean_rec_length;
+ stat_info->data_file_length= stats.data_file_length;
+ stat_info->max_data_file_length= stats.max_data_file_length;
+ stat_info->index_file_length= stats.index_file_length;
+ stat_info->delete_length= stats.delete_length;
+ stat_info->create_time= stats.create_time;
+ stat_info->update_time= stats.update_time;
+ stat_info->check_time= stats.check_time;
+ stat_info->check_sum= 0;
if (table_flags() & (ulong) HA_HAS_CHECKSUM)
- stat_info->check_sum= checksum();
+ stat_info->check_sum= checksum();
return;
}
@@ -2352,7 +2289,7 @@ int ha_create_table(THD *thd, const char *path,
name= share.path.str;
if (lower_case_table_names == 2 &&
- !(table.file->table_flags() & HA_FILE_BASED))
+ !(table.file->ha_table_flags() & HA_FILE_BASED))
{
/* Ensure that handler gets name in lower case */
strmov(name_buff, name);
@@ -2431,7 +2368,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
if (lower_case_table_names == 2 &&
- !(table.file->table_flags() & HA_FILE_BASED))
+ !(table.file->ha_table_flags() & HA_FILE_BASED))
{
/* Ensure that handler gets name in lower case */
my_casedn_str(files_charset_info, path);
@@ -2781,6 +2718,9 @@ int handler::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
multi_range_sorted= sorted;
multi_range_buffer= buffer;
+ table->mark_columns_used_by_index_no_reset(active_index, table->read_set);
+ table->column_bitmaps_set(table->read_set, table->write_set);
+
for (multi_range_curr= ranges, multi_range_end= ranges + range_count;
multi_range_curr < multi_range_end;
multi_range_curr++)
@@ -3023,7 +2963,7 @@ static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin,
handlerton *hton= (handlerton *) plugin->plugin->info;
handler *file;
if (hton->state == SHOW_OPTION_YES && hton->create &&
- (file= hton->create((TABLE_SHARE*) 0)))
+ (file= hton->create((TABLE_SHARE*) 0, current_thd->mem_root)))
{
List_iterator_fast<char> it(*found_exts);
const char **ext, *old_ext;
@@ -3160,7 +3100,7 @@ namespace {
char const *name;
};
- int table_name_compare(void const *a, void const *b)
+ static int table_name_compare(void const *a, void const *b)
{
st_table_data const *x = (st_table_data const*) a;
st_table_data const *y = (st_table_data const*) b;
@@ -3170,7 +3110,7 @@ namespace {
return res != 0 ? res : strcmp(x->name, y->name);
}
- bool check_table_binlog_row_based(THD *thd, TABLE *table)
+ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
{
static st_table_data const ignore[] = {
{ "mysql", "event" },
@@ -3191,44 +3131,29 @@ namespace {
DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
table->s->cached_row_logging_check == 1);
- return
- thd->current_stmt_binlog_row_based &&
- thd && (thd->options & OPTION_BIN_LOG) &&
- mysql_bin_log.is_open() &&
- table->s->cached_row_logging_check;
+ return (thd->current_stmt_binlog_row_based &&
+ (thd->options & OPTION_BIN_LOG) &&
+ mysql_bin_log.is_open() &&
+ table->s->cached_row_logging_check);
}
}
-template<class RowsEventT> int binlog_log_row(TABLE* table,
+template<class RowsEventT> int binlog_log_row(TABLE *table,
const byte *before_record,
const byte *after_record)
{
if (table->file->is_injective())
return 0;
bool error= 0;
- THD *const thd= current_thd;
-
- if (check_table_binlog_row_based(thd, table))
- {
- MY_BITMAP cols;
- /* Potential buffer on the stack for the bitmap */
- uint32 bitbuf[BITMAP_STACKBUF_SIZE/sizeof(uint32)];
- uint n_fields= table->s->fields;
- my_bool use_bitbuf= n_fields <= sizeof(bitbuf)*8;
- if (likely(!(error= bitmap_init(&cols,
- use_bitbuf ? bitbuf : NULL,
- (n_fields + 7) & ~7UL,
- false))))
- {
- bitmap_set_all(&cols);
- error=
- RowsEventT::binlog_row_logging_function(thd, table,
- table->file->has_transactions(),
- &cols, table->s->fields,
- before_record, after_record);
- if (!use_bitbuf)
- bitmap_free(&cols);
- }
+
+ if (check_table_binlog_row_based(table->in_use, table))
+ {
+ error=
+ RowsEventT::binlog_row_logging_function(table->in_use, table,
+ table->file->has_transactions(),
+ &table->s->all_set,
+ table->s->fields,
+ before_record, after_record);
}
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
}
@@ -3289,6 +3214,28 @@ int handler::ha_external_lock(THD *thd, int lock_type)
DBUG_RETURN(0);
}
+
+/*
+ Check handler usage and reset state of file to after 'open'
+*/
+
+int handler::ha_reset()
+{
+ DBUG_ENTER("ha_reset");
+ /* Check that we have called all proper delallocation functions */
+ DBUG_ASSERT((byte*) table->def_read_set.bitmap +
+ table->s->column_bitmap_size ==
+ (char*) 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 */
+ DBUG_ASSERT(inited == NONE);
+ /* Free cache used by filesort */
+ free_io_cache(table);
+ DBUG_RETURN(reset());
+}
+
+
int handler::ha_write_row(byte *buf)
{
int error;
@@ -3331,3 +3278,16 @@ int handler::ha_delete_row(const byte *buf)
#endif
return 0;
}
+
+
+/*
+ use_hidden_primary_key() is called in case of an update/delete when
+ (table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
+ but we don't have a primary key
+*/
+
+void handler::use_hidden_primary_key()
+{
+ /* fallback to use all columns in the table to identify row */
+ table->use_all_columns();
+}