00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "myisam_priv.h"
00022
00023 using namespace drizzled;
00024
00025 static ha_rows _mi_record_pos(MI_INFO *, const unsigned char *, key_part_map,
00026 enum ha_rkey_function);
00027 static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,unsigned char *, uint,uint,internal::my_off_t);
00028 static uint32_t _mi_keynr(MI_INFO *info,MI_KEYDEF *,unsigned char *, unsigned char *,uint32_t *);
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 ha_rows mi_records_in_range(MI_INFO *info, int inx,
00049 key_range *min_key, key_range *max_key)
00050 {
00051 ha_rows start_pos,end_pos,res;
00052
00053 if ((inx = _mi_check_index(info,inx)) < 0)
00054 return(HA_POS_ERROR);
00055
00056 if (fast_mi_readinfo(info))
00057 return(HA_POS_ERROR);
00058 info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
00059
00060 switch(info->s->keyinfo[inx].key_alg){
00061 case HA_KEY_ALG_BTREE:
00062 default:
00063 start_pos= (min_key ? _mi_record_pos(info, min_key->key,
00064 min_key->keypart_map, min_key->flag)
00065 : (ha_rows) 0);
00066 end_pos= (max_key ? _mi_record_pos(info, max_key->key,
00067 max_key->keypart_map, max_key->flag)
00068 : info->state->records + (ha_rows) 1);
00069 res= (end_pos < start_pos ? (ha_rows) 0 :
00070 (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
00071 if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
00072 res=HA_POS_ERROR;
00073 }
00074
00075 fast_mi_writeinfo(info);
00076
00077 return(res);
00078 }
00079
00080
00081
00082
00083 static ha_rows _mi_record_pos(MI_INFO *info, const unsigned char *key,
00084 key_part_map keypart_map,
00085 enum ha_rkey_function search_flag)
00086 {
00087 uint32_t inx=(uint) info->lastinx, nextflag, key_len;
00088 MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
00089 unsigned char *key_buff;
00090 double pos;
00091
00092 assert(keypart_map);
00093
00094 key_buff=info->lastkey+info->s->base.max_key_length;
00095 key_len=_mi_pack_key(info,inx,key_buff,(unsigned char*) key, keypart_map,
00096 (HA_KEYSEG**) 0);
00097 nextflag=myisam_read_vec[search_flag];
00098 if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
00099 key_len=USE_WHOLE_KEY;
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 pos=_mi_search_pos(info,keyinfo,key_buff,key_len,
00136 nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE,
00137 info->s->state.key_root[inx]);
00138 if (pos >= 0.0)
00139 {
00140 return((uint32_t) (pos*info->state->records+0.5));
00141 }
00142 return(HA_POS_ERROR);
00143 }
00144
00145
00146
00147
00148
00149 static double _mi_search_pos(register MI_INFO *info,
00150 register MI_KEYDEF *keyinfo,
00151 unsigned char *key, uint32_t key_len, uint32_t nextflag,
00152 register internal::my_off_t pos)
00153 {
00154 int flag;
00155 uint32_t nod_flag, keynr, max_keynr= 0;
00156 bool after_key;
00157 unsigned char *keypos,*buff;
00158 double offset;
00159
00160 if (pos == HA_OFFSET_ERROR)
00161 return(0.5);
00162
00163 if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,1)))
00164 goto err;
00165 flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
00166 &keypos,info->lastkey, &after_key);
00167 nod_flag=mi_test_if_nod(buff);
00168 keynr=_mi_keynr(info,keyinfo,buff,keypos,&max_keynr);
00169
00170 if (flag)
00171 {
00172 if (flag == MI_FOUND_WRONG_KEY)
00173 return(-1);
00174
00175
00176
00177
00178
00179 if (flag > 0 && ! nod_flag)
00180 offset= 1.0;
00181 else if ((offset=_mi_search_pos(info,keyinfo,key,key_len,nextflag,
00182 _mi_kpos(nod_flag,keypos))) < 0)
00183 return(offset);
00184 }
00185 else
00186 {
00187
00188
00189
00190
00191 offset=1.0;
00192 if ((nextflag & SEARCH_FIND) && nod_flag &&
00193 ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
00194 key_len != USE_WHOLE_KEY))
00195 {
00196
00197
00198
00199
00200 if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
00201 _mi_kpos(nod_flag,keypos))) < 0)
00202 return(offset);
00203 }
00204 }
00205 return((keynr+offset)/(max_keynr+1));
00206 err:
00207 return (-1.0);
00208 }
00209
00210
00211
00212
00213 static uint32_t _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
00214 unsigned char *keypos, uint32_t *ret_max_key)
00215 {
00216 uint32_t nod_flag,keynr,max_key;
00217 unsigned char t_buff[MI_MAX_KEY_BUFF],*end;
00218
00219 end= page+mi_getint(page);
00220 nod_flag=mi_test_if_nod(page);
00221 page+=2+nod_flag;
00222
00223 if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
00224 {
00225 *ret_max_key= (uint) (end-page)/(keyinfo->keylength+nod_flag);
00226 return (uint) (keypos-page)/(keyinfo->keylength+nod_flag);
00227 }
00228
00229 max_key=keynr=0;
00230 t_buff[0]=0;
00231 while (page < end)
00232 {
00233 if (!(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff))
00234 return 0;
00235 max_key++;
00236 if (page == keypos)
00237 keynr=max_key;
00238 }
00239 *ret_max_key=max_key;
00240 return(keynr);
00241 }