summaryrefslogtreecommitdiff
path: root/sql/filesort.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r--sql/filesort.cc626
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= &not_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)