summaryrefslogtreecommitdiff
path: root/sql/filesort.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r--sql/filesort.cc214
1 files changed, 95 insertions, 119 deletions
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 1df2f93676d..c94bbd1e55d 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -22,12 +22,9 @@
Sorts a database
*/
-#include <my_global.h>
+#include "mariadb.h"
#include "sql_priv.h"
#include "filesort.h"
-#ifdef HAVE_STDDEF_H
-#include <stddef.h> /* for macro offsetof */
-#endif
#include <m_ctype.h>
#include "sql_sort.h"
#include "probes_mysql.h"
@@ -37,14 +34,8 @@
#include "bounded_queue.h"
#include "filesort_utils.h"
#include "sql_select.h"
-#include "log_slow.h"
#include "debug_sync.h"
-/// How to write record_ref.
-#define WRITE_REF(file,from) \
-if (my_b_write((file),(uchar*) (from),param->ref_length)) \
- DBUG_RETURN(1);
-
/* functions defined in this file */
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
@@ -72,7 +63,7 @@ static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
uchar *buff, uchar *buff_end);
static bool check_if_pq_applicable(Sort_param *param, SORT_INFO *info,
TABLE *table,
- ha_rows records, ulong memory_available);
+ ha_rows records, size_t memory_available);
void Sort_param::init_for_filesort(uint sortlen, TABLE *table,
ulong max_length_for_sort_data,
@@ -93,7 +84,10 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table,
table->field, sort_length, &addon_buf);
}
if (addon_field)
- res_length= addon_buf.length;
+ {
+ DBUG_ASSERT(addon_buf.length < UINT_MAX32);
+ res_length= (uint)addon_buf.length;
+ }
else
{
res_length= ref_length;
@@ -103,7 +97,7 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table,
*/
sort_length+= ref_length;
}
- rec_length= sort_length + addon_buf.length;
+ rec_length= sort_length + (uint)addon_buf.length;
max_rows= maxrows;
}
@@ -378,7 +372,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
}
}
tracker->report_merge_passes_at_end(thd->query_plan_fsort_passes);
- if (error)
+ if (unlikely(error))
{
int kill_errno= thd->killed_errno();
DBUG_ASSERT(thd->is_error() || kill_errno || thd->killed == ABORT_QUERY);
@@ -416,7 +410,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
(longlong) sort->found_rows));
MYSQL_FILESORT_DONE(error, num_rows);
- if (error)
+ if (unlikely(error))
{
delete sort;
sort= 0;
@@ -565,7 +559,8 @@ const char* dbug_print_table_row(TABLE *table)
else
output.append(",");
- output.append((*pfield)->field_name? (*pfield)->field_name: "NULL");
+ output.append((*pfield)->field_name.str ?
+ (*pfield)->field_name.str: "NULL");
}
output.append(")=(");
@@ -616,7 +611,8 @@ static void dbug_print_record(TABLE *table, bool print_rowid)
fprintf(DBUG_FILE, "record (");
for (pfield= table->field; *pfield ; pfield++)
- fprintf(DBUG_FILE, "%s%s", (*pfield)->field_name, (pfield[1])? ", ":"");
+ fprintf(DBUG_FILE, "%s%s", (*pfield)->field_name.str,
+ (pfield[1])? ", ":"");
fprintf(DBUG_FILE, ") = ");
fprintf(DBUG_FILE, "(");
@@ -705,10 +701,9 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
Bounded_queue<uchar, uchar> *pq,
ha_rows *found_rows)
{
- int error,flag,quick_select;
- uint idx,indexpos,ref_length;
- uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
- my_off_t record;
+ int error, quick_select;
+ uint idx, indexpos;
+ uchar *ref_pos, *next_pos, ref_buff[MAX_REFLENGTH];
TABLE *sort_form;
handler *file;
MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set;
@@ -723,14 +718,10 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
error=quick_select=0;
sort_form=param->sort_form;
file=sort_form->file;
- ref_length=param->ref_length;
ref_pos= ref_buff;
quick_select=select && select->quick;
- record=0;
*found_rows= 0;
- flag= ((file->ha_table_flags() & HA_REC_NOT_IN_SEQ) || quick_select);
- if (flag)
- ref_pos= &file->ref[0];
+ ref_pos= &file->ref[0];
next_pos=ref_pos;
DBUG_EXECUTE_IF("show_explain_in_find_all_keys",
@@ -742,7 +733,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
next_pos=(uchar*) 0; /* Find records in sequence */
DBUG_EXECUTE_IF("bug14365043_1",
DBUG_SET("+d,ha_rnd_init_fail"););
- if (file->ha_rnd_init_with_error(1))
+ if (unlikely(file->ha_rnd_init_with_error(1)))
DBUG_RETURN(HA_POS_ERROR);
file->extra_opt(HA_EXTRA_CACHE, thd->variables.read_buff_size);
}
@@ -778,29 +769,15 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
for (;;)
{
if (quick_select)
- {
- if ((error= select->quick->get_next()))
- break;
- file->position(sort_form->record[0]);
- DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE););
- }
+ error= select->quick->get_next();
else /* Not quick-select */
- {
- {
- error= file->ha_rnd_next(sort_form->record[0]);
- if (!flag)
- {
- my_store_ptr(ref_pos,ref_length,record); // Position to row
- record+= sort_form->s->db_record_offset;
- }
- else if (!error)
- file->position(sort_form->record[0]);
- }
- if (error && error != HA_ERR_RECORD_DELETED)
- break;
- }
+ error= file->ha_rnd_next(sort_form->record[0]);
+ if (unlikely(error))
+ break;
+ file->position(sort_form->record[0]);
+ DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE););
- if (thd->check_killed())
+ if (unlikely(thd->check_killed()))
{
DBUG_PRINT("info",("Sort killed by user"));
if (!quick_select)
@@ -812,7 +789,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
}
bool write_record= false;
- if (error == 0)
+ if (likely(error == 0))
{
param->examined_rows++;
if (select && select->cond)
@@ -830,11 +807,11 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
MY_BITMAP *tmp_write_set= sort_form->write_set;
MY_BITMAP *tmp_vcol_set= sort_form->vcol_set;
- if (select->cond->with_subselect)
+ if (select->cond->with_subquery())
sort_form->column_bitmaps_set(save_read_set, save_write_set,
save_vcol_set);
write_record= (select->skip_record(thd) > 0);
- if (select->cond->with_subselect)
+ if (select->cond->with_subquery())
sort_form->column_bitmaps_set(tmp_read_set,
tmp_write_set,
tmp_vcol_set);
@@ -865,7 +842,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
}
/* It does not make sense to read more keys in case of a fatal error */
- if (thd->is_error())
+ if (unlikely(thd->is_error()))
break;
/*
@@ -885,11 +862,11 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
/* Signal we should use orignal column read and write maps */
sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set);
- if (thd->is_error())
+ if (unlikely(thd->is_error()))
DBUG_RETURN(HA_POS_ERROR);
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
- if (error != HA_ERR_END_OF_FILE)
+ if (unlikely(error != HA_ERR_END_OF_FILE))
{
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); // purecov: inspected
DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
@@ -1029,8 +1006,10 @@ Type_handler_string_result::make_sort_key(uchar *to, Item *item,
if (use_strnxfrm(cs))
{
- uint tmp_length __attribute__((unused));
- tmp_length= cs->coll->strnxfrm(cs, to, sort_field->length,
+#ifdef DBUG_ASSERT_EXISTS
+ size_t tmp_length=
+#endif
+ cs->coll->strnxfrm(cs, to, sort_field->length,
item->max_char_length() *
cs->strxfrm_multiply,
(uchar*) res->ptr(), res->length(),
@@ -1185,7 +1164,8 @@ static void make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos)
}
else
{ // Item
- sort_field->item->make_sort_key(to, sort_field->item, sort_field, param);
+ sort_field->item->type_handler()->make_sort_key(to, sort_field->item,
+ sort_field, param);
if ((maybe_null= sort_field->item->maybe_null))
to++;
}
@@ -1347,10 +1327,10 @@ static bool save_index(Sort_param *param, uint count,
false - PQ will be slower than merge-sort, or there is not enough memory.
*/
-bool check_if_pq_applicable(Sort_param *param,
+static bool check_if_pq_applicable(Sort_param *param,
SORT_INFO *filesort_info,
TABLE *table, ha_rows num_rows,
- ulong memory_available)
+ size_t memory_available)
{
DBUG_ENTER("check_if_pq_applicable");
@@ -1372,7 +1352,7 @@ bool check_if_pq_applicable(Sort_param *param,
DBUG_RETURN(false);
}
- ulong num_available_keys=
+ size_t num_available_keys=
memory_available / (param->rec_length + sizeof(char*));
// We need 1 extra record in the buffer, when using PQ.
param->max_keys_per_buffer= (uint) param->max_rows + 1;
@@ -1402,7 +1382,7 @@ bool check_if_pq_applicable(Sort_param *param,
// Try to strip off addon fields.
if (param->addon_field)
{
- const ulong row_length=
+ const size_t row_length=
param->sort_length + param->ref_length + sizeof(char*);
num_available_keys= memory_available / row_length;
@@ -1412,7 +1392,7 @@ bool check_if_pq_applicable(Sort_param *param,
const double sort_merge_cost=
get_merge_many_buffs_cost_fast(num_rows,
num_available_keys,
- row_length);
+ (uint)row_length);
/*
PQ has cost:
(insert + qsort) * log(queue size) / TIME_FOR_COMPARE_ROWID +
@@ -1506,27 +1486,28 @@ cleanup:
/**
Read data to buffer.
- @retval
- (uint)-1 if something goes wrong
+ @retval Number of bytes read
+ (ulong)-1 if something goes wrong
*/
-uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
- uint rec_length)
+ulong read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
+ uint rec_length)
{
- uint count;
- uint length;
+ ulong count;
+ ulong length= 0;
- if ((count=(uint) MY_MIN((ha_rows) buffpek->max_keys,buffpek->count)))
+ if ((count= (ulong) MY_MIN((ha_rows) buffpek->max_keys,buffpek->count)))
{
- if (my_b_pread(fromfile, (uchar*) buffpek->base,
- (length= rec_length*count), buffpek->file_pos))
- return ((uint) -1);
+ length= rec_length*count;
+ if (unlikely(my_b_pread(fromfile, (uchar*) buffpek->base, length,
+ buffpek->file_pos)))
+ return ((ulong) -1);
buffpek->key=buffpek->base;
buffpek->file_pos+= length; /* New filepos */
buffpek->count-= count;
buffpek->mem_count= count;
}
- return (count*rec_length);
+ return (length);
} /* read_to_buffer */
@@ -1580,18 +1561,18 @@ void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
@retval
0 OK
@retval
- other error
+ 1 ERROR
*/
-int merge_buffers(Sort_param *param, IO_CACHE *from_file,
- IO_CACHE *to_file, uchar *sort_buffer,
- BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
- int flag)
+bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
+ IO_CACHE *to_file, uchar *sort_buffer,
+ BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
+ int flag)
{
- int error;
+ bool error= 0;
uint rec_length,res_length,offset;
size_t sort_length;
- ulong maxcount;
+ ulong maxcount, bytes_read;
ha_rows max_rows,org_max_rows;
my_off_t to_start_filepos;
uchar *strpos;
@@ -1609,7 +1590,6 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
thd->inc_status_sort_merge_passes();
thd->query_plan_fsort_passes++;
- error=0;
rec_length= param->rec_length;
res_length= param->res_length;
sort_length= param->sort_length;
@@ -1637,18 +1617,18 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
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, first_cmp_arg, 0, 0))
+ if (unlikely(init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
+ (queue_compare) cmp, first_cmp_arg, 0, 0)))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
{
buffpek->base= strpos;
buffpek->max_keys= maxcount;
- strpos+=
- (uint) (error= (int) read_to_buffer(from_file, buffpek, rec_length));
-
- if (error == -1)
+ bytes_read= read_to_buffer(from_file, buffpek, rec_length);
+ if (unlikely(bytes_read == (ulong) -1))
goto err; /* purecov: inspected */
+
+ strpos+= bytes_read;
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
queue_insert(&queue, (uchar*) buffpek);
}
@@ -1668,13 +1648,13 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
buffpek->key+= rec_length;
if (! --buffpek->mem_count)
{
- if (!(error= (int) read_to_buffer(from_file, buffpek,
- rec_length)))
+ if (unlikely(!(bytes_read= read_to_buffer(from_file, buffpek,
+ rec_length))))
{
(void) queue_remove_top(&queue);
reuse_freed_buff(&queue, buffpek, rec_length);
}
- else if (error == -1)
+ else if (unlikely(bytes_read == (ulong) -1))
goto err; /* purecov: inspected */
}
queue_replace_top(&queue); // Top element has been used
@@ -1684,10 +1664,9 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
while (queue.elements > 1)
{
- if (killable && thd->check_killed())
- {
- error= 1; goto err; /* purecov: inspected */
- }
+ if (killable && unlikely(thd->check_killed()))
+ goto err; /* purecov: inspected */
+
for (;;)
{
buffpek= (BUFFPEK*) queue_top(&queue);
@@ -1724,9 +1703,7 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
if (!check_dupl_count || dupl_count >= min_dupl_count)
{
if (my_b_write(to_file, src+wr_offset, wr_len))
- {
- error=1; goto err; /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
}
if (cmp)
{
@@ -1737,7 +1714,7 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
}
if (!--max_rows)
{
- error= 0; /* purecov: inspected */
+ /* Nothing more to do */
goto end; /* purecov: inspected */
}
@@ -1745,14 +1722,14 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
buffpek->key+= rec_length;
if (! --buffpek->mem_count)
{
- if (!(error= (int) read_to_buffer(from_file, buffpek,
- rec_length)))
+ if (unlikely(!(bytes_read= read_to_buffer(from_file, buffpek,
+ rec_length))))
{
(void) queue_remove_top(&queue);
reuse_freed_buff(&queue, buffpek, rec_length);
break; /* One buffer have been removed */
}
- else if (error == -1)
+ else if (unlikely(bytes_read == (ulong) -1))
goto err; /* purecov: inspected */
}
queue_replace_top(&queue); /* Top element has been replaced */
@@ -1788,14 +1765,9 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
{
src= unique_buff;
if (my_b_write(to_file, src+wr_offset, wr_len))
- {
- error=1; goto err; /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
if (!--max_rows)
- {
- error= 0;
goto end;
- }
}
}
@@ -1811,9 +1783,7 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
{
if (my_b_write(to_file, (uchar*) buffpek->key,
(size_t)(rec_length*buffpek->mem_count)))
- {
- error= 1; goto err; /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
}
else
{
@@ -1830,21 +1800,26 @@ int merge_buffers(Sort_param *param, IO_CACHE *from_file,
continue;
}
if (my_b_write(to_file, src, wr_len))
- {
- error=1; goto err;
- }
+ goto err;
}
}
}
- while ((error=(int) read_to_buffer(from_file, buffpek, rec_length))
- != -1 && error != 0);
+ while (likely(!(error=
+ (bytes_read= read_to_buffer(from_file, buffpek,
+ rec_length)) == (ulong) -1)) &&
+ bytes_read != 0);
end:
lastbuff->count= MY_MIN(org_max_rows-max_rows, param->max_rows);
lastbuff->file_pos= to_start_filepos;
-err:
+cleanup:
delete_queue(&queue);
DBUG_RETURN(error);
+
+err:
+ error= 1;
+ goto cleanup;
+
} /* merge_buffers */
@@ -1884,7 +1859,7 @@ Type_handler_string_result::sortlength(THD *thd,
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
if (use_strnxfrm((cs= item->collation.collation)))
{
- sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
+ sortorder->length= (uint)cs->coll->strnxfrmlen(cs, sortorder->length);
}
else if (cs == &my_charset_bin)
{
@@ -1967,14 +1942,15 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
if (use_strnxfrm((cs=sortorder->field->sort_charset())))
{
*multi_byte_charset= true;
- sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
+ sortorder->length= (uint)cs->coll->strnxfrmlen(cs, sortorder->length);
}
if (sortorder->field->maybe_null())
length++; // Place for NULL marker
}
else
{
- sortorder->item->sortlength(thd, sortorder->item, sortorder);
+ sortorder->item->type_handler()->sortlength(thd, sortorder->item,
+ sortorder);
if (use_strnxfrm(sortorder->item->collation.collation))
{
*multi_byte_charset= true;