diff options
author | Monty <monty@mariadb.org> | 2017-05-17 00:34:48 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-05-17 00:34:48 +0300 |
commit | 6378c95ee07cccc2f2187b2caddc4496e14827d9 (patch) | |
tree | 1e7b9066e15288e3471f0c800e5dda820d3d0daf | |
parent | 314350a722e65081472113c53657ad239f3bef72 (diff) | |
download | mariadb-git-6378c95ee07cccc2f2187b2caddc4496e14827d9.tar.gz |
Fix that end_bulk_insert() doesn't write to to-be-deleted files
This affected mainly MyISAM and Aria engines.
Also fixed that end_bulk_insert() detects errors from
internal mi_end_bulk_insert() and ma_end_bulk_insert()
- delete_tree() and delete_tree_element() now has an
extra argument that marks if future calls to
tree->free should be ignored.
- tree->free changed to function returning int, to be
able to signal errors.
- Restored deleting flag in MyISAM that was accidently
disabled in mi_extra(PREPARE_FOR_DROP)
-rw-r--r-- | include/maria.h | 2 | ||||
-rw-r--r-- | include/my_tree.h | 6 | ||||
-rw-r--r-- | include/myisam.h | 2 | ||||
-rw-r--r-- | mysys/tree.c | 65 | ||||
-rw-r--r-- | sql/item_sum.cc | 2 | ||||
-rw-r--r-- | sql/sql_analyse.cc | 23 | ||||
-rw-r--r-- | sql/sql_analyse.h | 4 | ||||
-rw-r--r-- | sql/uniques.cc | 4 | ||||
-rw-r--r-- | storage/heap/hp_clear.c | 2 | ||||
-rw-r--r-- | storage/maria/ha_maria.cc | 33 | ||||
-rw-r--r-- | storage/maria/ma_ft_boolean_search.c | 2 | ||||
-rw-r--r-- | storage/maria/ma_ft_nlq_search.c | 4 | ||||
-rw-r--r-- | storage/maria/ma_ft_parser.c | 4 | ||||
-rw-r--r-- | storage/maria/ma_write.c | 13 | ||||
-rw-r--r-- | storage/maria/maria_pack.c | 8 | ||||
-rw-r--r-- | storage/myisam/ft_boolean_search.c | 2 | ||||
-rw-r--r-- | storage/myisam/ft_nlq_search.c | 4 | ||||
-rw-r--r-- | storage/myisam/ft_parser.c | 4 | ||||
-rw-r--r-- | storage/myisam/ft_stopwords.c | 7 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.cc | 28 | ||||
-rw-r--r-- | storage/myisam/mi_extra.c | 2 | ||||
-rw-r--r-- | storage/myisam/mi_write.c | 11 | ||||
-rw-r--r-- | storage/myisam/myisamlog.c | 4 | ||||
-rw-r--r-- | storage/myisam/myisampack.c | 8 |
24 files changed, 159 insertions, 85 deletions
diff --git a/include/maria.h b/include/maria.h index e25fa4c24ee..f88ad610213 100644 --- a/include/maria.h +++ b/include/maria.h @@ -392,7 +392,7 @@ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, ulonglong key_map, int maria_init_bulk_insert(MARIA_HA *info, size_t cache_size, ha_rows rows); void maria_flush_bulk_insert(MARIA_HA *info, uint inx); -void maria_end_bulk_insert(MARIA_HA *info); +int maria_end_bulk_insert(MARIA_HA *info, my_bool abort); int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves); void maria_versioning(MARIA_HA *info, my_bool versioning); void maria_ignore_trids(MARIA_HA *info); diff --git a/include/my_tree.h b/include/my_tree.h index 02cab02b52e..e175492431e 100644 --- a/include/my_tree.h +++ b/include/my_tree.h @@ -48,7 +48,7 @@ typedef uint32 element_count; typedef int (*tree_walk_action)(void *,element_count,void *); typedef enum { free_init, free_free, free_end } TREE_FREE; -typedef void (*tree_element_free)(void*, TREE_FREE, void *); +typedef int (*tree_element_free)(void*, TREE_FREE, void *); typedef struct st_tree_element { struct st_tree_element *left,*right; @@ -77,8 +77,8 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, int size, qsort_cmp2 compare, tree_element_free free_element, void *custom_arg, myf my_flags); -void delete_tree(TREE*); -void reset_tree(TREE*); +int delete_tree(TREE*, my_bool abort); +int reset_tree(TREE*); /* similar to delete tree, except we do not my_free() blocks in mem_root */ #define is_tree_inited(tree) ((tree)->root != 0) diff --git a/include/myisam.h b/include/myisam.h index dfbc00f64aa..e54b7fb5662 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -418,7 +418,7 @@ my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map, int mi_init_bulk_insert(MI_INFO *info, size_t cache_size, ha_rows rows); void mi_flush_bulk_insert(MI_INFO *info, uint inx); -void mi_end_bulk_insert(MI_INFO *info); +int mi_end_bulk_insert(MI_INFO *info, my_bool abort); int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map, KEY_CACHE *key_cache); void mi_change_key_cache(KEY_CACHE *old_key_cache, diff --git a/mysys/tree.c b/mysys/tree.c index 5eaeb30037d..e106dd43c00 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -66,7 +66,7 @@ #define DEFAULT_ALLOC_SIZE 8192 #define DEFAULT_ALIGN_SIZE 8192 -static void delete_tree_element(TREE *,TREE_ELEMENT *); +static int delete_tree_element(TREE *,TREE_ELEMENT *, my_bool abort); static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *, tree_walk_action,void *); static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *, @@ -136,22 +136,30 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, DBUG_VOID_RETURN; } -static void free_tree(TREE *tree, myf free_flags) +static int free_tree(TREE *tree, my_bool abort, myf free_flags) { + int error, first_error= 0; DBUG_ENTER("free_tree"); DBUG_PRINT("enter",("tree: 0x%lx", (long) tree)); if (tree->root) /* If initialized */ { if (tree->with_delete) - delete_tree_element(tree,tree->root); + { + if ((error= delete_tree_element(tree, tree->root, abort))) + { + first_error= first_error ? first_error : error; + abort= 1; + } + } else { if (tree->free) { if (tree->memory_limit) (*tree->free)(NULL, free_init, tree->custom_arg); - delete_tree_element(tree,tree->root); + if ((error= delete_tree_element(tree, tree->root, abort))) + first_error= first_error ? first_error : error; if (tree->memory_limit) (*tree->free)(NULL, free_end, tree->custom_arg); } @@ -162,32 +170,61 @@ static void free_tree(TREE *tree, myf free_flags) tree->elements_in_tree=0; tree->allocated=0; - DBUG_VOID_RETURN; + DBUG_RETURN(first_error); } -void delete_tree(TREE* tree) + +/** + Delete tree. + + @param tree Tree + @param abort 0 if normal, 1 if tree->free should not be called. + + @return 0 ok + <> 0 Returns first <> 0 from (tree->free)(*,free_free,*) + + @Notes + If one (tree->free)(,free_free,) returns <> 0, no future + tree->free(*,free_free,*) will be called. + Other tree->free operations (free_init, free_end) will be called +*/ + + +int delete_tree(TREE* tree, my_bool abort) { - free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */ + return free_tree(tree, abort, MYF(0)); /* my_free() mem_root if applicable */ } -void reset_tree(TREE* tree) +int reset_tree(TREE* tree) { /* do not free mem_root, just mark blocks as free */ - free_tree(tree, MYF(MY_MARK_BLOCKS_FREE)); + return free_tree(tree, 0, MYF(MY_MARK_BLOCKS_FREE)); } -static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) +static int delete_tree_element(TREE *tree, TREE_ELEMENT *element, + my_bool abort) { + int error, first_error= 0; if (element != &tree->null_element) { - delete_tree_element(tree,element->left); - if (tree->free) - (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); - delete_tree_element(tree,element->right); + if ((first_error= delete_tree_element(tree, element->left, abort))) + abort= 1; + if (!abort && tree->free) + { + if ((error= (*tree->free)(ELEMENT_KEY(tree,element), free_free, + tree->custom_arg))) + { + first_error= first_error ? first_error : error; + abort= 1; + } + } + if ((error= delete_tree_element(tree, element->right, abort))) + first_error= first_error ? first_error : error; if (tree->with_delete) my_free(element); } + return first_error; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 6dccd67316f..77cd20e7386 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3290,7 +3290,7 @@ void Item_func_group_concat::cleanup() table= 0; if (tree) { - delete_tree(tree); + delete_tree(tree, 0); tree= 0; } if (unique_filter) diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index d6af0410ad2..1022dde079d 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -298,9 +298,10 @@ bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num) } // get_ev_num_info -void free_string(String *s) +int free_string(String *s) { s->free(); + return 0; } @@ -374,7 +375,7 @@ void field_str::add() if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg)) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree); + delete_tree(&tree, 0); } else { @@ -382,7 +383,7 @@ void field_str::add() if ((treemem += length) > pc->max_treemem) { room_in_tree = 0; // Remove tree, too big tree - delete_tree(&tree); + delete_tree(&tree, 0); } } } @@ -441,7 +442,7 @@ void field_real::add() if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg))) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree); + delete_tree(&tree, 0); } /* if element->count == 1, this element can be found only once from tree @@ -450,7 +451,7 @@ void field_real::add() else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree); + delete_tree(&tree, 0); } } @@ -507,7 +508,7 @@ void field_decimal::add() if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg))) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree); + delete_tree(&tree, 0); } /* if element->count == 1, this element can be found only once from tree @@ -516,7 +517,7 @@ void field_decimal::add() else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree); + delete_tree(&tree, 0); } } @@ -574,7 +575,7 @@ void field_longlong::add() if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg))) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree); + delete_tree(&tree, 0); } /* if element->count == 1, this element can be found only once from tree @@ -583,7 +584,7 @@ void field_longlong::add() else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree); + delete_tree(&tree, 0); } } @@ -630,7 +631,7 @@ void field_ulonglong::add() if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg))) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree); + delete_tree(&tree, 0); } /* if element->count == 1, this element can be found only once from tree @@ -639,7 +640,7 @@ void field_ulonglong::add() else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree); + delete_tree(&tree, 0); } } diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h index 820877f2a69..6704de4ed6d 100644 --- a/sql/sql_analyse.h +++ b/sql/sql_analyse.h @@ -68,7 +68,7 @@ int compare_ulonglong2(void* cmp_arg __attribute__((unused)), int compare_decimal2(int* len, const char *s, const char *t); Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result, List<Item> &field_list); -void free_string(String*); +int free_string(String*); class analyse; class field_info :public Sql_alloc @@ -86,7 +86,7 @@ public: nulls(0), min_length(0), max_length(0), room_in_tree(1), found(0),item(a), pc(b) {}; - virtual ~field_info() { delete_tree(&tree); } + virtual ~field_info() { delete_tree(&tree, 0); } virtual void add() = 0; virtual void get_opt_type(String*, ha_rows) = 0; virtual String *get_min_arg(String *) = 0; diff --git a/sql/uniques.cc b/sql/uniques.cc index f2fa0bf7b1a..da334cc4b8a 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -364,7 +364,7 @@ double Unique::get_use_cost(uint *buffer, size_t nkeys, uint key_size, Unique::~Unique() { close_cached_file(&file); - delete_tree(&tree); + delete_tree(&tree, 0); delete_dynamic(&file_ptrs); } @@ -384,7 +384,7 @@ bool Unique::flush() (void*) this, left_root_right) || insert_dynamic(&file_ptrs, (uchar*) &file_ptr)) return 1; - delete_tree(&tree); + delete_tree(&tree, 0); return 0; } diff --git a/storage/heap/hp_clear.c b/storage/heap/hp_clear.c index 2b1502e6475..b940fd87264 100644 --- a/storage/heap/hp_clear.c +++ b/storage/heap/hp_clear.c @@ -91,7 +91,7 @@ void hp_clear_keys(HP_SHARE *info) HP_KEYDEF *keyinfo = info->keydef + key; if (keyinfo->algorithm == HA_KEY_ALG_BTREE) { - delete_tree(&keyinfo->rb_tree); + delete_tree(&keyinfo->rb_tree, 0); } else { diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 548c4a2112e..9d258982fdc 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2207,14 +2207,23 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) int ha_maria::end_bulk_insert() { - int err; + int first_error, error; + my_bool abort= file->s->deleting; DBUG_ENTER("ha_maria::end_bulk_insert"); - maria_end_bulk_insert(file); - if ((err= maria_extra(file, HA_EXTRA_NO_CACHE, 0))) - goto end; - if (can_enable_indexes && !file->s->deleting) - err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); -end: + + if ((first_error= maria_end_bulk_insert(file, abort))) + abort= 1; + + if ((error= maria_extra(file, HA_EXTRA_NO_CACHE, 0))) + { + first_error= first_error ? first_error : error; + abort= 1; + } + + if (!abort && can_enable_indexes) + if ((error= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE))) + first_error= first_error ? first_error : error; + if (bulk_insert_single_undo != BULK_INSERT_NONE) { DBUG_ASSERT(can_enable_indexes); @@ -2222,12 +2231,12 @@ end: Table was transactional just before start_bulk_insert(). No need to flush pages if we did a repair (which already flushed). */ - err|= - _ma_reenable_logging_for_table(file, - bulk_insert_single_undo == - BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR); + if ((error= _ma_reenable_logging_for_table(file, + bulk_insert_single_undo == + BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR))) + first_error= first_error ? first_error : error; } - DBUG_RETURN(err); + DBUG_RETURN(first_error); } diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c index a37a1322ad0..4f98bb3db41 100644 --- a/storage/maria/ma_ft_boolean_search.c +++ b/storage/maria/ma_ft_boolean_search.c @@ -1036,7 +1036,7 @@ void maria_ft_boolean_close_search(FT_INFO *ftb) { if (is_tree_inited(& ftb->no_dupes)) { - delete_tree(& ftb->no_dupes); + delete_tree(&ftb->no_dupes, 0); } free_root(& ftb->mem_root, MYF(0)); my_free(ftb); diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index 8d0ac74c131..3252b95e89e 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -320,8 +320,8 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query, (qsort2_cmp)&FT_DOC_cmp, 0); err: - delete_tree(&aio.dtree); - delete_tree(&wtree); + delete_tree(&aio.dtree, 0); + delete_tree(&wtree, 0); info->cur_row.lastpos= saved_lastpos; DBUG_RETURN(dlist); } diff --git a/storage/maria/ma_ft_parser.c b/storage/maria/ma_ft_parser.c index f0a2e1e1425..00d5baacaa1 100644 --- a/storage/maria/ma_ft_parser.c +++ b/storage/maria/ma_ft_parser.c @@ -61,7 +61,7 @@ FT_WORD * maria_ft_linearize(TREE *wtree, MEM_ROOT *mem_root) docstat.sum=0; tree_walk(wtree,(tree_walk_action)&walk_and_copy,&docstat,left_root_right); } - delete_tree(wtree); + delete_tree(wtree, 0); if (!wlist) DBUG_RETURN(NULL); @@ -283,7 +283,7 @@ static int maria_ft_add_word(MYSQL_FTPARSER_PARAM *param, w.len= word_len; if (!tree_insert(wtree, &w, 0, wtree->custom_arg)) { - delete_tree(wtree); + delete_tree(wtree, 0); DBUG_RETURN(1); } DBUG_RETURN(0); diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index fdcb5abd090..1261379f4d6 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -1786,8 +1786,10 @@ void maria_flush_bulk_insert(MARIA_HA *info, uint inx) } } -void maria_end_bulk_insert(MARIA_HA *info) + +int maria_end_bulk_insert(MARIA_HA *info, my_bool abort) { + int first_error= 0; DBUG_ENTER("maria_end_bulk_insert"); if (info->bulk_insert) { @@ -1796,15 +1798,20 @@ void maria_end_bulk_insert(MARIA_HA *info) { if (is_tree_inited(&info->bulk_insert[i])) { + int error; if (info->s->deleting) reset_free_element(&info->bulk_insert[i]); - delete_tree(&info->bulk_insert[i]); + if ((error= delete_tree(&info->bulk_insert[i], abort))) + { + first_error= first_error ? first_error : error; + abort= 1; + } } } my_free(info->bulk_insert); info->bulk_insert= 0; } - DBUG_VOID_RETURN; + DBUG_RETURN(first_error); } diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c index 814c50e1db8..c087697bf0b 100644 --- a/storage/maria/maria_pack.c +++ b/storage/maria/maria_pack.c @@ -836,7 +836,7 @@ static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, uint trees, if (huff_counts[i].tree_buff) { my_free(huff_counts[i].tree_buff); - delete_tree(&huff_counts[i].int_tree); + delete_tree(&huff_counts[i].int_tree, 0); } } my_free(huff_counts); @@ -934,7 +934,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) (count->field_length == 1 && count->int_tree.elements_in_tree > 1)) { - delete_tree(&count->int_tree); + delete_tree(&count->int_tree, 0); my_free(count->tree_buff); count->tree_buff=0; } @@ -1333,7 +1333,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, else { my_free(huff_counts->tree_buff); - delete_tree(&huff_counts->int_tree); + delete_tree(&huff_counts->int_tree, 0); huff_counts->tree_buff=0; } if (tree.element_buffer) @@ -3156,7 +3156,7 @@ static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count) if (huff_counts->tree_buff) { my_free(huff_counts->tree_buff); - delete_tree(&huff_counts->int_tree); + delete_tree(&huff_counts->int_tree, 0); huff_counts->tree_buff= NULL; DBUG_PRINT("fakebigcodes", ("freed distinct column values")); } diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index a44e24c9db1..dee57513912 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -1039,7 +1039,7 @@ void ft_boolean_close_search(FT_INFO *ftb) { if (is_tree_inited(& ftb->no_dupes)) { - delete_tree(& ftb->no_dupes); + delete_tree(&ftb->no_dupes, 0); } free_root(& ftb->mem_root, MYF(0)); my_free(ftb); diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index d9a9a03919e..3945484c8eb 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -316,8 +316,8 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, uchar *query, 0); err: - delete_tree(&aio.dtree); - delete_tree(&wtree); + delete_tree(&aio.dtree, 0); + delete_tree(&wtree, 0); info->lastpos=saved_lastpos; DBUG_RETURN(dlist); } diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c index c8d99b68e8a..fc3a649dd53 100644 --- a/storage/myisam/ft_parser.c +++ b/storage/myisam/ft_parser.c @@ -59,7 +59,7 @@ FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root) docstat.sum=0; tree_walk(wtree,(tree_walk_action)&walk_and_copy,&docstat,left_root_right); } - delete_tree(wtree); + delete_tree(wtree, 0); if (!wlist) DBUG_RETURN(NULL); @@ -277,7 +277,7 @@ static int ft_add_word(MYSQL_FTPARSER_PARAM *param, w.len= word_len; if (!tree_insert(wtree, &w, 0, wtree->custom_arg)) { - delete_tree(wtree); + delete_tree(wtree, 0); DBUG_RETURN(1); } DBUG_RETURN(0); diff --git a/storage/myisam/ft_stopwords.c b/storage/myisam/ft_stopwords.c index 3bf31bf3d66..7c743743adc 100644 --- a/storage/myisam/ft_stopwords.c +++ b/storage/myisam/ft_stopwords.c @@ -38,11 +38,12 @@ static int FT_STOPWORD_cmp(void* cmp_arg __attribute__((unused)), (uchar *)w2->pos,w2->len,0); } -static void FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, - void *arg __attribute__((unused))) +static int FT_STOPWORD_free(FT_STOPWORD *w, TREE_FREE action, + void *arg __attribute__((unused))) { if (action == free_free) my_free((void*)w->pos); + return 0; } static int ft_add_stopword(const char *w) @@ -134,7 +135,7 @@ void ft_free_stopwords() if (stopwords3) { - delete_tree(stopwords3); /* purecov: inspected */ + delete_tree(stopwords3, 0); /* purecov: inspected */ my_free(stopwords3); stopwords3=0; } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 210111d89ff..3c6684623e9 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1689,8 +1689,9 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) which have been activated by start_bulk_insert(). SYNOPSIS - end_bulk_insert() - no arguments + end_bulk_insert(fatal_error) + abort 0 normal end, store everything + 1 abort quickly. No need to flush/write anything. Table will be deleted RETURN 0 OK @@ -1699,10 +1700,20 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags) int ha_myisam::end_bulk_insert() { + int first_error, error; + my_bool abort= file->s->deleting; DBUG_ENTER("ha_myisam::end_bulk_insert"); - mi_end_bulk_insert(file); - int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0); - if (!err && !file->s->deleting) + + if ((first_error= mi_end_bulk_insert(file, abort))) + abort= 1; + + if ((error= mi_extra(file, HA_EXTRA_NO_CACHE, 0))) + { + first_error= first_error ? first_error : error; + abort= 1; + } + + if (!abort) { if (can_enable_indexes) { @@ -1713,16 +1724,17 @@ int ha_myisam::end_bulk_insert() setting the indexes as active and trying to recreate them. */ - if (((err= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE)) != 0) && + if (((first_error= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE)) != 0) && table->in_use->killed) { delete_all_rows(); /* not crashed, despite being killed during repair */ file->s->state.changed&= ~(STATE_CRASHED|STATE_CRASHED_ON_REPAIR); } - } + } } - DBUG_RETURN(err); + DBUG_PRINT("exit", ("first_error: %d", first_error)); + DBUG_RETURN(first_error); } diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index 3d6049c0172..8a2bc82d166 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -259,7 +259,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) break; case HA_EXTRA_PREPARE_FOR_DROP: /* Signals about intent to delete this table */ - //share->deleting= TRUE; + share->deleting= TRUE; share->global_changed= FALSE; /* force writing changed flag */ _mi_mark_file_changed(info); /* Fall trough */ diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index ff12f335af1..6603eb789a1 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -1033,8 +1033,9 @@ void mi_flush_bulk_insert(MI_INFO *info, uint inx) } } -void mi_end_bulk_insert(MI_INFO *info) +int mi_end_bulk_insert(MI_INFO *info, my_bool abort) { + int first_error= 0; if (info->bulk_insert) { uint i; @@ -1042,10 +1043,16 @@ void mi_end_bulk_insert(MI_INFO *info) { if (is_tree_inited(& info->bulk_insert[i])) { - delete_tree(& info->bulk_insert[i]); + int error; + if ((error= delete_tree(& info->bulk_insert[i], abort))) + { + first_error= first_error ? first_error : error; + abort= 1; + } } } my_free(info->bulk_insert); info->bulk_insert=0; } + return first_error; } diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c index 7ce03ca9485..eb06c75f0e0 100644 --- a/storage/myisam/myisamlog.c +++ b/storage/myisam/myisamlog.c @@ -649,7 +649,7 @@ static int examine_log(char * file_name, char **table_names) } } end_key_cache(dflt_key_cache,1); - delete_tree(&tree); + delete_tree(&tree, 0); (void) end_io_cache(&cache); (void) my_close(file,MYF(0)); if (write_file && my_fclose(write_file,MYF(MY_WME))) @@ -669,7 +669,7 @@ static int examine_log(char * file_name, char **table_names) fflush(stderr); end: end_key_cache(dflt_key_cache, 1); - delete_tree(&tree); + delete_tree(&tree, 0); (void) end_io_cache(&cache); (void) my_close(file,MYF(0)); if (write_file) diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 966edc877cd..6fb2a5a69d5 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -861,7 +861,7 @@ static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, uint trees, if (huff_counts[i].tree_buff) { my_free(huff_counts[i].tree_buff); - delete_tree(&huff_counts[i].int_tree); + delete_tree(&huff_counts[i].int_tree, 0); } } my_free(huff_counts); @@ -967,7 +967,7 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) (count->field_length == 1 && count->int_tree.elements_in_tree > 1)) { - delete_tree(&count->int_tree); + delete_tree(&count->int_tree, 0); my_free(count->tree_buff); count->tree_buff=0; } @@ -1366,7 +1366,7 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, else { my_free(huff_counts->tree_buff); - delete_tree(&huff_counts->int_tree); + delete_tree(&huff_counts->int_tree, 0); huff_counts->tree_buff=0; } if (tree.element_buffer) @@ -3166,7 +3166,7 @@ static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count) if (huff_counts->tree_buff) { my_free(huff_counts->tree_buff); - delete_tree(&huff_counts->int_tree); + delete_tree(&huff_counts->int_tree, 0); huff_counts->tree_buff= NULL; DBUG_PRINT("fakebigcodes", ("freed distinct column values")); } |