diff options
Diffstat (limited to 'storage/myisam')
-rw-r--r-- | storage/myisam/ha_myisam.cc | 20 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.h | 2 | ||||
-rw-r--r-- | storage/myisam/mi_extra.c | 10 | ||||
-rw-r--r-- | storage/myisam/mi_key.c | 13 | ||||
-rw-r--r-- | storage/myisam/mi_range.c | 68 | ||||
-rw-r--r-- | storage/myisam/mi_rkey.c | 4 | ||||
-rw-r--r-- | storage/myisam/mi_rnext.c | 4 | ||||
-rw-r--r-- | storage/myisam/mi_rnext_same.c | 4 | ||||
-rw-r--r-- | storage/myisam/mi_rprev.c | 4 | ||||
-rw-r--r-- | storage/myisam/myisamdef.h | 11 |
10 files changed, 114 insertions, 26 deletions
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 9ab7d156251..012691ef2da 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -769,7 +769,8 @@ ulong ha_myisam::index_flags(uint inx, uint part, bool all_parts) const else { flags= HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE | - HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN; + HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN | + HA_DO_RANGE_FILTER_PUSHDOWN; } return flags; } @@ -1880,6 +1881,9 @@ int ha_myisam::index_init(uint idx, bool sorted) active_index=idx; if (pushed_idx_cond_keyno == idx) mi_set_index_cond_func(file, handler_index_cond_check, this); + if (pushed_rowid_filter) + mi_set_rowid_filter_func(file, handler_rowid_filter_check, + handler_rowid_filter_is_active, this); return 0; } @@ -1891,6 +1895,7 @@ int ha_myisam::index_end() //pushed_idx_cond_keyno= MAX_KEY; mi_set_index_cond_func(file, NULL, 0); in_range_check_pushed_down= FALSE; + mi_set_rowid_filter_func(file, NULL, NULL, 0); ds_mrr.dsmrr_close(); #if !defined(DBUG_OFF) && defined(SQL_SELECT_FIXED_FOR_UPDATE) file->update&= ~HA_STATE_AKTIV; // Forget active row @@ -1926,6 +1931,9 @@ int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key, end_range= NULL; if (index == pushed_idx_cond_keyno) mi_set_index_cond_func(file, handler_index_cond_check, this); + if (pushed_rowid_filter) + mi_set_rowid_filter_func(file, handler_rowid_filter_check, + handler_rowid_filter_is_active, this); res= mi_rkey(file, buf, index, key, keypart_map, find_flag); mi_set_index_cond_func(file, NULL, 0); return res; @@ -2591,6 +2599,14 @@ Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg) return NULL; } +bool ha_myisam::rowid_filter_push(Rowid_filter* rowid_filter) +{ + pushed_rowid_filter= rowid_filter; + mi_set_rowid_filter_func(file, handler_rowid_filter_check, + handler_rowid_filter_is_active, this); + return false; +} + struct st_mysql_storage_engine myisam_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -2681,7 +2697,7 @@ my_bool ha_myisam::register_query_cache_table(THD *thd, const char *table_name, If the table size is unknown the SELECT statement can't be cached. - When concurrent inserts are disabled at table open, mi_open() + When concurrent inserts are disabled at table open, mi_ondopen() does not assign a get_status() function. In this case the local ("current") status is never updated. We would wrongly think that we cannot cache the statement. diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 804963f5efc..f9f11b6f480 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -172,6 +172,8 @@ public: /* Index condition pushdown implementation */ Item *idx_cond_push(uint keyno, Item* idx_cond); + bool rowid_filter_push(Rowid_filter* rowid_filter); + private: DsMrr_impl ds_mrr; friend ICP_RESULT index_cond_func_myisam(void *arg); diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index 194ad5bf07a..15f0297002f 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -423,6 +423,16 @@ void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func, info->index_cond_func_arg= func_arg; } +void mi_set_rowid_filter_func(MI_INFO *info, + rowid_filter_func_t check_func, + rowid_filter_func_t is_active_func, + void *func_arg) +{ + info->rowid_filter_func= check_func; + info->rowid_filter_is_active_func= is_active_func; + info->rowid_filter_func_arg= func_arg; +} + /* Start/Stop Inserting Duplicates Into a Table, WL#1648. */ diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c index 4bd01dcbfa0..8bf63af8f5f 100644 --- a/storage/myisam/mi_key.c +++ b/storage/myisam/mi_key.c @@ -529,6 +529,19 @@ ICP_RESULT mi_check_index_cond(register MI_INFO *info, uint keynr, return res; } + +int mi_check_rowid_filter(MI_INFO *info) +{ + return info->rowid_filter_func(info->rowid_filter_func_arg); +} + +int mi_check_rowid_filter_is_active(MI_INFO *info) +{ + if (info->rowid_filter_is_active_func == NULL) + return 0; + return info->rowid_filter_is_active_func(info->rowid_filter_func_arg); +} + /* Retrieve auto_increment info diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c index 2074c873979..185f2ca61fa 100644 --- a/storage/myisam/mi_range.c +++ b/storage/myisam/mi_range.c @@ -22,9 +22,10 @@ #include "myisamdef.h" #include "rt_index.h" -static ha_rows _mi_record_pos(MI_INFO *, const uchar *, key_part_map, - enum ha_rkey_function); -static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,my_off_t); +static double _mi_record_pos(MI_INFO *, const uchar *, key_part_map, + enum ha_rkey_function); +static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint, + my_off_t,my_bool); static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *); /* @@ -48,7 +49,8 @@ static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *); ha_rows mi_records_in_range(MI_INFO *info, int inx, key_range *min_key, key_range *max_key) { - ha_rows start_pos,end_pos,res; + ha_rows res; + double start_pos,end_pos,diff; DBUG_ENTER("mi_records_in_range"); if ((inx = _mi_check_index(info,inx)) < 0) @@ -94,16 +96,27 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, #endif case HA_KEY_ALG_BTREE: default: - start_pos= (min_key ? _mi_record_pos(info, min_key->key, - min_key->keypart_map, min_key->flag) - : (ha_rows) 0); + start_pos= (min_key ?_mi_record_pos(info, min_key->key, + min_key->keypart_map, min_key->flag) + : (double) 0); end_pos= (max_key ? _mi_record_pos(info, max_key->key, max_key->keypart_map, max_key->flag) - : info->state->records + (ha_rows) 1); + : (double) info->state->records); res= (end_pos < start_pos ? (ha_rows) 0 : (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos)); if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR) res=HA_POS_ERROR; + else + { + diff= end_pos - start_pos; + if (diff >= 0) + { + if (!(res= (diff + 0.5))) + res= 1; + } + else + res= 0; + } } if (info->s->concurrent_insert) @@ -115,11 +128,25 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx, } - /* Find relative position (in records) for key in index-tree */ +/* + To find an approximate relative position of a key tuple among all index + key tuples would not be hard if we considered B-trees where all key + tuples were contained only in leaf nodes. If we consider a B-tree where + key tuples are stored also in non-leaf nodes we have to convert such + tree into the tree of the first type. The transformation procedure is + simple: the key tuple k goes alter the last key tuple in the most right + sub-tree pointer to which is coupled with k. As a result of this + transformation each leaf node except the most right one in the tree will + contain one extra key tuple following those originally belonging to + the leaf. +*/ + + +/* Find relative position (in records) for key in index-tree */ -static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key, - key_part_map keypart_map, - enum ha_rkey_function search_flag) +static double _mi_record_pos(MI_INFO *info, const uchar *key, + key_part_map keypart_map, + enum ha_rkey_function search_flag) { uint inx=(uint) info->lastinx, nextflag, key_len; MI_KEYDEF *keyinfo=info->s->keyinfo+inx; @@ -175,11 +202,11 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key, */ pos=_mi_search_pos(info,keyinfo,key_buff,key_len, nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE, - info->s->state.key_root[inx]); + info->s->state.key_root[inx], TRUE); if (pos >= 0.0) { - DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records))); - DBUG_RETURN((ulong) (pos*info->state->records+0.5)); + DBUG_PRINT("exit",("pos: %g",(pos*info->state->records))); + DBUG_RETURN(pos*info->state->records); } DBUG_RETURN(HA_POS_ERROR); } @@ -191,7 +218,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key, static double _mi_search_pos(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, - register my_off_t pos) + register my_off_t pos, my_bool last_in_level) { int flag; uint nod_flag,keynr,UNINIT_VAR(max_keynr); @@ -222,7 +249,8 @@ static double _mi_search_pos(register MI_INFO *info, if (flag > 0 && ! nod_flag) offset= 1.0; else if ((offset=_mi_search_pos(info,keyinfo,key,key_len,nextflag, - _mi_kpos(nod_flag,keypos))) < 0) + _mi_kpos(nod_flag,keypos), + last_in_level && after_key)) < 0) DBUG_RETURN(offset); } else @@ -241,13 +269,15 @@ static double _mi_search_pos(register MI_INFO *info, Matches keynr + [0-1] */ if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND, - _mi_kpos(nod_flag,keypos))) < 0) + _mi_kpos(nod_flag,keypos), + last_in_level && after_key)) < 0) DBUG_RETURN(offset); /* Read error */ } } DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d", keynr,offset,max_keynr,nod_flag,flag)); - DBUG_RETURN((keynr+offset)/(max_keynr+1)); + DBUG_RETURN((keynr+offset-MY_TEST(!nod_flag))/ + (max_keynr+MY_TEST(nod_flag || !last_in_level))); err: DBUG_PRINT("exit",("Error: %d",my_errno)); DBUG_RETURN (-1.0); diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c index 1dddb8b49ad..c0f9b2046fc 100644 --- a/storage/myisam/mi_rkey.c +++ b/storage/myisam/mi_rkey.c @@ -120,7 +120,9 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, (search_flag != HA_READ_KEY_EXACT || last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) || (info->index_cond_func && - (res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH)) + (res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) || + (mi_check_rowid_filter_is_active(info) && + !mi_check_rowid_filter(info))) { uint not_used[2]; /* diff --git a/storage/myisam/mi_rnext.c b/storage/myisam/mi_rnext.c index 6e3701abe6b..c3af209fd71 100644 --- a/storage/myisam/mi_rnext.c +++ b/storage/myisam/mi_rnext.c @@ -102,7 +102,9 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) while ((info->s->concurrent_insert && info->lastpos >= info->state->data_file_length) || (info->index_cond_func && - (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH)) + (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) || + (mi_check_rowid_filter_is_active(info) && + !mi_check_rowid_filter(info))) { /* If we are at the last key on the key page, allow writers to diff --git a/storage/myisam/mi_rnext_same.c b/storage/myisam/mi_rnext_same.c index d6856459ae7..ac818bfa2da 100644 --- a/storage/myisam/mi_rnext_same.c +++ b/storage/myisam/mi_rnext_same.c @@ -95,7 +95,9 @@ int mi_rnext_same(MI_INFO *info, uchar *buf) */ if (info->lastpos < info->state->data_file_length && (!info->index_cond_func || - (icp_res= mi_check_index_cond(info, inx, buf)) != ICP_NO_MATCH)) + (icp_res= mi_check_index_cond(info, inx, buf)) != ICP_NO_MATCH) && + (!mi_check_rowid_filter_is_active(info) || + mi_check_rowid_filter(info))) break; } } diff --git a/storage/myisam/mi_rprev.c b/storage/myisam/mi_rprev.c index 27fbda95574..a78bab6a040 100644 --- a/storage/myisam/mi_rprev.c +++ b/storage/myisam/mi_rprev.c @@ -59,7 +59,9 @@ int mi_rprev(MI_INFO *info, uchar *buf, int inx) while ((share->concurrent_insert && info->lastpos >= info->state->data_file_length) || (info->index_cond_func && - (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH)) + (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) || + (mi_check_rowid_filter_is_active(info) && + !mi_check_rowid_filter(info))) { /* If we are at the last (i.e. first?) key on the key page, diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 2f8d52863fc..8ba2bbcc209 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -306,6 +306,9 @@ struct st_myisam_info my_bool create_unique_index_by_sort; index_cond_func_t index_cond_func; /* Index condition function */ void *index_cond_func_arg; /* parameter for the func */ + rowid_filter_func_t rowid_filter_func; /* rowid filter check function */ + rowid_filter_func_t rowid_filter_is_active_func; /* is activefunction */ + void *rowid_filter_func_arg; /* parameter for the func */ THR_LOCK_DATA lock; uchar *rtree_recursion_state; /* For RTREE */ int rtree_recursion_depth; @@ -725,14 +728,20 @@ int mi_munmap_file(MI_INFO *info); void mi_remap_file(MI_INFO *info, my_off_t size); ICP_RESULT mi_check_index_cond(MI_INFO *info, uint keynr, uchar *record); +int mi_check_rowid_filter(MI_INFO *info); +int mi_check_rowid_filter_is_active(MI_INFO *info); /* Functions needed by mi_check */ int killed_ptr(HA_CHECK *param); void mi_check_print_error(HA_CHECK *param, const char *fmt, ...); void mi_check_print_warning(HA_CHECK *param, const char *fmt, ...); void mi_check_print_info(HA_CHECK *param, const char *fmt, ...); pthread_handler_t thr_find_all_keys(void *arg); -extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func, +extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t check_func, void *func_arg); +extern void mi_set_rowid_filter_func(MI_INFO *info, + rowid_filter_func_t check_func, + rowid_filter_func_t is_active_func, + void *func_arg); int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file, ulonglong *dirty_part_map); |