diff options
-rw-r--r-- | include/my_base.h | 1 | ||||
-rw-r--r-- | mysql-test/r/status_user.result | 6 | ||||
-rw-r--r-- | sql/ha_partition.cc | 47 | ||||
-rw-r--r-- | sql/ha_partition.h | 7 | ||||
-rw-r--r-- | sql/handler.cc | 53 | ||||
-rw-r--r-- | sql/handler.h | 128 | ||||
-rw-r--r-- | sql/key.cc | 3 | ||||
-rw-r--r-- | sql/opt_range.cc | 54 | ||||
-rw-r--r-- | sql/sp.cc | 16 | ||||
-rw-r--r-- | sql/sql_class.h | 146 | ||||
-rw-r--r-- | sql/sql_select.cc | 7 | ||||
-rw-r--r-- | sql/sql_table.cc | 21 | ||||
-rw-r--r-- | sql/table.cc | 9 | ||||
-rw-r--r-- | sql/tztime.cc | 15 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.cc | 70 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.h | 1 |
16 files changed, 266 insertions, 318 deletions
diff --git a/include/my_base.h b/include/my_base.h index 06a62766ca8..2aa49bd1787 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -300,6 +300,7 @@ enum ha_base_keytype { */ #define HA_END_SPACE_ARE_EQUAL 512 #define HA_BIT_PART 1024 +#define HA_CAN_MEMCMP 2048 /* internal, never stored in frm */ /* optionbits for database */ #define HA_OPTION_PACK_RECORD 1 diff --git a/mysql-test/r/status_user.result b/mysql-test/r/status_user.result index 9fb631e209e..a39f0819c58 100644 --- a/mysql-test/r/status_user.result +++ b/mysql-test/r/status_user.result @@ -100,8 +100,8 @@ Handler_commit 19 Handler_delete 1 Handler_discover 0 Handler_prepare 18 -Handler_read_first 1 -Handler_read_key 8 +Handler_read_first 0 +Handler_read_key 3 Handler_read_next 0 Handler_read_prev 0 Handler_read_rnd 0 @@ -113,7 +113,7 @@ Handler_update 5 Handler_write 7 select variable_value - @global_read_key as "handler_read_key" from information_schema.global_status where variable_name="handler_read_key"; handler_read_key -8 +3 set @@global.userstat=0; select * from information_schema.index_statistics; TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 8d890caea84..1b430275d59 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3636,6 +3636,7 @@ int ha_partition::rnd_next(uchar *buf) int result= HA_ERR_END_OF_FILE; uint part_id= m_part_spec.start_part; DBUG_ENTER("ha_partition::rnd_next"); + decrement_statistics(&SSV::ha_read_rnd_next_count); if (NO_CURRENT_PART_ID == part_id) { @@ -3779,6 +3780,7 @@ int ha_partition::rnd_pos(uchar * buf, uchar *pos) uint part_id; handler *file; DBUG_ENTER("ha_partition::rnd_pos"); + decrement_statistics(&SSV::ha_read_rnd_count); part_id= uint2korr((const uchar *) pos); DBUG_ASSERT(part_id < m_tot_parts); @@ -3991,6 +3993,7 @@ int ha_partition::index_read_map(uchar *buf, const uchar *key, enum ha_rkey_function find_flag) { DBUG_ENTER("ha_partition::index_read_map"); + decrement_statistics(&SSV::ha_read_key_count); end_range= 0; m_index_scan_type= partition_index_read; m_start_key.key= key; @@ -4119,6 +4122,7 @@ int ha_partition::common_index_read(uchar *buf, bool have_start_key) int ha_partition::index_first(uchar * buf) { DBUG_ENTER("ha_partition::index_first"); + decrement_statistics(&SSV::ha_read_first_count); end_range= 0; m_index_scan_type= partition_index_first; @@ -4150,6 +4154,7 @@ int ha_partition::index_first(uchar * buf) int ha_partition::index_last(uchar * buf) { DBUG_ENTER("ha_partition::index_last"); + decrement_statistics(&SSV::ha_read_last_count); m_index_scan_type= partition_index_last; DBUG_RETURN(common_first_last(buf)); @@ -4178,39 +4183,6 @@ int ha_partition::common_first_last(uchar *buf) /* - Read last using key - - SYNOPSIS - index_read_last_map() - buf Read row in MySQL Row Format - key Key - keypart_map Which part of key is used - - RETURN VALUE - >0 Error code - 0 Success - - DESCRIPTION - This is used in join_read_last_key to optimise away an ORDER BY. - Can only be used on indexes supporting HA_READ_ORDER -*/ - -int ha_partition::index_read_last_map(uchar *buf, const uchar *key, - key_part_map keypart_map) -{ - DBUG_ENTER("ha_partition::index_read_last"); - - m_ordered= TRUE; // Safety measure - end_range= 0; - m_index_scan_type= partition_index_read_last; - m_start_key.key= key; - m_start_key.keypart_map= keypart_map; - m_start_key.flag= HA_READ_PREFIX_LAST; - DBUG_RETURN(common_index_read(buf, TRUE)); -} - - -/* Read next record in a forward index scan SYNOPSIS @@ -4228,6 +4200,7 @@ int ha_partition::index_read_last_map(uchar *buf, const uchar *key, int ha_partition::index_next(uchar * buf) { DBUG_ENTER("ha_partition::index_next"); + decrement_statistics(&SSV::ha_read_next_count); /* TODO(low priority): @@ -4264,6 +4237,7 @@ int ha_partition::index_next(uchar * buf) int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen) { DBUG_ENTER("ha_partition::index_next_same"); + decrement_statistics(&SSV::ha_read_next_count); DBUG_ASSERT(keylen == m_start_key.length); DBUG_ASSERT(m_index_scan_type != partition_index_last); @@ -4291,6 +4265,7 @@ int ha_partition::index_next_same(uchar *buf, const uchar *key, uint keylen) int ha_partition::index_prev(uchar * buf) { DBUG_ENTER("ha_partition::index_prev"); + decrement_statistics(&SSV::ha_read_prev_count); /* TODO: read comment in index_next */ DBUG_ASSERT(m_index_scan_type != partition_index_first); @@ -4704,12 +4679,6 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) error= file->ha_index_last(rec_buf_ptr); reverse_order= TRUE; break; - case partition_index_read_last: - error= file->ha_index_read_last_map(rec_buf_ptr, - m_start_key.key, - m_start_key.keypart_map); - reverse_order= TRUE; - break; case partition_read_range: { /* diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 15744b36edb..7fc33b46b16 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -64,9 +64,8 @@ private: partition_index_first= 1, partition_index_first_unordered= 2, partition_index_last= 3, - partition_index_read_last= 4, - partition_read_range = 5, - partition_no_index_scan= 6 + partition_read_range = 4, + partition_no_index_scan= 5 }; /* Data for the partition handler */ int m_mode; // Open mode @@ -458,8 +457,6 @@ public: virtual int index_first(uchar * buf); virtual int index_last(uchar * buf); virtual int index_next_same(uchar * buf, const uchar * key, uint keylen); - virtual int index_read_last_map(uchar * buf, const uchar * key, - key_part_map keypart_map); /* read_first_row is virtual method but is only implemented by diff --git a/sql/handler.cc b/sql/handler.cc index 9c3f35e8647..56b2ccde493 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2044,12 +2044,6 @@ handler *handler::clone(MEM_ROOT *mem_root) } - -void handler::ha_statistic_increment(ulong SSV::*offset) const -{ - status_var_increment(table->in_use->status_var.*offset); -} - void **handler::ha_data(THD *thd) const { return thd_ha_data(thd, ht); @@ -2131,8 +2125,6 @@ int handler::read_first_row(uchar * buf, uint primary_key) register int error; DBUG_ENTER("handler::read_first_row"); - ha_statistic_increment(&SSV::ha_read_first_count); - /* If there is very few deleted rows in the table, find the first row by scanning the table. @@ -2142,14 +2134,14 @@ int handler::read_first_row(uchar * buf, uint primary_key) !(index_flags(primary_key, 0, 0) & HA_READ_ORDER)) { (void) ha_rnd_init(1); - while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ; + while ((error= ha_rnd_next(buf)) == HA_ERR_RECORD_DELETED) ; (void) ha_rnd_end(); } else { /* Find the first row through the primary key */ if (!(error = ha_index_init(primary_key, 0))) - error= index_first(buf); + error= ha_index_first(buf); (void) ha_index_end(); } DBUG_RETURN(error); @@ -2520,10 +2512,10 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment, 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); + ha_index_init(table->s->next_number_index, 1); if (table->s->next_number_keypart == 0) { // Autoincrement at key-start - error=index_last(table->record[1]); + error=ha_index_last(table->record[1]); /* MySQL implicitely assumes such method does locking (as MySQL decides to use nr+increment without checking again with the handler, in @@ -2555,7 +2547,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment, else nr= ((ulonglong) table->next_number_field-> val_int_offset(table->s->rec_buff_length)+1); - index_end(); + ha_index_end(); (void) extra(HA_EXTRA_NO_KEYREAD); *first_value= nr; } @@ -3110,6 +3102,33 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) return update_frm_version(table); } +/* + Calculate cost of 'index only' scan for given index and number of records. + + SYNOPSIS + handler->keyread_read_time() + index key to read + ranges number of ranges + rows #of records to read + + NOTES + It is assumed that we will read trough all key ranges and that all + key blocks are half full (normally things are much better). It is also + assumed that each time we read the next key from the index, the handler + performs a random seek, thus the cost is proportional to the number of + blocks read. +*/ + +double handler::keyread_read_time(uint index, uint ranges, ha_rows rows) +{ + double read_time; + uint keys_per_block= (stats.block_size/2/ + (table->key_info[index].key_length + ref_length) + 1); + read_time=((double) (rows+keys_per_block-1)/ (double) keys_per_block); + return read_time; +} + + /** A helper function to mark a transaction read-write, if it is started. @@ -3503,7 +3522,7 @@ int ha_enable_transaction(THD *thd, bool on) int handler::index_next_same(uchar *buf, const uchar *key, uint keylen) { int error; - DBUG_ENTER("index_next_same"); + DBUG_ENTER("handler::index_next_same"); if (!(error=index_next(buf))) { my_ptrdiff_t ptrdiff= buf - table->record[0]; @@ -3548,6 +3567,7 @@ int handler::index_next_same(uchar *buf, const uchar *key, uint keylen) key_part->field->move_field_offset(-ptrdiff); } } + DBUG_PRINT("return",("%i", error)); DBUG_RETURN(error); } @@ -4598,6 +4618,8 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) if (!result) my_eof(thd); + else if (!thd->is_error()) + my_error(ER_GET_ERRNO, MYF(0), 0); return result; } @@ -4798,6 +4820,7 @@ int handler::ha_write_row(uchar *buf) DBUG_ENTER("handler::ha_write_row"); mark_trx_read_write(); + increment_statistics(&SSV::ha_write_count); if (unlikely(error= write_row(buf))) DBUG_RETURN(error); @@ -4820,6 +4843,7 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data) DBUG_ASSERT(new_data == table->record[0]); mark_trx_read_write(); + increment_statistics(&SSV::ha_update_count); if (unlikely(error= update_row(old_data, new_data))) return error; @@ -4835,6 +4859,7 @@ int handler::ha_delete_row(const uchar *buf) Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function; mark_trx_read_write(); + increment_statistics(&SSV::ha_delete_count); if (unlikely(error= delete_row(buf))) return error; diff --git a/sql/handler.h b/sql/handler.h index c17e06f31b6..5f94e9adbb0 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -843,7 +843,6 @@ inline LEX_STRING *hton_name(const handlerton *hton) #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter #define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate #define HTON_HIDDEN (1 << 3) //Engine does not appear in lists -#define HTON_FLUSH_AFTER_RENAME (1 << 4) #define HTON_NOT_USER_SELECTABLE (1 << 5) #define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported #define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables @@ -1439,6 +1438,7 @@ public: { return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; } virtual double read_time(uint index, uint ranges, ha_rows rows) { return rows2double(ranges+rows); } + virtual double keyread_read_time(uint index, uint ranges, ha_rows rows); virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; } bool has_transactions() { return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; } @@ -1572,17 +1572,6 @@ protected: virtual int index_last(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_next_same(uchar *buf, const uchar *key, uint keylen); - /** - @brief - The following functions works like index_read, but it find the last - row with the current key value or prefix. - */ - virtual int index_read_last_map(uchar * buf, const uchar * key, - key_part_map keypart_map) - { - uint key_len= calculate_key_len(table, active_index, key, keypart_map); - return index_read_last(buf, key, key_len); - } inline void update_index_statistics() { index_rows_read[active_index]++; @@ -1593,68 +1582,15 @@ public: /* Similar functions like the above, but does statistics counting */ inline int ha_index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map, - enum ha_rkey_function find_flag) - { - int error= index_read_map(buf, key, keypart_map, find_flag); - if (!error) - update_index_statistics(); - return error; - } + enum ha_rkey_function find_flag); inline int ha_index_read_idx_map(uchar * buf, uint index, const uchar * key, key_part_map keypart_map, - enum ha_rkey_function find_flag) - { - int error= index_read_idx_map(buf, index, key, keypart_map, find_flag); - if (!error) - { - rows_read++; - index_rows_read[index]++; - } - return error; - } - inline int ha_index_next(uchar * buf) - { - int error= index_next(buf); - if (!error) - update_index_statistics(); - return error; - } - inline int ha_index_prev(uchar * buf) - { - int error= index_prev(buf); - if (!error) - update_index_statistics(); - return error; - } - inline int ha_index_first(uchar * buf) - { - int error= index_first(buf); - if (!error) - update_index_statistics(); - return error; - } - inline int ha_index_last(uchar * buf) - { - int error= index_last(buf); - if (!error) - update_index_statistics(); - return error; - } - inline int ha_index_next_same(uchar *buf, const uchar *key, uint keylen) - { - int error= index_next_same(buf, key, keylen); - if (!error) - update_index_statistics(); - return error; - } - inline int ha_index_read_last_map(uchar * buf, const uchar * key, - key_part_map keypart_map) - { - int error= index_read_last_map(buf, key, keypart_map); - if (!error) - update_index_statistics(); - return error; - } + enum ha_rkey_function find_flag); + inline int ha_index_next(uchar * buf); + inline int ha_index_prev(uchar * buf); + inline int ha_index_first(uchar * buf); + inline int ha_index_last(uchar * buf); + inline int ha_index_next_same(uchar *buf, const uchar *key, uint keylen); virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p, KEY_MULTI_RANGE *ranges, uint range_count, @@ -1688,41 +1624,11 @@ private: public: /* Same as above, but with statistics */ - inline int ha_ft_read(uchar *buf) - { - int error= ft_read(buf); - if (!error) - rows_read++; - return error; - } - inline int ha_rnd_next(uchar *buf) - { - int error= rnd_next(buf); - if (!error) - rows_read++; - return error; - } - inline int ha_rnd_pos(uchar *buf, uchar *pos) - { - int error= rnd_pos(buf, pos); - if (!error) - rows_read++; - return error; - } - inline int ha_rnd_pos_by_record(uchar *buf) - { - int error= rnd_pos_by_record(buf); - if (!error) - rows_read++; - return error; - } - inline int ha_read_first_row(uchar *buf, uint primary_key) - { - int error= read_first_row(buf, primary_key); - if (!error) - rows_read++; - return error; - } + inline int ha_ft_read(uchar *buf); + inline int ha_rnd_next(uchar *buf); + inline int ha_rnd_pos(uchar *buf, uchar *pos); + inline int ha_rnd_pos_by_record(uchar *buf); + inline int ha_read_first_row(uchar *buf, uint primary_key); /** The following 3 function is only needed for tables that may be @@ -2041,8 +1947,10 @@ public: virtual bool check_if_supported_virtual_columns(void) { return FALSE;} protected: + /* deprecated, don't use in new engines */ + inline void ha_statistic_increment(ulong SSV::*offset) const { } + /* Service methods for use by storage engines. */ - void ha_statistic_increment(ulong SSV::*offset) const; void **ha_data(THD *) const; THD *ha_thd(void) const; @@ -2068,6 +1976,8 @@ private: if (!mark_trx_done) mark_trx_read_write_part2(); } + inline void increment_statistics(ulong SSV::*offset) const; + inline void decrement_statistics(ulong SSV::*offset) const; /* Low-level primitives for storage engines. These should be @@ -2155,8 +2065,6 @@ private: virtual int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag) { return HA_ERR_WRONG_COMMAND; } - virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) - { return (my_errno= HA_ERR_WRONG_COMMAND); } /** This method is similar to update_row, however the handler doesn't need to execute the updates at this point in time. The handler can be certain diff --git a/sql/key.cc b/sql/key.cc index 5b2ae8029dd..89423e5280e 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -278,8 +278,7 @@ bool key_cmp_if_same(TABLE *table,const uchar *key,uint idx,uint key_length) key++; store_length--; } - if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART | - HA_BIT_PART)) + if (!(key_part->key_part_flag & HA_CAN_MEMCMP)) { if (key_part->field->key_cmp(key, key_part->length)) return 1; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e08ed31fa37..d13a2e6a0af 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -707,10 +707,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, static TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, double read_time); -static -TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree); -static double get_index_only_read_time(const PARAM* param, ha_rows records, - int keynr); +static TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree); #ifndef DBUG_OFF static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map, @@ -2314,9 +2311,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, if (!head->covering_keys.is_clear_all()) { int key_for_use= find_shortest_key(head, &head->covering_keys); - double key_read_time= (get_index_only_read_time(¶m, records, - key_for_use) + - (double) records / TIME_FOR_COMPARE); + double key_read_time= param.table->file->keyread_read_time(key_for_use, + 1, records) + + (double) records / TIME_FOR_COMPARE; DBUG_PRINT("info", ("'all'+'using index' scan will be using key %d, " "read time %g", key_for_use, key_read_time)); if (key_read_time < read_time) @@ -3938,42 +3935,6 @@ skip_to_ror_scan: } -/* - Calculate cost of 'index only' scan for given index and number of records. - - SYNOPSIS - get_index_only_read_time() - param parameters structure - records #of records to read - keynr key to read - - NOTES - It is assumed that we will read trough the whole key range and that all - key blocks are half full (normally things are much better). It is also - assumed that each time we read the next key from the index, the handler - performs a random seek, thus the cost is proportional to the number of - blocks read. - - TODO: - Move this to handler->read_time() by adding a flag 'index-only-read' to - this call. The reason for doing this is that the current function doesn't - handle the case when the row is stored in the b-tree (like in innodb - clustered index) -*/ - -static double get_index_only_read_time(const PARAM* param, ha_rows records, - int keynr) -{ - double read_time; - uint keys_per_block= (param->table->file->stats.block_size/2/ - (param->table->key_info[keynr].key_length+ - param->table->file->ref_length) + 1); - read_time=((double) (records+keys_per_block-1)/ - (double) keys_per_block); - return read_time; -} - - typedef struct st_ror_scan_info { uint idx; /* # of used key in param->keys */ @@ -4050,8 +4011,8 @@ ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg) bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr-1); } ror_scan->index_read_cost= - get_index_only_read_time(param, param->table->quick_rows[ror_scan->keynr], - ror_scan->keynr); + param->table->file->keyread_read_time(ror_scan->keynr, 1, + param->table->quick_rows[ror_scan->keynr]); DBUG_RETURN(ror_scan); } @@ -4886,7 +4847,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, We can resolve this by only reading through this key. 0.01 is added to avoid races between range and 'index' scan. */ - found_read_time= get_index_only_read_time(param,found_records,keynr) + + found_read_time= param->table->file->keyread_read_time(keynr,1, + found_records) + cpu_cost + 0.01; } else diff --git a/sql/sp.cc b/sql/sp.cc index 4d4b9728aad..ac509a3bb2d 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1276,6 +1276,7 @@ sp_drop_db_routines(THD *thd, char *db) TABLE *table; int ret; uint key_len; + uchar keybuf[MAX_KEY_LENGTH]; DBUG_ENTER("sp_drop_db_routines"); DBUG_PRINT("enter", ("db: %s", db)); @@ -1285,12 +1286,14 @@ sp_drop_db_routines(THD *thd, char *db) table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info); key_len= table->key_info->key_part[0].store_length; + table->field[MYSQL_PROC_FIELD_DB]->get_key_image(keybuf, key_len, Field::itRAW); + + ret= SP_OK; table->file->ha_index_init(0, 1); - if (!table->file->ha_index_read_map(table->record[0], - (uchar *) table->field[MYSQL_PROC_FIELD_DB]->ptr, - (key_part_map)1, HA_READ_KEY_EXACT)) + if (!table->file->ha_index_read_map(table->record[0], keybuf, (key_part_map)1, + HA_READ_KEY_EXACT)) { int nxtres; bool deleted= FALSE; @@ -1305,11 +1308,8 @@ sp_drop_db_routines(THD *thd, char *db) nxtres= 0; break; } - } while (!(nxtres= table->file-> - ha_index_next_same(table->record[0], - (uchar *)table->field[MYSQL_PROC_FIELD_DB]-> - ptr, - key_len))); + } while (!(nxtres= table->file->ha_index_next_same(table->record[0], + keybuf, key_len))); if (nxtres != HA_ERR_END_OF_FILE) ret= SP_KEY_NOT_FOUND; if (deleted) diff --git a/sql/sql_class.h b/sql/sql_class.h index 77459819c2c..038dff7bcac 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3133,4 +3133,150 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, STATUS_VAR *dec_var); void mark_transaction_to_rollback(THD *thd, bool all); +/* + inline handler methods that need to know TABLE and THD structures +*/ +inline void handler::increment_statistics(ulong SSV::*offset) const +{ + status_var_increment(table->in_use->status_var.*offset); +} + +inline void handler::decrement_statistics(ulong SSV::*offset) const +{ + status_var_decrement(table->in_use->status_var.*offset); +} + +inline int handler::ha_index_read_map(uchar * buf, const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + DBUG_ASSERT(inited==INDEX); + increment_statistics(&SSV::ha_read_key_count); + int error= index_read_map(buf, key, keypart_map, find_flag); + if (!error) + update_index_statistics(); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_index_read_idx_map(uchar * buf, uint index, + const uchar * key, + key_part_map keypart_map, + enum ha_rkey_function find_flag) +{ + increment_statistics(&SSV::ha_read_key_count); + int error= index_read_idx_map(buf, index, key, keypart_map, find_flag); + if (!error) + { + rows_read++; + index_rows_read[index]++; + } + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_index_next(uchar * buf) +{ + DBUG_ASSERT(inited==INDEX); + increment_statistics(&SSV::ha_read_next_count); + int error= index_next(buf); + if (!error) + update_index_statistics(); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_index_prev(uchar * buf) +{ + DBUG_ASSERT(inited==INDEX); + increment_statistics(&SSV::ha_read_prev_count); + int error= index_prev(buf); + if (!error) + update_index_statistics(); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_index_first(uchar * buf) +{ + DBUG_ASSERT(inited==INDEX); + increment_statistics(&SSV::ha_read_first_count); + int error= index_first(buf); + if (!error) + update_index_statistics(); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_index_last(uchar * buf) +{ + DBUG_ASSERT(inited==INDEX); + increment_statistics(&SSV::ha_read_last_count); + int error= index_last(buf); + if (!error) + update_index_statistics(); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_index_next_same(uchar *buf, const uchar *key, + uint keylen) +{ + DBUG_ASSERT(inited==INDEX); + increment_statistics(&SSV::ha_read_next_count); + int error= index_next_same(buf, key, keylen); + if (!error) + update_index_statistics(); + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_ft_read(uchar *buf) +{ + int error= ft_read(buf); + if (!error) + rows_read++; + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_rnd_next(uchar *buf) +{ + increment_statistics(&SSV::ha_read_rnd_next_count); + int error= rnd_next(buf); + if (!error) + rows_read++; + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_rnd_pos(uchar *buf, uchar *pos) +{ + increment_statistics(&SSV::ha_read_rnd_count); + int error= rnd_pos(buf, pos); + if (!error) + rows_read++; + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_rnd_pos_by_record(uchar *buf) +{ + int error= rnd_pos_by_record(buf); + if (!error) + rows_read++; + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + +inline int handler::ha_read_first_row(uchar *buf, uint primary_key) +{ + int error= read_first_row(buf, primary_key); + if (!error) + rows_read++; + table->status=error ? STATUS_NOT_FOUND: 0; + return error; +} + + #endif /* MYSQL_SERVER */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 652fb1e44a7..8df5e4f697f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12249,9 +12249,10 @@ join_read_last_key(JOIN_TAB *tab) } if (cp_buffer_from_ref(tab->join->thd, table, &tab->ref)) return -1; - if ((error= table->file->ha_index_read_last_map(table->record[0], - tab->ref.key_buff, - make_prev_keypart_map(tab->ref.key_parts)))) + if ((error= table->file->ha_index_read_map(table->record[0], + tab->ref.key_buff, + make_prev_keypart_map(tab->ref.key_parts), + HA_READ_PREFIX_LAST))) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) return report_error(table, error); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a36775fdd20..624aab93e33 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7668,27 +7668,6 @@ view_err: if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) DBUG_RETURN(TRUE); - if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME)) - { - /* - For the alter table to be properly flushed to the logs, we - have to open the new table. If not, we get a problem on server - shutdown. But we do not need to attach MERGE children. - */ - char path[FN_REFLEN]; - TABLE *t_table; - build_table_filename(path + 1, sizeof(path) - 1, new_db, table_name, "", 0); - t_table= open_temporary_table(thd, path, new_db, tmp_name, 0); - if (t_table) - { - intern_close_table(t_table); - my_free(t_table, MYF(0)); - } - else - sql_print_warning("Could not open table %s.%s after rename\n", - new_db,table_name); - ha_flush_logs(old_db_type); - } table_list->table=0; // For query cache query_cache_invalidate3(thd, table_list, 0); diff --git a/sql/table.cc b/sql/table.cc index 86312031cac..b9a2a8be2f1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1594,6 +1594,15 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, */ if (field->real_maybe_null()) key_part->key_part_flag|= HA_NULL_PART; + /* + Sometimes we can compare key parts for equality with memcmp. + But not always. + */ + if (!(key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART | + HA_BIT_PART)) && + key_part->type != HA_KEYTYPE_FLOAT && + key_part->type == HA_KEYTYPE_DOUBLE) + key_part->key_part_flag|= HA_CAN_MEMCMP; } keyinfo->usable_key_parts= usable_parts; // Filesort diff --git a/sql/tztime.cc b/sql/tztime.cc index 3802c284057..457bbeec676 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1813,6 +1813,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) uint tzid, ttid; my_time_t ttime; char buff[MAX_FIELD_WIDTH]; + uchar keybuff[32]; String abbr(buff, sizeof(buff), &my_charset_latin1); char *alloc_buff, *tz_name_buff; /* @@ -1891,9 +1892,10 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table= tz_tables->table; tz_tables= tz_tables->next_local; table->field[0]->store((longlong) tzid, TRUE); + table->field[0]->get_key_image(keybuff, sizeof(keybuff), Field::itRAW); (void)table->file->ha_index_init(0, 1); - if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + if (table->file->ha_index_read_map(table->record[0], keybuff, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { sql_print_error("Can't find description of time zone '%u'", tzid); @@ -1918,9 +1920,10 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table= tz_tables->table; tz_tables= tz_tables->next_local; table->field[0]->store((longlong) tzid, TRUE); + table->field[0]->get_key_image(keybuff, sizeof(keybuff), Field::itRAW); (void)table->file->ha_index_init(0, 1); - res= table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + res= table->file->ha_index_read_map(table->record[0], keybuff, (key_part_map)1, HA_READ_KEY_EXACT); while (!res) { @@ -1968,8 +1971,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) tmp_tz_info.typecnt= ttid + 1; - res= table->file->ha_index_next_same(table->record[0], - table->field[0]->ptr, 4); + res= table->file->ha_index_next_same(table->record[0], keybuff, 4); } if (res != HA_ERR_END_OF_FILE) @@ -1991,7 +1993,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0, 1); - res= table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, + res= table->file->ha_index_read_map(table->record[0], keybuff, (key_part_map)1, HA_READ_KEY_EXACT); while (!res) { @@ -2021,8 +2023,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) ("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u", tzid, (ulong) ttime, ttid)); - res= table->file->ha_index_next_same(table->record[0], - table->field[0]->ptr, 4); + res= table->file->ha_index_next_same(table->record[0], keybuff, 4); } /* diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index d2bbb4bd405..d5577eb09be 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -776,8 +776,6 @@ int ha_myisam::close(void) int ha_myisam::write_row(uchar *buf) { - ha_statistic_increment(&SSV::ha_write_count); - /* If we have a timestamp column, update it to the current time */ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -1663,7 +1661,6 @@ bool ha_myisam::is_crashed() const int ha_myisam::update_row(const uchar *old_data, uchar *new_data) { - ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); return mi_update(file,old_data,new_data); @@ -1671,7 +1668,6 @@ int ha_myisam::update_row(const uchar *old_data, uchar *new_data) int ha_myisam::delete_row(const uchar *buf) { - ha_statistic_increment(&SSV::ha_delete_count); return mi_delete(file,buf); } @@ -1679,84 +1675,48 @@ int ha_myisam::index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag) { - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_key_count); - int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_rkey(file, buf, active_index, key, keypart_map, find_flag); } int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag) { - ha_statistic_increment(&SSV::ha_read_key_count); - int error=mi_rkey(file, buf, index, key, keypart_map, find_flag); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -int ha_myisam::index_read_last_map(uchar *buf, const uchar *key, - key_part_map keypart_map) -{ - DBUG_ENTER("ha_myisam::index_read_last"); - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_key_count); - int error=mi_rkey(file, buf, active_index, key, keypart_map, - HA_READ_PREFIX_LAST); - table->status=error ? STATUS_NOT_FOUND: 0; - DBUG_RETURN(error); + return mi_rkey(file, buf, index, key, keypart_map, find_flag); } int ha_myisam::index_next(uchar *buf) { - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_next_count); - int error=mi_rnext(file,buf,active_index); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_rnext(file,buf,active_index); } int ha_myisam::index_prev(uchar *buf) { - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_prev_count); - int error=mi_rprev(file,buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_rprev(file,buf, active_index); } int ha_myisam::index_first(uchar *buf) { - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_first_count); - int error=mi_rfirst(file, buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_rfirst(file, buf, active_index); } int ha_myisam::index_last(uchar *buf) { - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_last_count); - int error=mi_rlast(file, buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_rlast(file, buf, active_index); } int ha_myisam::index_next_same(uchar *buf, const uchar *key __attribute__((unused)), uint length __attribute__((unused))) { + DBUG_ENTER("ha_myisam::index_next_same"); int error; - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_next_count); do { error= mi_rnext_same(file,buf); } while (error == HA_ERR_RECORD_DELETED); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + DBUG_PRINT("return",("%i", error)); + DBUG_RETURN(error); } @@ -1769,10 +1729,7 @@ int ha_myisam::rnd_init(bool scan) int ha_myisam::rnd_next(uchar *buf) { - ha_statistic_increment(&SSV::ha_read_rnd_next_count); - int error=mi_scan(file, buf); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_scan(file, buf); } int ha_myisam::remember_rnd_pos() @@ -1788,10 +1745,7 @@ int ha_myisam::restart_rnd_next(uchar *buf) int ha_myisam::rnd_pos(uchar *buf, uchar *pos) { - ha_statistic_increment(&SSV::ha_read_rnd_count); - int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length)); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; + return mi_rrnd(file, buf, my_get_ptr(pos,ref_length)); } void ha_myisam::position(const uchar *record) @@ -2092,8 +2046,6 @@ int ha_myisam::ft_read(uchar *buf) &LOCK_status); // why ? error=ft_handler->please->read_next(ft_handler,(char*) buf); - - table->status=error ? STATUS_NOT_FOUND: 0; return error; } diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 7a1595573d4..271aad66e6e 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -71,7 +71,6 @@ class ha_myisam: public handler int index_read_idx_map(uchar *buf, uint index, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag); - int index_read_last_map(uchar *buf, const uchar *key, key_part_map keypart_map); int index_next(uchar * buf); int index_prev(uchar * buf); int index_first(uchar * buf); |