54 static int FT_SUPERDOC_cmp(
void* cmp_arg __attribute__((unused)),
57 if (p1->doc.dpos < p2->doc.dpos)
59 if (p1->doc.dpos == p2->doc.dpos)
66 int UNINIT_VAR(subkeys), r;
73 uchar *keybuff=aio->keybuff;
74 MI_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
76 uint
extra= HA_FT_WLEN + info->s->rec_reflength;
77 #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
83 DBUG_ENTER(
"walk_and_match");
85 word->weight=LWS_FOR_QUERY;
87 keylen=_ft_make_key(info,aio->keynr,keybuff,word,0);
91 if (share->concurrent_insert)
94 key_root= share->state.key_root[aio->keynr];
97 for (r=_mi_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root) ;
99 (subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 &&
100 info->lastpos >= info->state->data_file_length ;
101 r= _mi_search_next(info, keyinfo, info->lastkey,
102 info->lastkey_length, SEARCH_BIGGER, key_root))
105 if (share->concurrent_insert)
108 info->update|= HA_STATE_AKTIV;
111 while (!r && gweight)
115 ha_compare_text(aio->charset,info->lastkey+1,
116 info->lastkey_length-extra-1, keybuff+1,keylen-1,0,0))
128 keyinfo=& info->s->ft2_keyinfo;
129 key_root=info->lastpos;
131 if (share->concurrent_insert)
133 r=_mi_search_first(info, keyinfo, key_root);
136 #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
137 ft_floatXget(tmp_weight, info->lastkey+info->lastkey_length-extra);
143 DBUG_RETURN(doc_cnt);
145 sdoc.doc.dpos=info->lastpos;
148 if (!(selem=tree_insert(&aio->dtree, &sdoc, 0, aio->dtree.custom_arg)))
151 sptr=(
FT_SUPERDOC *)ELEMENT_KEY((&aio->dtree), selem);
156 sptr->doc.weight+=sptr->tmp_weight*sptr->word_ptr->weight;
159 sptr->tmp_weight=tmp_weight;
163 gweight=word->weight*GWS_IN_USE;
164 if (gweight < 0 || doc_cnt > 2000000)
167 if (share->concurrent_insert)
170 if (_mi_test_if_changed(info) == 0)
171 r=_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
172 SEARCH_BIGGER, key_root);
174 r=_mi_search(info, keyinfo, info->lastkey, info->lastkey_length,
175 SEARCH_BIGGER, key_root);
177 while ((subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 &&
178 !r && info->lastpos >= info->state->data_file_length)
179 r= _mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
180 SEARCH_BIGGER, key_root);
182 if (share->concurrent_insert)
185 word->weight=gweight;
192 uint32 count __attribute__((unused)),
FT_DOC **
to)
194 DBUG_ENTER(
"walk_and_copy");
195 from->doc.weight+=from->tmp_weight*from->word_ptr->weight;
196 (*to)->dpos=from->doc.dpos;
197 (*to)->weight=from->doc.weight;
203 uint32 count __attribute__((unused)),
QUEUE *best)
205 DBUG_ENTER(
"walk_and_copy");
206 from->doc.weight+=from->tmp_weight*from->word_ptr->weight;
207 set_if_smaller(best->elements, ft_query_expansion_limit-1);
208 queue_insert(best, (uchar *)& from->doc);
213 static int FT_DOC_cmp(
void *unused __attribute__((unused)),
216 double c= b->weight - a->weight;
217 return ((c < 0) ? -1 : (c > 0) ? 1 : 0);
228 my_off_t saved_lastpos=info->lastpos;
231 DBUG_ENTER(
"ft_init_nlq_search");
234 if ((
int) (keynr = _mi_check_index(info,keynr)) < 0)
236 if (_mi_readinfo(info,F_RDLCK,1))
242 aio.charset=info->s->keyinfo[keynr].seg->charset;
243 aio.keybuff=info->lastkey+info->s->base.max_key_length;
244 parser= info->s->keyinfo[keynr].parser;
245 if (! (ftparser_param= ftparser_call_initializer(info, keynr, 0)))
248 memset(&wtree, 0,
sizeof(wtree));
250 init_tree(&aio.dtree,0,0,
sizeof(
FT_SUPERDOC),(qsort_cmp2)&FT_SUPERDOC_cmp,0,
253 ft_parse_init(&wtree, aio.charset);
254 ftparser_param->flags= 0;
255 if (ft_parse(&wtree, query, query_len, parser, ftparser_param,
259 if (tree_walk(&wtree, (tree_walk_action)&walk_and_match, &aio,
263 if (flags & FT_EXPAND && ft_query_expansion_limit)
266 init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
268 tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
269 &best, left_root_right);
270 while (best.elements)
272 my_off_t docid=((
FT_DOC *)queue_remove(& best, 0))->dpos;
273 if (!(*info->read_record)(info,docid,record))
275 info->update|= HA_STATE_AKTIV;
276 ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY;
277 if (unlikely(_mi_ft_parse(&wtree, info, keynr, record, ftparser_param,
286 reset_tree(&aio.dtree);
287 if (tree_walk(&wtree, (tree_walk_action)&walk_and_match, &aio,
299 (
int)(aio.dtree.elements_in_tree-1),
304 dlist->please= (
struct _ft_vft *) & _ft_vft_nlq;
305 dlist->ndocs=aio.dtree.elements_in_tree;
307 dlist->info=aio.info;
310 tree_walk(&aio.dtree, (tree_walk_action) &walk_and_copy,
311 &dptr, left_root_right);
313 if (flags & FT_SORTED)
314 my_qsort2(dlist->doc, dlist->ndocs,
sizeof(
FT_DOC), (qsort2_cmp)&FT_DOC_cmp,
318 delete_tree(&aio.dtree);
320 info->lastpos=saved_lastpos;
329 if (++handler->curdoc >= handler->ndocs)
332 return HA_ERR_END_OF_FILE;
335 info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
337 info->lastpos=handler->doc[handler->curdoc].dpos;
338 if (!(*info->read_record)(info,info->lastpos,(uchar*) record))
340 info->update|= HA_STATE_AKTIV;
347 float ft_nlq_find_relevance(
FT_INFO *handler,
348 uchar *record __attribute__((unused)),
349 uint length __attribute__((unused)))
352 FT_DOC *docs=handler->doc;
353 my_off_t docid=handler->info->lastpos;
355 if (docid == HA_POS_ERROR)
360 for (a=0, b=handler->ndocs, c=(a+b)/2; b-a>1; c=(a+b)/2)
362 if (docs[c].dpos > docid)
368 if (a < handler->ndocs && docs[a].dpos == docid)
369 return (
float) docs[a].weight;
375 void ft_nlq_close_search(
FT_INFO *handler)
381 float ft_nlq_get_relevance(
FT_INFO *handler)
383 return (
float) handler->doc[handler->curdoc].weight;
387 void ft_nlq_reinit_search(
FT_INFO *handler)