829
827
(*key_checksum)+= mi_byte_checksum((uchar*) key,
830
828
key_length- info->s->rec_reflength);
831
829
record= _mi_dpos(info,0,key+key_length);
832
if (keyinfo->flag & HA_FULLTEXT) /* special handling for ft2 */
836
get_key_full_length_rdonly(off, key);
837
subkeys=ft_sintXkorr(key+off);
841
if (chk_index_down(param,info,&info->s->ft2_keyinfo,record,
842
temp_buff,&tmp_keys,key_checksum,1))
844
if (tmp_keys + subkeys)
846
mi_check_print_error(param,
847
"Number of words in the 2nd level tree "
848
"does not match the number in the header. "
849
"Parent word in on the page %s, offset %u",
850
llstr(page,llbuff), (uint) (old_keypos-buff));
858
830
if (record >= info->state->data_file_length)
2359
2302
info->state->records=info->state->del=share->state.split=0;
2360
2303
info->state->empty=0;
2362
if (sort_param.keyinfo->flag & HA_FULLTEXT)
2364
uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
2365
sort_param.keyinfo->seg->charset->mbmaxlen;
2366
sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
2368
fulltext indexes may have much more entries than the
2369
number of rows in the table. We estimate the number here.
2371
Note, built-in parser is always nr. 0 - see ftparser_call_initializer()
2373
if (sort_param.keyinfo->ftparser_nr == 0)
2376
for built-in parser the number of generated index entries
2377
cannot be larger than the size of the data file divided
2378
by the minimal word's length
2380
sort_info.max_records=
2381
(ha_rows) (sort_info.filelength/ft_min_word_len+1);
2386
for external plugin parser we cannot tell anything at all :(
2387
so, we'll use all the sort memory and start from ~10 buffpeks.
2388
(see _create_index_by_sort)
2390
sort_info.max_records=
2391
10*param->sort_buffer_length/sort_param.key_length;
2394
sort_param.key_read=sort_ft_key_read;
2395
sort_param.key_write=sort_ft_key_write;
2399
2306
sort_param.key_read=sort_key_read;
2400
2307
sort_param.key_write=sort_key_write;
3118
3011
DBUG_RETURN(sort_write_record(sort_param));
3119
3012
} /* sort_key_read */
3121
static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key)
3124
SORT_INFO *sort_info=sort_param->sort_info;
3125
MI_INFO *info=sort_info->info;
3127
DBUG_ENTER("sort_ft_key_read");
3129
if (!sort_param->wordlist)
3133
free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
3134
if ((error=sort_get_next_record(sort_param)))
3136
if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record,
3137
&sort_param->wordroot)))
3141
error=sort_write_record(sort_param);
3143
sort_param->wordptr=sort_param->wordlist=wptr;
3148
wptr=(FT_WORD*)(sort_param->wordptr);
3151
sort_param->real_key_length=(info->s->rec_reflength+
3152
_ft_make_key(info, sort_param->key,
3153
key, wptr++, sort_param->filepos));
3155
if (sort_param->key_length > sort_param->real_key_length)
3156
bzero(key+sort_param->real_key_length,
3157
(sort_param->key_length-sort_param->real_key_length));
3161
free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
3162
sort_param->wordlist=0;
3163
error=sort_write_record(sort_param);
3166
sort_param->wordptr=(void*)wptr;
3169
} /* sort_ft_key_read */
3173
3016
Read next record from file using parameters in sort_info.
3813
3656
(uchar*) a, HA_OFFSET_ERROR));
3814
3657
} /* sort_key_write */
3816
int sort_ft_buf_flush(MI_SORT_PARAM *sort_param)
3818
SORT_INFO *sort_info=sort_param->sort_info;
3819
SORT_KEY_BLOCKS *key_block=sort_info->key_block;
3820
MYISAM_SHARE *share=sort_info->info->s;
3821
uint val_off, val_len;
3823
SORT_FT_BUF *ft_buf=sort_info->ft_buf;
3826
val_len=share->ft2_keyinfo.keylength;
3827
get_key_full_length_rdonly(val_off, ft_buf->lastkey);
3828
to=ft_buf->lastkey+val_off;
3832
/* flushing first-level tree */
3833
error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
3835
for (from=to+val_len;
3836
!error && from < ft_buf->buf;
3839
memcpy(to, from, val_len);
3840
error=sort_insert_key(sort_param,key_block,ft_buf->lastkey,
3845
/* flushing second-level tree keyblocks */
3846
error=flush_pending_blocks(sort_param);
3847
/* updating lastkey with second-level tree info */
3848
ft_intXstore(ft_buf->lastkey+val_off, -ft_buf->count);
3849
_mi_dpointer(sort_info->info, ft_buf->lastkey+val_off+HA_FT_WLEN,
3850
share->state.key_root[sort_param->key]);
3851
/* restoring first level tree data in sort_info/sort_param */
3852
sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks;
3853
sort_param->keyinfo=share->keyinfo+sort_param->key;
3854
share->state.key_root[sort_param->key]=HA_OFFSET_ERROR;
3855
/* writing lastkey in first-level tree */
3856
return error ? error :
3857
sort_insert_key(sort_param,sort_info->key_block,
3858
ft_buf->lastkey,HA_OFFSET_ERROR);
3861
static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
3863
uint a_len, val_off, val_len, error;
3865
SORT_INFO *sort_info=sort_param->sort_info;
3866
SORT_FT_BUF *ft_buf=sort_info->ft_buf;
3867
SORT_KEY_BLOCKS *key_block=sort_info->key_block;
3869
val_len=HA_FT_WLEN+sort_info->info->s->base.rec_reflength;
3870
get_key_full_length_rdonly(a_len, (uchar *)a);
3875
use two-level tree only if key_reflength fits in rec_reflength place
3876
and row format is NOT static - for _mi_dpointer not to garble offsets
3878
if ((sort_info->info->s->base.key_reflength <=
3879
sort_info->info->s->base.rec_reflength) &&
3880
(sort_info->info->s->options &
3881
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
3882
ft_buf=(SORT_FT_BUF *)my_malloc(sort_param->keyinfo->block_length +
3883
sizeof(SORT_FT_BUF), MYF(MY_WME));
3887
sort_param->key_write=sort_key_write;
3888
return sort_key_write(sort_param, a);
3890
sort_info->ft_buf=ft_buf;
3891
goto word_init_ft_buf; /* no need to duplicate the code */
3893
get_key_full_length_rdonly(val_off, ft_buf->lastkey);
3895
if (ha_compare_text(sort_param->seg->charset,
3896
((uchar *)a)+1,a_len-1,
3897
ft_buf->lastkey+1,val_off-1, 0, 0)==0)
3899
if (!ft_buf->buf) /* store in second-level tree */
3902
return sort_insert_key(sort_param,key_block,
3903
((uchar *)a)+a_len, HA_OFFSET_ERROR);
3906
/* storing the key in the buffer. */
3907
memcpy (ft_buf->buf, (char *)a+a_len, val_len);
3908
ft_buf->buf+=val_len;
3909
if (ft_buf->buf < ft_buf->end)
3912
/* converting to two-level tree */
3913
p=ft_buf->lastkey+val_off;
3915
while (key_block->inited)
3917
sort_info->key_block=key_block;
3918
sort_param->keyinfo=& sort_info->info->s->ft2_keyinfo;
3919
ft_buf->count=(ft_buf->buf - p)/val_len;
3921
/* flushing buffer to second-level tree */
3922
for (error=0; !error && p < ft_buf->buf; p+= val_len)
3923
error=sort_insert_key(sort_param,key_block,p,HA_OFFSET_ERROR);
3928
/* flushing buffer */
3929
if ((error=sort_ft_buf_flush(sort_param)))
3934
memcpy(ft_buf->lastkey, a, a_len);
3935
ft_buf->buf=ft_buf->lastkey+a_len;
3937
32 is just a safety margin here
3938
(at least max(val_len, sizeof(nod_flag)) should be there).
3939
May be better performance could be achieved if we'd put
3940
(sort_info->keyinfo->block_length-32)/XXX
3942
TODO: benchmark the best value for XXX.
3944
ft_buf->end=ft_buf->lastkey+ (sort_param->keyinfo->block_length-32);
3946
} /* sort_ft_key_write */
3949
3660
/* get pointer to record from a key */