diff options
Diffstat (limited to 'sql/filesort.cc')
-rw-r--r-- | sql/filesort.cc | 214 |
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; |