Index: sql/uniques.cc =================================================================== --- sql/uniques.cc (revision 1) +++ sql/uniques.cc (working copy) @@ -417,7 +417,7 @@ <> 0 error */ -static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size, +static bool merge_walk(uchar *in_merge_buffer, ulong in_merge_buffer_size, uint key_length, BUFFPEK *begin, BUFFPEK *end, tree_walk_action walk_action, void *walk_action_arg, qsort_cmp2 compare, const void *compare_arg, @@ -425,11 +425,30 @@ { BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg }; QUEUE queue; + + /* return 1 here make the result to be 0, looks buggy*/ if (end <= begin || - merge_buffer_size < (ulong) (key_length * (end - begin + 1)) || + // merge_buffer_size < (ulong) (key_length * (end - begin + 1)) || init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0, buffpek_compare, &compare_context)) return 1; + + bool exceed_tmp_table_size= false; + uchar *merge_buffer= NULL; + ulong merge_buffer_size= (ulong) key_length * (end - begin + 1); + + if (in_merge_buffer_size >= merge_buffer_size) + { + merge_buffer= in_merge_buffer; + merge_buffer_size= in_merge_buffer_size; + } + else + { + exceed_tmp_table_size= true; + + merge_buffer= (uchar*)my_malloc(merge_buffer_size, MYF(0)); + } + /* we need space for one key when a piece of merge buffer is re-read */ merge_buffer_size-= key_length; uchar *save_key_buff= merge_buffer + merge_buffer_size; @@ -524,6 +543,11 @@ res= 0; end: delete_queue(&queue); + + /* delete temp merge_buffer if necessary */ + if (exceed_tmp_table_size) + my_free(merge_buffer); + return res; }