diff options
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r-- | sql/filesort.cc | 626 |
1 files changed, 349 insertions, 277 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc index f56e5b3a771..2850ada1ffb 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -14,7 +14,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Sorts a database */ +/** + @file + + @brief + Sorts a database +*/ #include "mysql_priv.h" #ifdef HAVE_STDDEF_H @@ -27,24 +32,24 @@ #define SKIP_DBUG_IN_FILESORT #endif - /* How to write record_ref. */ - +/// 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(char **old_pos, register uint fields, uint length, myf my_flag); -static byte *read_buffpek_from_file(IO_CACHE *buffer_file, uint count, - byte *buf); +static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count, + uchar *buf); 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, uint maxbuffer,IO_CACHE *tempfile, @@ -57,43 +62,46 @@ 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); - -/* - Sort a table - - SYNOPSIS - filesort() - table Table to sort - sortorder How to sort the table - s_length Number of elements in sortorder - select condition to apply to the rows - special Not used. - (This could be used to sort the rows pointed on by - select->file) - examined_rows Store number of examined rows here - - IMPLEMENTATION - Creates a set of pointers that can be used to read the rows - in sorted order. This should be done with the functions - in records.cc - - REQUIREMENTS - Before calling filesort, one must have done - table->file->info(HA_STATUS_VARIABLE) - - RETURN + uchar *buff); +/** + Sort a table. + Creates a set of pointers that can be used to read the rows + in sorted order. This should be done with the functions + in records.cc. + + Before calling filesort, one must have done + table->file->info(HA_STATUS_VARIABLE) + + The result set is stored in table->io_cache or + table->record_pointers. + + @param thd Current thread + @param table Table to sort + @param sortorder How to sort the table + @param s_length Number of elements in sortorder + @param select condition to apply to the rows + @param max_rows Return only this many rows + @param sort_positions Set to 1 if we want to force sorting by position + (Needed by UPDATE/INSERT or ALTER TABLE) + @param examined_rows Store number of examined rows here + + @todo + check why we do this (param.keys--) + @note + If we sort by position (like if sort_positions is 1) filesort() will + call table->prepare_for_position(). + + @retval HA_POS_ERROR Error - # Number of rows - + @retval + \# Number of rows + @retval examined_rows will be set to number of examined rows - - The result set is stored in table->io_cache or - table->record_pointers */ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, - SQL_SELECT *select, ha_rows max_rows, ha_rows *examined_rows) + SQL_SELECT *select, ha_rows max_rows, + bool sort_positions, ha_rows *examined_rows) { int error; ulong memavl, min_sort_memory; @@ -137,8 +145,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, param.ref_length= table->file->ref_length; param.addon_field= 0; param.addon_length= 0; - if (!(table->file->table_flags() & HA_FAST_KEY_READ) && - !table->fulltext_searched) + if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && + !table->fulltext_searched && !sort_positions) { /* Get the descriptors of all fields whose values are appended @@ -156,7 +164,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; } @@ -174,17 +182,17 @@ 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) { records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2), - table->file->records)+EXTRA_RECORDS; + table->file->stats.records)+EXTRA_RECORDS; selected_records_file=0; } else @@ -201,7 +209,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; @@ -251,7 +259,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, table_sort.buffpek= 0; } if (!(table_sort.buffpek= - read_buffpek_from_file(&buffpek_pointers, maxbuffer, + (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek))) goto err; buffpek= (BUFFPEK *) table_sort.buffpek; @@ -291,9 +299,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; } @@ -331,19 +339,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; } @@ -357,7 +365,7 @@ void filesort_free_buffers(TABLE *table, bool full) } } - /* Make a array of string pointers */ +/** Make a array of string pointers. */ static char **make_char_array(char **old_pos, register uint fields, uint length, myf my_flag) @@ -378,22 +386,22 @@ static char **make_char_array(char **old_pos, register uint fields, } /* make_char_array */ -/* Read 'count' number of buffer pointers into memory */ +/** Read 'count' number of buffer pointers into memory. */ -static byte *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, - byte *buf) +static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, + uchar *buf) { ulong length= sizeof(BUFFPEK)*count; - byte *tmp= buf; + uchar *tmp= buf; DBUG_ENTER("read_buffpek_from_file"); if (count > UINT_MAX/sizeof(BUFFPEK)) return 0; /* sizeof(BUFFPEK)*count will overflow */ if (!tmp) - tmp= (byte *)my_malloc(length, MYF(MY_WME)); + tmp= (uchar *)my_malloc(length, MYF(MY_WME)); if (tmp) { if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) || - my_b_read(buffpek_pointers, tmp, length)) + my_b_read(buffpek_pointers, (uchar*) tmp, length)) { my_free((char*) tmp, MYF(0)); tmp=0; @@ -453,38 +461,40 @@ static void dbug_print_record(TABLE *table, bool print_rowid) } #endif -/* +/** Search after sort_keys and write them into tempfile. - SYNOPSIS - find_all_keys() - param Sorting parameter - select Use this to get source data - sort_keys Array of pointers to sort key + addon buffers. - buffpek_pointers File to write BUFFPEKs describing sorted segments - in tempfile. - tempfile File to write sorted sequences of sortkeys to. - indexfile If !NULL, use it for source data (contains rowids) - - NOTE + All produced sequences are guaranteed to be non-empty. + + @param param Sorting parameter + @param select Use this to get source data + @param sort_keys Array of pointers to sort key + addon buffers. + @param buffpek_pointers File to write BUFFPEKs describing sorted segments + in tempfile. + @param tempfile File to write sorted sequences of sortkeys to. + @param indexfile If !NULL, use it for source data (contains rowids) + + @note Basic idea: - while (get_next_sortkey()) - { - if (no free space in sort_keys buffers) - { - sort sort_keys buffer; - dump sorted sequence to 'tempfile'; - dump BUFFPEK describing sequence location into 'buffpek_pointers'; - } - put sort key into 'sort_keys'; - } - if (sort_keys has some elements && dumped at least once) - sort-dump-dump as above; - else - don't sort, leave sort_keys array to be sorted by caller. - - All produced sequences are guaranteed to be non-empty. - RETURN + @verbatim + while (get_next_sortkey()) + { + if (no free space in sort_keys buffers) + { + sort sort_keys buffer; + dump sorted sequence to 'tempfile'; + dump BUFFPEK describing sequence location into 'buffpek_pointers'; + } + put sort key into 'sort_keys'; + } + if (sort_keys has some elements && dumped at least once) + sort-dump-dump as above; + else + don't sort, leave sort_keys array to be sorted by caller. + @endverbatim + + @retval Number of records written on success. + @retval HA_POS_ERROR on error. */ @@ -495,14 +505,17 @@ 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; volatile THD::killed_state *killed= &thd->killed; handler *file; + MY_BITMAP *save_read_set, *save_write_set; DBUG_ENTER("find_all_keys"); - DBUG_PRINT("info",("using: %s",(select?select->quick?"ranges":"where":"every row"))); + DBUG_PRINT("info",("using: %s", + (select ? select->quick ? "ranges" : "where": + "every row"))); idx=indexpos=0; error=quick_select=0; @@ -512,14 +525,14 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ref_pos= ref_buff; quick_select=select && select->quick; record=0; - flag= ((!indexfile && file->table_flags() & HA_REC_NOT_IN_SEQ) + flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ) || quick_select); if (indexfile || flag) ref_pos= &file->ref[0]; 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); @@ -531,6 +544,19 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, DBUG_RETURN(HA_POS_ERROR); } + /* Remember original bitmaps */ + save_read_set= sort_form->read_set; + save_write_set= sort_form->write_set; + /* Set up temporary column read map for columns used by sort */ + bitmap_clear_all(&sort_form->tmp_set); + /* Temporary set for register_used_fields and register_field_in_read_map */ + sort_form->read_set= &sort_form->tmp_set; + register_used_fields(param); + if (select && select->cond) + select->cond->walk(&Item::register_field_in_read_map, 1, + (uchar*) sort_form); + sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set); + for (;;) { if (quick_select) @@ -547,7 +573,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; @@ -595,7 +621,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, else file->unlock_row(); /* It does not make sense to read more keys in case of a fatal error */ - if (thd->net.report_error) + if (thd->is_error()) break; } if (!quick_select) @@ -605,9 +631,12 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, file->ha_rnd_end(); } - if (thd->net.report_error) + if (thd->is_error()) DBUG_RETURN(HA_POS_ERROR); + /* Signal we should use orignal column read and write maps */ + sort_form->column_bitmaps_set(save_read_set, save_write_set); + DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos)); if (error != HA_ERR_END_OF_FILE) { @@ -623,23 +652,25 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } /* find_all_keys */ -/* +/** + @details Sort the buffer and write: - 1) the sorted sequence to tempfile - 2) a BUFFPEK describing the sorted sequence position to buffpek_pointers - (was: Skriver en buffert med nycklar till filen) - SYNOPSIS - write_keys() - param Sort parameters - sort_keys Array of pointers to keys to sort - count Number of elements in sort_keys array - buffpek_pointers One 'BUFFPEK' struct will be written into this file. - The BUFFPEK::{file_pos, count} will indicate where - the sorted data was stored. - tempfile The sorted sequence will be written into this file. - - RETURN + -# the sorted sequence to tempfile + -# a BUFFPEK describing the sorted sequence position to buffpek_pointers + + (was: Skriver en buffert med nycklar till filen) + + @param param Sort parameters + @param sort_keys Array of pointers to keys to sort + @param count Number of elements in sort_keys array + @param buffpek_pointers One 'BUFFPEK' struct will be written into this file. + The BUFFPEK::{file_pos, count} will indicate where + the sorted data was stored. + @param tempfile The sorted sequence will be written into this file. + + @retval 0 OK + @retval 1 Error */ @@ -647,7 +678,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"); @@ -657,7 +688,7 @@ 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, @@ -671,9 +702,9 @@ write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, 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); @@ -682,8 +713,8 @@ err: } /* write_keys */ -/* - Store length as suffix in high-byte-first order +/** + Store length as suffix in high-byte-first order. */ static inline void store_length(uchar *to, uint length, uint pack_length) @@ -705,10 +736,10 @@ static inline void store_length(uchar *to, uint length, uint pack_length) } - /* makes a sort-key from record */ +/** Make 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; @@ -735,7 +766,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 @@ -744,62 +775,70 @@ static void make_sortkey(register SORTPARAM *param, switch (sort_field->result_type) { case STRING_RESULT: { - CHARSET_INFO *cs=item->collation.collation; - char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' '); - int diff; - uint sort_field_length; - - if (maybe_null) - *to++=1; - /* All item->str() to use some extra byte for end null.. */ - String tmp((char*) to,sort_field->length+4,cs); - String *res= item->str_result(&tmp); - if (!res) - { - if (maybe_null) - bzero((char*) to-1,sort_field->length+1); - else - { - DBUG_PRINT("warning", - ("Got null on something that shouldn't be null")); - bzero((char*) to,sort_field->length); // Avoid crash - } - break; - } - length= res->length(); - sort_field_length= sort_field->length - sort_field->suffix_length; - diff=(int) (sort_field_length - length); - if (diff < 0) - { - diff=0; /* purecov: inspected */ - length= sort_field_length; - } - if (sort_field->suffix_length) - { - /* Store length last in result_string */ - store_length(to + sort_field_length, length, - sort_field->suffix_length); - } - if (sort_field->need_strxnfrm) + CHARSET_INFO *cs=item->collation.collation; + char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' '); + int diff; + uint sort_field_length; + + if (maybe_null) + *to++=1; + /* All item->str() to use some extra byte for end null.. */ + String tmp((char*) to,sort_field->length+4,cs); + String *res= item->str_result(&tmp); + if (!res) + { + if (maybe_null) + bzero((char*) to-1,sort_field->length+1); + else { - char *from=(char*) res->ptr(); - uint tmp_length; - if ((unsigned char *)from == to) - { - set_if_smaller(length,sort_field->length); - memcpy(param->tmp_buffer,from,length); - from=param->tmp_buffer; - } - tmp_length= my_strnxfrm(cs,to,sort_field->length, - (unsigned char *) from, length); - DBUG_ASSERT(tmp_length == sort_field->length); + /* purecov: begin deadcode */ + /* + This should only happen during extreme conditions if we run out + of memory or have an item marked not null when it can be null. + This code is here mainly to avoid a hard crash in this case. + */ + DBUG_ASSERT(0); + DBUG_PRINT("warning", + ("Got null on something that shouldn't be null")); + bzero((char*) to,sort_field->length); // Avoid crash + /* purecov: end */ } - else + break; + } + length= res->length(); + sort_field_length= sort_field->length - sort_field->suffix_length; + diff=(int) (sort_field_length - length); + if (diff < 0) + { + diff=0; + length= sort_field_length; + } + if (sort_field->suffix_length) + { + /* Store length last in result_string */ + store_length(to + sort_field_length, length, + sort_field->suffix_length); + } + if (sort_field->need_strxnfrm) + { + char *from=(char*) res->ptr(); + uint tmp_length; + if ((uchar*) from == to) { - my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length); - cs->cset->fill(cs, (char *)to+length,diff,fill_char); + set_if_smaller(length,sort_field->length); + memcpy(param->tmp_buffer,from,length); + from=param->tmp_buffer; } - break; + tmp_length= my_strnxfrm(cs,to,sort_field->length, + (uchar*) from, length); + DBUG_ASSERT(tmp_length == sort_field->length); + } + else + { + my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length); + cs->cset->fill(cs, (char *)to+length,diff,fill_char); + } + break; } case INT_RESULT: { @@ -856,7 +895,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; @@ -874,7 +913,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: @@ -924,13 +963,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; @@ -939,25 +978,68 @@ 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; } + +/* + Register fields used by sorting in the sorted table's read set +*/ + +static void register_used_fields(SORTPARAM *param) +{ + reg1 SORT_FIELD *sort_field; + TABLE *table=param->sort_form; + MY_BITMAP *bitmap= table->read_set; + + for (sort_field= param->local_sortorder ; + sort_field != param->end ; + sort_field++) + { + Field *field; + if ((field= sort_field->field)) + { + if (field->table == table) + bitmap_set_bit(bitmap, field->field_index); + } + else + { // Item + sort_field->item->walk(&Item::register_field_in_read_map, 1, + (uchar *) table); + } + } + + if (param->addon_field) + { + SORT_ADDON_FIELD *addonf= param->addon_field; + Field *field; + for ( ; (field= addonf->field) ; addonf++) + bitmap_set_bit(bitmap, field->field_index); + } + else + { + /* Save filepos last */ + table->prepare_for_position(); + } +} + + 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++) { @@ -968,7 +1050,7 @@ static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, } - /* Merge buffers to make < MERGEBUFF2 buffers */ +/** Merge buffers to make < MERGEBUFF2 buffers. */ int merge_many_buff(SORTPARAM *param, uchar *sort_buffer, BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file) @@ -1021,8 +1103,12 @@ cleanup: } /* merge_many_buff */ - /* Read data to buffer */ - /* This returns (uint) -1 if something goes wrong */ +/** + Read data to buffer. + + @retval + (uint)-1 if something goes wrong +*/ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, uint rec_length) @@ -1032,7 +1118,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; @@ -1044,15 +1130,15 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, } /* read_to_buffer */ -/* - Put all room used by freed buffer to use in adjacent buffer. Note, that - we can't simply distribute memory evenly between all buffers, because - new areas must not overlap with old ones. - SYNOPSIS - reuse_freed_buff() - queue IN list of non-empty buffers, without freed buffer - reuse IN empty buffer - key_length IN key length +/** + Put all room used by freed buffer to use in adjacent buffer. + + Note, that we can't simply distribute memory evenly between all buffers, + because new areas must not overlap with old ones. + + @param[in] queue list of non-empty buffers, without freed buffer + @param[in] reuse empty buffer + @param[in] key_length key length */ void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) @@ -1077,22 +1163,22 @@ void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length) } -/* - Merge buffers to one buffer - SYNOPSIS - merge_buffers() - param Sort parameter - from_file File with source data (BUFFPEKs point to this file) - to_file File to write the sorted result data. - sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys. - lastbuff OUT Store here BUFFPEK describing data written to to_file - Fb First element in source BUFFPEKs array - Tb Last element in source BUFFPEKs array - flag - - RETURN - 0 - OK - other - error +/** + Merge buffers to one buffer. + + @param param Sort parameter + @param from_file File with source data (BUFFPEKs point to this file) + @param to_file File to write the sorted result data. + @param sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys. + @param lastbuff OUT Store here BUFFPEK describing data written to to_file + @param Fb First element in source BUFFPEKs array + @param Tb Last element in source BUFFPEKs array + @param flag + + @retval + 0 OK + @retval + other error */ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, @@ -1101,7 +1187,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; @@ -1114,8 +1201,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, 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; @@ -1157,7 +1243,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) @@ -1172,7 +1258,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 */ } @@ -1206,14 +1292,14 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, } 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 */ } @@ -1268,7 +1354,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 */ @@ -1282,7 +1368,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; } @@ -1328,23 +1414,21 @@ static uint suffix_length(ulong string_length) -/* - Calculate length of sort key - - SYNOPSIS - sortlength() - thd Thread handler - sortorder Order of items to sort - uint s_length Number of items to sort - multi_byte_charset (out) - Set to 1 if we are using multi-byte charset - (In which case we have to use strxnfrm()) - - NOTES - sortorder->length is updated for each sort item +/** + Calculate length of sort key. + + @param thd Thread handler + @param sortorder Order of items to sort + @param s_length Number of items to sort + @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset + (In which case we have to use strxnfrm()) + + @note + sortorder->length is updated for each sort item. + @n sortorder->need_strxnfrm is set 1 if we have to use strxnfrm - RETURN + @return Total length of sort buffer in bytes */ @@ -1431,33 +1515,31 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, } -/* +/** Get descriptors of fields appended to sorted fields and - calculate its total length - - SYNOPSIS - get_addon_fields() - thd Current thread - ptabfields Array of references to the table fields - sortlength Total length of sorted fields - plength out: Total length of appended fields - - DESCRIPTION - The function first finds out what fields are used in the result set. - Then it calculates the length of the buffer to store the values of - these fields together with the value of sort values. - If the calculated length is not greater than max_length_for_sort_data - the function allocates memory for an array of descriptors containing - layouts for the values of the non-sorted fields in the buffer and - fills them. - - NOTES + calculate its total length. + + The function first finds out what fields are used in the result set. + Then it calculates the length of the buffer to store the values of + these fields together with the value of sort values. + If the calculated length is not greater than max_length_for_sort_data + the function allocates memory for an array of descriptors containing + layouts for the values of the non-sorted fields in the buffer and + fills them. + + @param thd Current thread + @param ptabfield Array of references to the table fields + @param sortlength Total length of sorted fields + @param[out] plength Total length of appended fields + + @note The null bits for the appended values are supposed to be put together and stored the buffer just ahead of the value of the first field. - RETURN + @return Pointer to the layout descriptors for the appended fields, if any - NULL - if we do not store field values with sort data. + @retval + NULL if we do not store field values with sort data. */ static SORT_ADDON_FIELD * @@ -1469,7 +1551,8 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) uint length= 0; uint fields= 0; uint null_fields= 0; - query_id_t query_id= thd->query_id; + MY_BITMAP *read_set= (*ptabfield)->table->read_set; + /* If there is a reference to a field in the query add it to the the set of appended fields. @@ -1481,18 +1564,9 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) */ *plength= 0; - /* - The following statement is added to avoid sorting in alter_table. - The fact is the filter 'field->query_id != thd->query_id' - doesn't work for alter table - */ - if (thd->lex->sql_command != SQLCOM_SELECT && - thd->lex->sql_command != SQLCOM_INSERT_SELECT && - thd->lex->sql_command != SQLCOM_CREATE_TABLE) - return 0; for (pfield= ptabfield; (field= *pfield) ; pfield++) { - if (field->query_id != query_id) + if (!bitmap_is_set(read_set, field->field_index)) continue; if (field->flags & BLOB_FLAG) return 0; @@ -1515,7 +1589,7 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) null_fields= 0; for (pfield= ptabfield; (field= *pfield) ; pfield++) { - if (field->query_id != thd->query_id) + if (!bitmap_is_set(read_set, field->field_index)) continue; addonf->field= field; addonf->offset= length; @@ -1541,25 +1615,23 @@ get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength) } -/* - Copy (unpack) values appended to sorted fields from a buffer back to +/** + Copy (unpack) values appended to sorted fields from a buffer back to their regular positions specified by the Field::ptr pointers. - SYNOPSIS - unpack_addon_fields() - addon_field Array of descriptors for appended fields - buff Buffer which to unpack the value from + @param addon_field Array of descriptors for appended fields + @param buff Buffer which to unpack the value from - NOTES + @note The function is supposed to be used only as a callback function when getting field values for the sorted result set. - RETURN + @return void. */ 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; @@ -1572,7 +1644,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); } } @@ -1583,7 +1655,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) |