diff options
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 316 |
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(); +} |