23 void _mi_ft_segiterator_init(
MI_INFO *info, uint keynr,
const uchar *
record,
26 DBUG_ENTER(
"_mi_ft_segiterator_init");
28 ftsi->num=info->s->keyinfo[keynr].keysegs;
29 ftsi->seg=info->s->keyinfo[keynr].seg;
34 void _mi_ft_segiterator_dummy_init(
const uchar *
record, uint len,
37 DBUG_ENTER(
"_mi_ft_segiterator_dummy_init");
57 DBUG_ENTER(
"_mi_ft_segiterator");
68 if (ftsi->seg->null_bit &&
69 (ftsi->rec[ftsi->seg->null_pos] & ftsi->seg->null_bit))
74 ftsi->pos= ftsi->rec+ftsi->seg->start;
75 if (ftsi->seg->flag & HA_VAR_LENGTH_PART)
77 uint pack_length= (ftsi->seg->bit_start);
78 ftsi->len= (pack_length == 1 ? (uint) *(uchar*) ftsi->pos :
79 uint2korr(ftsi->pos));
80 ftsi->pos+= pack_length;
83 if (ftsi->seg->flag & HA_BLOB_PART)
85 ftsi->len=_mi_calc_blob_length(ftsi->seg->bit_start,ftsi->pos);
86 memcpy(&ftsi->pos, ftsi->pos+ftsi->seg->bit_start,
sizeof(
char*));
89 ftsi->len=ftsi->seg->length;
101 DBUG_ENTER(
"_mi_ft_parse");
103 _mi_ft_segiterator_init(info, keynr, record, &ftsi);
105 ft_parse_init(parsed, info->s->keyinfo[keynr].seg->charset);
106 parser= info->s->keyinfo[keynr].parser;
107 while (_mi_ft_segiterator(&ftsi))
110 if (ft_parse(parsed, (uchar *)ftsi.pos, ftsi.len, parser, param, mem_root))
116 FT_WORD *_mi_ft_parserecord(
MI_INFO *info, uint keynr,
const uchar *record,
121 DBUG_ENTER(
"_mi_ft_parserecord");
122 if (! (param= ftparser_call_initializer(info, keynr, 0)))
124 memset(&ptree, 0,
sizeof(ptree));
126 if (_mi_ft_parse(&ptree, info, keynr, record, param, mem_root))
129 DBUG_RETURN(ft_linearize(&ptree, mem_root));
132 static int _mi_ft_store(
MI_INFO *info, uint keynr, uchar *keybuf,
133 FT_WORD *wlist, my_off_t filepos)
136 DBUG_ENTER(
"_mi_ft_store");
138 for (; wlist->pos; wlist++)
140 key_length=_ft_make_key(info,keynr,keybuf,wlist,filepos);
141 if (_mi_ck_write(info,keynr,(uchar*) keybuf,key_length))
147 static int _mi_ft_erase(
MI_INFO *info, uint keynr, uchar *keybuf,
148 FT_WORD *wlist, my_off_t filepos)
150 uint key_length, err=0;
151 DBUG_ENTER(
"_mi_ft_erase");
153 for (; wlist->pos; wlist++)
155 key_length=_ft_make_key(info,keynr,keybuf,wlist,filepos);
156 if (_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length))
167 #define THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT 1
168 #define GEE_THEY_ARE_ABSOLUTELY_IDENTICAL 0
170 int _mi_ft_cmp(
MI_INFO *info, uint keynr,
const uchar *rec1,
const uchar *
rec2)
173 const CHARSET_INFO *cs= info->s->keyinfo[keynr].seg->charset;
174 DBUG_ENTER(
"_mi_ft_cmp");
175 _mi_ft_segiterator_init(info, keynr, rec1, &ftsi1);
176 _mi_ft_segiterator_init(info, keynr, rec2, &ftsi2);
178 while (_mi_ft_segiterator(&ftsi1) && _mi_ft_segiterator(&ftsi2))
180 if ((ftsi1.pos != ftsi2.pos) &&
181 (!ftsi1.pos || !ftsi2.pos ||
182 ha_compare_text(cs, (uchar*) ftsi1.pos,ftsi1.len,
183 (uchar*) ftsi2.pos,ftsi2.len,0,0)))
184 DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT);
186 DBUG_RETURN(GEE_THEY_ARE_ABSOLUTELY_IDENTICAL);
192 int _mi_ft_update(
MI_INFO *info, uint keynr, uchar *keybuf,
193 const uchar *oldrec,
const uchar *newrec, my_off_t pos)
196 FT_WORD *oldlist,*newlist, *old_word, *new_word;
197 const CHARSET_INFO *cs= info->s->keyinfo[keynr].seg->charset;
200 DBUG_ENTER(
"_mi_ft_update");
202 if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec,
203 &info->ft_memroot)) ||
204 !(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec,
209 while(old_word->pos && new_word->pos)
211 cmp= ha_compare_text(cs, (uchar*) old_word->pos,old_word->len,
212 (uchar*) new_word->pos,new_word->len,0,0);
213 cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5);
217 key_length=_ft_make_key(info,keynr,keybuf,old_word,pos);
218 if ((error=_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length)))
223 key_length=_ft_make_key(info,keynr,keybuf,new_word,pos);
224 if ((error=_mi_ck_write(info,keynr,(uchar*) keybuf,key_length)))
227 if (cmp<=0) old_word++;
228 if (cmp>=0) new_word++;
231 error=_mi_ft_erase(info,keynr,keybuf,old_word,pos);
232 else if (new_word->pos)
233 error=_mi_ft_store(info,keynr,keybuf,new_word,pos);
236 free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE));
243 int _mi_ft_add(
MI_INFO *info, uint keynr, uchar *keybuf,
const uchar *record,
248 DBUG_ENTER(
"_mi_ft_add");
249 DBUG_PRINT(
"enter",(
"keynr: %d",keynr));
251 if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot)))
252 error=_mi_ft_store(info,keynr,keybuf,wlist,pos);
254 free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE));
255 DBUG_PRINT(
"exit",(
"Return: %d",error));
262 int _mi_ft_del(
MI_INFO *info, uint keynr, uchar *keybuf,
const uchar *record,
267 DBUG_ENTER(
"_mi_ft_del");
268 DBUG_PRINT(
"enter",(
"keynr: %d",keynr));
270 if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot)))
271 error=_mi_ft_erase(info,keynr,keybuf,wlist,pos);
273 free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE));
274 DBUG_PRINT(
"exit",(
"Return: %d",error));
278 uint _ft_make_key(
MI_INFO *info, uint keynr, uchar *keybuf,
FT_WORD *wptr,
281 uchar
buf[HA_FT_MAXBYTELEN+16];
282 DBUG_ENTER(
"_ft_make_key");
284 #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
286 float weight=(float) ((filepos==HA_OFFSET_ERROR) ? 0 : wptr->weight);
287 mi_float4store(buf,weight);
293 int2store(buf+HA_FT_WLEN,wptr->len);
294 memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len);
295 DBUG_RETURN(_mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos));
303 uint _mi_ft_convert_to_ft2(
MI_INFO *info, uint keynr, uchar *key)
307 MI_KEYDEF *keyinfo=&info->s->ft2_keyinfo;
308 uchar *key_ptr= (uchar*) dynamic_array_ptr(da, 0), *end;
309 uint length, key_length;
310 DBUG_ENTER(
"_mi_ft_convert_to_ft2");
314 length=(keyinfo->block_length-2) / keyinfo->keylength;
315 set_if_smaller(length, da->elements);
316 length=length * keyinfo->keylength;
318 get_key_full_length_rdonly(key_length, key);
319 while (_mi_ck_delete(info, keynr, key, key_length) == 0)
328 mi_putint(info->buff,length+2,0);
329 memcpy(info->buff+2, key_ptr, length);
330 info->buff_used=info->page_changed=1;
331 if ((root= _mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR ||
332 _mi_write_keypage(info,keyinfo,root,DFLT_INIT_HITS,info->buff))
336 end= (uchar*) dynamic_array_ptr(da, da->elements);
337 for (key_ptr+=length; key_ptr < end; key_ptr+=keyinfo->keylength)
338 if(_mi_ck_real_write_btree(info, keyinfo, key_ptr, 0, &root, SEARCH_SAME))
342 ft_intXstore(key+key_length, - (
int) da->elements);
343 _mi_dpointer(info, key+key_length+HA_FT_WLEN, root);
345 DBUG_RETURN(_mi_ck_real_write_btree(info,
346 info->s->keyinfo+keynr,
348 &info->s->state.key_root[keynr],