18
18
Used when optimizing querries.
21
#include "myisam_priv.h"
21
#include "myisamdef.h"
23
static ha_rows _mi_record_pos(MI_INFO *, const unsigned char *, key_part_map,
24
static ha_rows _mi_record_pos(MI_INFO *, const uchar *, key_part_map,
24
25
enum ha_rkey_function);
25
static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,unsigned char *, uint,uint,my_off_t);
26
static uint32_t _mi_keynr(MI_INFO *info,MI_KEYDEF *,unsigned char *, unsigned char *,uint32_t *);
26
static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,my_off_t);
27
static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *);
29
30
Estimate how many records there is in a given range
42
43
HA_POS_ERROR error (or we can't estimate number of rows)
43
44
number Estimated number of rows
46
47
ha_rows mi_records_in_range(MI_INFO *info, int inx,
47
48
key_range *min_key, key_range *max_key)
49
50
ha_rows start_pos,end_pos,res;
51
DBUG_ENTER("mi_records_in_range");
51
53
if ((inx = _mi_check_index(info,inx)) < 0)
54
DBUG_RETURN(HA_POS_ERROR);
54
56
if (fast_mi_readinfo(info))
57
DBUG_RETURN(HA_POS_ERROR);
56
58
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
57
59
if (info->s->concurrent_insert)
58
pthread_rwlock_rdlock(&info->s->key_root_lock[inx]);
60
rw_rdlock(&info->s->key_root_lock[inx]);
60
62
switch(info->s->keyinfo[inx].key_alg){
63
#ifdef HAVE_RTREE_KEYS
64
case HA_KEY_ALG_RTREE:
70
The problem is that the optimizer doesn't support
71
RTree keys properly at the moment.
72
Hope this will be fixed some day.
73
But now NULL in the min_key means that we
74
didn't make the task for the RTree key
75
and expect BTree functionality from it.
76
As it's not able to handle such request
84
key_buff= info->lastkey+info->s->base.max_key_length;
85
start_key_len= _mi_pack_key(info,inx, key_buff,
86
(uchar*) min_key->key, min_key->keypart_map,
88
res= rtree_estimate(info, inx, key_buff, start_key_len,
89
myisam_read_vec[min_key->flag]);
90
res= res ? res : 1; /* Don't return 0 */
61
94
case HA_KEY_ALG_BTREE:
63
96
start_pos= (min_key ? _mi_record_pos(info, min_key->key,
75
108
if (info->s->concurrent_insert)
76
pthread_rwlock_unlock(&info->s->key_root_lock[inx]);
109
rw_unlock(&info->s->key_root_lock[inx]);
77
110
fast_mi_writeinfo(info);
112
DBUG_PRINT("info",("records: %ld",(ulong) (res)));
83
117
/* Find relative position (in records) for key in index-tree */
85
static ha_rows _mi_record_pos(MI_INFO *info, const unsigned char *key,
119
static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
86
120
key_part_map keypart_map,
87
121
enum ha_rkey_function search_flag)
89
uint32_t inx=(uint) info->lastinx, nextflag, key_len;
123
uint inx=(uint) info->lastinx, nextflag, key_len;
90
124
MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
91
unsigned char *key_buff;
128
DBUG_ENTER("_mi_record_pos");
129
DBUG_PRINT("enter",("search_flag: %d",search_flag));
130
DBUG_ASSERT(keypart_map);
96
132
key_buff=info->lastkey+info->s->base.max_key_length;
97
key_len=_mi_pack_key(info,inx,key_buff,(unsigned char*) key, keypart_map,
133
key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key, keypart_map,
135
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
136
(uchar*) key_buff,key_len););
99
137
nextflag=myisam_read_vec[search_flag];
100
138
if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
101
139
key_len=USE_WHOLE_KEY;
139
177
info->s->state.key_root[inx]);
142
return((uint32_t) (pos*info->state->records+0.5));
180
DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records)));
181
DBUG_RETURN((ulong) (pos*info->state->records+0.5));
144
return(HA_POS_ERROR);
183
DBUG_RETURN(HA_POS_ERROR);
151
190
static double _mi_search_pos(register MI_INFO *info,
152
191
register MI_KEYDEF *keyinfo,
153
unsigned char *key, uint32_t key_len, uint32_t nextflag,
192
uchar *key, uint key_len, uint nextflag,
154
193
register my_off_t pos)
157
uint32_t nod_flag, keynr, max_keynr= 0;
159
unsigned char *keypos,*buff;
196
uint nod_flag, keynr, max_keynr= 0;
200
DBUG_ENTER("_mi_search_pos");
162
202
if (pos == HA_OFFSET_ERROR)
165
205
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,1)))
174
214
if (flag == MI_FOUND_WRONG_KEY)
175
return(-1); /* error */
215
DBUG_RETURN(-1); /* error */
177
217
Didn't found match. keypos points at next (bigger) key
178
218
Try to find a smaller, better matching key.
183
223
else if ((offset=_mi_search_pos(info,keyinfo,key,key_len,nextflag,
184
224
_mi_kpos(nod_flag,keypos))) < 0)
202
242
if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
203
243
_mi_kpos(nod_flag,keypos))) < 0)
204
return(offset); /* Read error */
244
DBUG_RETURN(offset); /* Read error */
207
return((keynr+offset)/(max_keynr+1));
247
DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d",
248
keynr,offset,max_keynr,nod_flag,flag));
249
DBUG_RETURN((keynr+offset)/(max_keynr+1));
251
DBUG_PRINT("exit",("Error: %d",my_errno));
213
256
/* Get keynummer of current key and max number of keys in nod */
215
static uint32_t _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
216
unsigned char *keypos, uint32_t *ret_max_key)
258
static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
259
uchar *keypos, uint *ret_max_key)
218
uint32_t nod_flag,keynr,max_key;
219
unsigned char t_buff[MI_MAX_KEY_BUFF],*end;
261
uint nod_flag,keynr,max_key;
262
uchar t_buff[MI_MAX_KEY_BUFF],*end;
221
264
end= page+mi_getint(page);
222
265
nod_flag=mi_test_if_nod(page);