diff options
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r-- | sql/filesort.cc | 150 |
1 files changed, 86 insertions, 64 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc index a80e4a0fa54..b6a5d844eac 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -30,19 +30,20 @@ /* How to write record_ref. */ #define WRITE_REF(file,from) \ -if (my_b_write((file),(byte*) (from),param->ref_length)) \ +if (my_b_write((file),(uchar*) (from),param->ref_length)) \ DBUG_RETURN(1); /* functions defined in this file */ -static char **make_char_array(register uint fields, uint length, myf my_flag); +static char **make_char_array(char **old_pos, register uint fields, + uint length, myf my_flag); static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffer_file, uint count); static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select, uchar * *sort_keys, IO_CACHE *buffer_file, IO_CACHE *tempfile,IO_CACHE *indexfile); static int write_keys(SORTPARAM *param,uchar * *sort_keys, uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile); -static void make_sortkey(SORTPARAM *param,uchar *to, byte *ref_pos); +static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos); static void register_used_fields(SORTPARAM *param); static int merge_index(SORTPARAM *param,uchar *sort_buffer, BUFFPEK *buffpek, @@ -56,7 +57,7 @@ static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, - byte *buff); + uchar *buff); /* Sort a table @@ -153,7 +154,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, if (param.addon_field) { param.res_length= param.addon_length; - if (!(table_sort.addon_buf= (byte *) my_malloc(param.addon_length, + if (!(table_sort.addon_buf= (uchar *) my_malloc(param.addon_length, MYF(MY_WME)))) goto err; } @@ -171,11 +172,11 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, if (select && select->quick) { - statistic_increment(thd->status_var.filesort_range_count, &LOCK_status); + status_var_increment(thd->status_var.filesort_range_count); } else { - statistic_increment(thd->status_var.filesort_scan_count, &LOCK_status); + status_var_increment(thd->status_var.filesort_scan_count); } #ifdef CAN_TRUST_RANGE if (select && select->quick && select->quick->records > 0L) @@ -198,7 +199,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } if (multi_byte_charset && - !(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME)))) + !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME)))) goto err; memavl= thd->variables.sortbuff_size; @@ -208,9 +209,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, ulong old_memavl; ulong keys= memavl/(param.rec_length+sizeof(char*)); param.keys=(uint) min(records+1, keys); - if (table_sort.sort_keys || - (table_sort.sort_keys= (uchar **) make_char_array(param.keys, param.rec_length, - MYF(0)))) + if ((table_sort.sort_keys= + (uchar **) make_char_array((char **) table_sort.sort_keys, + param.keys, param.rec_length, MYF(0)))) break; old_memavl=memavl; if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory) @@ -245,7 +246,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, { if (!table_sort.buffpek && table_sort.buffpek_len < maxbuffer && !(table_sort.buffpek= - (byte *) read_buffpek_from_file(&buffpek_pointers, maxbuffer))) + (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer))) goto err; buffpek= (BUFFPEK *) table_sort.buffpek; table_sort.buffpek_len= maxbuffer; @@ -255,7 +256,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME))) goto err; - reinit_io_cache(outfile,WRITE_CACHE,0L,0,0); + if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0)) + goto err; /* Use also the space previously used by string pointers in sort_buffer @@ -283,9 +285,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, x_free(param.tmp_buffer); if (!subselect || !subselect->is_uncacheable()) { - x_free((gptr) sort_keys); + x_free((uchar*) sort_keys); table_sort.sort_keys= 0; - x_free((gptr) buffpek); + x_free((uchar*) buffpek); table_sort.buffpek= 0; table_sort.buffpek_len= 0; } @@ -323,19 +325,19 @@ void filesort_free_buffers(TABLE *table, bool full) { if (table->sort.record_pointers) { - my_free((gptr) table->sort.record_pointers,MYF(0)); + my_free((uchar*) table->sort.record_pointers,MYF(0)); table->sort.record_pointers=0; } if (full) { if (table->sort.sort_keys ) { - x_free((gptr) table->sort.sort_keys); + x_free((uchar*) table->sort.sort_keys); table->sort.sort_keys= 0; } if (table->sort.buffpek) { - x_free((gptr) table->sort.buffpek); + x_free((uchar*) table->sort.buffpek); table->sort.buffpek= 0; table->sort.buffpek_len= 0; } @@ -351,14 +353,16 @@ void filesort_free_buffers(TABLE *table, bool full) /* Make a array of string pointers */ -static char **make_char_array(register uint fields, uint length, myf my_flag) +static char **make_char_array(char **old_pos, register uint fields, + uint length, myf my_flag) { register char **pos; - char **old_pos,*char_pos; + char *char_pos; DBUG_ENTER("make_char_array"); - if ((old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)), - my_flag))) + if (old_pos || + (old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)), + my_flag))) { pos=old_pos; char_pos=((char*) (pos+fields)) -length; while (fields--) *(pos++) = (char_pos+= length); @@ -375,11 +379,13 @@ static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count) ulong length; BUFFPEK *tmp; DBUG_ENTER("read_buffpek_from_file"); + if (count > UINT_MAX/sizeof(BUFFPEK)) + return 0; /* sizeof(BUFFPEK)*count will overflow */ tmp=(BUFFPEK*) my_malloc(length=sizeof(BUFFPEK)*count, MYF(MY_WME)); if (tmp) { if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) || - my_b_read(buffpek_pointers, (byte*) tmp, length)) + my_b_read(buffpek_pointers, (uchar*) tmp, length)) { my_free((char*) tmp, MYF(0)); tmp=0; @@ -431,7 +437,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, { int error,flag,quick_select; uint idx,indexpos,ref_length; - byte *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; + uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; my_off_t record; TABLE *sort_form; THD *thd= current_thd; @@ -458,7 +464,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, next_pos=ref_pos; if (! indexfile && ! quick_select) { - next_pos=(byte*) 0; /* Find records in sequence */ + next_pos=(uchar*) 0; /* Find records in sequence */ file->ha_rnd_init(1); file->extra_opt(HA_EXTRA_CACHE, current_thd->variables.read_buff_size); @@ -483,7 +489,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, register_used_fields(param); if (select && select->cond) select->cond->walk(&Item::register_field_in_read_map, 1, - (byte*) sort_form); + (uchar*) sort_form); sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set); for (;;) @@ -501,7 +507,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, { if (indexfile) { - if (my_b_read(indexfile,(byte*) ref_pos,ref_length)) /* purecov: deadcode */ + if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */ { error= my_errno ? my_errno : -1; /* Abort */ break; @@ -609,7 +615,7 @@ static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, IO_CACHE *buffpek_pointers, IO_CACHE *tempfile) { - uint sort_length, rec_length; + size_t sort_length, rec_length; uchar **end; BUFFPEK buffpek; DBUG_ENTER("write_keys"); @@ -619,20 +625,23 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, #ifdef MC68000 quicksort(sort_keys,count,sort_length); #else - my_string_ptr_sort((gptr) sort_keys, (uint) count, sort_length); + my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length); #endif if (!my_b_inited(tempfile) && open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME))) goto err; /* purecov: inspected */ + /* check we won't have more buffpeks than we can possibly keep in memory */ + if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (ulonglong)UINT_MAX) + goto err; buffpek.file_pos= my_b_tell(tempfile); if ((ha_rows) count > param->max_rows) count=(uint) param->max_rows; /* purecov: inspected */ buffpek.count=(ha_rows) count; for (end=sort_keys+count ; sort_keys != end ; sort_keys++) - if (my_b_write(tempfile, (byte*) *sort_keys, (uint) rec_length)) + if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length)) goto err; - if (my_b_write(buffpek_pointers, (byte*) &buffpek, sizeof(buffpek))) + if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek))) goto err; DBUG_RETURN(0); @@ -667,7 +676,7 @@ static inline void store_length(uchar *to, uint length, uint pack_length) /* makes a sort-key from record */ static void make_sortkey(register SORTPARAM *param, - register uchar *to, byte *ref_pos) + register uchar *to, uchar *ref_pos) { reg3 Field *field; reg1 SORT_FIELD *sort_field; @@ -694,7 +703,7 @@ static void make_sortkey(register SORTPARAM *param, else *to++=1; } - field->sort_string((char*) to,sort_field->length); + field->sort_string(to, sort_field->length); } else { // Item @@ -823,7 +832,7 @@ static void make_sortkey(register SORTPARAM *param, } *to++=1; } - my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, (char*)to, + my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to, item->max_length - (item->decimals ? 1:0), item->decimals); break; @@ -841,7 +850,7 @@ static void make_sortkey(register SORTPARAM *param, } *to++=1; } - change_double_for_sort(value,(byte*) to); + change_double_for_sort(value,(uchar*) to); break; } case ROW_RESULT: @@ -891,13 +900,13 @@ static void make_sortkey(register SORTPARAM *param, else { #ifdef HAVE_purify - uchar *end= (uchar*) field->pack((char *) to, field->ptr); + uchar *end= field->pack(to, field->ptr); uint length= (uint) ((to + addonf->length) - end); DBUG_ASSERT((int) length >= 0); if (length) bzero(end, length); #else - (void) field->pack((char *) to, field->ptr); + (void) field->pack(to, field->ptr); #endif } to+= addonf->length; @@ -906,7 +915,7 @@ static void make_sortkey(register SORTPARAM *param, else { /* Save filepos last */ - memcpy((byte*) to, ref_pos, (size_s) param->ref_length); + memcpy((uchar*) to, ref_pos, (size_t) param->ref_length); } return; } @@ -935,7 +944,7 @@ static void register_used_fields(SORTPARAM *param) else { // Item sort_field->item->walk(&Item::register_field_in_read_map, 1, - (byte *) table); + (uchar *) table); } } @@ -958,16 +967,16 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, FILESORT_INFO *table_sort) { uint offset,res_length; - byte *to; + uchar *to; DBUG_ENTER("save_index"); - my_string_ptr_sort((gptr) sort_keys, (uint) count, param->sort_length); + my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length); res_length= param->res_length; offset= param->rec_length-res_length; if ((ha_rows) count > param->max_rows) count=(uint) param->max_rows; if (!(to= table_sort->record_pointers= - (byte*) my_malloc(res_length*count, MYF(MY_WME)))) + (uchar*) my_malloc(res_length*count, MYF(MY_WME)))) DBUG_RETURN(1); /* purecov: inspected */ for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++) { @@ -983,7 +992,7 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, int merge_many_buff(SORTPARAM *param, uchar *sort_buffer, BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file) { - register int i; + register uint i; IO_CACHE t_file2,*from_file,*to_file,*temp; BUFFPEK *lastbuff; DBUG_ENTER("merge_many_buff"); @@ -998,14 +1007,16 @@ int merge_many_buff(SORTPARAM *param, uchar *sort_buffer, from_file= t_file ; to_file= &t_file2; while (*maxbuffer >= MERGEBUFF2) { - reinit_io_cache(from_file,READ_CACHE,0L,0,0); - reinit_io_cache(to_file,WRITE_CACHE,0L,0,0); + if (reinit_io_cache(from_file,READ_CACHE,0L,0,0)) + goto cleanup; + if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0)) + goto cleanup; lastbuff=buffpek; - for (i=0 ; i <= (int) *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) + for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF) { if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++, buffpek+i,buffpek+i+MERGEBUFF-1,0)) - break; /* purecov: inspected */ + goto cleanup; } if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++, buffpek+i,buffpek+ *maxbuffer,0)) @@ -1017,6 +1028,7 @@ int merge_many_buff(SORTPARAM *param, uchar *sort_buffer, setup_io_cache(to_file); *maxbuffer= (uint) (lastbuff-buffpek)-1; } +cleanup: close_cached_file(to_file); // This holds old result if (to_file == t_file) { @@ -1039,7 +1051,7 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) { - if (my_pread(fromfile->file,(byte*) buffpek->base, + if (my_pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos,MYF_RW)) return((uint) -1); /* purecov: inspected */ buffpek->key=buffpek->base; @@ -1108,7 +1120,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, int flag) { int error; - uint rec_length,sort_length,res_length,offset; + uint rec_length,res_length,offset; + size_t sort_length; ulong maxcount; ha_rows max_rows,org_max_rows; my_off_t to_start_filepos; @@ -1116,12 +1129,12 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, BUFFPEK *buffpek; QUEUE queue; qsort2_cmp cmp; + void *first_cmp_arg; volatile THD::killed_state *killed= ¤t_thd->killed; THD::killed_state not_killable; DBUG_ENTER("merge_buffers"); - statistic_increment(current_thd->status_var.filesort_merge_passes, - &LOCK_status); + status_var_increment(current_thd->status_var.filesort_merge_passes); if (param->not_killable) { killed= ¬_killable; @@ -1141,9 +1154,18 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, /* The following will fire if there is not enough space in sort_buffer */ DBUG_ASSERT(maxcount!=0); + if (param->unique_buff) + { + cmp= param->compare; + first_cmp_arg= (void *) ¶m->cmp_context; + } + else + { + cmp= get_ptr_compare(sort_length); + first_cmp_arg= (void*) &sort_length; + } if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0, - (queue_compare) (cmp= get_ptr_compare(sort_length)), - (void*) &sort_length)) + (queue_compare) cmp, first_cmp_arg)) DBUG_RETURN(1); /* purecov: inspected */ for (buffpek= Fb ; buffpek <= Tb ; buffpek++) { @@ -1154,7 +1176,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, if (error == -1) goto err; /* purecov: inspected */ buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected - queue_insert(&queue, (byte*) buffpek); + queue_insert(&queue, (uchar*) buffpek); } if (param->unique_buff) @@ -1169,7 +1191,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, */ buffpek= (BUFFPEK*) queue_top(&queue); memcpy(param->unique_buff, buffpek->key, rec_length); - if (my_b_write(to_file, (byte*) buffpek->key, rec_length)) + if (my_b_write(to_file, (uchar*) buffpek->key, rec_length)) { error=1; goto err; /* purecov: inspected */ } @@ -1196,21 +1218,21 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, buffpek= (BUFFPEK*) queue_top(&queue); if (cmp) // Remove duplicates { - if (!(*cmp)(&sort_length, &(param->unique_buff), + if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key)) goto skip_duplicate; memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length); } if (flag == 0) { - if (my_b_write(to_file,(byte*) buffpek->key, rec_length)) + if (my_b_write(to_file,(uchar*) buffpek->key, rec_length)) { error=1; goto err; /* purecov: inspected */ } } else { - if (my_b_write(to_file, (byte*) buffpek->key+offset, res_length)) + if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length)) { error=1; goto err; /* purecov: inspected */ } @@ -1248,7 +1270,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, */ if (cmp) { - if (!(*cmp)(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key)) + if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key)) { buffpek->key+= rec_length; // Remove duplicate --buffpek->mem_count; @@ -1265,7 +1287,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, max_rows-= buffpek->mem_count; if (flag == 0) { - if (my_b_write(to_file,(byte*) buffpek->key, + if (my_b_write(to_file,(uchar*) buffpek->key, (rec_length*buffpek->mem_count))) { error= 1; goto err; /* purecov: inspected */ @@ -1279,7 +1301,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, strpos != end ; strpos+= rec_length) { - if (my_b_write(to_file, (byte *) strpos, res_length)) + if (my_b_write(to_file, (uchar *) strpos, res_length)) { error=1; goto err; } @@ -1548,7 +1570,7 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) */ static void -unpack_addon_fields(struct st_sort_addon_field *addon_field, byte *buff) +unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff) { Field *field; SORT_ADDON_FIELD *addonf= addon_field; @@ -1561,7 +1583,7 @@ unpack_addon_fields(struct st_sort_addon_field *addon_field, byte *buff) continue; } field->set_notnull(); - field->unpack(field->ptr, (char *) buff+addonf->offset); + field->unpack(field->ptr, buff + addonf->offset); } } @@ -1572,7 +1594,7 @@ unpack_addon_fields(struct st_sort_addon_field *addon_field, byte *buff) #define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG) -void change_double_for_sort(double nr,byte *to) +void change_double_for_sort(double nr,uchar *to) { uchar *tmp=(uchar*) to; if (nr == 0.0) |