diff options
author | Sergei Golubchik <sergii@pisem.net> | 2010-11-25 18:17:28 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2010-11-25 18:17:28 +0100 |
commit | 65ca700def99289cc31a7040537f5aa6e12bf485 (patch) | |
tree | 97b3a07299b626c519da0e80c122b5b79b933914 /storage/myisam | |
parent | 2ab57de38d13d927ddff2d51aed4af34e13998f5 (diff) | |
parent | 6e5bcca7935d3c62f84bb640e5357664a210ee12 (diff) | |
download | mariadb-git-65ca700def99289cc31a7040537f5aa6e12bf485.tar.gz |
merge.
checkpoint.
does not compile.
Diffstat (limited to 'storage/myisam')
52 files changed, 1598 insertions, 1146 deletions
diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt index 487fbded2df..5abd8c29e64 100644 --- a/storage/myisam/CMakeLists.txt +++ b/storage/myisam/CMakeLists.txt @@ -15,6 +15,7 @@ SET(MYISAM_SOURCES ft_boolean_search.c ft_nlq_search.c ft_parser.c ft_static.c ha_myisam.cc + ft_myisam.c ft_stopwords.c ft_update.c mi_cache.c mi_changed.c mi_check.c mi_checksum.c mi_close.c mi_create.c mi_dbug.c mi_delete.c mi_delete_all.c mi_delete_table.c mi_dynrec.c mi_extra.c mi_info.c @@ -65,3 +66,4 @@ ENDIF() IF (MSVC) SET_TARGET_PROPERTIES(myisamchk myisampack PROPERTIES LINK_FLAGS "setargv.obj") ENDIF() + diff --git a/storage/myisam/Makefile.am b/storage/myisam/Makefile.am index 5c3370ac6c5..5d8a5e9753b 100644 --- a/storage/myisam/Makefile.am +++ b/storage/myisam/Makefile.am @@ -28,7 +28,7 @@ LDADD = DEFS = @DEFS@ EXTRA_DIST = mi_test_all.sh mi_test_all.res CMakeLists.txt plug.in -pkgdata_DATA = mi_test_all mi_test_all.res +pkgdata_DATA = pkglib_LIBRARIES = libmyisam.a bin_PROGRAMS = myisamchk myisamlog myisampack myisam_ftdump @@ -94,8 +94,8 @@ libmyisam_a_SOURCES = mi_open.c mi_extra.c mi_info.c mi_rkey.c \ mi_delete_table.c mi_rename.c mi_check.c \ mi_keycache.c mi_preload.c \ ft_parser.c ft_stopwords.c ft_static.c \ - ft_update.c ft_boolean_search.c ft_nlq_search.c sort.c \ - ha_myisam.cc \ + ft_update.c ft_boolean_search.c ft_nlq_search.c \ + sort.c ha_myisam.cc ft_myisam.c \ rt_index.c rt_key.c rt_mbr.c rt_split.c sp_key.c CLEANFILES = test?.MY? FT?.MY? isam.log mi_test_all rt_test.MY? sp_test.MY? diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index b54b4c6ce49..7d615d837d3 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -182,7 +182,7 @@ typedef struct st_my_ftb_param static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, - char *word, int word_len, + const uchar *word, mysql_ft_size_t word_len, MYSQL_FTPARSER_BOOLEAN_INFO *info) { MY_FTB_PARAM *ftb_param= param->mysql_ftparam; @@ -198,7 +198,7 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, case FT_TOKEN_WORD: ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root, sizeof(FTB_WORD) + - (info->trunc ? MI_MAX_KEY_BUFF : + (info->trunc ? HA_MAX_KEY_BUFF : word_len * ftb_param->ftb->charset->mbmaxlen + HA_FT_WLEN + ftb_param->ftb->info->s->rec_reflength)); @@ -284,24 +284,24 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param, static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param, - char *query, int len) + const uchar *query, mysql_ft_size_t len) { MY_FTB_PARAM *ftb_param= param->mysql_ftparam; MYSQL_FTPARSER_BOOLEAN_INFO info; CHARSET_INFO *cs= ftb_param->ftb->charset; - uchar **start= (uchar**) &query; - uchar *end= (uchar*) query + len; + const uchar **start= &query; + const uchar *end= query + len; FT_WORD w; info.prev= ' '; info.quot= 0; while (ft_get_word(cs, start, end, &w, &info)) - param->mysql_add_word(param, (char*) w.pos, w.len, &info); + param->mysql_add_word(param, w.pos, w.len, &info); return(0); } -static int _ftb_parse_query(FTB *ftb, uchar *query, uint len, +static int _ftb_parse_query(FTB *ftb, uchar *query, mysql_ft_size_t len, struct st_mysql_ftparser *parser) { MYSQL_FTPARSER_PARAM *param; @@ -323,7 +323,7 @@ static int _ftb_parse_query(FTB *ftb, uchar *query, uint len, param->mysql_add_word= ftb_query_add_word; param->mysql_ftparam= (void *)&ftb_param; param->cs= ftb->charset; - param->doc= (char*) query; + param->doc= query; param->length= len; param->flags= 0; param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO; @@ -484,16 +484,18 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) static void _ftb_init_index_search(FT_INFO *ftb) { - int i; + uint i; FTB_WORD *ftbw; if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY) return; ftb->state=INDEX_SEARCH; - for (i=ftb->queue.elements; i; i--) + for (i= queue_last_element(&ftb->queue); + (int) i >= (int) queue_first_element(&ftb->queue); + i--) { - ftbw=(FTB_WORD *)(ftb->queue.root[i]); + ftbw=(FTB_WORD *)(queue_element(&ftb->queue, i)); if (ftbw->flags & FTB_FLAG_TRUNC) { @@ -552,7 +554,7 @@ static void _ftb_init_index_search(FT_INFO *ftb) FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, uchar *query, - uint query_len, CHARSET_INFO *cs) + mysql_ft_size_t query_len, CHARSET_INFO *cs) { FTB *ftb; FTB_EXPR *ftbe; @@ -597,14 +599,14 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, uchar *query, sizeof(void *)))) goto err; reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0, - (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0); + (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0, 0, 0); for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev) queue_insert(&ftb->queue, (uchar *)ftbw); ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root, sizeof(FTB_WORD *)*ftb->queue.elements); - memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements); + memcpy(ftb->list, &queue_top(&ftb->queue), sizeof(FTB_WORD *)*ftb->queue.elements); my_qsort2(ftb->list, ftb->queue.elements, sizeof(FTB_WORD *), - (qsort2_cmp)FTB_WORD_cmp_list, ftb->charset); + (qsort2_cmp)FTB_WORD_cmp_list, (void*) ftb->charset); if (ftb->queue.elements<2) ftb->with_scan &= ~FTB_FLAG_TRUNC; ftb->state=READY; return ftb; @@ -627,7 +629,7 @@ typedef struct st_my_ftb_phrase_param static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param, - char *word, int word_len, + const uchar *word, mysql_ft_size_t word_len, MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) { MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam; @@ -659,15 +661,16 @@ static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param, static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, - char *document, int len) + const uchar *document, + mysql_ft_size_t len) { FT_WORD word; MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam; const uchar *docend= (uchar*) document + len; - while (ft_simple_get_word(phrase_param->cs, (uchar**) &document, docend, + while (ft_simple_get_word(phrase_param->cs, &document, docend, &word, FALSE)) { - param->mysql_add_word(param, (char*) word.pos, word.len, 0); + param->mysql_add_word(param, word.pos, word.len, 0); if (phrase_param->match) break; } @@ -690,8 +693,9 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param, -1 is returned if error occurs. */ -static int _ftb_check_phrase(FTB *ftb, const uchar *document, uint len, - FTB_EXPR *ftbe, struct st_mysql_ftparser *parser) +static int _ftb_check_phrase(FTB *ftb, const uchar *document, + mysql_ft_size_t len, + FTB_EXPR *ftbe, struct st_mysql_ftparser *parser) { MY_FTB_PHRASE_PARAM ftb_param; MYSQL_FTPARSER_PARAM *param; @@ -712,7 +716,7 @@ static int _ftb_check_phrase(FTB *ftb, const uchar *document, uint len, param->mysql_add_word= ftb_phrase_add_word; param->mysql_ftparam= (void *)&ftb_param; param->cs= ftb->charset; - param->doc= (char *) document; + param->doc= document; param->length= len; param->flags= 0; param->mode= MYSQL_FTPARSER_WITH_STOPWORDS; @@ -839,7 +843,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record) /* update queue */ _ft2_search(ftb, ftbw, 0); - queue_replaced(& ftb->queue); + queue_replace_top(&ftb->queue); } ftbe=ftb->root; @@ -885,8 +889,9 @@ typedef struct st_my_ftb_find_param static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, - char *word, int len, - MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) + const uchar *word, mysql_ft_size_t len, + MYSQL_FTPARSER_BOOLEAN_INFO + *boolean_info __attribute__((unused))) { MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam; FT_INFO *ftb= ftb_param->ftb; @@ -899,8 +904,8 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, 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, + if (ha_compare_text(ftb->charset, word, len, + ftbw->word+1, ftbw->len-1, (my_bool) (ftbw->flags & FTB_FLAG_TRUNC), 0) < 0) b= c; else @@ -926,8 +931,8 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, for (; c >= 0; c--) { ftbw= ftb->list[c]; - if (ha_compare_text(ftb->charset, (uchar*)word, len, - (uchar*)ftbw->word + 1,ftbw->len - 1, + if (ha_compare_text(ftb->charset, word, len, + ftbw->word + 1,ftbw->len - 1, (my_bool)(ftbw->flags & FTB_FLAG_TRUNC), 0)) { if (ftb->with_scan & FTB_FLAG_TRUNC) @@ -946,14 +951,14 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param, static int ftb_find_relevance_parse(MYSQL_FTPARSER_PARAM *param, - char *doc, int len) + const uchar *doc, mysql_ft_size_t len) { MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam; FT_INFO *ftb= ftb_param->ftb; - uchar *end= (uchar*) doc + len; + const uchar *end= doc + len; FT_WORD w; - while (ft_simple_get_word(ftb->charset, (uchar**) &doc, end, &w, TRUE)) - param->mysql_add_word(param, (char*) w.pos, w.len, 0); + while (ft_simple_get_word(ftb->charset, &doc, end, &w, TRUE)) + param->mysql_add_word(param, w.pos, w.len, 0); return(0); } @@ -1009,7 +1014,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, uchar *record, uint length) { if (!ftsi.pos) continue; - param->doc= (char *)ftsi.pos; + param->doc= ftsi.pos; param->length= ftsi.len; if (unlikely(parser->parse(param))) return 0; diff --git a/storage/myisam/ft_myisam.c b/storage/myisam/ft_myisam.c new file mode 100644 index 00000000000..7bcc62d5bf5 --- /dev/null +++ b/storage/myisam/ft_myisam.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Written by Sergei A. Golubchik, who has a shared copyright to this code */ + +/* + This function is for interface functions between fulltext and myisam +*/ + +#include "ftdefs.h" + +FT_INFO *ft_init_search(uint flags, void *info, uint keynr, + uchar *query, size_t query_len, + CHARSET_INFO *cs, uchar *record) +{ + FT_INFO *res; + if (flags & FT_BOOL) + res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len,cs); + else + res= ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags, + record); + return res; +} diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 937bb6ffe19..e19765efe3e 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -63,7 +63,8 @@ static int FT_SUPERDOC_cmp(void* cmp_arg __attribute__((unused)), static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) { - int subkeys, r; + FT_WEIGTH subkeys; + int r; uint keylen, doc_cnt; FT_SUPERDOC sdoc, *sptr; TREE_ELEMENT *selem; @@ -90,7 +91,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) /* Skip rows inserted by current inserted */ for (r=_mi_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root) ; !r && - (subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 && + (subkeys.i= ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 && info->lastpos >= info->state->data_file_length ; r= _mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length, SEARCH_BIGGER, key_root)) @@ -107,7 +108,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) info->lastkey_length-extra-1, keybuff+1,keylen-1,0,0)) break; - if (subkeys<0) + if (subkeys.i < 0) { if (doc_cnt) DBUG_RETURN(1); /* index is corrupted */ @@ -123,7 +124,8 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) goto do_skip; } #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT - ft_floatXget(tmp_weight, info->lastkey+info->lastkey_length-extra); + /* The weight we read was actually a float */ + tmp_weight= subkeys.f; #else #error #endif @@ -160,7 +162,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) r=_mi_search(info, keyinfo, info->lastkey, info->lastkey_length, SEARCH_BIGGER, key_root); do_skip: - while ((subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 && + while ((subkeys.i= ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 && !r && info->lastpos >= info->state->data_file_length) r= _mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length, SEARCH_BIGGER, key_root); @@ -203,7 +205,8 @@ static int FT_DOC_cmp(void *unused __attribute__((unused)), FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query, - uint query_len, uint flags, uchar *record) + mysql_ft_size_t query_len, uint flags, + uchar *record) { TREE wtree; ALL_IN_ONE aio; @@ -248,12 +251,12 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query, { QUEUE best; init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp, - 0); + 0, 0, 0); tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push, &best, left_root_right); while (best.elements) { - my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos; + my_off_t docid= ((FT_DOC *)queue_remove_top(&best))->dpos; if (!(*info->read_record)(info,docid,record)) { info->update|= HA_STATE_AKTIV; diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index 663d7869f71..af16240bca2 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -106,10 +106,10 @@ my_bool ft_boolean_check_syntax_string(const uchar *str) 3 - right bracket 4 - stopword found */ -uchar ft_get_word(CHARSET_INFO *cs, uchar **start, uchar *end, +uchar ft_get_word(CHARSET_INFO *cs, const uchar **start, const uchar *end, FT_WORD *word, MYSQL_FTPARSER_BOOLEAN_INFO *param) { - uchar *doc=*start; + const uchar *doc= *start; int ctype; uint mwc, length; int mbl; @@ -174,7 +174,7 @@ uchar ft_get_word(CHARSET_INFO *cs, uchar **start, uchar *end, if ((param->trunc=(doc<end && *doc == FTB_TRUNC))) doc++; - if (((length >= ft_min_word_len && !is_stopword((char*) word->pos, + if (((length >= ft_min_word_len && !is_stopword(word->pos, word->len)) || param->trunc) && length < ft_max_word_len) { @@ -199,10 +199,11 @@ ret: return param->type; } -uchar ft_simple_get_word(CHARSET_INFO *cs, uchar **start, const uchar *end, - FT_WORD *word, my_bool skip_stopwords) +uchar ft_simple_get_word(CHARSET_INFO *cs, const uchar **start, + const uchar *end, FT_WORD *word, + my_bool skip_stopwords) { - uchar *doc= *start; + const uchar *doc= *start; uint mwc, length; int mbl; int ctype; @@ -214,7 +215,7 @@ uchar ft_simple_get_word(CHARSET_INFO *cs, uchar **start, const uchar *end, { if (doc >= end) DBUG_RETURN(0); - mbl= cs->cset->ctype(cs, &ctype, (uchar*)doc, (uchar*)end); + mbl= cs->cset->ctype(cs, &ctype, doc, end); if (true_word_char(ctype, *doc)) break; } @@ -223,7 +224,7 @@ uchar ft_simple_get_word(CHARSET_INFO *cs, uchar **start, const uchar *end, for (word->pos= doc; doc < end; length++, doc+= (mbl > 0 ? mbl : (mbl < 0 ? -mbl : 1))) { - mbl= cs->cset->ctype(cs, &ctype, (uchar*)doc, (uchar*)end); + mbl= cs->cset->ctype(cs, &ctype, doc, end); if (true_word_char(ctype, *doc)) mwc= 0; else if (!misc_word_char(*doc) || mwc) @@ -236,7 +237,7 @@ uchar ft_simple_get_word(CHARSET_INFO *cs, uchar **start, const uchar *end, if (skip_stopwords == FALSE || (length >= ft_min_word_len && length < ft_max_word_len && - !is_stopword((char*) word->pos, word->len))) + !is_stopword(word->pos, word->len))) { *start= doc; DBUG_RETURN(1); @@ -249,14 +250,16 @@ void ft_parse_init(TREE *wtree, CHARSET_INFO *cs) { DBUG_ENTER("ft_parse_init"); if (!is_tree_inited(wtree)) - init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL, cs); + init_tree(wtree,0,0,sizeof(FT_WORD),(qsort_cmp2)&FT_WORD_cmp,0,NULL, + (void*) cs); DBUG_VOID_RETURN; } static int ft_add_word(MYSQL_FTPARSER_PARAM *param, - char *word, int word_len, - MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused))) + const uchar *word, mysql_ft_size_t word_len, + MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info + __attribute__((unused))) { TREE *wtree; FT_WORD w; @@ -284,23 +287,23 @@ static int ft_add_word(MYSQL_FTPARSER_PARAM *param, static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param, - char *doc_arg, int doc_len) + const uchar *doc_arg, mysql_ft_size_t doc_len) { - uchar *doc= (uchar*) doc_arg; - uchar *end= doc + doc_len; + const uchar *doc= doc_arg; + const uchar *end= doc + doc_len; MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam; TREE *wtree= ft_param->wtree; FT_WORD w; DBUG_ENTER("ft_parse_internal"); while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE)) - if (param->mysql_add_word(param, (char*) w.pos, w.len, 0)) + if (param->mysql_add_word(param, w.pos, w.len, 0)) DBUG_RETURN(1); DBUG_RETURN(0); } -int ft_parse(TREE *wtree, uchar *doc, int doclen, +int ft_parse(TREE *wtree, const uchar *doc, mysql_ft_size_t doclen, struct st_mysql_ftparser *parser, MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root) { @@ -315,7 +318,7 @@ int ft_parse(TREE *wtree, uchar *doc, int doclen, param->mysql_add_word= ft_add_word; param->mysql_ftparam= &my_param; param->cs= wtree->custom_arg; - param->doc= (char*) doc; + param->doc= doc; param->length= doclen; param->mode= MYSQL_FTPARSER_SIMPLE_MODE; DBUG_RETURN(parser->parse(param)); @@ -375,8 +378,8 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info, mysql_add_word != 0 - parser is initialized, or no initialization needed. */ info->ftparser_param[ftparser_nr].mysql_add_word= - (int (*)(struct st_mysql_ftparser_param *, char *, int, - MYSQL_FTPARSER_BOOLEAN_INFO *)) 1; + (int (*)(struct st_mysql_ftparser_param *, const uchar *, + mysql_ft_size_t, MYSQL_FTPARSER_BOOLEAN_INFO *)) 1; if (parser->init && parser->init(&info->ftparser_param[ftparser_nr])) return 0; } diff --git a/storage/myisam/ft_static.c b/storage/myisam/ft_static.c index 78fbc5781e9..6a0bda5b666 100644 --- a/storage/myisam/ft_static.c +++ b/storage/myisam/ft_static.c @@ -54,20 +54,6 @@ const struct _ft_vft _ft_vft_boolean= { ft_boolean_get_relevance, ft_boolean_reinit_search }; - -FT_INFO *ft_init_search(uint flags, void *info, uint keynr, - uchar *query, uint query_len, CHARSET_INFO *cs, - uchar *record) -{ - FT_INFO *res; - if (flags & FT_BOOL) - res= ft_init_boolean_search((MI_INFO *)info, keynr, query, query_len,cs); - else - res= ft_init_nlq_search((MI_INFO *)info, keynr, query, query_len, flags, - record); - return res; -} - const char *ft_stopword_file= 0; const char *ft_precompiled_stopwords[]= { diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index e8d81cbbbb1..1079cf83417 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -24,8 +24,8 @@ static CHARSET_INFO *ft_stopword_cs= NULL; typedef struct st_ft_stopwords { - const char * pos; - uint len; + const uchar* pos; + size_t len; } FT_STOPWORD; static TREE *stopwords3=NULL; @@ -34,8 +34,8 @@ static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)), FT_STOPWORD *w1, FT_STOPWORD *w2) { return ha_compare_text(ft_stopword_cs, - (uchar *)w1->pos,w1->len, - (uchar *)w2->pos,w2->len,0,0); + w1->pos, w1->len, + w2->pos, w2->len, 0, 0); } static void FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, @@ -48,17 +48,19 @@ static void FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, static int ft_add_stopword(const char *w) { FT_STOPWORD sw; - return !w || - (((sw.len= (uint) strlen(sw.pos=w)) >= ft_min_word_len) && - (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL)); + return (!w || + (((sw.len= (uint) strlen((char*) (sw.pos=(const uchar *)w))) >= + ft_min_word_len) && + (tree_insert(stopwords3, &sw, 0, stopwords3->custom_arg)==NULL))); } int ft_init_stopwords() { + DBUG_ENTER("ft_init_stopwords"); if (!stopwords3) { if (!(stopwords3=(TREE *)my_malloc(sizeof(TREE),MYF(0)))) - return -1; + DBUG_RETURN(-1); init_tree(stopwords3,0,0,sizeof(FT_STOPWORD),(qsort_cmp2)&FT_STOPWORD_cmp, 0, (ft_stopword_file ? (tree_element_free)&FT_STOPWORD_free : 0), @@ -77,15 +79,16 @@ int ft_init_stopwords() { File fd; uint len; - uchar *buffer, *start, *end; + uchar *buffer; + const uchar *start, *end; FT_WORD w; int error=-1; if (!*ft_stopword_file) - return 0; + DBUG_RETURN(0); if ((fd=my_open(ft_stopword_file, O_RDONLY, MYF(MY_WME))) == -1) - return -1; + DBUG_RETURN(-1); len=(uint)my_seek(fd, 0L, MY_SEEK_END, MYF(0)); my_seek(fd, 0L, MY_SEEK_SET, MYF(0)); if (!(start=buffer=my_malloc(len+1, MYF(MY_WME)))) @@ -102,7 +105,7 @@ err1: my_free(buffer); err0: my_close(fd, MYF(MY_WME)); - return error; + DBUG_RETURN(error); } else { @@ -112,14 +115,15 @@ err0: for (;*sws;sws++) { if (ft_add_stopword(*sws)) - return -1; + DBUG_RETURN(-1); } ft_stopword_file="(built-in)"; /* for SHOW VARIABLES */ } - return 0; + DBUG_RETURN(0); } -int is_stopword(char *word, uint len) + +int is_stopword(const uchar *word, size_t len) { FT_STOPWORD sw; sw.pos=word; @@ -130,6 +134,8 @@ int is_stopword(char *word, uint len) void ft_free_stopwords() { + DBUG_ENTER("ft_free_stopwords"); + if (stopwords3) { delete_tree(stopwords3); /* purecov: inspected */ @@ -137,4 +143,5 @@ void ft_free_stopwords() stopwords3=0; } ft_stopword_file= 0; + DBUG_VOID_RETURN; } diff --git a/storage/myisam/ftdefs.h b/storage/myisam/ftdefs.h index ddcf1a8dc26..b26fa523b42 100644 --- a/storage/myisam/ftdefs.h +++ b/storage/myisam/ftdefs.h @@ -96,22 +96,23 @@ #define FTB_RQUOT (ft_boolean_syntax[11]) typedef struct st_ft_word { - uchar * pos; - uint len; + const uchar *pos; double weight; + size_t len; } FT_WORD; -int is_stopword(char *word, uint len); +int is_stopword(const uchar *word, size_t len); uint _ft_make_key(MI_INFO *, uint , uchar *, FT_WORD *, my_off_t); -uchar ft_get_word(CHARSET_INFO *, uchar **, uchar *, FT_WORD *, +uchar ft_get_word(CHARSET_INFO *, const uchar **, const uchar *, FT_WORD *, MYSQL_FTPARSER_BOOLEAN_INFO *); -uchar ft_simple_get_word(CHARSET_INFO *, uchar **, const uchar *, +uchar ft_simple_get_word(CHARSET_INFO *, const uchar **, const uchar *, FT_WORD *, my_bool); typedef struct _st_ft_seg_iterator { - uint num, len; + uint num; + mysql_ft_size_t len; HA_KEYSEG *seg; const uchar *rec, *pos; } FT_SEG_ITERATOR; @@ -121,15 +122,16 @@ void _mi_ft_segiterator_dummy_init(const uchar *, uint, FT_SEG_ITERATOR *); uint _mi_ft_segiterator(FT_SEG_ITERATOR *); void ft_parse_init(TREE *, CHARSET_INFO *); -int ft_parse(TREE *, uchar *, int, struct st_mysql_ftparser *parser, +int ft_parse(TREE *, const uchar *, int, struct st_mysql_ftparser *parser, MYSQL_FTPARSER_PARAM *, MEM_ROOT *); FT_WORD * ft_linearize(TREE *, MEM_ROOT *); FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const uchar *, MEM_ROOT *); uint _mi_ft_parse(TREE *, MI_INFO *, uint, const uchar *, MYSQL_FTPARSER_PARAM *, MEM_ROOT *); -FT_INFO *ft_init_nlq_search(MI_INFO *, uint, uchar *, uint, uint, uchar *); -FT_INFO *ft_init_boolean_search(MI_INFO *, uint, uchar *, uint, CHARSET_INFO *); +FT_INFO *ft_init_nlq_search(MI_INFO *, uint, uchar *, mysql_ft_size_t, uint, + uchar *); +FT_INFO *ft_init_boolean_search(MI_INFO *, uint, uchar *, mysql_ft_size_t, CHARSET_INFO *); extern const struct _ft_vft _ft_vft_nlq; int ft_nlq_read_next(FT_INFO *, char *); diff --git a/storage/myisam/fulltext.h b/storage/myisam/fulltext.h index 853eb6362e6..9aef2d0d002 100644 --- a/storage/myisam/fulltext.h +++ b/storage/myisam/fulltext.h @@ -20,33 +20,8 @@ #include "myisamdef.h" #include "ft_global.h" -#define HA_FT_WTYPE HA_KEYTYPE_FLOAT -#define HA_FT_WLEN 4 -#define FT_SEGS 2 - -/** - Accessor methods for the weight and the number of subkeys in a buffer. - - The weight is of float type and subkeys number is of integer type. Both - are stored in the same position of the buffer and the stored object is - identified by the sign (bit): the weight value is positive whilst the - number of subkeys is negative. - - In light of C's strict-aliasing rules, which roughly state that an object - must not be accessed through incompatible types, these methods are used to - avoid any problems arising from the type duality inside the buffer. The - values are retrieved using a character type which can access any object. -*/ -#define ft_sintXkorr(A) mi_sint4korr(A) -#define ft_intXstore(T,A) mi_int4store(T,A) -#define ft_floatXget(V,M) mi_float4get(V,M) - - -extern const HA_KEYSEG ft_keysegs[FT_SEGS]; - int _mi_ft_cmp(MI_INFO *, uint, const uchar *, const uchar *); int _mi_ft_add(MI_INFO *, uint, uchar *, const uchar *, my_off_t); int _mi_ft_del(MI_INFO *, uint, uchar *, const uchar *, my_off_t); uint _mi_ft_convert_to_ft2(MI_INFO *, uint, uchar *); - diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 87de58076cd..fc6a9829072 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -132,13 +132,13 @@ static handler *myisam_create_handler(handlerton *hton, // collect errors printed by mi_check routines -static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, +static void mi_check_print_msg(HA_CHECK *param, const char* msg_type, const char *fmt, va_list args) { THD* thd = (THD*)param->thd; Protocol *protocol= thd->protocol; size_t length, msg_length; - char msgbuf[MI_MAX_MSG_BUF]; + char msgbuf[HA_MAX_MSG_BUF]; char name[NAME_LEN*2+2]; msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); @@ -313,7 +313,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, record= table_arg->record[0]; recpos= 0; recinfo_pos= recinfo; - while (recpos < (uint) share->reclength) + while (recpos < (uint) share->stored_rec_length) { Field **field, *found= 0; minpos= share->reclength; @@ -339,30 +339,31 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d", (long) found, recpos, minpos, length)); if (recpos != minpos) - { // Reserved space (Null bits?) + { + /* reserve space for null bits */ bzero((char*) recinfo_pos, sizeof(*recinfo_pos)); - recinfo_pos->type= (int) FIELD_NORMAL; + recinfo_pos->type= FIELD_NORMAL; recinfo_pos++->length= (uint16) (minpos - recpos); } if (!found) break; if (found->flags & BLOB_FLAG) - recinfo_pos->type= (int) FIELD_BLOB; + recinfo_pos->type= FIELD_BLOB; else if (found->type() == MYSQL_TYPE_VARCHAR) recinfo_pos->type= FIELD_VARCHAR; else if (!(options & HA_OPTION_PACK_RECORD)) - recinfo_pos->type= (int) FIELD_NORMAL; + recinfo_pos->type= FIELD_NORMAL; else if (found->zero_pack()) - recinfo_pos->type= (int) FIELD_SKIP_ZERO; + recinfo_pos->type= FIELD_SKIP_ZERO; else - recinfo_pos->type= (int) ((length <= 3 || - (found->flags & ZEROFILL_FLAG)) ? - FIELD_NORMAL : - found->type() == MYSQL_TYPE_STRING || - found->type() == MYSQL_TYPE_VAR_STRING ? - FIELD_SKIP_ENDSPACE : - FIELD_SKIP_PRESPACE); + recinfo_pos->type= ((length <= 3 || + (found->flags & ZEROFILL_FLAG)) ? + FIELD_NORMAL : + found->type() == MYSQL_TYPE_STRING || + found->type() == MYSQL_TYPE_VAR_STRING ? + FIELD_SKIP_ENDSPACE : + FIELD_SKIP_PRESPACE); if (found->null_ptr) { recinfo_pos->null_bit= found->null_bit; @@ -388,7 +389,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out, Check for underlying table conformance SYNOPSIS - check_definition() + myisam_check_definition() t1_keyinfo in First table key definition t1_recinfo in First table record definition t1_keys in Number of keys in first table @@ -557,13 +558,12 @@ int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo, extern "C" { -volatile int *killed_ptr(MI_CHECK *param) +int killed_ptr(HA_CHECK *param) { - /* In theory Unsafe conversion, but should be ok for now */ - return (int*) &(((THD *)(param->thd))->killed); + return thd_killed((THD*)param->thd); } -void mi_check_print_error(MI_CHECK *param, const char *fmt,...) +void mi_check_print_error(HA_CHECK *param, const char *fmt,...) { param->error_printed|=1; param->out_flag|= O_DATA_LOST; @@ -573,7 +573,7 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...) va_end(args); } -void mi_check_print_info(MI_CHECK *param, const char *fmt,...) +void mi_check_print_info(HA_CHECK *param, const char *fmt,...) { va_list args; va_start(args, fmt); @@ -581,7 +581,7 @@ void mi_check_print_info(MI_CHECK *param, const char *fmt,...) va_end(args); } -void mi_check_print_warning(MI_CHECK *param, const char *fmt,...) +void mi_check_print_warning(HA_CHECK *param, const char *fmt,...) { param->warning_printed=1; param->out_flag|= O_DATA_LOST; @@ -705,6 +705,9 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) if (!(file=mi_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER))) return (my_errno ? my_errno : -1); + + file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref; + if (!table->s->tmp_table) /* No need to perform a check for tmp table */ { if ((my_errno= table2myisam(table, &keyinfo, &recinfo, &recs))) @@ -736,7 +739,19 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) if (!table->s->db_record_offset) int_table_flags|=HA_REC_NOT_IN_SEQ; if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) - int_table_flags|=HA_HAS_CHECKSUM; + { + /* + Set which type of automatic checksum we have + The old checksum and new checksum are identical if there is no + null fields. + Files with new checksum has the HA_OPTION_NULL_FIELDS bit set. + */ + if ((file->s->options & HA_OPTION_NULL_FIELDS) || + !file->s->has_null_fields) + int_table_flags|= HA_HAS_NEW_CHECKSUM; + if (!(file->s->options & HA_OPTION_NULL_FIELDS)) + int_table_flags|= HA_HAS_OLD_CHECKSUM; + } for (i= 0; i < table->s->keys; i++) { @@ -763,14 +778,14 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked) int ha_myisam::close(void) { MI_INFO *tmp=file; + if (!tmp) + return 0; file=0; return mi_close(tmp); } int ha_myisam::write_row(uchar *buf) { - ha_statistic_increment(&SSV::ha_write_count); - /* If we have a timestamp column, update it to the current time */ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -792,10 +807,13 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) { if (!file) return HA_ADMIN_INTERNAL_ERROR; int error; - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); MYISAM_SHARE* share = file->s; const char *old_proc_info=thd->proc_info; + if (!¶m) + return HA_ADMIN_INTERNAL_ERROR; + thd_proc_info(thd, "Checking table"); myisamchk_init(¶m); param.thd = thd; @@ -803,7 +821,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) param.db_name= table->s->db.str; param.table_name= table->alias; param.testflag = check_opt->flags | T_CHECK | T_SILENT; - param.stats_method= (enum_mi_stats_method)THDVAR(thd, stats_method); + param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); if (!(table->db_stat & HA_READ_ONLY)) param.testflag|= T_STATISTICS; @@ -832,13 +850,13 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) (param.testflag & (T_EXTEND | T_MEDIUM)))) || mi_is_crashed(file)) { - uint old_testflag=param.testflag; + ulonglong old_testflag= param.testflag; param.testflag|=T_MEDIUM; if (!(error= init_io_cache(¶m.read_cache, file->dfile, my_default_record_cache_size, READ_CACHE, share->pack.header_length, 1, MYF(MY_WME)))) { - error= chk_data_link(¶m, file, param.testflag & T_EXTEND); + error= chk_data_link(¶m, file, test(param.testflag & T_EXTEND)); end_io_cache(&(param.read_cache)); } param.testflag= old_testflag; @@ -884,9 +902,12 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) { int error=0; - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); MYISAM_SHARE* share = file->s; + if (!¶m) + return HA_ADMIN_INTERNAL_ERROR; + myisamchk_init(¶m); param.thd = thd; param.op_name= "analyze"; @@ -895,7 +916,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | T_DONT_CHECK_CHECKSUM); param.using_global_keycache = 1; - param.stats_method= (enum_mi_stats_method)THDVAR(thd, stats_method); + param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); if (!(share->state.changed & STATE_NOT_ANALYZED)) return HA_ADMIN_ALREADY_DONE; @@ -916,10 +937,10 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) { int error; - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); ha_rows start_records; - if (!file) return HA_ADMIN_INTERNAL_ERROR; + if (!file || !¶m) return HA_ADMIN_INTERNAL_ERROR; myisamchk_init(¶m); param.thd = thd; @@ -935,7 +956,9 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) if (test_all_bits(param.testflag, (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK))) { - param.testflag&= ~T_RETRY_WITHOUT_QUICK; + param.testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK); + /* Ensure we don't loose any rows when retrying without quick */ + param.testflag|= T_SAFE_REPAIR; sql_print_information("Retrying repair of: '%s' without quick", table->s->path.str); continue; @@ -965,8 +988,9 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) { int error; - if (!file) return HA_ADMIN_INTERNAL_ERROR; - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + + if (!file || !¶m) return HA_ADMIN_INTERNAL_ERROR; myisamchk_init(¶m); param.thd = thd; @@ -985,10 +1009,10 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) } -int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) +int ha_myisam::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) { int error=0; - uint local_testflag=param.testflag; + ulonglong local_testflag= param.testflag; bool optimize_done= !do_optimize, statistics_done=0; const char *old_proc_info=thd->proc_info; char fixed_name[FN_REFLEN]; @@ -1024,7 +1048,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ? mi_get_mask_all_keys_active(share->base.keys) : share->state.key_map); - uint testflag=param.testflag; + ulonglong testflag= param.testflag; if (mi_test_if_sort_rep(file,file->state->records,key_map,0) && (local_testflag & T_REP_BY_SORT)) { @@ -1038,7 +1062,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map)); thd_proc_info(thd, buf); error = mi_repair_parallel(¶m, file, fixed_name, - param.testflag & T_QUICK); + test(param.testflag & T_QUICK)); thd_proc_info(thd, "Repair done"); // to reset proc_info, as // it was pointing to local buffer } @@ -1046,7 +1070,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) { thd_proc_info(thd, "Repair by sorting"); error = mi_repair_by_sort(¶m, file, fixed_name, - param.testflag & T_QUICK); + test(param.testflag & T_QUICK)); } } else @@ -1054,9 +1078,9 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool do_optimize) thd_proc_info(thd, "Repair with keycache"); param.testflag &= ~T_REP_BY_SORT; error= mi_repair(¶m, file, fixed_name, - param.testflag & T_QUICK); + test(param.testflag & T_QUICK)); } - param.testflag=testflag; + param.testflag= testflag | (param.testflag & T_RETRY_WITHOUT_QUICK); optimize_done=1; } if (!error) @@ -1160,7 +1184,10 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) if (error != HA_ADMIN_OK) { /* Send error to user */ - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + if (!¶m) + return HA_ADMIN_INTERNAL_ERROR; + myisamchk_init(¶m); param.thd= thd; param.op_name= "assign_to_keycache"; @@ -1224,7 +1251,9 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) err: { - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + if (!¶m) + return HA_ADMIN_INTERNAL_ERROR; myisamchk_init(¶m); param.thd= thd; param.op_name= "preload_keys"; @@ -1334,8 +1363,12 @@ int ha_myisam::enable_indexes(uint mode) else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE) { THD *thd=current_thd; - MI_CHECK param; + HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); const char *save_proc_info=thd->proc_info; + + if (!¶m) + return HA_ADMIN_INTERNAL_ERROR; + thd_proc_info(thd, "Creating index"); myisamchk_init(¶m); param.op_name= "recreating_index"; @@ -1343,7 +1376,7 @@ int ha_myisam::enable_indexes(uint mode) T_CREATE_MISSING_KEYS); param.myf_rw&= ~MY_WAIT_IF_FULL; param.sort_buffer_length= THDVAR(thd, sort_buffer_size); - param.stats_method= (enum_mi_stats_method)THDVAR(thd, stats_method); + param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); param.tmpdir=&mysql_tmpdir_list; if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair) { @@ -1471,7 +1504,7 @@ int ha_myisam::end_bulk_insert() { mi_end_bulk_insert(file); int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0); - if (!err) + if (!err && !file->s->deleting) { if (can_enable_indexes) { @@ -1539,7 +1572,6 @@ bool ha_myisam::is_crashed() const int ha_myisam::update_row(const uchar *old_data, uchar *new_data) { - ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); return mi_update(file,old_data,new_data); @@ -1547,19 +1579,58 @@ int ha_myisam::update_row(const uchar *old_data, uchar *new_data) int ha_myisam::delete_row(const uchar *buf) { - ha_statistic_increment(&SSV::ha_delete_count); return mi_delete(file,buf); } + +C_MODE_START + +ICP_RESULT index_cond_func_myisam(void *arg) +{ + ha_myisam *h= (ha_myisam*)arg; + if (h->end_range) + { + if (h->compare_key2(h->end_range) > 0) + return ICP_OUT_OF_RANGE; /* caller should return HA_ERR_END_OF_FILE already */ + } + return (ICP_RESULT) test(h->pushed_idx_cond->val_int()); +} + +C_MODE_END + + +int ha_myisam::index_init(uint idx, bool sorted) +{ + active_index=idx; + if (pushed_idx_cond_keyno == idx) + mi_set_index_cond_func(file, index_cond_func_myisam, this); + return 0; +} + + +int ha_myisam::index_end() +{ + active_index=MAX_KEY; + //pushed_idx_cond_keyno= MAX_KEY; + mi_set_index_cond_func(file, NULL, 0); + in_range_check_pushed_down= FALSE; + ds_mrr.dsmrr_close(); + return 0; +} + +int ha_myisam::rnd_end() +{ + ds_mrr.dsmrr_close(); + return 0; +} + int ha_myisam::index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag) { MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_key_count); int error=mi_rkey(file, buf, active_index, key, keypart_map, find_flag); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); return error; } @@ -1569,34 +1640,16 @@ int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key, enum ha_rkey_function find_flag) { MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); - ha_statistic_increment(&SSV::ha_read_key_count); int error=mi_rkey(file, buf, index, key, keypart_map, find_flag); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); return error; } -int ha_myisam::index_read_last_map(uchar *buf, const uchar *key, - key_part_map keypart_map) -{ - MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); - DBUG_ENTER("ha_myisam::index_read_last"); - DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_key_count); - int error=mi_rkey(file, buf, active_index, key, keypart_map, - HA_READ_PREFIX_LAST); - table->status=error ? STATUS_NOT_FOUND: 0; - MYSQL_INDEX_READ_ROW_DONE(error); - DBUG_RETURN(error); -} - int ha_myisam::index_next(uchar *buf) { MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_next_count); int error=mi_rnext(file,buf,active_index); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); return error; } @@ -1605,9 +1658,7 @@ int ha_myisam::index_prev(uchar *buf) { MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_prev_count); int error=mi_rprev(file,buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); return error; } @@ -1616,9 +1667,7 @@ int ha_myisam::index_first(uchar *buf) { MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_first_count); int error=mi_rfirst(file, buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); return error; } @@ -1627,10 +1676,9 @@ int ha_myisam::index_last(uchar *buf) { MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); DBUG_ASSERT(inited==INDEX); - ha_statistic_increment(&SSV::ha_read_last_count); int error=mi_rlast(file, buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); +#warning move that to wrappers return error; } @@ -1641,12 +1689,10 @@ int ha_myisam::index_next_same(uchar *buf, int error; DBUG_ASSERT(inited==INDEX); MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str); - ha_statistic_increment(&SSV::ha_read_next_count); do { error= mi_rnext_same(file,buf); } while (error == HA_ERR_RECORD_DELETED); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_INDEX_READ_ROW_DONE(error); return error; } @@ -1663,25 +1709,27 @@ int ha_myisam::rnd_next(uchar *buf) { MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, TRUE); - ha_statistic_increment(&SSV::ha_read_rnd_next_count); int error=mi_scan(file, buf); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_READ_ROW_DONE(error); return error; } -int ha_myisam::restart_rnd_next(uchar *buf, uchar *pos) +int ha_myisam::remember_rnd_pos() { - return rnd_pos(buf,pos); + position((uchar*) 0); + return 0; +} + +int ha_myisam::restart_rnd_next(uchar *buf) +{ + return rnd_pos(buf, ref); } int ha_myisam::rnd_pos(uchar *buf, uchar *pos) { MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, FALSE); - ha_statistic_increment(&SSV::ha_read_rnd_count); int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length)); - table->status=error ? STATUS_NOT_FOUND: 0; MYSQL_READ_ROW_DONE(error); return error; } @@ -1714,6 +1762,16 @@ int ha_myisam::info(uint flag) stats.max_data_file_length= misam_info.max_data_file_length; stats.max_index_file_length= misam_info.max_index_file_length; stats.create_time= (ulong) misam_info.create_time; + /* + We want the value of stats.mrr_length_per_rec to be platform independent. + The size of the chunk at the end of the join buffer used for MRR needs + is calculated now basing on the values passed in the stats structure. + The remaining part of the join buffer is used for records. A different + number of records in the buffer results in a different number of buffer + refills and in a different order of records in the result set. + */ + stats.mrr_length_per_rec= misam_info.reflength + 8; // 8=max(sizeof(void *)) + ref_length= misam_info.reflength; share->db_options_in_use= misam_info.options; stats.block_size= myisam_block_size; /* record block size */ @@ -1769,8 +1827,13 @@ int ha_myisam::extra(enum ha_extra_function operation) return mi_extra(file, operation, 0); } + int ha_myisam::reset(void) { + pushed_idx_cond= NULL; + pushed_idx_cond_keyno= MAX_KEY; + mi_set_index_cond_func(file, NULL, 0); + ds_mrr.dsmrr_close(); return mi_reset(file); } @@ -1901,7 +1964,7 @@ void ha_myisam::get_auto_increment(ulonglong offset, ulonglong increment, { ulonglong nr; int error; - uchar key[MI_MAX_KEY_LENGTH]; + uchar key[HA_MAX_KEY_LENGTH]; if (!table->s->next_number_key_offset) { // Autoincrement at key-start @@ -1985,8 +2048,6 @@ int ha_myisam::ft_read(uchar *buf) &LOCK_status); // why ? error=ft_handler->please->read_next(ft_handler,(char*) buf); - - table->status=error ? STATUS_NOT_FOUND: 0; return error; } @@ -2016,6 +2077,27 @@ bool ha_myisam::check_if_incompatible_data(HA_CREATE_INFO *info, return COMPATIBLE_DATA_YES; } + +/** + Check if a table is incompatible with the current version. + + The cases are: + - Table has checksum, varchars and are not of dynamic record type +*/ + +int ha_myisam::check_for_upgrade(HA_CHECK_OPT *check_opt) +{ + if (!(file->s->options & HA_OPTION_NULL_FIELDS) && + !(file->s->options & HA_OPTION_PACK_RECORD) && + file->s->has_varchar_fields) + { + /* We need alter there to get the HA_OPTION_NULL_FIELDS flag to be set */ + return HA_ADMIN_NEEDS_ALTER; + } + return HA_ADMIN_OK; +} + + extern int mi_panic(enum ha_panic_function flag); int myisam_panic(handlerton *hton, ha_panic_function flag) { @@ -2060,6 +2142,61 @@ static struct st_mysql_sys_var* myisam_sysvars[]= { 0 }; +/**************************************************************************** + * MyISAM MRR implementation: use DS-MRR + ***************************************************************************/ + +int ha_myisam::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, + uint n_ranges, uint mode, + HANDLER_BUFFER *buf) +{ + return ds_mrr.dsmrr_init(this, seq, seq_init_param, n_ranges, mode, buf); +} + +int ha_myisam::multi_range_read_next(char **range_info) +{ + return ds_mrr.dsmrr_next(range_info); +} + +ha_rows ha_myisam::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, + void *seq_init_param, + uint n_ranges, uint *bufsz, + uint *flags, COST_VECT *cost) +{ + /* + This call is here because there is no location where this->table would + already be known. + TODO: consider moving it into some per-query initialization call. + */ + ds_mrr.init(this, table); + return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz, + flags, cost); +} + +ha_rows ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys, + uint *bufsz, uint *flags, + COST_VECT *cost) +{ + ds_mrr.init(this, table); + return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost); +} + +/* MyISAM MRR implementation ends */ + + +/* Index condition pushdown implementation*/ + + +Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg) +{ + pushed_idx_cond_keyno= keyno_arg; + pushed_idx_cond= idx_cond_arg; + in_range_check_pushed_down= TRUE; + if (active_index == pushed_idx_cond_keyno) + mi_set_index_cond_func(file, index_cond_func_myisam, this); + return NULL; +} + struct st_mysql_storage_engine myisam_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -2079,6 +2216,23 @@ mysql_declare_plugin(myisam) NULL } mysql_declare_plugin_end; +maria_declare_plugin(myisam) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &myisam_storage_engine, + "MyISAM", + "MySQL AB", + "Default engine as of MySQL 3.23 with great performance", + PLUGIN_LICENSE_GPL, + myisam_init, /* Plugin Init */ + NULL, /* Plugin Deinit */ + 0x0100, /* 1.0 */ + NULL, /* status variables */ + NULL, /* system variables */ + "1.0", /* string version */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ +} +maria_declare_plugin_end; #ifdef HAVE_QUERY_CACHE diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 1a8246ae882..61585013678 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -21,6 +21,7 @@ /* class for the the myisam handler */ #include <myisam.h> +#include <myisamchk.h> #include <ft_global.h> #include "handler.h" /* handler */ #include "table.h" /* TABLE_SHARE */ @@ -39,13 +40,17 @@ extern TYPELIB myisam_recover_typelib; extern const char *myisam_recover_names[]; extern ulonglong myisam_recover_options; +C_MODE_START +ICP_RESULT index_cond_func_myisam(void *arg); +C_MODE_END + class ha_myisam: public handler { MI_INFO *file; ulonglong int_table_flags; char *data_file_name, *index_file_name; bool can_enable_indexes; - int repair(THD *thd, MI_CHECK ¶m, bool optimize); + int repair(THD *thd, HA_CHECK ¶m, bool optimize); public: ha_myisam(handlerton *hton, TABLE_SHARE *table_arg); @@ -55,15 +60,19 @@ class ha_myisam: public handler const char *index_type(uint key_number); const char **bas_ext() const; ulonglong table_flags() const { return int_table_flags; } + int index_init(uint idx, bool sorted); + int index_end(); + int rnd_end(); + ulong index_flags(uint inx, uint part, bool all_parts) const { return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ? 0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE | - HA_READ_ORDER | HA_KEYREAD_ONLY); + HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN); } uint max_supported_keys() const { return MI_MAX_KEY; } - uint max_supported_key_length() const { return MI_MAX_KEY_LENGTH; } - uint max_supported_key_part_length() const { return MI_MAX_KEY_LENGTH; } + uint max_supported_key_length() const { return HA_MAX_KEY_LENGTH; } + uint max_supported_key_part_length() const { return HA_MAX_KEY_LENGTH; } uint checksum() const; int open(const char *name, int mode, uint test_if_locked); @@ -76,7 +85,6 @@ class ha_myisam: public handler int index_read_idx_map(uchar *buf, uint index, const uchar *key, key_part_map keypart_map, enum ha_rkey_function find_flag); - int index_read_last_map(uchar *buf, const uchar *key, key_part_map keypart_map); int index_next(uchar * buf); int index_prev(uchar * buf); int index_first(uchar * buf); @@ -99,7 +107,8 @@ class ha_myisam: public handler int rnd_init(bool scan); int rnd_next(uchar *buf); int rnd_pos(uchar * buf, uchar *pos); - int restart_rnd_next(uchar *buf, uchar *pos); + int remember_rnd_pos(); + int restart_rnd_next(uchar *buf); void position(const uchar *record); int info(uint); int extra(enum ha_extra_function operation); @@ -124,6 +133,7 @@ class ha_myisam: public handler ulonglong *nb_reserved_values); int rename_table(const char * from, const char * to); int delete_table(const char *name); + int check_for_upgrade(HA_CHECK_OPT *check_opt); int check(THD* thd, HA_CHECK_OPT* check_opt); int analyze(THD* thd,HA_CHECK_OPT* check_opt); int repair(THD* thd, HA_CHECK_OPT* check_opt); @@ -134,6 +144,7 @@ class ha_myisam: public handler int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt); int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); + bool check_if_supported_virtual_columns(void) { return TRUE;} #ifdef HAVE_QUERY_CACHE my_bool register_query_cache_table(THD *thd, char *table_key, uint key_length, @@ -145,4 +156,23 @@ class ha_myisam: public handler { return file; } +public: + /** + * Multi Range Read interface + */ + int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param, + uint n_ranges, uint mode, HANDLER_BUFFER *buf); + int multi_range_read_next(char **range_info); + ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq, + void *seq_init_param, + uint n_ranges, uint *bufsz, + uint *flags, COST_VECT *cost); + ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys, + uint *bufsz, uint *flags, COST_VECT *cost); + + /* Index condition pushdown implementation */ + Item *idx_cond_push(uint keyno, Item* idx_cond); +private: + DsMrr_impl ds_mrr; + friend ICP_RESULT index_cond_func_myisam(void *arg); }; diff --git a/storage/myisam/mi_cache.c b/storage/myisam/mi_cache.c index 139a50a7c0d..ddbfda11326 100644 --- a/storage/myisam/mi_cache.c +++ b/storage/myisam/mi_cache.c @@ -98,8 +98,8 @@ int _mi_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, uint length, DBUG_PRINT("error", ("Error %d reading next-multi-part block (Got %d bytes)", my_errno, (int) read_length)); - if (!my_errno || my_errno == -1) - my_errno=HA_ERR_WRONG_IN_RECORD; + if (!my_errno || my_errno == -1 || my_errno == HA_ERR_FILE_TOO_SHORT) + my_errno= HA_ERR_WRONG_IN_RECORD; DBUG_RETURN(1); } bzero(buff+read_length,MI_BLOCK_INFO_HEADER_LENGTH - in_buff_length - diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 6bf01cd63c7..89644e5f978 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -54,14 +54,14 @@ /* Functions defined in this file */ -static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr); -static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo, +static int check_k_link(HA_CHECK *param, MI_INFO *info,uint nr); +static int chk_index(HA_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, ha_checksum *key_checksum, uint level); static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo); static ha_checksum calc_checksum(ha_rows count); static int writekeys(MI_SORT_PARAM *sort_param); -static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo, +static int sort_one_index(HA_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo, my_off_t pagepos, File new_file); static int sort_key_read(MI_SORT_PARAM *sort_param,void *key); static int sort_ft_key_read(MI_SORT_PARAM *sort_param,void *key); @@ -75,19 +75,19 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param, reg1 SORT_KEY_BLOCKS *key_block, uchar *key, my_off_t prev_block); static int sort_delete_record(MI_SORT_PARAM *sort_param); -/*static int flush_pending_blocks(MI_CHECK *param);*/ -static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks, +/*static int flush_pending_blocks(HA_CHECK *param);*/ +static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, uint buffer_length); static ha_checksum mi_byte_checksum(const uchar *buf, uint length); -static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share); +static void set_data_file_type(MI_SORT_INFO *sort_info, MYISAM_SHARE *share); -void myisamchk_init(MI_CHECK *param) +void myisamchk_init(HA_CHECK *param) { bzero((uchar*) param,sizeof(*param)); + /* Set all params that are not 0 */ param->opt_follow_links=1; param->keys_in_use= ~(ulonglong) 0; param->search_after_block=HA_OFFSET_ERROR; - param->auto_increment_value= 0; param->use_buffers=USE_BUFFER_INIT; param->read_buffer_length=READ_BUFFER_INIT; param->write_buffer_length=READ_BUFFER_INIT; @@ -95,18 +95,14 @@ void myisamchk_init(MI_CHECK *param) param->sort_key_blocks=BUFFERS_WHEN_SORTING; param->tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL; param->myf_rw=MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL); - param->start_check_pos=0; param->max_record_length= LONGLONG_MAX; param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE; param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; -#ifdef THREAD - param->need_print_msg_lock= 0; -#endif } /* Check the status flags for the table */ -int chk_status(MI_CHECK *param, register MI_INFO *info) +int chk_status(HA_CHECK *param, register MI_INFO *info) { MYISAM_SHARE *share=info->s; @@ -134,7 +130,7 @@ int chk_status(MI_CHECK *param, register MI_INFO *info) /* Check delete links */ -int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) +int chk_del(HA_CHECK *param, register MI_INFO *info, ulonglong test_flag) { reg2 ha_rows i; uint delete_link_length; @@ -164,7 +160,7 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) empty=0; for (i= info->state->del ; i > 0L && next_link != HA_OFFSET_ERROR ; i--) { - if (*killed_ptr(param)) + if (killed_ptr(param)) DBUG_RETURN(1); if (test_flag & T_VERBOSE) printf(" %9s",llstr(next_link,buff)); @@ -242,7 +238,7 @@ wrong: /* Check delete links in index file */ -static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) +static int check_k_link(HA_CHECK *param, register MI_INFO *info, uint nr) { my_off_t next_link; uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH; @@ -259,7 +255,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) records= (ha_rows) (info->state->key_file_length / block_size); while (next_link != HA_OFFSET_ERROR && records > 0) { - if (*killed_ptr(param)) + if (killed_ptr(param)) DBUG_RETURN(1); if (param->testflag & T_VERBOSE) printf("%16s",llstr(next_link,llbuff)); @@ -320,7 +316,7 @@ static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr) /* Check sizes of files */ -int chk_size(MI_CHECK *param, register MI_INFO *info) +int chk_size(HA_CHECK *param, register MI_INFO *info) { int error=0; register my_off_t skr,size; @@ -331,7 +327,8 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) /* The following is needed if called externally (not from myisamchk) */ flush_key_blocks(info->s->key_cache, - info->s->kfile, FLUSH_FORCE_WRITE); + info->s->kfile, &info->s->dirty_part_map, + FLUSH_FORCE_WRITE); size= mysql_file_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)); if ((skr=(my_off_t) info->state->key_file_length) != size) @@ -396,7 +393,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) /* Check keys */ -int chk_key(MI_CHECK *param, register MI_INFO *info) +int chk_key(HA_CHECK *param, register MI_INFO *info) { uint key,found_keys=0,full_text_keys=0,result=0; ha_rows keys; @@ -581,7 +578,7 @@ do_stat: } /* chk_key */ -static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, +static int chk_index_down(HA_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, ha_checksum *key_checksum, uint level) { @@ -728,7 +725,7 @@ int mi_collect_stats_nonulls_next(HA_KEYSEG *keyseg, ulonglong *notnull, /* Check if index is ok */ -static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, +static int chk_index(HA_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t page, uchar *buff, ha_rows *keys, ha_checksum *key_checksum, uint level) { @@ -752,7 +749,10 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, } if (keyinfo->flag & HA_NOSAME) - comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* Not real duplicates */ + { + /* Not real duplicates */ + comp_flag= SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT; + } else comp_flag=SEARCH_SAME; /* Keys in positionorder */ nod_flag=mi_test_if_nod(buff); @@ -773,7 +773,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, } for ( ;; ) { - if (*killed_ptr(param)) + if (killed_ptr(param)) goto err; memcpy((char*) info->lastkey,(char*) key,key_length); info->lastkey_length=key_length; @@ -797,9 +797,9 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, (flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length, comp_flag, diff_pos)) >=0) { - DBUG_DUMP("old",(uchar*) info->lastkey, info->lastkey_length); - DBUG_DUMP("new",(uchar*) key, key_length); - DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos)); + DBUG_DUMP("old",info->lastkey, info->lastkey_length); + DBUG_DUMP("new",key, key_length); + DBUG_DUMP("new_in_page",old_keypos,(uint) (keypos-old_keypos)); if (comp_flag & SEARCH_FIND && flag == 0) mi_check_print_error(param,"Found duplicated key at page %s",llstr(page,llbuff)); @@ -868,8 +868,8 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, DBUG_PRINT("test",("page: %s record: %s filelength: %s", llstr(page,llbuff),llstr(record,llbuff2), llstr(info->state->data_file_length,llbuff3))); - DBUG_DUMP("key",(uchar*) key,key_length); - DBUG_DUMP("new_in_page",(uchar*) old_keypos,(uint) (keypos-old_keypos)); + DBUG_DUMP("key",key,key_length); + DBUG_DUMP("new_in_page",old_keypos,(uint) (keypos-old_keypos)); goto err; } param->record_checksum+=(ha_checksum) record; @@ -931,7 +931,7 @@ static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo) /* Check that record-link is ok */ -int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) +int chk_data_link(HA_CHECK *param, MI_INFO *info, my_bool extend) { int error,got_error,flag; uint key,UNINIT_VAR(left_length),b_type,field; @@ -985,9 +985,12 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) bzero((char*) key_checksum, info->s->base.keys * sizeof(key_checksum[0])); while (pos < info->state->data_file_length) { - if (*killed_ptr(param)) + if (killed_ptr(param)) goto err2; switch (info->s->data_file_type) { + case BLOCK_RECORD: + DBUG_ASSERT(0); /* Impossible */ + break; case STATIC_RECORD: if (my_b_read(¶m->read_cache,(uchar*) record, info->s->base.pack_reclength)) @@ -1001,7 +1004,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) del_length+=info->s->base.pack_reclength; continue; /* Record removed */ } - param->glob_crc+= mi_static_checksum(info,record); + param->glob_crc+= (*info->s->calc_check_checksum)(info,record); used+=info->s->base.pack_reclength; break; case DYNAMIC_RECORD: @@ -1155,7 +1158,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) } else { - info->checksum=mi_checksum(info,record); + info->checksum= (*info->s->calc_check_checksum)(info,record); if (param->testflag & (T_EXTEND | T_MEDIUM | T_VERBOSE)) { if (_mi_rec_check(info,record, info->rec_buff,block_info.rec_len, @@ -1201,15 +1204,10 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) llstr(start_recpos,llbuff)); got_error=1; } - if (static_row_size) - param->glob_crc+= mi_static_checksum(info,record); - else - param->glob_crc+= mi_checksum(info,record); + param->glob_crc+= (*info->s->calc_check_checksum)(info,record); link_used+= (block_info.filepos - start_recpos); used+= (pos-start_recpos); break; - case BLOCK_RECORD: - assert(0); /* Impossible */ } /* switch */ if (! got_error) { @@ -1335,7 +1333,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) if (splits != info->s->state.split) { mi_check_print_warning(param, - "Found %10s key parts. Should be: %s", + "Found %10s parts. Should be: %s", llstr(splits,llbuff), llstr(info->s->state.split,llbuff2)); } @@ -1428,7 +1426,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) then recrate all indexes. */ -static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force) +static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force) { MYISAM_SHARE *share= info->s; MI_STATE_INFO *state= &share->state; @@ -1472,6 +1470,7 @@ static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force) */ DBUG_PRINT("repair", ("all disabled are empty: create missing")); error= flush_key_blocks(share->key_cache, share->kfile, + &share->dirty_part_map, FLUSH_FORCE_WRITE); goto end; } @@ -1486,6 +1485,7 @@ static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force) /* Remove all key blocks of this index file from key cache. */ if ((error= flush_key_blocks(share->key_cache, share->kfile, + &share->dirty_part_map, FLUSH_IGNORE_CHANGED))) goto end; /* purecov: inspected */ @@ -1511,7 +1511,7 @@ static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force) /* Recover old table by reading each record and writing all keys */ /* Save new datafile-name in temp_filename */ -int mi_repair(MI_CHECK *param, register MI_INFO *info, +int mi_repair(HA_CHECK *param, register MI_INFO *info, char * name, int rep_quick) { int error,got_error; @@ -1520,7 +1520,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, File new_file; MYISAM_SHARE *share=info->s; char llbuff[22],llbuff2[22]; - SORT_INFO sort_info; + MI_SORT_INFO sort_info; MI_SORT_PARAM sort_param; DBUG_ENTER("mi_repair"); @@ -1547,7 +1547,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, if (!param->using_global_keycache) (void) init_key_cache(dflt_key_cache, param->key_cache_block_size, - param->use_buffers, 0, 0); + param->use_buffers, 0, 0, 0); if (init_io_cache(¶m->read_cache,info->dfile, (uint) param->read_buffer_length, @@ -1770,7 +1770,8 @@ err: (void) end_io_cache(¶m->read_cache); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); (void) end_io_cache(&info->rec_cache); - got_error|=flush_blocks(param, share->key_cache, share->kfile); + got_error|=flush_blocks(param, share->key_cache, share->kfile, + &share->dirty_part_map); if (!got_error && param->testflag & T_UNPACK) { share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; @@ -1900,7 +1901,7 @@ int movepoint(register MI_INFO *info, uchar *record, my_off_t oldpos, /* Tell system that we want all memory for our cache */ -void lock_memory(MI_CHECK *param __attribute__((unused))) +void lock_memory(HA_CHECK *param __attribute__((unused))) { #ifdef SUN_OS /* Key-cacheing thrases on sun 4.1 */ if (param->opt_lock_memory) @@ -1916,9 +1917,10 @@ void lock_memory(MI_CHECK *param __attribute__((unused))) /* Flush all changed blocks to disk */ -int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file) +int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file, + ulonglong *dirty_part_map) { - if (flush_key_blocks(key_cache, file, FLUSH_RELEASE)) + if (flush_key_blocks(key_cache, file, dirty_part_map, FLUSH_RELEASE)) { mi_check_print_error(param,"%d when trying to write bufferts",my_errno); return(1); @@ -1931,7 +1933,7 @@ int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file) /* Sort index for more efficent reads */ -int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name) +int mi_sort_index(HA_CHECK *param, register MI_INFO *info, char * name) { reg2 uint key; reg1 MI_KEYDEF *keyinfo; @@ -1987,7 +1989,8 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, char * name) } /* Flush key cache for this file if we are calling this outside myisamchk */ - flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); + flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, + FLUSH_IGNORE_CHANGED); share->state.version=(ulong) time((time_t*) 0); old_state= share->state; /* save state if not stored */ @@ -2034,7 +2037,7 @@ err2: /* Sort records recursive using one index */ -static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, +static int sort_one_index(HA_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pagepos, File new_file) { uint length,nod_flag,used_length, key_length; @@ -2145,12 +2148,12 @@ int change_to_newfile(const char * filename, const char * old_ext, /* Locks a whole file */ /* Gives an error-message if file can't be locked */ -int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type, +int lock_file(HA_CHECK *param, File file, my_off_t start, int lock_type, const char *filetype, const char *filename) { if (my_lock(file,lock_type,start,F_TO_EOF, param->testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) : - MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT))) + MYF(MY_SEEK_NOT_DONE | MY_SHORT_WAIT))) { mi_check_print_error(param," %d when locking %s '%s'",my_errno,filetype,filename); param->error_printed=2; /* Don't give that data is crashed */ @@ -2162,7 +2165,7 @@ int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type, /* Copy a block between two files */ -int filecopy(MI_CHECK *param, File to,File from,my_off_t start, +int filecopy(HA_CHECK *param, File to,File from,my_off_t start, my_off_t length, const char *type) { char tmp_buff[IO_SIZE],*buff; @@ -2213,7 +2216,7 @@ err: <>0 Error */ -int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, +int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, const char * name, int rep_quick) { int got_error; @@ -2227,7 +2230,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, HA_KEYSEG *keyseg; ulong *rec_per_key_part; char llbuff[22]; - SORT_INFO sort_info; + MI_SORT_INFO sort_info; ulonglong UNINIT_VAR(key_map); DBUG_ENTER("mi_repair_by_sort"); @@ -2495,7 +2498,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, goto err; } - if (rep_quick & T_FORCE_UNIQUENESS) + if (rep_quick && (param->testflag & T_FORCE_UNIQUENESS)) { my_off_t skr=info->state->data_file_length+ (share->options & HA_OPTION_COMPRESS_RECORD ? @@ -2534,7 +2537,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, memcpy( &share->state.state, info->state, sizeof(*info->state)); err: - got_error|= flush_blocks(param, share->key_cache, share->kfile); + got_error|= flush_blocks(param, share->key_cache, share->kfile, + &share->dirty_part_map); (void) end_io_cache(&info->rec_cache); if (!got_error) { @@ -2626,7 +2630,7 @@ err: <>0 Error */ -int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, +int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, const char * name, int rep_quick) { #ifndef THREAD @@ -2645,7 +2649,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, char llbuff[22]; IO_CACHE new_data_cache; /* For non-quick repair. */ IO_CACHE_SHARE io_share; - SORT_INFO sort_info; + MI_SORT_INFO sort_info; ulonglong UNINIT_VAR(key_map); pthread_attr_t thr_attr; ulong max_pack_reclength; @@ -2669,14 +2673,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, /* Quick repair (not touching data file, rebuilding indexes): { - Read cache is (MI_CHECK *param)->read_cache using info->dfile. + Read cache is (HA_CHECK *param)->read_cache using info->dfile. } Non-quick repair (rebuilding data file and indexes): { Master thread: - Read cache is (MI_CHECK *param)->read_cache using info->dfile. + Read cache is (HA_CHECK *param)->read_cache using info->dfile. Write cache is (MI_INFO *info)->rec_cache using new_file. Slave threads: @@ -3017,7 +3021,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, goto err; } - if (rep_quick & T_FORCE_UNIQUENESS) + if (rep_quick && (param->testflag & T_FORCE_UNIQUENESS)) { my_off_t skr=info->state->data_file_length+ (share->options & HA_OPTION_COMPRESS_RECORD ? @@ -3055,7 +3059,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, memcpy(&share->state.state, info->state, sizeof(*info->state)); err: - got_error|= flush_blocks(param, share->key_cache, share->kfile); + got_error|= flush_blocks(param, share->key_cache, share->kfile, + &share->dirty_part_map); /* Destroy the write cache. The master thread did already detach from the share by remove_io_thread() or it was not yet started (if the @@ -3128,7 +3133,7 @@ err: static int sort_key_read(MI_SORT_PARAM *sort_param, void *key) { int error; - SORT_INFO *sort_info=sort_param->sort_info; + MI_SORT_INFO *sort_info=sort_param->sort_info; MI_INFO *info=sort_info->info; DBUG_ENTER("sort_key_read"); @@ -3145,7 +3150,7 @@ static int sort_key_read(MI_SORT_PARAM *sort_param, void *key) (info->s->rec_reflength+ _mi_make_key(info, sort_param->key, (uchar*) key, sort_param->record, sort_param->filepos)); -#ifdef HAVE_purify +#ifdef HAVE_valgrind bzero(key+sort_param->real_key_length, (sort_param->key_length-sort_param->real_key_length)); #endif @@ -3155,7 +3160,7 @@ static int sort_key_read(MI_SORT_PARAM *sort_param, void *key) static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) { int error; - SORT_INFO *sort_info=sort_param->sort_info; + MI_SORT_INFO *sort_info=sort_param->sort_info; MI_INFO *info=sort_info->info; FT_WORD *wptr=0; DBUG_ENTER("sort_ft_key_read"); @@ -3185,7 +3190,7 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key) sort_param->real_key_length=(info->s->rec_reflength+ _ft_make_key(info, sort_param->key, key, wptr++, sort_param->filepos)); -#ifdef HAVE_purify +#ifdef HAVE_valgrind if (sort_param->key_length > sort_param->real_key_length) bzero(key+sort_param->real_key_length, (sort_param->key_length-sort_param->real_key_length)); @@ -3242,17 +3247,20 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) my_off_t pos; uchar *UNINIT_VAR(to); MI_BLOCK_INFO block_info; - SORT_INFO *sort_info=sort_param->sort_info; - MI_CHECK *param=sort_info->param; + MI_SORT_INFO *sort_info=sort_param->sort_info; + HA_CHECK *param=sort_info->param; MI_INFO *info=sort_info->info; MYISAM_SHARE *share=info->s; char llbuff[22],llbuff2[22]; DBUG_ENTER("sort_get_next_record"); - if (*killed_ptr(param)) + if (killed_ptr(param)) DBUG_RETURN(1); switch (share->data_file_type) { + case BLOCK_RECORD: + DBUG_ASSERT(0); /* Impossible */ + break; case STATIC_RECORD: for (;;) { @@ -3277,7 +3285,9 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) { if (sort_param->calc_checksum) param->glob_crc+= (info->checksum= - mi_static_checksum(info,sort_param->record)); + (*info->s->calc_check_checksum)(info, + sort_param-> + record)); DBUG_RETURN(0); } if (!sort_param->fix_datafile && sort_param->master) @@ -3553,7 +3563,8 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) if (sort_param->read_cache.error < 0) DBUG_RETURN(1); if (sort_param->calc_checksum) - info->checksum= mi_checksum(info, sort_param->record); + info->checksum= (*info->s->calc_check_checksum)(info, + sort_param->record); if ((param->testflag & (T_EXTEND | T_REP)) || searching) { if (_mi_rec_check(info, sort_param->record, sort_param->rec_buff, @@ -3638,11 +3649,11 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) info->packed_length=block_info.rec_len; if (sort_param->calc_checksum) param->glob_crc+= (info->checksum= - mi_checksum(info, sort_param->record)); + (*info->s->calc_check_checksum)(info, + sort_param-> + record)); DBUG_RETURN(0); } - case BLOCK_RECORD: - assert(0); /* Impossible */ } DBUG_RETURN(1); /* Impossible */ } @@ -3670,8 +3681,8 @@ int sort_write_record(MI_SORT_PARAM *sort_param) ulong block_length,reclength; uchar *from; uchar block_buff[8]; - SORT_INFO *sort_info=sort_param->sort_info; - MI_CHECK *param=sort_info->param; + MI_SORT_INFO *sort_info=sort_param->sort_info; + HA_CHECK *param=sort_info->param; MI_INFO *info=sort_info->info; MYISAM_SHARE *share=info->s; DBUG_ENTER("sort_write_record"); @@ -3679,6 +3690,9 @@ int sort_write_record(MI_SORT_PARAM *sort_param) if (sort_param->fix_datafile) { switch (sort_info->new_data_file_type) { + case BLOCK_RECORD: + DBUG_ASSERT(0); /* Impossible */ + break; case STATIC_RECORD: if (my_b_write(&info->rec_cache,sort_param->record, share->base.pack_reclength)) @@ -3688,7 +3702,6 @@ int sort_write_record(MI_SORT_PARAM *sort_param) } sort_param->filepos+=share->base.pack_reclength; info->s->state.split++; - /* sort_info->param->glob_crc+=mi_static_checksum(info, sort_param->record); */ break; case DYNAMIC_RECORD: if (! info->blobs) @@ -3697,7 +3710,7 @@ int sort_write_record(MI_SORT_PARAM *sort_param) { /* must be sure that local buffer is big enough */ reclength=info->s->base.pack_reclength+ - _my_calc_total_blob_length(info,sort_param->record)+ + _mi_calc_total_blob_length(info,sort_param->record)+ ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ MI_DYN_DELETE_BLOCK_HEADER; if (sort_info->buff_length < reclength) @@ -3711,10 +3724,9 @@ int sort_write_record(MI_SORT_PARAM *sort_param) from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER); } /* We can use info->checksum here as only one thread calls this. */ - info->checksum=mi_checksum(info,sort_param->record); + info->checksum= (*info->s->calc_check_checksum)(info,sort_param->record); reclength=_mi_rec_pack(info,from,sort_param->record); flag=0; - /* sort_info->param->glob_crc+=info->checksum; */ do { @@ -3754,8 +3766,6 @@ int sort_write_record(MI_SORT_PARAM *sort_param) sort_param->filepos+=reclength+length; info->s->state.split++; break; - case BLOCK_RECORD: - assert(0); /* Impossible */ } } if (sort_param->master) @@ -3788,24 +3798,26 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) { uint diff_pos[2]; char llbuff[22],llbuff2[22]; - SORT_INFO *sort_info=sort_param->sort_info; - MI_CHECK *param= sort_info->param; + MI_SORT_INFO *sort_info=sort_param->sort_info; + HA_CHECK *param= sort_info->param; int cmp; if (sort_info->key_block->inited) { - cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, - (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE, + cmp=ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey, + (uchar*) a, USE_WHOLE_KEY, + SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT, diff_pos); if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL) - ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey, + ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey, (uchar*) a, USE_WHOLE_KEY, SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos); else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS) { diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg, sort_param->notnull, - sort_info->key_block->lastkey, + (uchar*) sort_info-> + key_block->lastkey, (uchar*)a); } sort_param->unique[diff_pos[0]-1]++; @@ -3828,8 +3840,8 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) llstr(sort_info->info->lastpos,llbuff), llstr(get_record_for_key(sort_info->info, sort_param->keyinfo, - sort_info->key_block-> - lastkey), + (uchar*) sort_info-> + key_block->lastkey), llbuff2)); param->testflag|=T_RETRY_WITHOUT_QUICK; if (sort_info->param->testflag & T_VERBOSE) @@ -3850,7 +3862,7 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a) int sort_ft_buf_flush(MI_SORT_PARAM *sort_param) { - SORT_INFO *sort_info=sort_param->sort_info; + MI_SORT_INFO *sort_info=sort_param->sort_info; SORT_KEY_BLOCKS *key_block=sort_info->key_block; MYISAM_SHARE *share=sort_info->info->s; uint val_off, val_len; @@ -3860,19 +3872,19 @@ int sort_ft_buf_flush(MI_SORT_PARAM *sort_param) val_len=share->ft2_keyinfo.keylength; get_key_full_length_rdonly(val_off, ft_buf->lastkey); - to=ft_buf->lastkey+val_off; + to= (uchar*) ft_buf->lastkey+val_off; if (ft_buf->buf) { /* flushing first-level tree */ - error=sort_insert_key(sort_param,key_block,ft_buf->lastkey, + error=sort_insert_key(sort_param,key_block, (uchar*) ft_buf->lastkey, HA_OFFSET_ERROR); for (from=to+val_len; - !error && from < ft_buf->buf; + !error && from < (uchar*) ft_buf->buf; from+= val_len) { memcpy(to, from, val_len); - error=sort_insert_key(sort_param,key_block,ft_buf->lastkey, + error=sort_insert_key(sort_param,key_block, (uchar*) ft_buf->lastkey, HA_OFFSET_ERROR); } return error; @@ -3881,8 +3893,8 @@ int sort_ft_buf_flush(MI_SORT_PARAM *sort_param) error=flush_pending_blocks(sort_param); /* updating lastkey with second-level tree info */ ft_intXstore(ft_buf->lastkey+val_off, -ft_buf->count); - _mi_dpointer(sort_info->info, ft_buf->lastkey+val_off+HA_FT_WLEN, - share->state.key_root[sort_param->key]); + _mi_dpointer(sort_info->info, (uchar*) ft_buf->lastkey+val_off+HA_FT_WLEN, + share->state.key_root[sort_param->key]); /* restoring first level tree data in sort_info/sort_param */ sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks; sort_param->keyinfo=share->keyinfo+sort_param->key; @@ -3890,14 +3902,14 @@ int sort_ft_buf_flush(MI_SORT_PARAM *sort_param) /* writing lastkey in first-level tree */ return error ? error : sort_insert_key(sort_param,sort_info->key_block, - ft_buf->lastkey,HA_OFFSET_ERROR); + (uchar*) ft_buf->lastkey,HA_OFFSET_ERROR); } static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a) { uint a_len, val_off, val_len, error; uchar *p; - SORT_INFO *sort_info=sort_param->sort_info; + MI_SORT_INFO *sort_info=sort_param->sort_info; SORT_FT_BUF *ft_buf=sort_info->ft_buf; SORT_KEY_BLOCKS *key_block=sort_info->key_block; @@ -3929,7 +3941,7 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a) if (ha_compare_text(sort_param->seg->charset, ((uchar *)a)+1,a_len-1, - ft_buf->lastkey+1,val_off-1, 0, 0)==0) + (uchar*) ft_buf->lastkey+1,val_off-1, 0, 0)==0) { if (!ft_buf->buf) /* store in second-level tree */ { @@ -3945,16 +3957,16 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a) return 0; /* converting to two-level tree */ - p=ft_buf->lastkey+val_off; + p= (uchar*) ft_buf->lastkey+val_off; while (key_block->inited) key_block++; sort_info->key_block=key_block; sort_param->keyinfo=& sort_info->info->s->ft2_keyinfo; - ft_buf->count=(uint) (ft_buf->buf - p)/val_len; + ft_buf->count=((uchar*) ft_buf->buf - p)/val_len; /* flushing buffer to second-level tree */ - for (error=0; !error && p < ft_buf->buf; p+= val_len) + for (error=0; !error && p < (uchar*) ft_buf->buf; p+= val_len) error=sort_insert_key(sort_param,key_block,p,HA_OFFSET_ERROR); ft_buf->buf=0; return error; @@ -4002,13 +4014,13 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param, MI_KEY_PARAM s_temp; MI_INFO *info; MI_KEYDEF *keyinfo=sort_param->keyinfo; - SORT_INFO *sort_info= sort_param->sort_info; - MI_CHECK *param=sort_info->param; + MI_SORT_INFO *sort_info= sort_param->sort_info; + HA_CHECK *param=sort_info->param; DBUG_ENTER("sort_insert_key"); - anc_buff=key_block->buff; + anc_buff= (uchar*) key_block->buff; info=sort_info->info; - lastkey=key_block->lastkey; + lastkey= (uchar*) key_block->lastkey; nod_flag= (key_block == sort_info->key_block ? 0 : info->s->base.key_reflength); @@ -4021,7 +4033,7 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param, DBUG_RETURN(1); } a_length=2+nod_flag; - key_block->end_pos=anc_buff+2; + key_block->end_pos= anc_buff+2; lastkey=0; /* No previous key in block */ } else @@ -4029,12 +4041,12 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param, /* Save pointer to previous block */ if (nod_flag) - _mi_kpointer(info,key_block->end_pos,prev_block); + _mi_kpointer(info,(uchar*) key_block->end_pos,prev_block); t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (uchar*) 0,lastkey,lastkey,key, &s_temp); - (*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp); + (*keyinfo->store_key)(keyinfo, (uchar*) key_block->end_pos+nod_flag,&s_temp); a_length+=t_length; mi_putint(anc_buff,a_length,nod_flag); key_block->end_pos+=t_length; @@ -4066,7 +4078,8 @@ static int sort_insert_key(MI_SORT_PARAM *sort_param, DBUG_DUMP("buff",(uchar*) anc_buff,mi_getint(anc_buff)); /* Write separator-key to block in next level */ - if (sort_insert_key(sort_param,key_block+1,key_block->lastkey,filepos)) + if (sort_insert_key(sort_param,key_block+1,(uchar*) key_block->lastkey, + filepos)) DBUG_RETURN(1); /* clear old block and write new key in it */ @@ -4082,8 +4095,8 @@ static int sort_delete_record(MI_SORT_PARAM *sort_param) uint i; int old_file,error; uchar *key; - SORT_INFO *sort_info=sort_param->sort_info; - MI_CHECK *param=sort_info->param; + MI_SORT_INFO *sort_info=sort_param->sort_info; + HA_CHECK *param=sort_info->param; MI_INFO *info=sort_info->info; DBUG_ENTER("sort_delete_record"); @@ -4139,7 +4152,7 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param) uint nod_flag,length; my_off_t filepos,key_file_length; SORT_KEY_BLOCKS *key_block; - SORT_INFO *sort_info= sort_param->sort_info; + MI_SORT_INFO *sort_info= sort_param->sort_info; myf myf_rw=sort_info->param->myf_rw; MI_INFO *info=sort_info->info; MI_KEYDEF *keyinfo=sort_param->keyinfo; @@ -4152,7 +4165,7 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param) key_block->inited=0; length=mi_getint(key_block->buff); if (nod_flag) - _mi_kpointer(info,key_block->end_pos,filepos); + _mi_kpointer(info,(uchar*) key_block->end_pos,filepos); key_file_length=info->state->key_file_length; bzero((uchar*) key_block->buff+length, keyinfo->block_length-length); if ((filepos=_mi_new(info,keyinfo,DFLT_INIT_HITS)) == HA_OFFSET_ERROR) @@ -4162,7 +4175,7 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param) if (key_file_length == info->state->key_file_length) { if (_mi_write_keypage(info, keyinfo, filepos, - DFLT_INIT_HITS, key_block->buff)) + DFLT_INIT_HITS, (uchar*) key_block->buff)) DBUG_RETURN(1); } else if (mysql_file_pwrite(info->s->kfile, (uchar*) key_block->buff, @@ -4177,7 +4190,7 @@ int flush_pending_blocks(MI_SORT_PARAM *sort_param) /* alloc space and pointers for key_blocks */ -static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks, +static SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, uint buffer_length) { reg1 uint i; @@ -4216,7 +4229,7 @@ int test_if_almost_full(MI_INFO *info) /* Recreate table with bigger more alloced record-data */ -int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename) +int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename) { int error; MI_INFO info; @@ -4390,7 +4403,7 @@ end: /* write suffix to data file if neaded */ -int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile) +int write_data_suffix(MI_SORT_INFO *sort_info, my_bool fix_datafile) { MI_INFO *info=sort_info->info; @@ -4411,7 +4424,7 @@ int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile) /* Update state and myisamchk_time of indexfile */ -int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) +int update_state_info(HA_CHECK *param, MI_INFO *info,uint update) { MYISAM_SHARE *share=info->s; @@ -4438,7 +4451,7 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update) { if (update & UPDATE_TIME) { - share->state.check_time= (long) time((time_t*) 0); + share->state.check_time= time((time_t*) 0); if (!share->state.create_time) share->state.create_time=share->state.check_time; } @@ -4483,7 +4496,7 @@ err: param->auto_increment is bigger than the biggest key. */ -void update_auto_increment_key(MI_CHECK *param, MI_INFO *info, +void update_auto_increment_key(HA_CHECK *param, MI_INFO *info, my_bool repair_only) { uchar *record= 0; @@ -4623,8 +4636,9 @@ void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part, let's ensure it is not */ set_if_bigger(tmp,1); - if (tmp >= (ulonglong) ~(ulong) 0) - tmp=(ulonglong) ~(ulong) 0; + /* Keys are stored as 32 byte int's; Ensure we don't get an overflow */ + if (tmp >= (ulonglong) ~(uint32) 0) + tmp=(ulonglong) ~(uint32) 0; *rec_per_key_part=(ulong) tmp; rec_per_key_part++; @@ -4714,7 +4728,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, static void -set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share) +set_data_file_type(MI_SORT_INFO *sort_info, MYISAM_SHARE *share) { if ((sort_info->new_data_file_type=share->data_file_type) == COMPRESSED_RECORD && sort_info->param->testflag & T_UNPACK) diff --git a/storage/myisam/mi_checksum.c b/storage/myisam/mi_checksum.c index 1aa56e571e3..8c408ef7ff5 100644 --- a/storage/myisam/mi_checksum.c +++ b/storage/myisam/mi_checksum.c @@ -19,27 +19,34 @@ ha_checksum mi_checksum(MI_INFO *info, const uchar *buf) { - uint i; ha_checksum crc=0; - MI_COLUMNDEF *rec=info->s->rec; + const uchar *record= buf; + MI_COLUMNDEF *column= info->s->rec; + MI_COLUMNDEF *column_end= column+ info->s->base.fields; + my_bool skip_null_bits= test(info->s->options & HA_OPTION_NULL_FIELDS); - for (i=info->s->base.fields ; i-- ; buf+=(rec++)->length) + for ( ; column != column_end ; buf+= column++->length) { const uchar *pos; ulong length; - switch (rec->type) { + + if ((record[column->null_pos] & column->null_bit) && + skip_null_bits) + continue; /* Null field */ + + switch (column->type) { case FIELD_BLOB: { - length=_mi_calc_blob_length(rec->length- - portable_sizeof_char_ptr, - buf); - memcpy((char*) &pos, buf+rec->length- portable_sizeof_char_ptr, + length=_mi_calc_blob_length(column->length- + portable_sizeof_char_ptr, + buf); + memcpy((char*) &pos, buf+column->length- portable_sizeof_char_ptr, sizeof(char*)); break; } case FIELD_VARCHAR: { - uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length-1); + uint pack_length= HA_VARCHAR_PACKLENGTH(column->length-1); if (pack_length == 1) length= (ulong) *(uchar*) buf; else @@ -48,7 +55,7 @@ ha_checksum mi_checksum(MI_INFO *info, const uchar *buf) break; } default: - length=rec->length; + length=column->length; pos=buf; break; } diff --git a/storage/myisam/mi_close.c b/storage/myisam/mi_close.c index 51408ab191c..fd10ef47968 100644 --- a/storage/myisam/mi_close.c +++ b/storage/myisam/mi_close.c @@ -64,8 +64,10 @@ int mi_close(register MI_INFO *info) if (share->kfile >= 0) abort();); if (share->kfile >= 0 && flush_key_blocks(share->key_cache, share->kfile, - share->temporary ? FLUSH_IGNORE_CHANGED : - FLUSH_RELEASE)) + &share->dirty_part_map, + ((share->temporary || share->deleting) ? + FLUSH_IGNORE_CHANGED : + FLUSH_RELEASE))) error=my_errno; if (share->kfile >= 0) { @@ -74,6 +76,7 @@ int mi_close(register MI_INFO *info) not change the crashed state. We can NOT write the state in other cases as other threads may be using the file at this point + IF using --external-locking. */ if (share->mode != O_RDONLY && mi_is_crashed(info)) mi_state_info_write(share->kfile, &share->state, 1); diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 46c61eb4709..3a842b966ab 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -37,11 +37,11 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, File UNINIT_VAR(dfile), UNINIT_VAR(file); int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; myf create_flag; - uint fields,length,max_key_length,packed,pointer,real_length_diff, + uint fields,length,max_key_length,packed,pack_bytes,pointer,real_length_diff, key_length,info_length,key_segs,options,min_key_length_skip, base_pos,long_varchar_count,varchar_length, max_key_block_length,unique_key_parts,fulltext_keys,offset; - uint aligned_key_start, block_length; + uint aligned_key_start, block_length, res; ulong reclength, real_reclength,min_pack_length; char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr; ulong pack_reclength; @@ -90,7 +90,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */ if (!(rec_per_key_part= - (ulong*) my_malloc((keys + uniques)*MI_MAX_KEY_SEG*sizeof(long), + (ulong*) my_malloc((keys + uniques)*HA_MAX_KEY_SEG*sizeof(long), MYF(MY_WME | MY_ZEROFILL)))) DBUG_RETURN(my_errno); @@ -103,6 +103,9 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, rec++,fields++) { reclength+=rec->length; + if (rec->null_bit) + options|= HA_OPTION_NULL_FIELDS; + if ((type=(enum en_fieldtype) rec->type) != FIELD_NORMAL && type != FIELD_CHECK) { @@ -137,6 +140,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, long_varchar_count++; pack_reclength+= 2; /* May be packed on 3 bytes */ } + options|= HA_OPTION_NULL_FIELDS; /* Use of mi_checksum() */ } else if (type != FIELD_SKIP_ZERO) { @@ -176,23 +180,30 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (flags & HA_CREATE_TMP_TABLE) { options|= HA_OPTION_TMP_TABLE; - create_mode|= O_EXCL | O_NOFOLLOW; + create_mode|= O_NOFOLLOW; } if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM)) { options|= HA_OPTION_CHECKSUM; min_pack_length++; } + /* + Don't set HA_OPTION_NULL_FIELDS if no checksums, as this flag makes + that file incompatible with MySQL. This is ok, as this flag is only + used if one specifics table level checksums. + */ + if (!(options & HA_OPTION_CHECKSUM)) + options&= ~HA_OPTION_NULL_FIELDS; if (flags & HA_CREATE_DELAY_KEY_WRITE) options|= HA_OPTION_DELAY_KEY_WRITE; if (flags & HA_CREATE_RELIES_ON_SQL_LAYER) options|= HA_OPTION_RELIES_ON_SQL_LAYER; - packed=(packed+7)/8; + pack_bytes= (packed+7)/8; if (pack_reclength != INT_MAX32) pack_reclength+= reclength+packed + test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_OPTION_PACK_RECORD)); - min_pack_length+=packed; + min_pack_length+= pack_bytes; if (!ci->data_file_length && ci->max_rows) { @@ -269,7 +280,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, keyseg->type != HA_KEYTYPE_VARBINARY2) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } } keydef->keysegs+=sp_segs; @@ -278,7 +289,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, min_key_length_skip+=SPLEN*2*SPDIMS; #else my_errno= HA_ERR_UNSUPPORTED; - goto err; + goto err_no_lock; #endif /*HAVE_SPATIAL*/ } else if (keydef->flag & HA_FULLTEXT) @@ -294,7 +305,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, keyseg->type != HA_KEYTYPE_VARTEXT2) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } if (!(keyseg->flag & HA_BLOB_PART) && (keyseg->type == HA_KEYTYPE_VARTEXT1 || @@ -416,10 +427,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } } /* if HA_FULLTEXT */ key_segs+=keydef->keysegs; - if (keydef->keysegs > MI_MAX_KEY_SEG) + if (keydef->keysegs > HA_MAX_KEY_SEG) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } /* key_segs may be 0 in the case when we only want to be able to @@ -431,7 +442,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; /* Get block length for key, if defined by user */ - block_length= (keydef->block_length ? + block_length= (keydef->block_length ? my_round_up_to_next_power(keydef->block_length) : myisam_block_size); block_length= max(block_length, MI_MIN_KEY_BLOCK_LENGTH); @@ -441,10 +452,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, pointer,MI_MAX_KEYPTR_SIZE, block_length); if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH || - length >= MI_MAX_KEY_BUFF) + length >= HA_MAX_KEY_BUFF) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } set_if_bigger(max_key_block_length,keydef->block_length); keydef->keylength= (uint16) key_length; @@ -487,11 +498,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, /* There are only 16 bits for the total header length. */ if (info_length > 65535) { - my_printf_error(0, "MyISAM table '%s' has too many columns and/or " + my_printf_error(HA_WRONG_CREATE_OPTION, + "MyISAM table '%s' has too many columns and/or " "indexes and/or unique constraints.", MYF(0), name + dirname_length(name)); my_errno= HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } bmove(share.state.header.file_version,(uchar*) myisam_file_magic,4); @@ -546,7 +558,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM); share.base.max_pack_length=pack_reclength; share.base.min_pack_length=min_pack_length; - share.base.pack_bits=packed; + share.base.pack_bits= pack_bytes; share.base.fields=fields; share.base.pack_fields=packed; @@ -560,7 +572,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, max(share.base.pack_reclength,MI_MIN_BLOCK_LENGTH) : MI_EXTEND_BLOCK_LENGTH; if (! (flags & HA_DONT_TOUCH_DATA)) - share.state.create_time= (long) time((time_t*) 0); + share.state.create_time= time((time_t*) 0); mysql_mutex_lock(&THR_LOCK_myisam); @@ -809,13 +821,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } errpos=0; mysql_mutex_unlock(&THR_LOCK_myisam); + res= 0; if (mysql_file_close(file, MYF(0))) - goto err; + res= my_errno; my_free(rec_per_key_part); - DBUG_RETURN(0); + DBUG_RETURN(res); err: mysql_mutex_unlock(&THR_LOCK_myisam); +err_no_lock: + save_errno=my_errno; switch (errpos) { case 3: diff --git a/storage/myisam/mi_dbug.c b/storage/myisam/mi_dbug.c index e450e81cecb..3bcacef0b69 100644 --- a/storage/myisam/mi_dbug.c +++ b/storage/myisam/mi_dbug.c @@ -45,6 +45,7 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, fprintf(stream,"NULL"); continue; } + end++; } switch (keyseg->type) { @@ -91,7 +92,7 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, key=end; break; case HA_KEYTYPE_ULONG_INT: - l_1=mi_sint4korr(key); + l_1=mi_uint4korr(key); (void) fprintf(stream,"%lu",(ulong) l_1); key=end; break; @@ -117,7 +118,7 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, case HA_KEYTYPE_LONGLONG: { char buff[21]; - longlong2str(mi_sint8korr(key),buff,-10); + longlong10_to_str(mi_sint8korr(key),buff,-10); (void) fprintf(stream,"%s",buff); key=end; break; @@ -125,11 +126,12 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, case HA_KEYTYPE_ULONGLONG: { char buff[21]; - longlong2str(mi_sint8korr(key),buff,10); + longlong10_to_str(mi_sint8korr(key),buff,10); (void) fprintf(stream,"%s",buff); key=end; break; } +#endif case HA_KEYTYPE_BIT: { uint i; @@ -139,8 +141,6 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg, key= end; break; } - -#endif case HA_KEYTYPE_VARTEXT1: /* VARCHAR and TEXT */ case HA_KEYTYPE_VARTEXT2: /* VARCHAR and TEXT */ case HA_KEYTYPE_VARBINARY1: /* VARBINARY and BLOB */ diff --git a/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c index 9314148cd8c..0817d9926ca 100644 --- a/storage/myisam/mi_delete.c +++ b/storage/myisam/mi_delete.c @@ -159,7 +159,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, DBUG_RETURN(my_errno=HA_ERR_CRASHED); } if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MI_MAX_KEY_BUFF*2))) + HA_MAX_KEY_BUFF*2))) { DBUG_PRINT("error",("Couldn't allocate memory")); DBUG_RETURN(my_errno=ENOMEM); @@ -171,8 +171,9 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo, goto err; } if ((error=d_search(info,keyinfo, - (keyinfo->flag & HA_FULLTEXT ? SEARCH_FIND | SEARCH_UPDATE - : SEARCH_SAME), + (keyinfo->flag & HA_FULLTEXT ? + SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT : + SEARCH_SAME), key,key_length,old_root,root_buff)) >0) { if (error == 2) @@ -221,7 +222,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, my_bool last_key; uchar *leaf_buff,*keypos; my_off_t UNINIT_VAR(leaf_page),next_block; - uchar lastkey[MI_MAX_KEY_BUFF]; + uchar lastkey[HA_MAX_KEY_BUFF]; DBUG_ENTER("d_search"); DBUG_DUMP("page",(uchar*) anc_buff,mi_getint(anc_buff)); @@ -310,7 +311,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, { leaf_page=_mi_kpos(nod_flag,keypos); if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MI_MAX_KEY_BUFF*2))) + HA_MAX_KEY_BUFF*2))) { DBUG_PRINT("error",("Couldn't allocate memory")); my_errno=ENOMEM; @@ -369,9 +370,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, { /* This happens only with packed keys */ DBUG_PRINT("test",("Enlarging of key when deleting")); if (!_mi_get_last_key(info,keyinfo,anc_buff,lastkey,keypos,&length)) - { goto err; - } ret_value=_mi_insert(info,keyinfo,key,anc_buff,keypos,lastkey, (uchar*) 0,(uchar*) 0,(my_off_t) 0,(my_bool) 0); } @@ -409,7 +408,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, int ret_value,length; uint a_length,nod_flag,tmp; my_off_t next_page; - uchar keybuff[MI_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; + uchar keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key; MYISAM_SHARE *share=info->s; MI_KEY_PARAM s_temp; DBUG_ENTER("del"); @@ -426,7 +425,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, { next_page= _mi_kpos(nod_flag,endpos); if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MI_MAX_KEY_BUFF*2))) + HA_MAX_KEY_BUFF*2))) DBUG_RETURN(-1); if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,next_buff,0)) ret_value= -1; @@ -513,7 +512,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo, uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag, key_reflength,key_length; my_off_t next_page; - uchar anc_key[MI_MAX_KEY_BUFF],leaf_key[MI_MAX_KEY_BUFF], + uchar anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF], *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*temp_pos,*prev_key, *after_key; MI_KEY_PARAM s_temp; diff --git a/storage/myisam/mi_delete_all.c b/storage/myisam/mi_delete_all.c index 7a2e24189e6..5940b927d9a 100644 --- a/storage/myisam/mi_delete_all.c +++ b/storage/myisam/mi_delete_all.c @@ -52,7 +52,8 @@ int mi_delete_all_rows(MI_INFO *info) If we are using delayed keys or if the user has done changes to the tables since it was locked then there may be key blocks in the key cache */ - flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED); + flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, + FLUSH_IGNORE_CHANGED); #ifdef HAVE_MMAP if (share->file_map) mi_munmap_file(info); diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index f429edd2759..70a59a11346 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -119,7 +119,7 @@ int mi_munmap_file(MI_INFO *info) { int ret; DBUG_ENTER("mi_unmap_file"); - if ((ret= my_munmap(info->s->file_map, info->s->mmaped_length))) + if ((ret= my_munmap(info->s->file_map, (size_t) info->s->mmaped_length))) DBUG_RETURN(ret); info->s->file_read= mi_nommap_pread; info->s->file_write= mi_nommap_pwrite; @@ -282,7 +282,7 @@ int _mi_write_blob_record(MI_INFO *info, const uchar *record) extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ MI_DYN_DELETE_BLOCK_HEADER+1); reclength= (info->s->base.pack_reclength + - _my_calc_total_blob_length(info,record)+ extra); + _mi_calc_total_blob_length(info,record)+ extra); if (!(rec_buff=(uchar*) my_alloca(reclength))) { my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ @@ -309,7 +309,7 @@ int _mi_update_blob_record(MI_INFO *info, my_off_t pos, const uchar *record) extra= (ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+ MI_DYN_DELETE_BLOCK_HEADER); reclength= (info->s->base.pack_reclength+ - _my_calc_total_blob_length(info,record)+ extra); + _mi_calc_total_blob_length(info,record)+ extra); if (!(rec_buff=(uchar*) my_alloca(reclength))) { my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */ @@ -1353,7 +1353,7 @@ err: /* Calc length of blob. Update info in blobs->length */ -ulong _my_calc_total_blob_length(MI_INFO *info, const uchar *record) +ulong _mi_calc_total_blob_length(MI_INFO *info, const uchar *record) { ulong length; MI_BLOB *blob,*end; @@ -1387,7 +1387,7 @@ ulong _mi_calc_blob_length(uint length, const uchar *pos) } -void _my_store_blob_length(uchar *pos,uint pack_length,uint length) +void _mi_store_blob_length(uchar *pos,uint pack_length,uint length) { switch (pack_length) { case 1: @@ -1598,7 +1598,7 @@ int _mi_cmp_dynamic_record(register MI_INFO *info, register const uchar *record) if (info->s->base.blobs) { if (!(buffer=(uchar*) my_alloca(info->s->base.pack_reclength+ - _my_calc_total_blob_length(info,record)))) + _mi_calc_total_blob_length(info,record)))) DBUG_RETURN(-1); } reclength=_mi_rec_pack(info,buffer,record); @@ -1856,7 +1856,7 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, uchar *buf, if (mysql_file_read(info->dfile, (uchar*) to, block_info.data_len, MYF(MY_NABP))) { - if (my_errno == -1) + if (my_errno == HA_ERR_FILE_TOO_SHORT) my_errno= HA_ERR_WRONG_IN_RECORD; /* Unexpected end of file */ goto err; } diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index baf8cb5e240..16ec536dbc6 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -216,7 +216,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) info->lock_wait=0; break; case HA_EXTRA_NO_WAIT_LOCK: - info->lock_wait=MY_DONT_WAIT; + info->lock_wait= MY_SHORT_WAIT; break; case HA_EXTRA_NO_KEYS: if (info->lock_type == F_UNLCK) @@ -257,20 +257,28 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) mysql_mutex_unlock(&THR_LOCK_myisam); break; case HA_EXTRA_PREPARE_FOR_DROP: + /* Signals about intent to delete this table */ + share->deleting= TRUE; + share->global_changed= FALSE; /* force writing changed flag */ + _mi_mark_file_changed(info); + /* Fall trough */ + case HA_EXTRA_PREPARE_FOR_RENAME: mysql_mutex_lock(&THR_LOCK_myisam); share->last_version= 0L; /* Impossible version */ -#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND - /* Close the isam and data files as Win32 can't drop an open table */ mysql_mutex_lock(&share->intern_lock); + /* Flush pages that we don't need anymore */ if (flush_key_blocks(share->key_cache, share->kfile, - (function == HA_EXTRA_FORCE_REOPEN ? - FLUSH_RELEASE : FLUSH_IGNORE_CHANGED))) + &share->dirty_part_map, + (function == HA_EXTRA_PREPARE_FOR_DROP ? + FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))) { error=my_errno; share->changed=1; mi_print_error(info->s, HA_ERR_CRASHED); mi_mark_crashed(info); /* Fatal error found */ } +#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND + /* Close the isam and data files as Win32 can't drop an open table */ if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) { info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); @@ -284,9 +292,19 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) info->lock_type = F_UNLCK; } if (share->kfile >= 0) + { + /* + We don't need to call _mi_decrement_open_count() if we are + dropping the table, as the files will be removed anyway. If we + are aborted before the files is removed, it's better to not + call it as in that case the automatic repair on open will add + the missing index entries + */ + if (function != HA_EXTRA_PREPARE_FOR_DROP) _mi_decrement_open_count(info); - if (share->kfile >= 0 && mysql_file_close(share->kfile, MYF(0))) - error=my_errno; + if (mysql_file_close(share->kfile,MYF(0))) + error=my_errno; + } { LIST *list_element ; for (list_element=myisam_open_list ; @@ -303,13 +321,14 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) } } share->kfile= -1; /* Files aren't open anymore */ - mysql_mutex_unlock(&share->intern_lock); #endif + mysql_mutex_unlock(&share->intern_lock); mysql_mutex_unlock(&THR_LOCK_myisam); break; case HA_EXTRA_FLUSH: if (!share->temporary) - flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP); + flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, + FLUSH_KEEP); #ifdef HAVE_PWRITE _mi_decrement_open_count(info); #endif @@ -373,6 +392,11 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) share->is_log_table= TRUE; mysql_mutex_unlock(&share->intern_lock); break; + case HA_EXTRA_DETACH_CHILD: /* When used with MERGE tables */ + info->open_flag&= ~HA_OPEN_MERGE_TABLE; + info->lock.priority&= ~THR_LOCK_MERGE_PRIV; + break; + case HA_EXTRA_KEY_CACHE: case HA_EXTRA_NO_KEY_CACHE: default: @@ -386,6 +410,12 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) DBUG_RETURN(error); } /* mi_extra */ +void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func, + void *func_arg) +{ + info->index_cond_func= func; + info->index_cond_func_arg= func_arg; +} /* Start/Stop Inserting Duplicates Into a Table, WL#1648. diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c index 75038fce070..f64a602e2be 100644 --- a/storage/myisam/mi_key.c +++ b/storage/myisam/mi_key.c @@ -31,7 +31,8 @@ set_if_smaller(char_length,length); \ } while(0) -static int _mi_put_key_in_record(MI_INFO *info,uint keynr,uchar *record); +static int _mi_put_key_in_record(MI_INFO *info,uint keynr, + my_bool unpack_blobs, uchar *record); /* Make a intern key from a record @@ -311,6 +312,9 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, _mi_put_key_in_record() info MyISAM handler keynr Key number that was used + unpack_blobs TRUE <=> Unpack blob columns + FALSE <=> Skip them. This is used by index condition + pushdown check function record Store key here Last read key is in info->lastkey @@ -324,7 +328,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, */ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, - uchar *record) + my_bool unpack_blobs, uchar *record) { reg2 uchar *key; uchar *pos,*key_end; @@ -417,16 +421,19 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, if (length > keyseg->length || key+length > key_end) goto err; #endif - memcpy(record+keyseg->start+keyseg->bit_start, - (char*) &blob_ptr,sizeof(char*)); - memcpy(blob_ptr,key,length); - blob_ptr+=length; + if (unpack_blobs) + { + memcpy(record+keyseg->start+keyseg->bit_start, + (char*) &blob_ptr,sizeof(char*)); + memcpy(blob_ptr,key,length); + blob_ptr+=length; - /* The above changed info->lastkey2. Inform mi_rnext_same(). */ - info->update&= ~HA_STATE_RNEXT_SAME; + /* The above changed info->lastkey2. Inform mi_rnext_same(). */ + info->update&= ~HA_STATE_RNEXT_SAME; - _my_store_blob_length(record+keyseg->start, - (uint) keyseg->bit_start,length); + _mi_store_blob_length(record+keyseg->start, + (uint) keyseg->bit_start,length); + } key+=length; } else if (keyseg->flag & HA_SWAP_KEY) @@ -470,7 +477,7 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, uchar *buf) { if (info->lastinx >= 0) { /* Read only key */ - if (_mi_put_key_in_record(info,(uint) info->lastinx,buf)) + if (_mi_put_key_in_record(info,(uint) info->lastinx, TRUE, buf)) { mi_print_error(info->s, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; @@ -486,6 +493,34 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, uchar *buf) /* + Save current key tuple to record and call index condition check function + + SYNOPSIS + mi_check_index_cond() + info MyISAM handler + keynr Index we're running a scan on + record Record buffer to use (it is assumed that index check function + will look for column values there) + + RETURN + ICP_ERROR Error + ICP_NO_MATCH Index condition is not satisfied, continue scanning + ICP_MATCH Index condition is satisfied + ICP_OUT_OF_RANGE Index condition is not satisfied, end the scan. +*/ + +int mi_check_index_cond(register MI_INFO *info, uint keynr, uchar *record) +{ + if (_mi_put_key_in_record(info, keynr, FALSE, record)) + { + mi_print_error(info->s, HA_ERR_CRASHED); + my_errno=HA_ERR_CRASHED; + return ICP_ERROR; + } + return info->index_cond_func(info->index_cond_func_arg); +} + +/* Retrieve auto_increment info SYNOPSIS diff --git a/storage/myisam/mi_keycache.c b/storage/myisam/mi_keycache.c index cbd9c7d76ab..be7d3cc6f1e 100644 --- a/storage/myisam/mi_keycache.c +++ b/storage/myisam/mi_keycache.c @@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info, in the old key cache. */ - if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE)) + if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, + FLUSH_RELEASE)) { error= my_errno; mi_print_error(info->s, HA_ERR_CRASHED); @@ -90,7 +91,8 @@ int mi_assign_to_key_cache(MI_INFO *info, (This can never fail as there is never any not written data in the new key cache) */ - (void) flush_key_blocks(key_cache, share->kfile, FLUSH_RELEASE); + (void) flush_key_blocks(key_cache, share->kfile, &share->dirty_part_map, + FLUSH_RELEASE); /* ensure that setting the key cache and changing the multi_key_cache @@ -102,6 +104,7 @@ int mi_assign_to_key_cache(MI_INFO *info, This should be seen at the lastes for the next call to an myisam function. */ share->key_cache= key_cache; + share->dirty_part_map= 0; /* store the key cache in the global hash structure for future opens */ if (multi_key_cache_set((uchar*) share->unique_file_name, diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 6134b4f46df..be308797286 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -22,6 +22,8 @@ #include "ftdefs.h" +static void mi_update_status_with_lock(MI_INFO *info); + /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */ int mi_lock_database(MI_INFO *info, int lock_type) @@ -56,13 +58,21 @@ int mi_lock_database(MI_INFO *info, int lock_type) case F_UNLCK: ftparser_call_deinitializer(info); if (info->lock_type == F_RDLCK) + { count= --share->r_locks; + mi_restore_status(info); + } else + { count= --share->w_locks; + mi_update_status_with_lock(info); + } --share->tot_locks; if (info->lock_type == F_WRLCK && !share->w_locks && !share->delay_key_write && flush_key_blocks(share->key_cache, - share->kfile,FLUSH_KEEP)) + share->kfile, + &share->dirty_part_map, + FLUSH_KEEP)) { error=my_errno; mi_print_error(info->s, HA_ERR_CRASHED); @@ -84,16 +94,16 @@ int mi_lock_database(MI_INFO *info, int lock_type) if (share->changed && !share->w_locks) { #ifdef HAVE_MMAP - if ((info->s->mmaped_length != info->s->state.state.data_file_length) && - (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS)) - { - if (info->s->concurrent_insert) - mysql_rwlock_wrlock(&info->s->mmap_lock); - mi_remap_file(info, info->s->state.state.data_file_length); - info->s->nonmmaped_inserts= 0; - if (info->s->concurrent_insert) - mysql_rwlock_unlock(&info->s->mmap_lock); - } + if ((info->s->mmaped_length != info->s->state.state.data_file_length) && + (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS)) + { + if (info->s->concurrent_insert) + mysql_rwlock_wrlock(&info->s->mmap_lock); + mi_remap_file(info, info->s->state.state.data_file_length); + info->s->nonmmaped_inserts= 0; + if (info->s->concurrent_insert) + mysql_rwlock_unlock(&info->s->mmap_lock); + } #endif share->state.process= share->last_process=share->this_process; share->state.unique= info->last_unique= info->this_unique; @@ -242,7 +252,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) a crash on windows if the table is renamed and later on referenced by the merge table. */ - if( info->owned_by_merge && (info->s)->kfile < 0 ) + if ((info->open_flag & HA_OPEN_MERGE_TABLE) && (info->s)->kfile < 0) { error = HA_ERR_NO_SUCH_TABLE; } @@ -267,13 +277,15 @@ int mi_lock_database(MI_INFO *info, int lock_type) (THR_WRITE_CONCURRENT_INSERT was used) */ -void mi_get_status(void* param, int concurrent_insert) +void mi_get_status(void* param, my_bool concurrent_insert) { MI_INFO *info=(MI_INFO*) param; DBUG_ENTER("mi_get_status"); - DBUG_PRINT("info",("key_file: %ld data_file: %ld concurrent_insert: %d", - (long) info->s->state.state.key_file_length, - (long) info->s->state.state.data_file_length, + DBUG_PRINT("info",("name: %s key_file: %lu data_file: %lu rows: %lu concurrent_insert: %d", + info->s->index_file_name, + (ulong) info->s->state.state.key_file_length, + (ulong) info->s->state.state.data_file_length, + (ulong) info->s->state.state.records, concurrent_insert)); #ifndef DBUG_OFF if (info->state->key_file_length > info->s->state.state.key_file_length || @@ -294,6 +306,7 @@ void mi_get_status(void* param, int concurrent_insert) void mi_update_status(void* param) { MI_INFO *info=(MI_INFO*) param; + DBUG_ENTER("mi_update_status"); /* Because someone may have closed the table we point at, we only update the state if its our own state. This isn't a problem as @@ -303,9 +316,11 @@ void mi_update_status(void* param) if (info->state == &info->save_state) { #ifndef DBUG_OFF - DBUG_PRINT("info",("updating status: key_file: %ld data_file: %ld", - (long) info->state->key_file_length, - (long) info->state->data_file_length)); + DBUG_PRINT("info", + ("updating status: key_file: %lu data_file: %lu rows: %lu", + (ulong) info->state->key_file_length, + (ulong) info->state->data_file_length, + (ulong) info->state->records)); if (info->state->key_file_length < info->s->state.state.key_file_length || info->state->data_file_length < info->s->state.state.data_file_length) DBUG_PRINT("warning",("old info: key_file: %ld data_file: %ld", @@ -313,6 +328,12 @@ void mi_update_status(void* param) (long) info->s->state.state.data_file_length)); #endif info->s->state.state= *info->state; +#ifdef HAVE_QUERY_CACHE + DBUG_PRINT("info", ("invalidator... '%s' (status update)", + info->filename)); + DBUG_ASSERT(info->s->chst_invalidator != NULL); + (*info->s->chst_invalidator)((const char *)info->filename); +#endif } info->state= &info->s->state.state; info->append_insert_at_end= 0; @@ -330,20 +351,50 @@ void mi_update_status(void* param) } info->opt_flag&= ~WRITE_CACHE_USED; } + DBUG_VOID_RETURN; +} + +/* + Same as mi_update_status() but take a lock in the table lock, to protect + against someone calling mi_get_status() from thr_lock() at the same time. +*/ + +static void mi_update_status_with_lock(MI_INFO *info) +{ + my_bool locked= 0; + if (info->state == &info->save_state) + { + locked= 1; + pthread_mutex_lock(&info->s->lock.mutex); + } + mi_update_status(info); + if (locked) + pthread_mutex_unlock(&info->s->lock.mutex); } void mi_restore_status(void *param) { MI_INFO *info= (MI_INFO*) param; + DBUG_ENTER("mi_restore_status"); + DBUG_PRINT("info",("key_file: %ld data_file: %ld", + (long) info->s->state.state.key_file_length, + (long) info->s->state.state.data_file_length)); info->state= &info->s->state.state; info->append_insert_at_end= 0; + DBUG_VOID_RETURN; } void mi_copy_status(void* to,void *from) { - ((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state; + MI_INFO *info= (MI_INFO*) to; + DBUG_ENTER("mi_copy_status"); + info->state= &((MI_INFO*) from)->save_state; + DBUG_PRINT("info",("key_file: %ld data_file: %ld", + (long) info->state->key_file_length, + (long) info->state->data_file_length)); + DBUG_VOID_RETURN; } @@ -371,17 +422,44 @@ void mi_copy_status(void* to,void *from) my_bool mi_check_status(void *param) { MI_INFO *info=(MI_INFO*) param; + DBUG_ENTER("mi_check_status"); + DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u", + (long) info->s->state.dellink, (uint) info->s->r_locks, + (uint) info->s->w_locks)); /* The test for w_locks == 1 is here because this thread has already done an external lock (in other words: w_locks == 1 means no other threads has a write lock) */ - DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u", - (long) info->s->state.dellink, (uint) info->s->r_locks, - (uint) info->s->w_locks)); - return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR || + DBUG_RETURN((my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR || (myisam_concurrent_insert == 2 && info->s->r_locks && - info->s->w_locks == 1)); + info->s->w_locks == 1))); +} + + +/** + Fix status for thr_lock_merge() + + @param org_table + @param new_table that should point on org_lock. new_table is 0 + in case this is the first occurence of the table in the lock + structure. +*/ + +void mi_fix_status(MI_INFO *org_table, MI_INFO *new_table) +{ + DBUG_ENTER("mi_fix_status"); + if (!new_table) + { + /* First in group. Set state as in mi_get_status() */ + org_table->state= &org_table->save_state; + } + else + { + /* Set new_table to use state from org_table (first lock of this table) */ + new_table->state= org_table->state; + } + DBUG_VOID_RETURN; } @@ -403,10 +481,10 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer) DBUG_RETURN(1); if (mi_state_info_read_dsk(share->kfile, &share->state, 1)) { - int error=my_errno ? my_errno : -1; + int error= my_errno ? my_errno : HA_ERR_FILE_TOO_SHORT; (void) my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF, MYF(MY_SEEK_NOT_DONE)); - my_errno=error; + my_errno= error; DBUG_RETURN(1); } } @@ -479,7 +557,8 @@ int _mi_test_if_changed(register MI_INFO *info) { /* Keyfile has changed */ DBUG_PRINT("info",("index file changed")); if (share->state.process != share->this_process) - (void) flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE); + (void) flush_key_blocks(share->key_cache, share->kfile, + &share->dirty_part_map, FLUSH_RELEASE); share->last_process=share->state.process; info->last_unique= share->state.unique; info->last_loop= share->state.update_count; @@ -554,7 +633,7 @@ int _mi_decrement_open_count(MI_INFO *info) { uint old_lock=info->lock_type; share->global_changed=0; - lock_error=mi_lock_database(info,F_WRLCK); + lock_error= my_disable_locking ? 0 : mi_lock_database(info,F_WRLCK); /* Its not fatal even if we couldn't get the lock ! */ if (share->state.open_count > 0) { @@ -564,7 +643,7 @@ int _mi_decrement_open_count(MI_INFO *info) sizeof(share->state.header), MYF(MY_NABP)); } - if (!lock_error) + if (!lock_error && !my_disable_locking) lock_error=mi_lock_database(info,old_lock); } return test(lock_error || write_error); diff --git a/storage/myisam/mi_log.c b/storage/myisam/mi_log.c index 5af4a057a95..e0c66bef996 100644 --- a/storage/myisam/mi_log.c +++ b/storage/myisam/mi_log.c @@ -130,7 +130,7 @@ void _myisam_log_record(enum myisam_log_commands command, MI_INFO *info, if (!info->s->base.blobs) length=info->s->base.reclength; else - length=info->s->base.reclength+ _my_calc_total_blob_length(info,record); + length=info->s->base.reclength+ _mi_calc_total_blob_length(info,record); buff[0]=(uchar) command; mi_int2store(buff+1,info->dfile); mi_int4store(buff+3,pid); diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index e3c29909067..2403bf70434 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -19,6 +19,7 @@ #include "sp_defs.h" #include "rt_index.h" #include <m_ctype.h> +#include <mysql_version.h> #ifdef __WIN__ #include <fcntl.h> @@ -50,6 +51,8 @@ MI_INFO *test_if_reopen(char *filename) { MI_INFO *info=(MI_INFO*) pos->data; MYISAM_SHARE *share=info->s; + DBUG_ASSERT(strcmp(share->unique_file_name,filename) || + share->last_version); if (!strcmp(share->unique_file_name,filename) && share->last_version) return info; } @@ -75,8 +78,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) uchar *disk_cache, *disk_pos, *end_pos; MI_INFO info,*m_info,*old_info; MYISAM_SHARE share_buff,*share; - ulong rec_per_key_part[HA_MAX_POSSIBLE_KEY*MI_MAX_KEY_SEG]; - my_off_t key_root[HA_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE]; + ulong *rec_per_key_part= 0; + my_off_t *key_root, *key_del; ulonglong max_key_file_length, max_data_file_length; DBUG_ENTER("mi_open"); @@ -88,7 +91,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) bzero((uchar*) &info,sizeof(info)); realpath_err= my_realpath(name_buff, - fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0)); + fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0)); if (my_is_symlink(org_name) && (realpath_err || (*myisam_test_invalid_symlink)(name_buff))) { @@ -101,14 +104,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) { share= &share_buff; bzero((uchar*) &share_buff,sizeof(share_buff)); - share_buff.state.rec_per_key_part=rec_per_key_part; - share_buff.state.key_root=key_root; - share_buff.state.key_del=key_del; share_buff.key_cache= multi_key_cache_search((uchar*) name_buff, - strlen(name_buff)); + strlen(name_buff), + dflt_key_cache); DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open", - if (strstr(name, "/t1")) + if (strstr(name, "/crashed")) { my_errno= HA_ERR_CRASHED; goto err; @@ -132,12 +133,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) my_errno= HA_ERR_NOT_A_TABLE; goto err; } - if (memcmp((uchar*) share->state.header.file_version, - (uchar*) myisam_file_magic, 4)) + if (bcmp(share->state.header.file_version, myisam_file_magic, 4)) { DBUG_PRINT("error",("Wrong header in %s",name_buff)); DBUG_DUMP("error_dump", share->state.header.file_version, - head_length); + (size_t) head_length); my_errno=HA_ERR_NOT_A_TABLE; goto err; } @@ -147,7 +147,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA | HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE | - HA_OPTION_RELIES_ON_SQL_LAYER)) + HA_OPTION_RELIES_ON_SQL_LAYER | HA_OPTION_NULL_FIELDS)) { DBUG_PRINT("error",("wrong options: 0x%lx", share->options)); my_errno=HA_ERR_OLD_FILE; @@ -183,7 +183,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) { if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF, MYF(open_flags & HA_OPEN_WAIT_IF_LOCKED ? - 0 : MY_DONT_WAIT))) && + 0 : MY_SHORT_WAIT))) && !(open_flags & HA_OPEN_IGNORE_IF_LOCKED)) goto err; } @@ -207,14 +207,19 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) } share->state_diff_length=len-MI_STATE_INFO_SIZE; - mi_state_info_read(disk_cache, &share->state); + if (!mi_state_info_read(disk_cache, &share->state)) + goto err; + rec_per_key_part= share->state.rec_per_key_part; + key_root= share->state.key_root; + key_del= share->state.key_del; + len= mi_uint2korr(share->state.header.base_info_length); if (len != MI_BASE_INFO_SIZE) { DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d", len,MI_BASE_INFO_SIZE)); } - disk_pos= my_n_base_info_read(disk_cache + base_pos, &share->base); + disk_pos= mi_n_base_info_read(disk_cache + base_pos, &share->base); share->state.state_length=base_pos; if (!(open_flags & HA_OPEN_FOR_REPAIR) && @@ -239,8 +244,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) } key_parts+=fulltext_keys*FT_SEGS; - if (share->base.max_key_length > MI_MAX_KEY_BUFF || keys > MI_MAX_KEY || - key_parts > MI_MAX_KEY * MI_MAX_KEY_SEG) + if (share->base.max_key_length > HA_MAX_KEY_BUFF || keys > MI_MAX_KEY || + key_parts > MI_MAX_KEY * HA_MAX_KEY_SEG) { DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts)); my_errno=HA_ERR_UNSUPPORTED; @@ -440,13 +445,20 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->rec[i].pack_type=0; share->rec[i].huff_tree=0; share->rec[i].offset=offset; - if (share->rec[i].type == (int) FIELD_BLOB) + if (share->rec[i].type == FIELD_BLOB) { share->blobs[j].pack_length= - share->rec[i].length-portable_sizeof_char_ptr; + share->rec[i].length - portable_sizeof_char_ptr; share->blobs[j].offset=offset; j++; } +#if MYSQL_VERSION_ID <= 60100 + /* This is to detect old checksum option */ + if (share->rec[i].null_bit) + share->has_null_fields= 1; + if (share->rec[i].type == FIELD_VARCHAR) + share->has_varchar_fields= 1; +#endif offset+=share->rec[i].length; } share->rec[i].type=(int) FIELD_LAST; /* End marker */ @@ -526,6 +538,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->lock.update_status=mi_update_status; share->lock.restore_status= mi_restore_status; share->lock.check_status=mi_check_status; + share->lock.fix_status= (void (*)(void *, void *)) mi_fix_status; } } #endif @@ -576,6 +589,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) info.s=share; info.lastpos= HA_OFFSET_ERROR; info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND); + info.open_flag= open_flags; info.opt_flag=READ_CHECK_USED; info.this_unique= (ulong) info.dfile; /* Uniq number in process */ if (share->data_file_type == COMPRESSED_RECORD) @@ -634,6 +648,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) mysql_mutex_unlock(&THR_LOCK_myisam); bzero(info.buff, share->base.max_key_block_length * 2); + my_free(rec_per_key_part, MYF(MY_ALLOW_ZERO_PTR)); if (myisam_log_file >= 0) { @@ -663,6 +678,7 @@ err: case 3: if (! lock_error) (void) my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)); + my_free(rec_per_key_part, MYF(MY_ALLOW_ZERO_PTR)); /* fall through */ case 2: my_afree(disk_cache); @@ -735,12 +751,14 @@ void mi_setup_functions(register MYISAM_SHARE *share) { share->read_record=_mi_read_pack_record; share->read_rnd=_mi_read_rnd_pack_record; - if (!(share->options & HA_OPTION_TEMP_COMPRESS_RECORD)) - share->calc_checksum=0; /* No checksum */ - else if (share->options & HA_OPTION_PACK_RECORD) + if ((share->options & + (HA_OPTION_PACK_RECORD | HA_OPTION_NULL_FIELDS))) share->calc_checksum= mi_checksum; else share->calc_checksum= mi_static_checksum; + share->calc_check_checksum= share->calc_checksum; + if (!(share->options & HA_OPTION_TEMP_COMPRESS_RECORD)) + share->calc_checksum=0; /* No checksum */ } else if (share->options & HA_OPTION_PACK_RECORD) { @@ -750,6 +768,7 @@ void mi_setup_functions(register MYISAM_SHARE *share) share->compare_record=_mi_cmp_dynamic_record; share->compare_unique=_mi_cmp_dynamic_unique; share->calc_checksum= mi_checksum; + share->calc_check_checksum= share->calc_checksum; /* add bits used to pack data to pack_reclength for faster allocation */ share->base.pack_reclength+= share->base.pack_bits; @@ -773,7 +792,11 @@ void mi_setup_functions(register MYISAM_SHARE *share) share->update_record=_mi_update_static_record; share->write_record=_mi_write_static_record; share->compare_unique=_mi_cmp_static_unique; - share->calc_checksum= mi_static_checksum; + if (share->options & HA_OPTION_NULL_FIELDS) + share->calc_checksum= mi_checksum; + else + share->calc_checksum= mi_static_checksum; + share->calc_check_checksum= share->calc_checksum; } share->file_read= mi_nommap_pread; share->file_write= mi_nommap_pwrite; @@ -943,6 +966,16 @@ uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state) ptr+= state->state_diff_length; + if (!state->rec_per_key_part) + { + if (!my_multi_malloc(MY_WME, + &state->rec_per_key_part,sizeof(long)*key_parts, + &state->key_root, keys*sizeof(my_off_t), + &state->key_del, key_blocks*sizeof(my_off_t), + NullS)) + return(0); + } + for (i=0; i < keys; i++) { state->key_root[i]= mi_sizekorr(ptr); ptr +=8; @@ -1022,7 +1055,7 @@ uint mi_base_info_write(File file, MI_BASE_INFO *base) } -uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) +uchar *mi_n_base_info_read(uchar *ptr, MI_BASE_INFO *base) { base->keystart = mi_sizekorr(ptr); ptr +=8; base->max_data_file_length = mi_sizekorr(ptr); ptr +=8; diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index d8d892a5bc9..ceb087d67c9 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -105,6 +105,7 @@ static void init_bit_buffer(MI_BIT_BUFF *bit_buff,uchar *buffer,uint length); static uint fill_and_get_bits(MI_BIT_BUFF *bit_buff,uint count); static void fill_buffer(MI_BIT_BUFF *bit_buff); static uint max_bit(uint value); +static uint read_pack_length(uint version, const uchar *buf, ulong *length); #ifdef HAVE_MMAP static uchar *_mi_mempack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, MI_BLOCK_INFO *info, uchar **rec_buff_p, @@ -1050,7 +1051,7 @@ static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff, return; } decode_bytes(rec,bit_buff,bit_buff->blob_pos,bit_buff->blob_pos+length); - _my_store_blob_length((uchar*) to,pack_length,length); + _mi_store_blob_length((uchar*) to,pack_length,length); memcpy((char*) to+pack_length, &bit_buff->blob_pos, sizeof(char*)); bit_buff->blob_pos+=length; } @@ -1674,7 +1675,7 @@ uint save_pack_length(uint version, uchar *block_buff, ulong length) } -uint read_pack_length(uint version, const uchar *buf, ulong *length) +static uint read_pack_length(uint version, const uchar *buf, ulong *length) { if (buf[0] < 254) { diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c index 90e31e72532..82acb801c90 100644 --- a/storage/myisam/mi_page.c +++ b/storage/myisam/mi_page.c @@ -87,10 +87,11 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, info->state->key_file_length != page+length) length= ((mi_getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1)); DBUG_RETURN((key_cache_write(info->s->key_cache, - info->s->kfile,page, level, (uchar*) buff,length, - (uint) keyinfo->block_length, - (int) ((info->lock_type != F_UNLCK) || - info->s->delay_key_write)))); + info->s->kfile, &info->s->dirty_part_map, + page, level, (uchar*) buff, length, + (uint) keyinfo->block_length, + (int) ((info->lock_type != F_UNLCK) || + info->s->delay_key_write)))); } /* mi_write_keypage */ @@ -109,7 +110,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos, mi_sizestore(buff,old_link); info->s->state.changed|= STATE_NOT_SORTED_PAGES; DBUG_RETURN(key_cache_write(info->s->key_cache, - info->s->kfile, pos , level, buff, + info->s->kfile, &info->s->dirty_part_map, + pos , level, buff, sizeof(buff), (uint) keyinfo->block_length, (int) (info->lock_type != F_UNLCK))); diff --git a/storage/myisam/mi_panic.c b/storage/myisam/mi_panic.c index 69865cfc0bb..e6a1d54a516 100644 --- a/storage/myisam/mi_panic.c +++ b/storage/myisam/mi_panic.c @@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag) if (info->s->options & HA_OPTION_READ_ONLY_DATA) break; #endif - if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE)) + if (flush_key_blocks(info->s->key_cache, info->s->kfile, + &info->s->dirty_part_map, FLUSH_RELEASE)) error=my_errno; if (info->opt_flag & WRITE_CACHE_USED) if (flush_io_cache(&info->rec_cache)) diff --git a/storage/myisam/mi_preload.c b/storage/myisam/mi_preload.c index 31537f7054b..79d3db83796 100644 --- a/storage/myisam/mi_preload.c +++ b/storage/myisam/mi_preload.c @@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) } } else - block_length= share->key_cache->key_cache_block_size; + block_length= share->key_cache->param_block_size; length= info->preload_buff_size/block_length * block_length; set_if_bigger(length, block_length); @@ -73,7 +73,8 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); - if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE)) + if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map, + FLUSH_RELEASE)) goto err; do diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c index 28bf5cbe033..8f598200634 100644 --- a/storage/myisam/mi_range.c +++ b/storage/myisam/mi_range.c @@ -152,7 +152,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key, operations with a comment like "Not real duplicates", whatever this means. From the condition above we can see that 'skip_end_space' is always false for these operations. The result is that trailing space - counts in key comparison and hence, emtpy strings ('', string length + counts in key comparison and hence, empty strings ('', string length zero, but not NULL) compare less that strings starting with control characters and these in turn compare less than strings starting with blanks. @@ -166,7 +166,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key, This is the reason that we add the SEARCH_UPDATE flag here. It makes the key estimation compare in the same way like key write operations - do. Olny so we will find the keys where they have been inserted. + do. Only so we will find the keys where they have been inserted. Adding the flag unconditionally does not hurt as it is used in the above mentioned condition only. So it can safely be used together @@ -259,7 +259,7 @@ static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key) { uint nod_flag,keynr,max_key; - uchar t_buff[MI_MAX_KEY_BUFF],*end; + uchar t_buff[HA_MAX_KEY_BUFF],*end; end= page+mi_getint(page); nod_flag=mi_test_if_nod(page); diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c index d3744c9a053..f5b3514faf6 100644 --- a/storage/myisam/mi_rkey.c +++ b/storage/myisam/mi_rkey.c @@ -29,6 +29,7 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, MI_KEYDEF *keyinfo; HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; + ICP_RESULT res= ICP_NO_MATCH; DBUG_ENTER("mi_rkey"); DBUG_PRINT("enter", ("base: 0x%lx buf: 0x%lx inx: %d search_flag: %d", (long) info, (long) buf, inx, search_flag)); @@ -85,6 +86,8 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, { mi_print_error(info->s, HA_ERR_CRASHED); my_errno=HA_ERR_CRASHED; + if (share->concurrent_insert) + rw_unlock(&share->key_root_lock[inx]); goto err; } break; @@ -103,55 +106,62 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key, saved the current data_file_length. Concurrent inserts always go to the end of the file. So we can test if the found key references a new record. + + If we are searching for a partial key (or using >, >=, < or <=) and + the data is outside of the data file, we need to continue searching + for the first key inside the data file. + + We do also continue searching if an index condition check function + is available. */ - if (info->lastpos >= info->state->data_file_length) + while ((info->lastpos >= info->state->data_file_length && + (search_flag != HA_READ_KEY_EXACT || + last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) || + (info->index_cond_func && + (res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH)) { - /* The key references a concurrently inserted record. */ + uint not_used[2]; + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + /* + Check that the found key does still match the search. + _mi_search_next() delivers the next key regardless of its + value. + */ if (search_flag == HA_READ_KEY_EXACT && - last_used_keyseg == keyinfo->seg + keyinfo->keysegs) + ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, not_used)) { - /* Simply ignore the key if it matches exactly. (Bug #29838) */ my_errno= HA_ERR_KEY_NOT_FOUND; info->lastpos= HA_OFFSET_ERROR; + break; } - else - { - /* - If searching for a partial key (or using >, >=, < or <=) and - the data is outside of the data file, we need to continue - searching for the first key inside the data file. - */ - do - { - uint not_used[2]; - /* - Skip rows that are inserted by other threads since we got - a lock. Note that this can only happen if we are not - searching after a full length exact key, because the keys - are sorted according to position. - */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; /* purecov: inspected */ - /* - Check that the found key does still match the search. - _mi_search_next() delivers the next key regardless of its - value. - */ - if (search_flag == HA_READ_KEY_EXACT && - ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, - use_key_length, SEARCH_FIND, not_used)) - { - /* purecov: begin inspected */ - my_errno= HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; - break; - /* purecov: end */ - } - } while (info->lastpos >= info->state->data_file_length); - } + } + if (res == ICP_OUT_OF_RANGE) + { + info->lastpos= HA_OFFSET_ERROR; + if (share->concurrent_insert) + rw_unlock(&share->key_root_lock[inx]); + DBUG_RETURN((my_errno= HA_ERR_KEY_NOT_FOUND)); + } + /* + Error if no row found within the data file. (Bug #29838) + Do not overwrite my_errno if already at HA_OFFSET_ERROR. + */ + if (info->lastpos != HA_OFFSET_ERROR && + info->lastpos >= info->state->data_file_length) + { + info->lastpos= HA_OFFSET_ERROR; + my_errno= HA_ERR_KEY_NOT_FOUND; } } } diff --git a/storage/myisam/mi_rnext.c b/storage/myisam/mi_rnext.c index e1a78a04e57..43b071bc464 100644 --- a/storage/myisam/mi_rnext.c +++ b/storage/myisam/mi_rnext.c @@ -28,6 +28,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) { int error,changed; uint flag; + ICP_RESULT res= 0; uint update_mask= HA_STATE_NEXT_FOUND; DBUG_ENTER("mi_rnext"); @@ -96,23 +97,36 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) } } - if (info->s->concurrent_insert) + if (!error) { - if (!error) + while ((info->s->concurrent_insert && + info->lastpos >= info->state->data_file_length) || + (info->index_cond_func && + (res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH)) { - while (info->lastpos >= info->state->data_file_length) - { - /* Skip rows inserted by other threads since we got a lock */ - if ((error=_mi_search_next(info,info->s->keyinfo+inx, - info->lastkey, - info->lastkey_length, - SEARCH_BIGGER, - info->s->state.key_root[inx]))) - break; - } + /* + Skip rows that are either inserted by other threads since + we got a lock or do not match pushed index conditions + */ + if ((error=_mi_search_next(info,info->s->keyinfo+inx, + info->lastkey, + info->lastkey_length, + SEARCH_BIGGER, + info->s->state.key_root[inx]))) + break; + } + if (!error && res == ICP_OUT_OF_RANGE) + { + if (info->s->concurrent_insert) + rw_unlock(&info->s->key_root_lock[inx]); + info->lastpos= HA_OFFSET_ERROR; + DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); } - mysql_rwlock_unlock(&info->s->key_root_lock[inx]); } + + if (info->s->concurrent_insert) + mysql_rwlock_unlock(&info->s->key_root_lock[inx]); + /* Don't clear if database-changed */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update|= update_mask; diff --git a/storage/myisam/mi_rnext_same.c b/storage/myisam/mi_rnext_same.c index 6779709fc80..54de367016b 100644 --- a/storage/myisam/mi_rnext_same.c +++ b/storage/myisam/mi_rnext_same.c @@ -75,8 +75,13 @@ int mi_rnext_same(MI_INFO *info, uchar *buf) info->lastpos= HA_OFFSET_ERROR; break; } - /* Skip rows that are inserted by other threads since we got a lock */ - if (info->lastpos < info->state->data_file_length) + /* + Skip + - rows that are inserted by other threads since we got a lock + - rows that don't match index condition */ + if (info->lastpos < info->state->data_file_length && + (!info->index_cond_func || + mi_check_index_cond(info, inx, buf) != ICP_NO_MATCH)) break; } } diff --git a/storage/myisam/mi_rprev.c b/storage/myisam/mi_rprev.c index f7dddefb647..89612b5a661 100644 --- a/storage/myisam/mi_rprev.c +++ b/storage/myisam/mi_rprev.c @@ -51,22 +51,36 @@ int mi_rprev(MI_INFO *info, uchar *buf, int inx) error=_mi_search(info,share->keyinfo+inx,info->lastkey, USE_WHOLE_KEY, flag, share->state.key_root[inx]); - if (share->concurrent_insert) + if (!error) { - if (!error) + int res= 0; + while ((share->concurrent_insert && + info->lastpos >= info->state->data_file_length) || + (info->index_cond_func && + !(res= mi_check_index_cond(info, inx, buf)))) { - while (info->lastpos >= info->state->data_file_length) - { - /* Skip rows that are inserted by other threads since we got a lock */ - if ((error=_mi_search_next(info,share->keyinfo+inx,info->lastkey, - info->lastkey_length, - SEARCH_SMALLER, - share->state.key_root[inx]))) - break; - } + /* + Skip rows that are either inserted by other threads since + we got a lock or do not match pushed index conditions + */ + if ((error=_mi_search_next(info,share->keyinfo+inx,info->lastkey, + info->lastkey_length, + SEARCH_SMALLER, + share->state.key_root[inx]))) + break; + } + if (!error && res == 2) + { + if (share->concurrent_insert) + rw_unlock(&share->key_root_lock[inx]); + info->lastpos= HA_OFFSET_ERROR; + DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE); } - mysql_rwlock_unlock(&share->key_root_lock[inx]); } + + if (share->concurrent_insert) + mysql_rwlock_unlock(&share->key_root_lock[inx]); + info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update|= HA_STATE_PREV_FOUND; if (error) diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c index 61ca3c37863..89d1b801695 100644 --- a/storage/myisam/mi_search.c +++ b/storage/myisam/mi_search.c @@ -66,7 +66,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, int error,flag; uint nod_flag; uchar *keypos,*maxpos; - uchar lastkey[MI_MAX_KEY_BUFF],*buff; + uchar lastkey[HA_MAX_KEY_BUFF],*buff; DBUG_ENTER("_mi_search"); DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu", (ulong) pos, nextflag, (ulong) info->lastpos)); @@ -248,7 +248,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, { int UNINIT_VAR(flag); uint nod_flag,UNINIT_VAR(length),not_used[2]; - uchar t_buff[MI_MAX_KEY_BUFF],*end; + uchar t_buff[HA_MAX_KEY_BUFF],*end; DBUG_ENTER("_mi_seq_search"); end= page+mi_getint(page); @@ -300,8 +300,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uint UNINIT_VAR(prefix_len), suffix_len; int key_len_skip, UNINIT_VAR(seg_len_pack), key_len_left; uchar *end, *kseg, *vseg; - uchar *sort_order=keyinfo->seg->charset->sort_order; - uchar tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; + const uchar *sort_order= keyinfo->seg->charset->sort_order; + uchar tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; uchar *UNINIT_VAR(saved_from), *UNINIT_VAR(saved_to); uchar *UNINIT_VAR(saved_vseg); uint saved_length=0, saved_prefix_len=0; @@ -919,7 +919,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, DBUG_ENTER("_mi_get_binary_pack_key"); page= *page_pos; - page_end=page+MI_MAX_KEY_BUFF+1; + page_end=page+HA_MAX_KEY_BUFF+1; start_key=key; /* @@ -1237,7 +1237,7 @@ int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo, { int error; uint nod_flag; - uchar lastkey[MI_MAX_KEY_BUFF]; + uchar lastkey[HA_MAX_KEY_BUFF]; DBUG_ENTER("_mi_search_next"); DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu", nextflag, (ulong) info->lastpos, @@ -1467,7 +1467,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, int length; uint key_length,ref_length,org_key_length=0, length_pack,new_key_length,diff_flag,pack_marker; - uchar *start,*end,*key_end,*sort_order; + uchar *start,*end,*key_end; + const uchar *sort_order; my_bool same_length; length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0; @@ -1748,7 +1749,7 @@ _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, uint length,key_length,ref_length; s_temp->totlength=key_length=_mi_keylength(keyinfo,key)+nod_flag; -#ifdef HAVE_purify +#ifdef HAVE_valgrind s_temp->n_length= s_temp->n_ref_length=0; /* For valgrind */ #endif s_temp->key=key; @@ -1801,13 +1802,13 @@ _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, } /* Check how many characters are identical to next key */ key= s_temp->key+next_length; + s_temp->prev_length= 0; while (*key++ == *next_key++) ; if ((ref_length= (uint) (key - s_temp->key)-1) == next_length) { s_temp->next_key_pos=0; return length; /* can't pack next key */ } - s_temp->prev_length=0; s_temp->n_ref_length=ref_length; return (int) (length-(ref_length - next_length) - next_length_pack + get_pack_length(ref_length)); diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c index f89f2a8d21d..e9dbc7c6a69 100644 --- a/storage/myisam/mi_test1.c +++ b/storage/myisam/mi_test1.c @@ -49,7 +49,8 @@ int main(int argc,char *argv[]) MY_INIT(argv[0]); my_init(); if (key_cacheing) - init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0); + init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0, + DEFAULT_KEY_CACHE_PARTITIONS); get_options(argc,argv); exit(run_test("test1")); @@ -79,6 +80,8 @@ static int run_test(const char *filename) recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24); if (extra_field == FIELD_VARCHAR) recinfo[2].length+= HA_VARCHAR_PACKLENGTH(recinfo[2].length); + recinfo[1].null_bit= null_fields ? 2 : 0; + if (opt_unique) { recinfo[3].type=FIELD_CHECK; @@ -630,7 +633,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), key_type= HA_KEYTYPE_VARTEXT1; break; case 'k': - if (key_length < 4 || key_length > MI_MAX_KEY_LENGTH) + if (key_length < 4 || key_length > HA_MAX_KEY_LENGTH) { fprintf(stderr,"Wrong key length\n"); exit(1); diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c index 127d93b5433..9babf7ad4f0 100644 --- a/storage/myisam/mi_test2.c +++ b/storage/myisam/mi_test2.c @@ -18,9 +18,6 @@ #ifndef USE_MY_FUNC /* We want to be able to dbug this !! */ #define USE_MY_FUNC #endif -#ifdef DBUG_OFF -#undef DBUG_OFF -#endif #include "myisamdef.h" #include <m_ctype.h> #include <my_bit.h> @@ -40,7 +37,7 @@ static void copy_key(struct st_myisam_info *info,uint inx, uchar *record,uchar *key); static int verbose=0,testflag=0, - first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0, + first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,do_locking=0, rec_pointer_size=0,pack_fields=1,use_log=0,silent=0, opt_quick_mode=0; static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1, @@ -218,8 +215,9 @@ int main(int argc, char *argv[]) if (!silent) printf("- Writing key:s\n"); if (key_cacheing) - init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0); - if (locking) + init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0, + DEFAULT_KEY_CACHE_PARTITIONS); + if (do_locking) mi_lock_database(file,F_WRLCK); if (write_cacheing) mi_extra(file,HA_EXTRA_WRITE_CACHE,0); @@ -331,9 +329,9 @@ int main(int argc, char *argv[]) if (use_blob) { if (i & 1) - put_blob_in_record(record+blob_pos,&blob_buffer); + put_blob_in_record(record2+blob_pos,&blob_buffer); else - bmove(record+blob_pos,read_record+blob_pos,8); + bmove(record2+blob_pos,read_record+blob_pos,8); } if (mi_update(file,read_record,record2)) { @@ -603,7 +601,7 @@ int main(int argc, char *argv[]) if (mi_rsame(file,read_record2,(int) i)) goto err; if (memcmp(read_record,read_record2,reclength) != 0) { - printf("is_rsame didn't find same record\n"); + printf("mi_rsame didn't find same record\n"); goto end; } } @@ -654,10 +652,10 @@ int main(int argc, char *argv[]) sprintf((char*) key2,"%6d",k); min_key.key= key; - min_key.length= USE_WHOLE_KEY; + min_key.keypart_map= HA_WHOLE_KEY; min_key.flag= HA_READ_AFTER_KEY; max_key.key= key2; - max_key.length= USE_WHOLE_KEY; + max_key.keypart_map= HA_WHOLE_KEY; max_key.flag= HA_READ_BEFORE_KEY; range_records= mi_records_in_range(file, 0, &min_key, &max_key); records=0; @@ -710,7 +708,7 @@ int main(int argc, char *argv[]) printf("- mi_extra(CACHE) + mi_rrnd.... + mi_extra(NO_CACHE)\n"); if (mi_reset(file) || mi_extra(file,HA_EXTRA_CACHE,0)) { - if (locking || (!use_blob && !pack_fields)) + if (do_locking || (!use_blob && !pack_fields)) { puts("got error from mi_extra(HA_EXTRA_CACHE)"); goto end; @@ -777,9 +775,8 @@ int main(int argc, char *argv[]) { ulong blob_length,pos; uchar *ptr; - longget(blob_length,read_record+blob_pos+4); - ptr=(uchar*) blob_length; - longget(blob_length,read_record+blob_pos); + memcpy_fixed(&ptr, read_record+blob_pos+4, sizeof(ptr)); + blob_length= uint4korr(read_record+blob_pos); for (pos=0 ; pos < blob_length ; pos++) { if (ptr[pos] != (uchar) (blob_length+pos)) @@ -815,6 +812,8 @@ end: mi_panic(HA_PANIC_CLOSE); /* Should close log */ if (!silent) { + KEY_CACHE_STATISTICS stats; + printf("\nFollowing test have been made:\n"); printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete); if (rec_pointer_size) @@ -831,12 +830,13 @@ end: puts("Write cacheing used"); if (write_cacheing) puts("quick mode"); - if (async_io && locking) + if (async_io && do_locking) puts("Asyncron io with locking used"); - else if (locking) + else if (do_locking) puts("Locking used"); if (use_blob) puts("blobs used"); + get_key_cache_statistics(dflt_key_cache, 0, &stats); printf("key cache status: \n\ blocks used:%10lu\n\ not flushed:%10lu\n\ @@ -844,12 +844,12 @@ w_requests: %10lu\n\ writes: %10lu\n\ r_requests: %10lu\n\ reads: %10lu\n", - dflt_key_cache->blocks_used, - dflt_key_cache->global_blocks_changed, - (ulong) dflt_key_cache->global_cache_w_requests, - (ulong) dflt_key_cache->global_cache_write, - (ulong) dflt_key_cache->global_cache_r_requests, - (ulong) dflt_key_cache->global_cache_read); + (ulong) stats.blocks_used, + (ulong) stats.blocks_changed, + (ulong) stats.write_requests, + (ulong) stats.writes, + (ulong) stats.read_requests, + (ulong) stats.reads); } end_key_cache(dflt_key_cache,1); if (blob_buffer) @@ -902,7 +902,7 @@ static void get_options(int argc, char **argv) use_log=1; break; case 'L': - locking=1; + do_locking=1; break; case 'A': /* use asyncron io */ async_io=1; diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c index c03a34df227..742fd06b0e3 100644 --- a/storage/myisam/mi_test3.c +++ b/storage/myisam/mi_test3.c @@ -15,6 +15,8 @@ /* Test av locking */ +#ifndef _WIN32 /*no fork() in Windows*/ + #include "myisam.h" #include <sys/types.h> #ifdef HAVE_SYS_WAIT_H @@ -175,8 +177,10 @@ void start_test(int id) exit(1); } if (key_cacheing && rnd(2) == 0) - init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0); - printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout); + init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0, + DEFAULT_KEY_CACHE_PARTITIONS); + printf("Process %d, pid: %ld\n", id, (long) getpid()); + fflush(stdout); for (error=i=0 ; i < tests && !error; i++) { @@ -360,7 +364,7 @@ int test_write(MI_INFO *file,int id,int lock_type) mi_extra(file,HA_EXTRA_WRITE_CACHE,0); } - sprintf((char*) record.id,"%7d",getpid()); + sprintf((char*) record.id,"%7ld",(long) getpid()); strnmov((char*) record.text,"Testing...", sizeof(record.text)); tries=(uint) rnd(100)+10; @@ -487,3 +491,14 @@ int test_update(MI_INFO *file,int id,int lock_type) } #include "mi_extrafunc.h" +#else /* _WIN32 */ + +#include <stdio.h> + +int main() +{ + fprintf(stderr,"this test has not been ported to Windows\n"); + return 0; +} + +#endif /* _WIN32 */ diff --git a/storage/myisam/mi_test_all.sh b/storage/myisam/mi_test_all.sh index 5989d9cfaf0..c6bc686e885 100755 --- a/storage/myisam/mi_test_all.sh +++ b/storage/myisam/mi_test_all.sh @@ -5,6 +5,7 @@ valgrind="valgrind --alignment=8 --leak-check=yes" silent="-s" +rm -f test1.TMD if test -f mi_test1$MACH ; then suffix=$MACH ; else suffix=""; fi ./mi_test1$suffix $silent diff --git a/storage/myisam/mi_update.c b/storage/myisam/mi_update.c index b538bcd0bb1..6d4150e5b79 100644 --- a/storage/myisam/mi_update.c +++ b/storage/myisam/mi_update.c @@ -23,7 +23,7 @@ int mi_update(register MI_INFO *info, const uchar *oldrec, uchar *newrec) int flag,key_changed,save_errno; reg3 my_off_t pos; uint i; - uchar old_key[MI_MAX_KEY_BUFF],*new_key; + uchar old_key[HA_MAX_KEY_BUFF],*new_key; my_bool auto_key_changed=0; ulonglong changed; MYISAM_SHARE *share=info->s; diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index bd56bb04f65..7b40a11f7c6 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -267,7 +267,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key, comp_flag=SEARCH_BIGGER; /* Put after same key */ else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT)) { - comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */ + comp_flag=SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT; /* No duplicates */ if (keyinfo->flag & HA_NULL_ARE_EQUAL) comp_flag|= SEARCH_NULL_ARE_EQUAL; } @@ -341,7 +341,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, int error,flag; uint nod_flag, search_key_length; uchar *temp_buff,*keypos; - uchar keybuff[MI_MAX_KEY_BUFF]; + uchar keybuff[HA_MAX_KEY_BUFF]; my_bool was_last_key; my_off_t next_page, dupp_key_pos; DBUG_ENTER("w_search"); @@ -349,7 +349,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY; if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+ - MI_MAX_KEY_BUFF*2))) + HA_MAX_KEY_BUFF*2))) DBUG_RETURN(-1); if (!_mi_fetch_keypage(info,keyinfo,page,DFLT_INIT_HITS,temp_buff,0)) goto err; @@ -697,21 +697,23 @@ uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, uchar *page, } /* _mi_find_half_pos */ - /* - Split buffer at last key - Returns pointer to the start of the key before the last key - key will contain the last key - */ +/* + Split buffer at last key + Returns pointer to the start of the key before the last key + key will contain the last key +*/ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, uchar *key, uint *return_key_length, uchar **after_key) { - uint keys,length,UNINIT_VAR(last_length),key_ref_length; - uchar *end,*lastpos,*UNINIT_VAR(prevpos); - uchar key_buff[MI_MAX_KEY_BUFF]; + uint keys,length,last_length,key_ref_length; + uchar *end,*lastpos,*prevpos; + uchar key_buff[HA_MAX_KEY_BUFF]; DBUG_ENTER("_mi_find_last_pos"); + LINT_INIT(last_length); + key_ref_length=2; length=mi_getint(page)-key_ref_length; page+=key_ref_length; @@ -728,10 +730,12 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, } end=page+length-key_ref_length; + DBUG_ASSERT(page < end); *key='\0'; length=0; lastpos=page; - while (page < end) + + do { prevpos=lastpos; lastpos=page; last_length=length; @@ -742,7 +746,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); } - } + } while (page < end); + *return_key_length=last_length; *after_key=lastpos; DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx", @@ -764,7 +769,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, length,keys; uchar *pos,*buff,*extra_buff; my_off_t next_page,new_pos; - uchar tmp_part_key[MI_MAX_KEY_BUFF]; + uchar tmp_part_key[HA_MAX_KEY_BUFF]; DBUG_ENTER("_mi_balance_page"); k_length=keyinfo->keylength; @@ -930,7 +935,7 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param) Probably I can use info->lastkey here, but I'm not sure, and to be safe I'd better use local lastkey. */ - uchar lastkey[MI_MAX_KEY_BUFF]; + uchar lastkey[HA_MAX_KEY_BUFF]; uint keylen; MI_KEYDEF *keyinfo; diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c index 1c534fe8d02..d51e079625e 100644 --- a/storage/myisam/myisam_ftdump.c +++ b/storage/myisam/myisam_ftdump.c @@ -53,7 +53,7 @@ static struct my_option my_long_options[] = int main(int argc,char *argv[]) { - int error=0, subkeys; + int error=0; uint keylen, keylen2=0, inx, doc_cnt=0; float weight= 1.0; double gws, min_gws=0, avg_gws=0; @@ -83,7 +83,7 @@ int main(int argc,char *argv[]) usage(); } - init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0); + init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0, 0); if (!(info=mi_open(argv[0], O_RDONLY, HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER))) @@ -109,11 +109,12 @@ int main(int argc,char *argv[]) while (!(error=mi_rnext(info,NULL,inx))) { + FT_WEIGTH subkeys; keylen=*(info->lastkey); - subkeys=ft_sintXkorr(info->lastkey+keylen+1); - if (subkeys >= 0) - ft_floatXget(weight, info->lastkey+keylen+1); + subkeys.i =ft_sintXkorr(info->lastkey+keylen+1); + if (subkeys.i >= 0) + weight= subkeys.f; #ifdef HAVE_SNPRINTF snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1); @@ -150,14 +151,14 @@ int main(int argc,char *argv[]) keylen2=keylen; doc_cnt=0; } - doc_cnt+= (subkeys >= 0 ? 1 : -subkeys); + doc_cnt+= (subkeys.i >= 0 ? 1 : -subkeys.i); } if (dump) { - if (subkeys>=0) + if (subkeys.i >= 0) printf("%9lx %20.7f %s\n", (long) info->lastpos,weight,buf); else - printf("%9lx => %17d %s\n",(long) info->lastpos,-subkeys,buf); + printf("%9lx => %17d %s\n",(long) info->lastpos,-subkeys.i,buf); } if (verbose && (total%HOW_OFTEN_TO_WRITE)==0) printf("%10ld\r",total); diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index 4df76e31872..f8eb3cb1bde 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -16,7 +16,6 @@ /* Describe, check and repair of MyISAM tables */ #include "fulltext.h" - #include <m_ctype.h> #include <stdarg.h> #include <my_getopt.h> @@ -35,7 +34,6 @@ static const char *set_collation_name, *opt_tmpdir; static CHARSET_INFO *set_collation; static long opt_myisam_block_size; static long opt_key_cache_block_size; -static const char *my_progname_short; static int stopwords_inited= 0; static MY_TMPDIR myisamchk_tmpdir; @@ -62,9 +60,9 @@ static const char *myisam_stats_method_str="nulls_unequal"; static void get_options(int *argc,char * * *argv); static void print_version(void); static void usage(void); -static int myisamchk(MI_CHECK *param, char *filename); -static void descript(MI_CHECK *param, register MI_INFO *info, char * name); -static int mi_sort_records(MI_CHECK *param, register MI_INFO *info, +static int myisamchk(HA_CHECK *param, char *filename); +static void descript(HA_CHECK *param, register MI_INFO *info, char * name); +static int mi_sort_records(HA_CHECK *param, register MI_INFO *info, char * name, uint sort_key, my_bool write_info, my_bool update_index); static int sort_record_index(MI_SORT_PARAM *sort_param, MI_INFO *info, @@ -72,15 +70,16 @@ static int sort_record_index(MI_SORT_PARAM *sort_param, MI_INFO *info, my_off_t page,uchar *buff,uint sortkey, File new_file, my_bool update_index); -MI_CHECK check_param; +HA_CHECK check_param; /* Main program */ int main(int argc, char **argv) { int error; + uchar rc; MY_INIT(argv[0]); - my_progname_short= my_progname+dirname_length(my_progname); + my_progname_short= "myisamchk"; myisamchk_init(&check_param); check_param.opt_lock_memory=1; /* Lock memory if possible */ @@ -100,7 +99,7 @@ int main(int argc, char **argv) (!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS | T_SORT_INDEX)))) { - uint old_testflag=check_param.testflag; + ulonglong old_testflag=check_param.testflag; if (!(check_param.testflag & T_REP)) check_param.testflag|= T_REP_BY_SORT; check_param.testflag&= ~T_EXTEND; /* Don't needed */ @@ -129,7 +128,8 @@ int main(int argc, char **argv) free_tmpdir(&myisamchk_tmpdir); ft_free_stopwords(); my_end(check_param.testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); - exit(error); + rc= (uchar) error; + exit(rc); #ifndef _lint return 0; /* No compiler warning */ #endif @@ -158,7 +158,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, "Directory where character sets are.", - &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (char**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -254,8 +254,7 @@ static struct my_option my_long_options[] = &check_param.opt_sort_key, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', - "Path for temporary files.", - &opt_tmpdir, + "Path for temporary files.", (char**) &opt_tmpdir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"update-state", 'U', "Mark tables as crashed if any errors were found.", @@ -314,13 +313,13 @@ static struct my_option my_long_options[] = HA_FT_MAXCHARLEN, 0, 1, 0}, { "ft_stopword_file", OPT_FT_STOPWORD_FILE, "Use stopwords from this file instead of built-in list.", - &ft_stopword_file, &ft_stopword_file, 0, GET_STR, + (char**) &ft_stopword_file, (char**) &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"stats_method", OPT_STATS_METHOD, "Specifies how index statistics collection code should treat NULLs. " "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", - &myisam_stats_method_str, &myisam_stats_method_str, 0, + (char**) &myisam_stats_method_str, (char**) &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -671,7 +670,7 @@ get_one_option(int optid, case OPT_STATS_METHOD: { int method; - enum_mi_stats_method method_conv; + enum_handler_stats_method method_conv; LINT_INIT(method_conv); myisam_stats_method_str= argument; if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) @@ -772,10 +771,10 @@ static void get_options(register int *argc,register char ***argv) /* Check table */ -static int myisamchk(MI_CHECK *param, char * filename) +static int myisamchk(HA_CHECK *param, char * filename) { int error,lock_type,recreate; - int rep_quick= param->testflag & (T_QUICK | T_FORCE_UNIQUENESS); + int rep_quick= test(param->testflag & (T_QUICK | T_FORCE_UNIQUENESS)); MI_INFO *info; File datafile; char llbuff[22],llbuff2[22]; @@ -913,7 +912,7 @@ static int myisamchk(MI_CHECK *param, char * filename) param->testflag|=T_REP_BY_SORT; /* if only STATISTICS */ if (!(param->testflag & T_SILENT)) printf("- '%s' has old table-format. Recreating index\n",filename); - rep_quick|=T_QUICK; + rep_quick= 1; } share=info->s; share->tot_locks-= share->r_locks; @@ -1074,7 +1073,7 @@ static int myisamchk(MI_CHECK *param, char * filename) { if (param->testflag & (T_EXTEND | T_MEDIUM)) (void) init_key_cache(dflt_key_cache,opt_key_cache_block_size, - param->use_buffers, 0, 0); + param->use_buffers, 0, 0, 0); (void) init_io_cache(¶m->read_cache,datafile, (uint) param->read_buffer_length, READ_CACHE, @@ -1087,8 +1086,9 @@ static int myisamchk(MI_CHECK *param, char * filename) if ((info->s->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) || (param->testflag & (T_EXTEND | T_MEDIUM))) - error|=chk_data_link(param, info, param->testflag & T_EXTEND); - error|=flush_blocks(param, share->key_cache, share->kfile); + error|=chk_data_link(param, info, test(param->testflag & T_EXTEND)); + error|=flush_blocks(param, share->key_cache, share->kfile, + &share->dirty_part_map); (void) end_io_cache(¶m->read_cache); } if (!error) @@ -1171,7 +1171,7 @@ end2: /* Write info about table */ -static void descript(MI_CHECK *param, register MI_INFO *info, char * name) +static void descript(HA_CHECK *param, register MI_INFO *info, char * name) { uint key,keyseg_nr,field,start; reg3 MI_KEYDEF *keyinfo; @@ -1276,7 +1276,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, char * name) printf("Recordlength: %13d\n",(int) share->base.pack_reclength); if (! mi_is_all_keys_active(share->state.key_map, share->base.keys)) { - longlong2str(share->state.key_map,buff,2); + longlong2str(share->state.key_map,buff,2,1); printf("Using only keys '%s' of %d possibly keys\n", buff, share->base.keys); } @@ -1429,7 +1429,7 @@ static void descript(MI_CHECK *param, register MI_INFO *info, char * name) /* Sort records according to one key */ -static int mi_sort_records(MI_CHECK *param, +static int mi_sort_records(HA_CHECK *param, register MI_INFO *info, char * name, uint sort_key, my_bool write_info, @@ -1443,7 +1443,7 @@ static int mi_sort_records(MI_CHECK *param, ha_rows old_record_count; MYISAM_SHARE *share=info->s; char llbuff[22],llbuff2[22]; - SORT_INFO sort_info; + MI_SORT_INFO sort_info; MI_SORT_PARAM sort_param; DBUG_ENTER("sort_records"); @@ -1489,7 +1489,7 @@ static int mi_sort_records(MI_CHECK *param, DBUG_RETURN(0); /* Nothing to do */ init_key_cache(dflt_key_cache, opt_key_cache_block_size, - (size_t) param->use_buffers, 0, 0); + (size_t) param->use_buffers, 0, 0, 0); if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length, WRITE_CACHE,share->pack.header_length,1, MYF(MY_WME | MY_WAIT_IF_FULL))) @@ -1599,8 +1599,8 @@ err: my_free(sort_info.buff); sort_info.buff=0; share->state.sortkey=sort_key; - DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) | - got_error); + DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile, + &share->dirty_part_map) | got_error); } /* sort_records */ @@ -1614,10 +1614,10 @@ static int sort_record_index(MI_SORT_PARAM *sort_param,MI_INFO *info, uint nod_flag,used_length,key_length; uchar *temp_buff,*keypos,*endpos; my_off_t next_page,rec_pos; - uchar lastkey[MI_MAX_KEY_BUFF]; + uchar lastkey[HA_MAX_KEY_BUFF]; char llbuff[22]; - SORT_INFO *sort_info= sort_param->sort_info; - MI_CHECK *param=sort_info->param; + MI_SORT_INFO *sort_info= sort_param->sort_info; + HA_CHECK *param=sort_info->param; DBUG_ENTER("sort_record_index"); nod_flag=mi_test_if_nod(buff); @@ -1701,17 +1701,15 @@ err: sorting */ -static int not_killed= 0; - -volatile int *killed_ptr(MI_CHECK *param __attribute__((unused))) +int killed_ptr(HA_CHECK *param __attribute__((unused))) { - return ¬_killed; /* always NULL */ + return 0; } /* print warnings and errors */ /* VARARGS */ -void mi_check_print_info(MI_CHECK *param __attribute__((unused)), +void mi_check_print_info(HA_CHECK *param __attribute__((unused)), const char *fmt,...) { va_list args; @@ -1724,7 +1722,7 @@ void mi_check_print_info(MI_CHECK *param __attribute__((unused)), /* VARARGS */ -void mi_check_print_warning(MI_CHECK *param, const char *fmt,...) +void mi_check_print_warning(HA_CHECK *param, const char *fmt,...) { va_list args; DBUG_ENTER("mi_check_print_warning"); @@ -1749,7 +1747,7 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...) /* VARARGS */ -void mi_check_print_error(MI_CHECK *param, const char *fmt,...) +void mi_check_print_error(HA_CHECK *param, const char *fmt,...) { va_list args; DBUG_ENTER("mi_check_print_error"); diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index c7f0cb27a40..304150601d7 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -15,8 +15,8 @@ /* This file is included by all internal myisam files */ -#include "myisam.h" /* Structs & some defines */ -#include "myisampack.h" /* packing of keys */ +#include "myisam.h" /* Structs & some defines */ +#include "myisampack.h" /* packing of keys */ #include <my_tree.h> #ifdef THREAD #include <my_pthread.h> @@ -33,10 +33,10 @@ typedef struct st_mi_status_info { - ha_rows records; /* Rows in table */ - ha_rows del; /* Removed rows */ - my_off_t empty; /* lost space in datafile */ - my_off_t key_empty; /* lost space in indexfile */ + ha_rows records; /* Rows in table */ + ha_rows del; /* Removed rows */ + my_off_t empty; /* lost space in datafile */ + my_off_t key_empty; /* lost space in indexfile */ my_off_t key_file_length; my_off_t data_file_length; ha_checksum checksum; @@ -45,116 +45,119 @@ typedef struct st_mi_status_info typedef struct st_mi_state_info { - struct { /* Fileheader */ + struct + { /* Fileheader */ uchar file_version[4]; uchar options[2]; uchar header_length[2]; uchar state_info_length[2]; uchar base_info_length[2]; uchar base_pos[2]; - uchar key_parts[2]; /* Key parts */ - uchar unique_key_parts[2]; /* Key parts + unique parts */ - uchar keys; /* number of keys in file */ - uchar uniques; /* number of UNIQUE definitions */ - uchar language; /* Language for indexes */ - uchar max_block_size_index; /* max keyblock size */ + uchar key_parts[2]; /* Key parts */ + uchar unique_key_parts[2]; /* Key parts + unique parts */ + uchar keys; /* number of keys in file */ + uchar uniques; /* number of UNIQUE definitions */ + uchar language; /* Language for indexes */ + uchar max_block_size_index; /* max keyblock size */ uchar fulltext_keys; uchar not_used; /* To align to 8 */ } header; MI_STATUS_INFO state; - ha_rows split; /* number of split blocks */ - my_off_t dellink; /* Link to next removed block */ + ha_rows split; /* number of split blocks */ + my_off_t dellink; /* Link to next removed block */ ulonglong auto_increment; - ulong process; /* process that updated table last */ - ulong unique; /* Unique number for this process */ - ulong update_count; /* Updated for each write lock */ + ulong process; /* process that updated table last */ + ulong unique; /* Unique number for this process */ + ulong update_count; /* Updated for each write lock */ ulong status; ulong *rec_per_key_part; - my_off_t *key_root; /* Start of key trees */ - my_off_t *key_del; /* delete links for trees */ - my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */ - - ulong sec_index_changed; /* Updated when new sec_index */ - ulong sec_index_used; /* which extra index are in use */ - ulonglong key_map; /* Which keys are in use */ ha_checksum checksum; /* Table checksum */ - ulong version; /* timestamp of create */ - time_t create_time; /* Time when created database */ - time_t recover_time; /* Time for last recover */ - time_t check_time; /* Time for last check */ - uint sortkey; /* sorted by this key (not used) */ + my_off_t *key_root; /* Start of key trees */ + my_off_t *key_del; /* delete links for trees */ + my_off_t rec_per_key_rows; /* Rows when calculating rec_per_key */ + + ulong sec_index_changed; /* Updated when new sec_index */ + ulong sec_index_used; /* which extra index are in use */ + ulonglong key_map; /* Which keys are in use */ + ulong version; /* timestamp of create */ + time_t create_time; /* Time when created database */ + time_t recover_time; /* Time for last recover */ + time_t check_time; /* Time for last check */ + uint sortkey; /* sorted by this key (not used) */ uint open_count; - uint8 changed; /* Changed since myisamchk */ + uint8 changed; /* Changed since myisamchk */ /* the following isn't saved on disk */ - uint state_diff_length; /* Should be 0 */ - uint state_length; /* Length of state header in file */ + uint state_diff_length; /* Should be 0 */ + uint state_length; /* Length of state header in file */ ulong *key_info; } MI_STATE_INFO; -#define MI_STATE_INFO_SIZE (24+14*8+7*4+2*2+8) -#define MI_STATE_KEY_SIZE 8 +#define MI_STATE_INFO_SIZE (24+14*8+7*4+2*2+8) +#define MI_STATE_KEY_SIZE 8 #define MI_STATE_KEYBLOCK_SIZE 8 -#define MI_STATE_KEYSEG_SIZE 4 -#define MI_STATE_EXTRA_SIZE ((MI_MAX_KEY+MI_MAX_KEY_BLOCK_SIZE)*MI_STATE_KEY_SIZE + MI_MAX_KEY*MI_MAX_KEY_SEG*MI_STATE_KEYSEG_SIZE) -#define MI_KEYDEF_SIZE (2+ 5*2) -#define MI_UNIQUEDEF_SIZE (2+1+1) -#define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) -#define MI_COLUMNDEF_SIZE (2*3+1) -#define MI_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16) -#define MI_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ +#define MI_STATE_KEYSEG_SIZE 4 +#define MI_STATE_EXTRA_SIZE ((MI_MAX_KEY+MI_MAX_KEY_BLOCK_SIZE)*MI_STATE_KEY_SIZE + MI_MAX_KEY*HA_MAX_KEY_SEG*MI_STATE_KEYSEG_SIZE) +#define MI_KEYDEF_SIZE (2+ 5*2) +#define MI_UNIQUEDEF_SIZE (2+1+1) +#define HA_KEYSEG_SIZE (6+ 2*2 + 4*2) +#define MI_COLUMNDEF_SIZE (2*3+1) +#define MI_BASE_INFO_SIZE (5*8 + 8*4 + 4 + 4*2 + 16) +#define MI_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */ typedef struct st_mi_base_info { - my_off_t keystart; /* Start of keys */ + my_off_t keystart; /* Start of keys */ my_off_t max_data_file_length; my_off_t max_key_file_length; my_off_t margin_key_file_length; - ha_rows records,reloc; /* Create information */ - ulong mean_row_length; /* Create information */ - ulong reclength; /* length of unpacked record */ - ulong pack_reclength; /* Length of full packed rec. */ + ha_rows records, reloc; /* Create information */ + ulong mean_row_length; /* Create information */ + ulong reclength; /* length of unpacked record */ + ulong pack_reclength; /* Length of full packed rec. */ ulong min_pack_length; - ulong max_pack_length; /* Max possibly length of packed rec.*/ + ulong max_pack_length; /* Max possibly length of packed rec.*/ ulong min_block_length; - ulong fields, /* fields in table */ - pack_fields; /* packed fields in table */ - uint rec_reflength; /* = 2-8 */ - uint key_reflength; /* = 2-8 */ - uint keys; /* same as in state.header */ - uint auto_key; /* Which key-1 is a auto key */ - uint blobs; /* Number of blobs */ - uint pack_bits; /* Length of packed bits */ - uint max_key_block_length; /* Max block length */ - uint max_key_length; /* Max key length */ + ulong fields, /* fields in table */ + pack_fields; /* packed fields in table */ + uint rec_reflength; /* = 2-8 */ + uint key_reflength; /* = 2-8 */ + uint keys; /* same as in state.header */ + uint auto_key; /* Which key-1 is a auto key */ + uint blobs; /* Number of blobs */ + uint pack_bits; /* Length of packed bits */ + uint max_key_block_length; /* Max block length */ + uint max_key_length; /* Max key length */ /* Extra allocation when using dynamic record format */ uint extra_alloc_bytes; uint extra_alloc_procent; /* The following are from the header */ - uint key_parts,all_key_parts; + uint key_parts, all_key_parts; } MI_BASE_INFO; - /* Structs used intern in database */ + /* Structs used intern in database */ -typedef struct st_mi_blob /* Info of record */ +typedef struct st_mi_blob /* Info of record */ { - ulong offset; /* Offset to blob in record */ - uint pack_length; /* Type of packed length */ - ulong length; /* Calc:ed for each record */ + ulong offset; /* Offset to blob in record */ + uint pack_length; /* Type of packed length */ + ulong length; /* Calc:ed for each record */ } MI_BLOB; -typedef struct st_mi_isam_pack { +typedef struct st_mi_isam_pack +{ ulong header_length; uint ref_length; uchar version; } MI_PACK; -#define MAX_NONMAPPED_INSERTS 1000 +#define MAX_NONMAPPED_INSERTS 1000 -typedef struct st_mi_isam_share { /* Shared between opens */ +typedef struct st_mi_isam_share +{ /* Shared between opens */ MI_STATE_INFO state; MI_BASE_INFO base; MI_KEYDEF ft2_keyinfo; /* Second-level ft-key definition */ @@ -170,26 +173,33 @@ typedef struct st_mi_isam_share { /* Shared between opens */ *index_file_name; uchar *file_map; /* mem-map of file if possible */ KEY_CACHE *key_cache; /* ref to the current key cache */ + /* To mark the key cache partitions containing dirty pages for this file */ + ulonglong dirty_part_map; MI_DECODE_TREE *decode_trees; uint16 *decode_tables; - int (*read_record)(struct st_myisam_info*, my_off_t, uchar*); - int (*write_record)(struct st_myisam_info*, const uchar*); - int (*update_record)(struct st_myisam_info*, my_off_t, const uchar*); - int (*delete_record)(struct st_myisam_info*); - int (*read_rnd)(struct st_myisam_info*, uchar*, my_off_t, my_bool); - int (*compare_record)(struct st_myisam_info*, const uchar *); /* Function to use for a row checksum. */ - ha_checksum (*calc_checksum)(struct st_myisam_info*, const uchar *); - int (*compare_unique)(struct st_myisam_info*, MI_UNIQUEDEF *, - const uchar *record, my_off_t pos); - size_t (*file_read)(MI_INFO *, uchar *, size_t, my_off_t, myf); - size_t (*file_write)(MI_INFO *, const uchar *, size_t, my_off_t, myf); - invalidator_by_filename invalidator; /* query cache invalidator */ - ulong this_process; /* processid */ - ulong last_process; /* For table-change-check */ - ulong last_version; /* Version on start */ - ulong options; /* Options used */ - ulong min_pack_length; /* Theese are used by packed data */ + int(*read_record) (struct st_myisam_info *, my_off_t, uchar*); + int(*write_record) (struct st_myisam_info *, const uchar*); + int(*update_record) (struct st_myisam_info *, my_off_t, const uchar*); + int(*delete_record) (struct st_myisam_info *); + int(*read_rnd) (struct st_myisam_info *, uchar*, my_off_t, my_bool); + int(*compare_record) (struct st_myisam_info *, const uchar*); + ha_checksum(*calc_checksum) (struct st_myisam_info *, const uchar*); + /* calculate checksum for a row during check table */ + ha_checksum(*calc_check_checksum)(struct st_myisam_info *, const uchar *); + int(*compare_unique) (struct st_myisam_info *, MI_UNIQUEDEF *, + const uchar *record, my_off_t pos); + size_t (*file_read) (MI_INFO *, uchar *, size_t, my_off_t, myf); + size_t (*file_write) (MI_INFO *, const uchar *, size_t, my_off_t, myf); + /* query cache invalidator for merged tables */ + invalidator_by_filename invalidator; + /* query cache invalidator for changing state */ + invalidator_by_filename chst_invalidator; + ulong this_process; /* processid */ + ulong last_process; /* For table-change-check */ + ulong last_version; /* Version on start */ + ulong options; /* Options used */ + ulong min_pack_length; /* Theese are used by packed data */ ulong max_pack_length; ulong state_diff_length; uint rec_reflength; /* rec_reflength in use now */ @@ -205,12 +215,14 @@ typedef struct st_mi_isam_share { /* Shared between opens */ enum data_file_type data_file_type; /* Below flag is needed to make log tables work with concurrent insert */ my_bool is_log_table; - - my_bool changed, /* If changed since lock */ - global_changed, /* If changed since open */ - not_flushed, - temporary,delay_key_write, - concurrent_insert; + /* This is 1 if they table checksum is of old type */ + my_bool has_null_fields; + my_bool has_varchar_fields; + + my_bool changed, /* If changed since lock */ + global_changed, /* If changed since open */ + not_flushed, temporary, delay_key_write, concurrent_insert; + my_bool deleting; /* we are going to delete this table */ #ifdef THREAD THR_LOCK lock; mysql_mutex_t intern_lock; /* Locking for use with _locking */ @@ -222,23 +234,16 @@ typedef struct st_mi_isam_share { /* Shared between opens */ mysql_rwlock_t mmap_lock; } MYISAM_SHARE; +typedef ICP_RESULT (*index_cond_func_t)(void *param); -typedef uint mi_bit_type; - -typedef struct st_mi_bit_buff { /* Used for packing of record */ - mi_bit_type current_byte; - uint bits; - uchar *pos,*end,*blob_pos,*blob_end; - uint error; -} MI_BIT_BUFF; - -struct st_myisam_info { - MYISAM_SHARE *s; /* Shared between open:s */ - MI_STATUS_INFO *state,save_state; - MI_BLOB *blobs; /* Pointer to blobs */ - MI_BIT_BUFF bit_buff; +struct st_myisam_info +{ + MYISAM_SHARE *s; /* Shared between open:s */ + MI_STATUS_INFO *state, save_state; + MI_BLOB *blobs; /* Pointer to blobs */ + MI_BIT_BUFF bit_buff; /* accumulate indexfile changes between write's */ - TREE *bulk_insert; + TREE *bulk_insert; DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */ MEM_ROOT ft_memroot; /* used by the parser */ MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */ @@ -254,137 +259,89 @@ struct st_myisam_info { uint32 int_keytree_version; /* -""- */ int (*read_record)(struct st_myisam_info*, my_off_t, uchar*); invalidator_by_filename invalidator; /* query cache invalidator */ - ulong this_unique; /* uniq filenumber or thread */ - ulong last_unique; /* last unique number */ - ulong this_loop; /* counter for this open */ - ulong last_loop; /* last used counter */ - my_off_t lastpos, /* Last record position */ - nextpos; /* Position to next record */ + ulong this_unique; /* uniq filenumber or thread */ + ulong last_unique; /* last unique number */ + ulong this_loop; /* counter for this open */ + ulong last_loop; /* last used counter */ + my_off_t lastpos, /* Last record position */ + nextpos; /* Position to next record */ my_off_t save_lastpos; - my_off_t pos; /* Intern variable */ - my_off_t last_keypage; /* Last key page read */ - my_off_t last_search_keypage; /* Last keypage when searching */ + my_off_t pos; /* Intern variable */ + my_off_t last_keypage; /* Last key page read */ + my_off_t last_search_keypage; /* Last keypage when searching */ my_off_t dupp_key_pos; ha_checksum checksum; /* Temp storage for row checksum */ - /* QQ: the folloing two xxx_length fields should be removed, - as they are not compatible with parallel repair */ - ulong packed_length,blob_length; /* Length of found, packed record */ - int dfile; /* The datafile */ - uint opt_flag; /* Optim. for space/speed */ - uint update; /* If file changed since open */ - int lastinx; /* Last used index */ - uint lastkey_length; /* Length of key in lastkey */ - uint last_rkey_length; /* Last length in mi_rkey() */ + /* + QQ: the folloing two xxx_length fields should be removed, + as they are not compatible with parallel repair + */ + ulong packed_length, blob_length; /* Length of found, packed record */ + int dfile; /* The datafile */ + uint open_flag; /* Parameters for open */ + uint opt_flag; /* Optim. for space/speed */ + uint once_flags; /* For MYISAMMRG */ + uint update; /* If file changed since open */ + int lastinx; /* Last used index */ + uint lastkey_length; /* Length of key in lastkey */ + uint last_rkey_length; /* Last length in mi_rkey() */ enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */ - uint save_lastkey_length; - uint pack_key_length; /* For MYISAMMRG */ + uint save_lastkey_length; + uint pack_key_length; /* For MYISAMMRG */ uint16 last_used_keyseg; /* For MyISAMMRG */ - int errkey; /* Got last error on this key */ - int lock_type; /* How database was locked */ - int tmp_lock_type; /* When locked by readinfo */ - uint data_changed; /* Somebody has changed data */ - uint save_update; /* When using KEY_READ */ - int save_lastinx; - LIST open_list; - IO_CACHE rec_cache; /* When cacheing records */ - uint preload_buff_size; /* When preloading indexes */ - myf lock_wait; /* is 0 or MY_DONT_WAIT */ - my_bool was_locked; /* Was locked in panic */ - my_bool append_insert_at_end; /* Set if concurrent insert */ + int errkey; /* Got last error on this key */ + int lock_type; /* How database was locked */ + int tmp_lock_type; /* When locked by readinfo */ + uint data_changed; /* Somebody has changed data */ + uint save_update; /* When using KEY_READ */ + int save_lastinx; + LIST open_list; + IO_CACHE rec_cache; /* When cacheing records */ + uint preload_buff_size; /* When preloading indexes */ + myf lock_wait; /* is 0 or MY_SHORT_WAIT */ + my_bool was_locked; /* Was locked in panic */ + my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode; - my_bool page_changed; /* If info->buff can't be used for rnext */ - my_bool buff_used; /* If info->buff has to be reread for rnext */ - my_bool once_flags; /* For MYISAMMRG */ -#ifdef __WIN__ - my_bool owned_by_merge; /* This MyISAM table is part of a merge union */ -#endif + /* If info->buff can't be used for rnext */ + my_bool page_changed; + /* If info->buff has to be reread for rnext */ + my_bool buff_used; + index_cond_func_t index_cond_func; /* Index condition function */ + void *index_cond_func_arg; /* parameter for the func */ #ifdef THREAD THR_LOCK_DATA lock; #endif - uchar *rtree_recursion_state; /* For RTREE */ - int rtree_recursion_depth; + uchar *rtree_recursion_state; /* For RTREE */ + int rtree_recursion_depth; }; -typedef struct st_buffpek { - my_off_t file_pos; /* Where we are in the sort file */ - uchar *base,*key; /* Key pointers */ - ha_rows count; /* Number of rows in table */ - ulong mem_count; /* numbers of keys in memory */ - ulong max_keys; /* Max keys in buffert */ -} BUFFPEK; - -typedef struct st_mi_sort_param -{ - pthread_t thr; - IO_CACHE read_cache, tempfile, tempfile_for_exceptions; - DYNAMIC_ARRAY buffpek; - MI_BIT_BUFF bit_buff; /* For parallel repair of packrec. */ - - /* - The next two are used to collect statistics, see update_key_parts for - description. - */ - ulonglong unique[MI_MAX_KEY_SEG+1]; - ulonglong notnull[MI_MAX_KEY_SEG+1]; - - my_off_t pos,max_pos,filepos,start_recpos; - uint key, key_length,real_key_length,sortbuff_size; - uint maxbuffers, keys, find_length, sort_keys_length; - my_bool fix_datafile, master; - my_bool calc_checksum; /* calculate table checksum */ - MI_KEYDEF *keyinfo; - HA_KEYSEG *seg; - SORT_INFO *sort_info; - uchar **sort_keys; - uchar *rec_buff; - void *wordlist, *wordptr; - MEM_ROOT wordroot; - uchar *record; - MY_TMPDIR *tmpdir; - int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *); - int (*key_read)(struct st_mi_sort_param *,void *); - int (*key_write)(struct st_mi_sort_param *, const void *); - void (*lock_in_memory)(MI_CHECK *); - int (*write_keys)(struct st_mi_sort_param *, register uchar **, - uint , struct st_buffpek *, IO_CACHE *); - uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); - int (*write_key)(struct st_mi_sort_param *, IO_CACHE *,uchar *, - uint, uint); -} MI_SORT_PARAM; - - /* Some defines used by isam-funktions */ - -#define USE_WHOLE_KEY MI_MAX_KEY_BUFF*2 /* Use whole key in _mi_search() */ -#define F_EXTRA_LCK -1 - - /* bits in opt_flag */ -#define MEMMAP_USED 32 +#define USE_WHOLE_KEY HA_MAX_KEY_BUFF*2 /* Use whole key in _mi_search() */ +#define F_EXTRA_LCK -1 +/* bits in opt_flag */ +#define MEMMAP_USED 32 #define REMEMBER_OLD_POS 64 -#define WRITEINFO_UPDATE_KEYFILE 1 -#define WRITEINFO_NO_UNLOCK 2 +#define WRITEINFO_UPDATE_KEYFILE 1 +#define WRITEINFO_NO_UNLOCK 2 - /* once_flags */ +/* once_flags */ #define USE_PACKED_KEYS 1 #define RRND_PRESERVE_LASTINX 2 - /* bits in state.changed */ - -#define STATE_CHANGED 1 -#define STATE_CRASHED 2 +/* bits in state.changed */ +#define STATE_CHANGED 1 +#define STATE_CRASHED 2 #define STATE_CRASHED_ON_REPAIR 4 -#define STATE_NOT_ANALYZED 8 +#define STATE_NOT_ANALYZED 8 #define STATE_NOT_OPTIMIZED_KEYS 16 -#define STATE_NOT_SORTED_PAGES 32 +#define STATE_NOT_SORTED_PAGES 32 - /* options to mi_read_cache */ +/* options to mi_read_cache */ +#define READING_NEXT 1 +#define READING_HEADER 2 -#define READING_NEXT 1 -#define READING_HEADER 2 - -#define mi_getint(x) ((uint) mi_uint2korr(x) & 32767) +#define mi_getint(x) ((uint) mi_uint2korr(x) & 32767) #define mi_putint(x,y,nod) { uint16 boh=(nod ? (uint16) 32768 : 0) + (uint16) (y);\ - mi_int2store(x,boh); } + mi_int2store(x,boh); } #define mi_test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0) #define mi_report_crashed(A, B) _mi_report_crashed((A), (B), __FILE__, __LINE__) #define mi_mark_crashed(x) do{(x)->s->state.changed|= STATE_CRASHED; \ @@ -427,38 +384,38 @@ typedef struct st_mi_sort_param #define get_pack_length(length) ((length) >= 255 ? 3 : 1) -#define MI_MIN_BLOCK_LENGTH 20 /* Because of delete-link */ -#define MI_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */ -#define MI_SPLIT_LENGTH ((MI_EXTEND_BLOCK_LENGTH+4)*2) -#define MI_MAX_DYN_BLOCK_HEADER 20 /* Max prefix of record-block */ +#define MI_MIN_BLOCK_LENGTH 20 /* Because of delete-link */ +#define MI_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */ +#define MI_SPLIT_LENGTH ((MI_EXTEND_BLOCK_LENGTH+4)*2) +#define MI_MAX_DYN_BLOCK_HEADER 20 /* Max prefix of record-block */ #define MI_BLOCK_INFO_HEADER_LENGTH 20 -#define MI_DYN_DELETE_BLOCK_HEADER 20 /* length of delete-block-header */ -#define MI_DYN_MAX_BLOCK_LENGTH ((1L << 24)-4L) -#define MI_DYN_MAX_ROW_LENGTH (MI_DYN_MAX_BLOCK_LENGTH - MI_SPLIT_LENGTH) -#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */ -#define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */ -#define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) +#define MI_DYN_DELETE_BLOCK_HEADER 20 /* length of delete-block-header */ +#define MI_DYN_MAX_BLOCK_LENGTH ((1L << 24)-4L) +#define MI_DYN_MAX_ROW_LENGTH (MI_DYN_MAX_BLOCK_LENGTH - MI_SPLIT_LENGTH) +#define MI_DYN_ALIGN_SIZE 4 /* Align blocks on this */ +#define MI_MAX_DYN_HEADER_BYTE 13 /* max header byte for dynamic rows */ +#define MI_MAX_BLOCK_LENGTH ((((ulong) 1 << 24)-1) & (~ (ulong) (MI_DYN_ALIGN_SIZE-1))) #define MI_REC_BUFF_OFFSET ALIGN_SIZE(MI_DYN_DELETE_BLOCK_HEADER+sizeof(uint32)) -#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ -#define PACK_TYPE_SPACE_FIELDS 2 -#define PACK_TYPE_ZERO_FILL 4 -#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */ +#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */ +#define PACK_TYPE_SPACE_FIELDS 2 +#define PACK_TYPE_ZERO_FILL 4 +#define MI_FOUND_WRONG_KEY 32738 /* Impossible value from ha_key_cmp */ -#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH) +#define MI_MAX_KEY_BLOCK_SIZE (MI_MAX_KEY_BLOCK_LENGTH/MI_MIN_KEY_BLOCK_LENGTH) #define MI_BLOCK_SIZE(key_length,data_pointer,key_pointer,block_size) (((((key_length)+(data_pointer)+(key_pointer))*4+(key_pointer)+2)/(block_size)+1)*(block_size)) -#define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */ -#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */ +#define MI_MAX_KEYPTR_SIZE 5 /* For calculating block lengths */ +#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */ -#define MI_MIN_SIZE_BULK_INSERT_TREE 16384 /* this is per key */ +#define MI_MIN_SIZE_BULK_INSERT_TREE 16384 /* this is per key */ #define MI_MIN_ROWS_TO_USE_BULK_INSERT 100 #define MI_MIN_ROWS_TO_DISABLE_INDEXES 100 #define MI_MIN_ROWS_TO_USE_WRITE_CACHE 10 /* The UNIQUE check is done with a hashed long key */ -#define MI_UNIQUE_HASH_TYPE HA_KEYTYPE_ULONG_INT +#define MI_UNIQUE_HASH_TYPE HA_KEYTYPE_ULONG_INT #define mi_unique_store(A,B) mi_int4store((A),(B)) #ifdef THREAD @@ -470,7 +427,7 @@ extern mysql_mutex_t THR_LOCK_myisam; #define mysql_rwlock_unlock(A) {} #endif - /* Some extern variables */ +/* Some extern variables */ extern LIST *myisam_open_list; extern uchar myisam_file_magic[], myisam_pack_file_magic[]; @@ -479,162 +436,167 @@ extern uint myisam_quick_table_bits; extern File myisam_log_file; extern ulong myisam_pid; - /* This is used by _mi_calc_xxx_key_length och _mi_store_key */ +/* This is used by _mi_calc_xxx_key_length och _mi_store_key */ typedef struct st_mi_s_param { - uint ref_length,key_length, - n_ref_length, - n_length, - totlength, - part_of_prev_key,prev_length,pack_marker; - uchar *key, *prev_key,*next_key_pos; + uint ref_length, key_length, + n_ref_length, + n_length, totlength, part_of_prev_key, prev_length, pack_marker; + uchar *key, *prev_key, *next_key_pos; my_bool store_not_null; } MI_KEY_PARAM; - /* Prototypes for intern functions */ +/* Prototypes for intern functions */ -extern int _mi_read_dynamic_record(MI_INFO *info,my_off_t filepos,uchar *buf); -extern int _mi_write_dynamic_record(MI_INFO*, const uchar*); -extern int _mi_update_dynamic_record(MI_INFO*, my_off_t, const uchar*); +extern int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, uchar *buf); +extern int _mi_write_dynamic_record(MI_INFO *, const uchar *); +extern int _mi_update_dynamic_record(MI_INFO *, my_off_t, const uchar *); extern int _mi_delete_dynamic_record(MI_INFO *info); -extern int _mi_cmp_dynamic_record(MI_INFO *info,const uchar *record); -extern int _mi_read_rnd_dynamic_record(MI_INFO *, uchar *,my_off_t, my_bool); -extern int _mi_write_blob_record(MI_INFO*, const uchar*); -extern int _mi_update_blob_record(MI_INFO*, my_off_t, const uchar*); -extern int _mi_read_static_record(MI_INFO *info, my_off_t filepos,uchar *buf); -extern int _mi_write_static_record(MI_INFO*, const uchar*); -extern int _mi_update_static_record(MI_INFO*, my_off_t, const uchar*); +extern int _mi_cmp_dynamic_record(MI_INFO *info, const uchar *record); +extern int _mi_read_rnd_dynamic_record(MI_INFO *, uchar *, my_off_t, my_bool); +extern int _mi_write_blob_record(MI_INFO *, const uchar *); +extern int _mi_update_blob_record(MI_INFO *, my_off_t, const uchar *); +extern int _mi_read_static_record(MI_INFO *info, my_off_t filepos, uchar *buf); +extern int _mi_write_static_record(MI_INFO *, const uchar *); +extern int _mi_update_static_record(MI_INFO *, my_off_t, const uchar *); extern int _mi_delete_static_record(MI_INFO *info); -extern int _mi_cmp_static_record(MI_INFO *info,const uchar *record); -extern int _mi_read_rnd_static_record(MI_INFO*, uchar *,my_off_t, my_bool); -extern int _mi_ck_write(MI_INFO *info,uint keynr,uchar *key,uint length); +extern int _mi_cmp_static_record(MI_INFO *info, const uchar *record); +extern int _mi_read_rnd_static_record(MI_INFO *, uchar *, my_off_t, my_bool); +extern int _mi_ck_write(MI_INFO *info, uint keynr, uchar *key, uint length); extern int _mi_ck_real_write_btree(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, uint key_length, my_off_t *root, uint comp_flag); -extern int _mi_enlarge_root(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, my_off_t *root); -extern int _mi_insert(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, - uchar *anc_buff,uchar *key_pos,uchar *key_buff, - uchar *father_buff, uchar *father_keypos, - my_off_t father_page, my_bool insert_last); -extern int _mi_split_page(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, - uchar *buff,uchar *key_buff, my_bool insert_last); -extern uchar *_mi_find_half_pos(uint nod_flag,MI_KEYDEF *keyinfo,uchar *page, - uchar *key,uint *return_key_length, - uchar **after_key); -extern int _mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag, - uchar *key_pos, uchar *org_key, - uchar *key_buff, - uchar *key, MI_KEY_PARAM *s_temp); -extern int _mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag, - uchar *key_pos, uchar *org_key, - uchar *key_buff, - uchar *key, MI_KEY_PARAM *s_temp); -extern int _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag, - uchar *key_pos, uchar *org_key, - uchar *prev_key, - uchar *key, MI_KEY_PARAM *s_temp); -extern int _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag, - uchar *key_pos,uchar *org_key, - uchar *prev_key, - uchar *key, MI_KEY_PARAM *s_temp); -void _mi_store_static_key(MI_KEYDEF *keyinfo, uchar *key_pos, - MI_KEY_PARAM *s_temp); -void _mi_store_var_pack_key(MI_KEYDEF *keyinfo, uchar *key_pos, - MI_KEY_PARAM *s_temp); -void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo, uchar *key_pos, - MI_KEY_PARAM *s_temp); - -extern int _mi_ck_delete(MI_INFO *info,uint keynr,uchar *key,uint key_length); -extern int _mi_readinfo(MI_INFO *info,int lock_flag,int check_keybuffer); -extern int _mi_writeinfo(MI_INFO *info,uint options); +extern int _mi_enlarge_root(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, + my_off_t *root); +extern int _mi_insert(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, + uchar *anc_buff, uchar *key_pos, uchar *key_buff, + uchar *father_buff, uchar *father_keypos, + my_off_t father_page, my_bool insert_last); +extern int _mi_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, + uchar *buff, uchar *key_buff, my_bool insert_last); +extern uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, + uchar *page, uchar *key, + uint *return_key_length, uchar ** after_key); +extern int _mi_calc_static_key_length(MI_KEYDEF *keyinfo, uint nod_flag, + uchar *key_pos, uchar *org_key, + uchar *key_buff, uchar *key, + MI_KEY_PARAM *s_temp); +extern int _mi_calc_var_key_length(MI_KEYDEF *keyinfo, uint nod_flag, + uchar *key_pos, uchar *org_key, + uchar *key_buff, uchar *key, + MI_KEY_PARAM *s_temp); +extern int _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo, uint nod_flag, + uchar *key_pos, uchar *org_key, + uchar *prev_key, uchar *key, + MI_KEY_PARAM *s_temp); +extern int _mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo, uint nod_flag, + uchar *key_pos, uchar *org_key, + uchar *prev_key, uchar *key, + MI_KEY_PARAM *s_temp); +void _mi_store_static_key(MI_KEYDEF *keyinfo, uchar *key_pos, + MI_KEY_PARAM *s_temp); +void _mi_store_var_pack_key(MI_KEYDEF *keyinfo, uchar *key_pos, + MI_KEY_PARAM *s_temp); +void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo, uchar *key_pos, + MI_KEY_PARAM *s_temp); + +extern int _mi_ck_delete(MI_INFO *info, uint keynr, uchar *key, + uint key_length); +extern int _mi_readinfo(MI_INFO *info, int lock_flag, int check_keybuffer); +extern int _mi_writeinfo(MI_INFO *info, uint options); extern int _mi_test_if_changed(MI_INFO *info); extern int _mi_mark_file_changed(MI_INFO *info); extern int _mi_decrement_open_count(MI_INFO *info); -extern int _mi_check_index(MI_INFO *info,int inx); -extern int _mi_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,uint key_len, - uint nextflag,my_off_t pos); -extern int _mi_bin_search(struct st_myisam_info *info,MI_KEYDEF *keyinfo, - uchar *page,uchar *key,uint key_len,uint comp_flag, - uchar * *ret_pos,uchar *buff, my_bool *was_last_key); -extern int _mi_seq_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page, - uchar *key,uint key_len,uint comp_flag, - uchar **ret_pos,uchar *buff, my_bool *was_last_key); -extern int _mi_prefix_search(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *page, - uchar *key,uint key_len,uint comp_flag, - uchar **ret_pos,uchar *buff, my_bool *was_last_key); -extern my_off_t _mi_kpos(uint nod_flag,uchar *after_key); -extern void _mi_kpointer(MI_INFO *info,uchar *buff,my_off_t pos); -extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag,uchar *after_key); +extern int _mi_check_index(MI_INFO *info, int inx); +extern int _mi_search(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, + uint key_len, uint nextflag, my_off_t pos); +extern int _mi_bin_search(struct st_myisam_info *info, MI_KEYDEF *keyinfo, + uchar *page, uchar *key, uint key_len, + uint comp_flag, uchar **ret_pos, uchar *buff, + my_bool *was_last_key); +extern int _mi_seq_search(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, + uchar *key, uint key_len, uint comp_flag, + uchar ** ret_pos, uchar *buff, + my_bool *was_last_key); +extern int _mi_prefix_search(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, + uchar *key, uint key_len, uint comp_flag, + uchar ** ret_pos, uchar *buff, + my_bool *was_last_key); +extern my_off_t _mi_kpos(uint nod_flag, uchar *after_key); +extern void _mi_kpointer(MI_INFO *info, uchar *buff, my_off_t pos); +extern my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key); extern my_off_t _mi_rec_pos(MYISAM_SHARE *info, uchar *ptr); -extern void _mi_dpointer(MI_INFO *info, uchar *buff,my_off_t pos); -extern int ha_key_cmp(HA_KEYSEG *keyseg, uchar *a,uchar *b, - uint key_length,uint nextflag,uint *diff_length); -extern uint _mi_get_static_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar * *page, - uchar *key); -extern uint _mi_get_pack_key(MI_KEYDEF *keyinfo,uint nod_flag,uchar * *page, - uchar *key); +extern void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos); +extern uint _mi_get_static_key(MI_KEYDEF *keyinfo, uint nod_flag, + uchar **page, uchar *key); +extern uint _mi_get_pack_key(MI_KEYDEF *keyinfo, uint nod_flag, uchar **page, + uchar *key); extern uint _mi_get_binary_pack_key(MI_KEYDEF *keyinfo, uint nod_flag, - uchar **page_pos, uchar *key); -extern uchar *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *keypos, - uchar *lastkey,uchar *endpos, - uint *return_key_length); + uchar ** page_pos, uchar *key); +extern uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, + uchar *keypos, uchar *lastkey, uchar *endpos, + uint *return_key_length); extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, - uchar *key, uchar *keypos, uint *return_key_length); -extern uint _mi_keylength(MI_KEYDEF *keyinfo,uchar *key); + uchar *key, uchar *keypos, + uint *return_key_length); +extern uint _mi_keylength(MI_KEYDEF *keyinfo, uchar *key); extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, - HA_KEYSEG *end); -extern uchar *_mi_move_key(MI_KEYDEF *keyinfo,uchar *to,uchar *from); -extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, - uint key_length,uint nextflag,my_off_t pos); -extern int _mi_search_first(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); -extern int _mi_search_last(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos); -extern uchar *_mi_fetch_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page, - int level,uchar *buff,int return_buffer); -extern int _mi_write_keypage(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t page, - int level, uchar *buff); -extern int _mi_dispose(MI_INFO *info,MI_KEYDEF *keyinfo,my_off_t pos, - int level); -extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo,int level); -extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key, - const uchar *record,my_off_t filepos); -extern uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, + HA_KEYSEG *end); +extern uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from); +extern int _mi_search_next(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, + uint key_length, uint nextflag, my_off_t pos); +extern int _mi_search_first(MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos); +extern int _mi_search_last(MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos); +extern uchar *_mi_fetch_keypage(MI_INFO *info, MI_KEYDEF *keyinfo, + my_off_t page, int level, uchar *buff, + int return_buffer); +extern int _mi_write_keypage(MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t page, + int level, uchar *buff); +extern int _mi_dispose(MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos, + int level); +extern my_off_t _mi_new(MI_INFO *info, MI_KEYDEF *keyinfo, int level); +extern uint _mi_make_key(MI_INFO *info, uint keynr, uchar *key, + const uchar *record, my_off_t filepos); +extern uint _mi_pack_key(MI_INFO *info, uint keynr, uchar *key, uchar *old, key_part_map keypart_map, - HA_KEYSEG **last_used_keyseg); -extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,uchar *buf); -extern int _mi_read_cache(IO_CACHE *info,uchar *buff,my_off_t pos, - uint length,int re_read_if_possibly); -extern ulonglong retrieve_auto_increment(MI_INFO *info,const uchar *record); + HA_KEYSEG ** last_used_keyseg); +extern int _mi_read_key_record(MI_INFO *info, my_off_t filepos, uchar *buf); +extern int _mi_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, + uint length, int re_read_if_possibly); +extern ulonglong retrieve_auto_increment(MI_INFO *info, const uchar *record); -extern uchar *mi_alloc_rec_buff(MI_INFO *,ulong, uchar**); +extern uchar *mi_alloc_rec_buff(MI_INFO *, ulong, uchar **); #define mi_get_rec_buff_ptr(info,buf) \ ((((info)->s->options & HA_OPTION_PACK_RECORD) && (buf)) ? \ (buf) - MI_REC_BUFF_OFFSET : (buf)) #define mi_get_rec_buff_len(info,buf) \ (*((uint32 *)(mi_get_rec_buff_ptr(info,buf)))) -extern ulong _mi_rec_unpack(MI_INFO *info,uchar *to,uchar *from, - ulong reclength); +extern ulong _mi_rec_unpack(MI_INFO *info, uchar *to, uchar *from, + ulong reclength); extern my_bool _mi_rec_check(MI_INFO *info,const uchar *record, uchar *packpos, ulong packed_length, my_bool with_checkum); -extern int _mi_write_part_record(MI_INFO *info,my_off_t filepos,ulong length, - my_off_t next_filepos,uchar **record, - ulong *reclength,int *flag); -extern void _mi_print_key(FILE *stream,HA_KEYSEG *keyseg,const uchar *key, - uint length); -extern my_bool _mi_read_pack_info(MI_INFO *info,pbool fix_keys); -extern int _mi_read_pack_record(MI_INFO *info,my_off_t filepos,uchar *buf); -extern int _mi_read_rnd_pack_record(MI_INFO*, uchar *,my_off_t, my_bool); +extern int _mi_write_part_record(MI_INFO *info, my_off_t filepos, ulong length, + my_off_t next_filepos, uchar ** record, + ulong *reclength, int *flag); +extern void _mi_print_key(FILE *stream, HA_KEYSEG *keyseg, const uchar *key, + uint length); +extern my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys); +extern int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, uchar *buf); +extern int _mi_read_rnd_pack_record(MI_INFO *, uchar *, my_off_t, my_bool); extern int _mi_pack_rec_unpack(MI_INFO *info, MI_BIT_BUFF *bit_buff, uchar *to, uchar *from, ulong reclength); -extern ulonglong mi_safe_mul(ulonglong a,ulonglong b); +extern ulonglong mi_safe_mul(ulonglong a, ulonglong b); extern int _mi_ft_update(MI_INFO *info, uint keynr, uchar *keybuf, - const uchar *oldrec, const uchar *newrec, my_off_t pos); + const uchar *oldrec, const uchar *newrec, + my_off_t pos); struct st_sort_info; -typedef struct st_mi_block_info { /* Parameter to _mi_get_block_info */ +typedef struct st_mi_block_info /* Parameter to _mi_get_block_info */ +{ uchar header[MI_BLOCK_INFO_HEADER_LENGTH]; ulong rec_len; ulong data_len; @@ -647,35 +609,37 @@ typedef struct st_mi_block_info { /* Parameter to _mi_get_block_info */ uint offset; } MI_BLOCK_INFO; - /* bits in return from _mi_get_block_info */ - -#define BLOCK_FIRST 1 -#define BLOCK_LAST 2 -#define BLOCK_DELETED 4 -#define BLOCK_ERROR 8 /* Wrong data */ -#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */ -#define BLOCK_FATAL_ERROR 32 /* hardware-error */ - -#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */ -#define MAXERR 20 -#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */ -#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE -#define INDEX_TMP_EXT ".TMM" -#define DATA_TMP_EXT ".TMD" - -#define UPDATE_TIME 1 -#define UPDATE_STAT 2 -#define UPDATE_SORT 4 -#define UPDATE_AUTO_INC 8 -#define UPDATE_OPEN_COUNT 16 - -#define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE) -#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) -#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) -#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) - -enum myisam_log_commands { - MI_LOG_OPEN,MI_LOG_WRITE,MI_LOG_UPDATE,MI_LOG_DELETE,MI_LOG_CLOSE,MI_LOG_EXTRA,MI_LOG_LOCK,MI_LOG_DELETE_ALL + /* bits in return from _mi_get_block_info */ + +#define BLOCK_FIRST 1 +#define BLOCK_LAST 2 +#define BLOCK_DELETED 4 +#define BLOCK_ERROR 8 /* Wrong data */ +#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */ +#define BLOCK_FATAL_ERROR 32 /* hardware-error */ + +#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */ +#define MAXERR 20 +#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */ +#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE +#define INDEX_TMP_EXT ".TMM" +#define DATA_TMP_EXT ".TMD" + +#define UPDATE_TIME 1 +#define UPDATE_STAT 2 +#define UPDATE_SORT 4 +#define UPDATE_AUTO_INC 8 +#define UPDATE_OPEN_COUNT 16 + +#define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE) +#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD) +#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD) +#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD) + +enum myisam_log_commands +{ + MI_LOG_OPEN, MI_LOG_WRITE, MI_LOG_UPDATE, MI_LOG_DELETE, MI_LOG_CLOSE, + MI_LOG_EXTRA, MI_LOG_LOCK, MI_LOG_DELETE_ALL }; #define myisam_log(a,b,c,d) if (myisam_log_file >= 0) _myisam_log(a,b,c,d) @@ -685,29 +649,25 @@ enum myisam_log_commands { #define fast_mi_writeinfo(INFO) if (!(INFO)->s->tot_locks) (void) _mi_writeinfo((INFO),0) #define fast_mi_readinfo(INFO) ((INFO)->lock_type == F_UNLCK) && _mi_readinfo((INFO),F_RDLCK,1) -#ifdef __cplusplus -extern "C" { -#endif - -extern uint _mi_get_block_info(MI_BLOCK_INFO *,File, my_off_t); -extern uint _mi_rec_pack(MI_INFO *info,uchar *to,const uchar *from); +C_MODE_START +extern uint _mi_get_block_info(MI_BLOCK_INFO *, File, my_off_t); +extern uint _mi_rec_pack(MI_INFO *info, uchar *to, const uchar *from); extern uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, MI_BLOCK_INFO *info, uchar **rec_buff_p, File file, my_off_t filepos); -extern void _my_store_blob_length(uchar *pos,uint pack_length,uint length); -extern void _myisam_log(enum myisam_log_commands command,MI_INFO *info, - const uchar *buffert,uint length); +extern void _mi_store_blob_length(uchar *pos, uint pack_length, uint length); +extern void _myisam_log(enum myisam_log_commands command, MI_INFO *info, + const uchar *buffert, uint length); extern void _myisam_log_command(enum myisam_log_commands command, - MI_INFO *info, const uchar *buffert, - uint length, int result); -extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info, - const uchar *record,my_off_t filepos, - int result); + MI_INFO *info, const uchar *buffert, + uint length, int result); +extern void _myisam_log_record(enum myisam_log_commands command, MI_INFO *info, + const uchar *record, my_off_t filepos, + int result); extern void mi_report_error(int errcode, const char *file_name); extern my_bool _mi_memmap_file(MI_INFO *info); extern void _mi_unmap_file(MI_INFO *info); extern uint save_pack_length(uint version, uchar *block_buff, ulong length); -extern uint read_pack_length(uint version, const uchar *buf, ulong *length); extern uint calc_pack_length(uint version, ulong length); extern size_t mi_mmap_pread(MI_INFO *info, uchar *Buffer, size_t Count, my_off_t offset, myf MyFlags); @@ -722,7 +682,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite); uchar *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state); uint mi_state_info_read_dsk(File file, MI_STATE_INFO *state, my_bool pRead); uint mi_base_info_write(File file, MI_BASE_INFO *base); -uchar *my_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); +uchar *mi_n_base_info_read(uchar *ptr, MI_BASE_INFO *base); int mi_keyseg_write(File file, const HA_KEYSEG *keyseg); uchar *mi_keyseg_read(uchar *ptr, HA_KEYSEG *keyseg); uint mi_keydef_write(File file, MI_KEYDEF *keydef); @@ -734,23 +694,24 @@ uchar *mi_recinfo_read(uchar *ptr, MI_COLUMNDEF *recinfo); extern int mi_disable_indexes(MI_INFO *info); extern int mi_enable_indexes(MI_INFO *info); extern int mi_indexes_are_disabled(MI_INFO *info); -ulong _my_calc_total_blob_length(MI_INFO *info, const uchar *record); +ulong _mi_calc_total_blob_length(MI_INFO *info, const uchar *record); ha_checksum mi_checksum(MI_INFO *info, const uchar *buf); ha_checksum mi_static_checksum(MI_INFO *info, const uchar *buf); my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, uchar *record, - ha_checksum unique_hash, my_off_t pos); + ha_checksum unique_hash, my_off_t pos); ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const uchar *buf); int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def, - const uchar *record, my_off_t pos); + const uchar *record, my_off_t pos); int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def, - const uchar *record, my_off_t pos); + const uchar *record, my_off_t pos); int mi_unique_comp(MI_UNIQUEDEF *def, const uchar *a, const uchar *b, - my_bool null_are_equal); -void mi_get_status(void* param, int concurrent_insert); -void mi_update_status(void* param); -void mi_restore_status(void* param); -void mi_copy_status(void* to,void *from); -my_bool mi_check_status(void* param); + my_bool null_are_equal); +void mi_get_status(void *param, my_bool concurrent_insert); +void mi_update_status(void *param); +void mi_restore_status(void *param); +void mi_copy_status(void *to, void *from); +my_bool mi_check_status(void *param); +void mi_fix_status(MI_INFO *org_table, MI_INFO *new_table); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); extern MI_INFO *test_if_reopen(char *filename); @@ -766,28 +727,21 @@ void mi_remap_file(MI_INFO *info, my_off_t size); void _mi_report_crashed(MI_INFO *file, const char *message, const char *sfile, uint sline); +int mi_check_index_cond(register MI_INFO *info, uint keynr, uchar *record); /* Functions needed by mi_check */ -volatile int *killed_ptr(MI_CHECK *param); -void mi_check_print_error(MI_CHECK *param, const char *fmt,...); -void mi_check_print_warning(MI_CHECK *param, const char *fmt,...); -void mi_check_print_info(MI_CHECK *param, const char *fmt,...); -int flush_pending_blocks(MI_SORT_PARAM *param); -int sort_ft_buf_flush(MI_SORT_PARAM *sort_param); -int thr_write_keys(MI_SORT_PARAM *sort_param); +int killed_ptr(HA_CHECK *param); +void mi_check_print_error(HA_CHECK *param, const char *fmt, ...); +void mi_check_print_warning(HA_CHECK *param, const char *fmt, ...); +void mi_check_print_info(HA_CHECK *param, const char *fmt, ...); #ifdef THREAD pthread_handler_t thr_find_all_keys(void *arg); #endif -int flush_blocks(MI_CHECK *param, KEY_CACHE *key_cache, File file); - -int sort_write_record(MI_SORT_PARAM *sort_param); -int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong); - -#ifdef __cplusplus -} -#endif +extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func, + void *func_arg); +int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file, + ulonglong *dirty_part_map); #ifdef HAVE_PSI_INTERFACE -C_MODE_START extern PSI_mutex_key mi_key_mutex_MYISAM_SHARE_intern_lock, mi_key_mutex_MI_SORT_INFO_mutex, mi_key_mutex_MI_CHECK_print_msg; @@ -802,6 +756,6 @@ extern PSI_file_key mi_key_file_datatmp, mi_key_file_dfile, mi_key_file_kfile, extern PSI_thread_key mi_key_thread_find_all_keys; void init_myisam_psi_keys(); -C_MODE_END #endif /* HAVE_PSI_INTERFACE */ +C_MODE_END diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c index 84743b8da51..a17823a45b5 100644 --- a/storage/myisam/myisamlog.c +++ b/storage/myisam/myisamlog.c @@ -331,7 +331,7 @@ static int examine_log(char * file_name, char **table_names) init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1, (tree_element_free) file_info_free, NULL); (void) init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE, - 0, 0); + 0, 0, 0); files_open=0; access_time=0; while (access_time++ != number_of_commands && @@ -806,7 +806,7 @@ static int find_record_with_key(struct file_info *file_info, uchar *record) { uint key; MI_INFO *info=file_info->isam; - uchar tmp_key[MI_MAX_KEY_BUFF]; + uchar tmp_key[HA_MAX_KEY_BUFF]; for (key=0 ; key < info->s->base.keys ; key++) { diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 84a7f2a1ba9..017f7d160b6 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -260,8 +260,8 @@ static struct my_option my_long_options[] = {"backup", 'b', "Make a backup of the table as table_name.OLD.", &backup, &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR_MP, - "Directory where character sets are.", &charsets_dir, - &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory where character sets are.", (char**) &charsets_dir, + (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', @@ -304,7 +304,7 @@ static void usage(void) puts("and you are welcome to modify and redistribute it under the GPL license\n"); puts("Pack a MyISAM-table to take much less space."); - puts("Keys are not updated, you must run myisamchk -rq on the datafile"); + puts("Keys are not updated, you must run myisamchk -rq on the index (.MYI) file"); puts("afterwards to update the keys."); puts("You should give the .MYI file as the filename argument."); @@ -568,7 +568,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) Create a global priority queue in preparation for making temporary Huffman trees. */ - if (init_queue(&queue,256,0,0,compare_huff_elements,0)) + if (init_queue(&queue, 256, 0, 0, compare_huff_elements, 0, 0, 0)) goto err; /* @@ -1541,7 +1541,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) if (queue.max_elements < found) { delete_queue(&queue); - if (init_queue(&queue,found,0,0,compare_huff_elements,0)) + if (init_queue(&queue,found, 0, 0, compare_huff_elements, 0, 0, 0)) return -1; } @@ -1645,8 +1645,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) Make a priority queue from the queue. Construct its index so that we have a partially ordered tree. */ - for (i=found/2 ; i > 0 ; i--) - _downheap(&queue,i); + queue_fix(&queue); /* The Huffman algorithm. */ bytes_packed=0; bits_packed=0; @@ -1657,12 +1656,9 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) Popping from a priority queue includes a re-ordering of the queue, to get the next least incidence element to the top. */ - a=(HUFF_ELEMENT*) queue_remove(&queue,0); - /* - Copy the next least incidence element. The queue implementation - reserves root[0] for temporary purposes. root[1] is the top. - */ - b=(HUFF_ELEMENT*) queue.root[1]; + a=(HUFF_ELEMENT*) queue_remove_top(&queue); + /* Copy the next least incidence element */ + b=(HUFF_ELEMENT*) queue_top(&queue); /* Get a new element from the element buffer. */ new_huff_el=huff_tree->element_buffer+found+i; /* The new element gets the sum of the two least incidence elements. */ @@ -1684,8 +1680,8 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) Replace the copied top element by the new element and re-order the queue. */ - queue.root[1]=(uchar*) new_huff_el; - queue_replaced(&queue); + queue_top(&queue)= (uchar*) new_huff_el; + queue_replace_top(&queue); } huff_tree->root=(HUFF_ELEMENT*) queue.root[1]; huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8; @@ -1816,8 +1812,7 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, Make a priority queue from the queue. Construct its index so that we have a partially ordered tree. */ - for (i=(found+1)/2 ; i > 0 ; i--) - _downheap(&queue,i); + queue_fix(&queue); /* The Huffman algorithm. */ for (i=0 ; i < found-1 ; i++) @@ -1831,12 +1826,9 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, incidence). Popping from a priority queue includes a re-ordering of the queue, to get the next least incidence element to the top. */ - a= (my_off_t*) queue_remove(&queue, 0); - /* - Copy the next least incidence element. The queue implementation - reserves root[0] for temporary purposes. root[1] is the top. - */ - b= (my_off_t*) queue.root[1]; + a= (my_off_t*) queue_remove_top(&queue); + /* Copy the next least incidence element. */ + b= (my_off_t*) queue_top(&queue); /* Create a new element in a local (automatic) buffer. */ new_huff_el= element_buffer + i; /* The new element gets the sum of the two least incidence elements. */ @@ -1856,8 +1848,8 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, queue. This successively replaces the references to counts by references to HUFF_ELEMENTs. */ - queue.root[1]=(uchar*) new_huff_el; - queue_replaced(&queue); + queue_top(&queue)= (uchar*) new_huff_el; + queue_replace_top(&queue); } DBUG_RETURN(bytes_packed+(bits_packed+7)/8); } diff --git a/storage/myisam/plug.in b/storage/myisam/plug.in index 051ec2d54aa..e92b5e56d7f 100644 --- a/storage/myisam/plug.in +++ b/storage/myisam/plug.in @@ -1,7 +1,7 @@ -MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine], - [Traditional non-transactional MySQL tables]) -MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam]) -MYSQL_PLUGIN_STATIC(myisam, [libmyisam.a]) -MYSQL_PLUGIN_MANDATORY(myisam) dnl Default -MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisam, [ha_myisam.cc]) +dnl MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine], +dnl [Traditional non-transactional MySQL tables]) +dnl MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam]) +dnl MYSQL_PLUGIN_STATIC(myisam, [libmyisam.a]) +dnl MYSQL_PLUGIN_MANDATORY(myisam) dnl Default +dnl MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(myisam, [ha_myisam.cc]) diff --git a/storage/myisam/rt_index.c b/storage/myisam/rt_index.c index 37a06606b3c..48eb48cc5e8 100644 --- a/storage/myisam/rt_index.c +++ b/storage/myisam/rt_index.c @@ -528,7 +528,7 @@ static int rtree_insert_req(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, DBUG_ENTER("rtree_insert_req"); if (!(page_buf = (uchar*)my_alloca((uint)keyinfo->block_length + - MI_MAX_KEY_BUFF))) + HA_MAX_KEY_BUFF))) { my_errno = HA_ERR_OUT_OF_MEM; DBUG_RETURN(-1); /* purecov: inspected */ diff --git a/storage/myisam/rt_test.c b/storage/myisam/rt_test.c index 7233300c539..50cdc538668 100644 --- a/storage/myisam/rt_test.c +++ b/storage/myisam/rt_test.c @@ -105,14 +105,20 @@ static int run_test(const char *filename) int nrecords=sizeof(rt_data)/(sizeof(double)*4);/* 3000;*/ int rec_length=0; int uniques=0; - int i; + int i, max_i; int error; int row_count=0; uchar record[MAX_REC_LENGTH]; uchar read_record[MAX_REC_LENGTH]; int upd= 10; ha_rows hrows; - + + bzero(&uniquedef, sizeof(uniquedef)); + bzero(&create_info, sizeof(create_info)); + bzero(recinfo, sizeof(recinfo)); + bzero(keyinfo, sizeof(keyinfo)); + bzero(keyseg, sizeof(keyseg)); + /* Define a column for NULLs and DEL markers*/ recinfo[0].type=FIELD_NORMAL; @@ -147,7 +153,6 @@ static int run_test(const char *filename) if (!silent) printf("- Creating isam-file\n"); - bzero((char*) &create_info,sizeof(create_info)); create_info.max_rows=10000000; if (mi_create(filename, @@ -194,7 +199,7 @@ static int run_test(const char *filename) create_record(record,i); bzero((char*) read_record,MAX_REC_LENGTH); - error=mi_rkey(file,read_record,0,record+1,0,HA_READ_MBR_EQUAL); + error=mi_rkey(file,read_record,0,record+1,HA_WHOLE_KEY,HA_READ_MBR_EQUAL); if (error && error!=HA_ERR_KEY_NOT_FOUND) { @@ -233,7 +238,8 @@ static int run_test(const char *filename) if (!silent) printf("- Updating rows with position\n"); - for (i=0; i < (nrecords - nrecords/4) ; i++) + /* We are looking for nrecords-necords/2 non-deleted records */ + for (i=0, max_i= nrecords - nrecords/2; i < max_i ; i++) { my_errno=0; bzero((char*) read_record,MAX_REC_LENGTH); @@ -241,7 +247,11 @@ static int run_test(const char *filename) if (error) { if (error==HA_ERR_RECORD_DELETED) + { + printf("found deleted record\n"); + max_i++; /* don't count such record */ continue; + } printf("pos: %2d mi_rrnd: %3d errno: %3d\n",i,error,my_errno); goto err; } @@ -266,7 +276,8 @@ static int run_test(const char *filename) create_record(record, nrecords*4/5); print_record(record,0," search for\n"); - if ((error=mi_rkey(file,read_record,0,record+1,0,HA_READ_MBR_INTERSECT))) + if ((error=mi_rkey(file,read_record,0,record+1,HA_WHOLE_KEY, + HA_READ_MBR_INTERSECT))) { printf("mi_rkey: %3d errno: %3d\n",error,my_errno); goto err; diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 9532b9f0474..903a893e779 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -15,7 +15,7 @@ /* Creates a index for a database by reading keys, sorting them and outputing - them in sorted order through SORT_INFO functions. + them in sorted order through MI_SORT_INFO functions. */ #include "fulltext.h" @@ -487,8 +487,8 @@ ok: int thr_write_keys(MI_SORT_PARAM *sort_param) { - SORT_INFO *sort_info=sort_param->sort_info; - MI_CHECK *param=sort_info->param; + MI_SORT_INFO *sort_info=sort_param->sort_info; + HA_CHECK *param=sort_info->param; ulong UNINIT_VAR(length), keys; ulong *rec_per_key_part=param->rec_per_key_part; int got_error=sort_info->got_error; @@ -903,7 +903,6 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, uchar *strpos; BUFFPEK *buffpek,**refpek; QUEUE queue; - volatile int *killed= killed_ptr(info->sort_info->param); DBUG_ENTER("merge_buffers"); count=error=0; @@ -917,13 +916,13 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0, (int (*)(void*, uchar *,uchar*)) info->key_cmp, - (void*) info)) + (void*) info, 0, 0)) DBUG_RETURN(1); /* purecov: inspected */ for (buffpek= Fb ; buffpek <= Tb ; buffpek++) { count+= buffpek->count; - buffpek->base= strpos; + buffpek->base= (uchar*) strpos; buffpek->max_keys=maxcount; strpos+= (uint) (error=(int) info->read_to_buffer(from_file,buffpek, sort_length)); @@ -936,10 +935,6 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, { for (;;) { - if (*killed) - { - error=1; goto err; - } buffpek=(BUFFPEK*) queue_top(&queue); if (to_file) { @@ -959,12 +954,18 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, buffpek->key+=sort_length; if (! --buffpek->mem_count) { + /* It's enough to check for killedptr before a slow operation */ + if (killed_ptr(info->sort_info->param)) + { + error=1; + goto err; + } if (!(error=(int) info->read_to_buffer(from_file,buffpek,sort_length))) { - uchar *base=buffpek->base; + uchar *base= buffpek->base; uint max_keys=buffpek->max_keys; - (void) queue_remove(&queue,0); + queue_remove_top(&queue); /* Put room used by buffer to use in other buffer */ for (refpek= (BUFFPEK**) &queue_top(&queue); @@ -989,11 +990,11 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, } else if (error == -1) goto err; /* purecov: inspected */ - queue_replaced(&queue); /* Top element has been replaced */ + queue_replace_top(&queue); /* Top element has been replaced */ } } buffpek=(BUFFPEK*) queue_top(&queue); - buffpek->base=(uchar *) sort_keys; + buffpek->base= (uchar*) sort_keys; buffpek->max_keys=keys; do { @@ -1008,7 +1009,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, else { register uchar *end; - strpos= buffpek->key; + strpos= (uchar*) buffpek->key; for (end=strpos+buffpek->mem_count*sort_length; strpos != end ; strpos+=sort_length) |