diff --git a/include/maria.h b/include/maria.h index c5bd8641c38675fab32d0e7d5a0af09c4e9be64b..d14ca10e9b567f6936f4fb8477aecea22740f53b 100644 --- a/include/maria.h +++ b/include/maria.h @@ -191,7 +191,7 @@ typedef struct st_maria_keydef /* Key definition with open & info */ uint16 maxlength; /* max length of (packed) key (auto) */ uint32 write_comp_flag; /* compare flag for write key (auto) */ uint32 version; /* For concurrent read/write */ - uint32 ftparser_nr; /* distinct ftparser number */ + uint32 ftkey_nr; /* full-text index number */ HA_KEYSEG *seg, *end; struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */ diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 8f5e07e27f28427a85dab81a1f38ad9be34e63d5..047ac0617069b764856a9bc0f08dbee4237af868 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -3675,7 +3675,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, Note, built-in parser is always nr. 0 - see ftparser_call_initializer() */ - if (sort_param.keyinfo->ftparser_nr == 0) + if (sort_param.keyinfo->ftkey_nr == 0) { /* for built-in parser the number of generated index entries @@ -4222,6 +4222,9 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, sort_param[0].fix_datafile= ! rep_quick; sort_param[0].calc_checksum= test(param->testflag & T_CALC_CHECKSUM); + if (!maria_ftparser_alloc_param(info)) + goto err; + sort_info.got_error=0; pthread_mutex_lock(&sort_info.mutex); diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index 3bcbd9edfbf61f0baa287400d02d30a712bd8d2c..148fc8c783c86c664ee882a4535ea85e9f058283 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -161,11 +161,11 @@ static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b) static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b) { - /* ORDER BY word DESC, ndepth DESC */ - int i= ha_compare_text(cs, (uchar*) (*b)->word+1,(*b)->len-1, - (uchar*) (*a)->word+1,(*a)->len-1,0,0); + /* ORDER BY word, ndepth */ + int i= ha_compare_text(cs, (uchar*) (*a)->word + 1,(*a)->len - 1, + (uchar*) (*b)->word + 1,(*b)->len - 1, 0, 0); if (!i) - i=CMP_NUM((*b)->ndepth,(*a)->ndepth); + i=CMP_NUM((*a)->ndepth, (*b)->ndepth); return i; } @@ -879,23 +879,49 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, FT_INFO *ftb= ftb_param->ftb; FTB_WORD *ftbw; int a, b, c; + /* + Find right-most element in the array of query words matching this + word from a document. + */ for (a= 0, b= ftb->queue.elements, c= (a+b)/2; b-a>1; c= (a+b)/2) { ftbw= ftb->list[c]; if (ha_compare_text(ftb->charset, (uchar*)word, len, (uchar*)ftbw->word+1, ftbw->len-1, - (my_bool)(ftbw->flags&FTB_FLAG_TRUNC), 0) > 0) + (my_bool)(ftbw->flags&FTB_FLAG_TRUNC), 0) < 0) b= c; else a= c; } + /* + If there were no words with truncation operator, we iterate to the + beginning of an array until array element is equal to the word from + a document. This is done mainly because the same word may be + mentioned twice (or more) in the query. + + In case query has words with truncation operator we must iterate + to the beginning of the array. There may be non-matching query words + between matching word with truncation operator and the right-most + matching element. E.g., if we're looking for 'aaa15' in an array of + 'aaa1* aaa14 aaa15 aaa16'. + + Worse of that there still may be match even if the binary search + above didn't find matching element. E.g., if we're looking for + 'aaa15' in an array of 'aaa1* aaa14 aaa16'. The binary search will + stop at 'aaa16'. + */ for (; c >= 0; c--) { ftbw= ftb->list[c]; if (ha_compare_text(ftb->charset, (uchar*)word, len, (uchar*)ftbw->word + 1,ftbw->len - 1, (my_bool)(ftbw->flags & FTB_FLAG_TRUNC), 0)) - break; + { + if (ftb->with_scan & FTB_FLAG_TRUNC) + continue; + else + break; + } if (ftbw->docid[1] == ftb->info->cur_row.lastpos) continue; ftbw->docid[1]= ftb->info->cur_row.lastpos; diff --git a/storage/maria/ma_ft_parser.c b/storage/maria/ma_ft_parser.c index 25704f1af5affafd6f58b1ad22292b5630eb7c6f..8eb40a207898bd08b71ce639a7387bee948f2755 100644 --- a/storage/maria/ma_ft_parser.c +++ b/storage/maria/ma_ft_parser.c @@ -326,59 +326,39 @@ int maria_ft_parse(TREE *wtree, uchar *doc, int doclen, #define MAX_PARAM_NR 2 -MYSQL_FTPARSER_PARAM *maria_ftparser_call_initializer(MARIA_HA *info, - uint keynr, uint paramnr) + +MYSQL_FTPARSER_PARAM* maria_ftparser_alloc_param(MARIA_HA *info) { - uint32 ftparser_nr; - struct st_mysql_ftparser *parser; - if (! info->ftparser_param) + if (!info->ftparser_param) { - /* info->ftparser_param can not be zero after the initialization, - because it always includes built-in fulltext parser. And built-in - parser can be called even if the table has no fulltext indexes and - no varchar/text fields. */ - if (! info->s->ftparsers) - { - /* It's ok that modification to shared structure is done w/o mutex - locks, because all threads would set the same variables to the - same values. */ - uint i, j, keys= info->s->state.header.keys, ftparsers= 1; - for (i= 0; i < keys; i++) - { - MARIA_KEYDEF *keyinfo= &info->s->keyinfo[i]; - if (keyinfo->flag & HA_FULLTEXT) - { - for (j= 0;; j++) - { - if (j == i) - { - keyinfo->ftparser_nr= ftparsers++; - break; - } - if (info->s->keyinfo[j].flag & HA_FULLTEXT && - keyinfo->parser == info->s->keyinfo[j].parser) - { - keyinfo->ftparser_nr= info->s->keyinfo[j].ftparser_nr; - break; - } - } - } - } - info->s->ftparsers= ftparsers; - } - /* - We have to allocate two MYSQL_FTPARSER_PARAM structures per plugin - because in a boolean search a parser is called recursively - ftb_find_relevance* calls ftb_check_phrase* - (MAX_PARAM_NR=2) + /* +. info->ftparser_param can not be zero after the initialization, + because it always includes built-in fulltext parser. And built-in + parser can be called even if the table has no fulltext indexes and + no varchar/text fields. + + ftb_find_relevance... parser (ftb_find_relevance_parse, + ftb_find_relevance_add_word) calls ftb_check_phrase... parser + (ftb_check_phrase_internal, ftb_phrase_add_word). Thus MAX_PARAM_NR=2. */ info->ftparser_param= (MYSQL_FTPARSER_PARAM *) my_malloc(MAX_PARAM_NR * sizeof(MYSQL_FTPARSER_PARAM) * - info->s->ftparsers, MYF(MY_WME|MY_ZEROFILL)); + info->s->ftkeys, MYF(MY_WME | MY_ZEROFILL)); init_alloc_root(&info->ft_memroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0); - if (! info->ftparser_param) - return 0; } + return info->ftparser_param; +} + + +MYSQL_FTPARSER_PARAM *maria_ftparser_call_initializer(MARIA_HA *info, + uint keynr, uint paramnr) +{ + uint32 ftparser_nr; + struct st_mysql_ftparser *parser; + + if (!maria_ftparser_alloc_param(info)) + return 0; + if (keynr == NO_SUCH_KEY) { ftparser_nr= 0; @@ -386,7 +366,7 @@ MYSQL_FTPARSER_PARAM *maria_ftparser_call_initializer(MARIA_HA *info, } else { - ftparser_nr= info->s->keyinfo[keynr].ftparser_nr; + ftparser_nr= info->s->keyinfo[keynr].ftkey_nr; parser= info->s->keyinfo[keynr].parser; } DBUG_ASSERT(paramnr < MAX_PARAM_NR); @@ -419,7 +399,7 @@ void maria_ftparser_call_deinitializer(MARIA_HA *info) for (j=0; j < MAX_PARAM_NR; j++) { MYSQL_FTPARSER_PARAM *ftparser_param= - &info->ftparser_param[keyinfo->ftparser_nr*MAX_PARAM_NR + j]; + &info->ftparser_param[keyinfo->ftkey_nr*MAX_PARAM_NR + j]; if (keyinfo->flag & HA_FULLTEXT && ftparser_param->mysql_add_word) { if (keyinfo->parser->deinit) diff --git a/storage/maria/ma_ftdefs.h b/storage/maria/ma_ftdefs.h index bd5309ea265517c105e9f985d674bb854b375600..7e83d774aed43d6debd81ce676eb0037b5ec7832 100644 --- a/storage/maria/ma_ftdefs.h +++ b/storage/maria/ma_ftdefs.h @@ -147,6 +147,7 @@ void maria_ft_boolean_close_search(FT_INFO *); float maria_ft_boolean_get_relevance(FT_INFO *); my_off_t maria_ft_boolean_get_docid(FT_INFO *); void maria_ft_boolean_reinit_search(FT_INFO *); +MYSQL_FTPARSER_PARAM* maria_ftparser_alloc_param(MARIA_HA *info); extern MYSQL_FTPARSER_PARAM *maria_ftparser_call_initializer(MARIA_HA *info, uint keynr, uint paramnr); diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index c6c786910db1d6bf630c6c1a60dc528059d71ace..cc004c23a252a6edbba6eaccb1389151770524dc 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -537,6 +537,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->block_size= share->base.block_size; /* Convenience */ { HA_KEYSEG *pos=share->keyparts; + uint32 ftkey_nr= 1; for (i=0 ; i < keys ; i++) { share->keyinfo[i].share= share; @@ -609,6 +610,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) share->ft2_keyinfo.end=pos; setup_key_functions(& share->ft2_keyinfo); } + share->keyinfo[i].ftkey_nr= ftkey_nr++; } setup_key_functions(share->keyinfo+i); share->keyinfo[i].end=pos; @@ -646,7 +648,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) pos->flag=0; pos++; } - share->ftparsers= 0; + share->ftkeys= ftkey_nr; } share->data_file_type= share->state.header.data_file_type; share->base_length= (BASE_ROW_HEADER_SIZE + @@ -1527,7 +1529,7 @@ uchar *_ma_keydef_read(uchar *ptr, MARIA_KEYDEF *keydef) keydef->underflow_block_length=keydef->block_length/3; keydef->version = 0; /* Not saved */ keydef->parser = &ft_default_parser; - keydef->ftparser_nr = 0; + keydef->ftkey_nr = 0; return ptr; } diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 7c2017c46715632ffb202d6fa155b0557fa76add..bbc3246f323a71872e186ceaf3290229406ae698 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -348,7 +348,7 @@ typedef struct st_maria_share ulong state_diff_length; uint rec_reflength; /* rec_reflength in use now */ uint keypage_header; - uint32 ftparsers; /* Number of distinct ftparsers + uint32 ftkeys; /* Number of distinct full-text keys + 1 */ PAGECACHE_FILE kfile; /* Shared keyfile */ File data_file; /* Shared data file */ diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index 234ac61c08dadd48ba85d26addbd7a6af9e21711..706a09353638840a2af27a223309a5f72ff971af 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -302,7 +302,7 @@ static void print_version(void) static void usage(void) { print_version(); - puts("Copyright (C) 2002 MySQL AB"); + puts("Copyright 2002-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc."); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); puts("and you are welcome to modify and redistribute it under the GPL license\n");