32 #include "probes_mysql.h" 
   33 #include "opt_range.h"                           
   34 #include "bounded_queue.h" 
   35 #include "filesort_utils.h" 
   39 #include "sql_optimizer.h"               
   48 static uchar *read_buffpek_from_file(
IO_CACHE *buffer_file, uint count,
 
   58 static void register_used_fields(
Sort_param *param);
 
   59 static int merge_index(
Sort_param *param,uchar *sort_buffer,
 
   63 static bool save_index(
Sort_param *param, uint count,
 
   65 static uint suffix_length(ulong string_length);
 
   74                                    ha_rows records, ulong memory_available);
 
   77 void Sort_param::init_for_filesort(uint sortlen, 
TABLE *
table,
 
   78                                    ulong max_length_for_sort_data,
 
   79                                    ha_rows maxrows, 
bool sort_positions)
 
   84       !table->fulltext_searched && !sort_positions)
 
   90     addon_field= get_addon_fields(max_length_for_sort_data,
 
   91                                   table->field, sort_length, &addon_length);
 
   94     res_length= addon_length;
 
   97     res_length= ref_length;
 
  102     sort_length+= ref_length;
 
  104   rec_length= sort_length + addon_length;
 
  110                                        const SORT_FIELD *sortorder,
 
  113   if (!trace->is_started())
 
  117   for (; s_length-- ; sortorder++)
 
  120     oto.add_alnum(
"direction", sortorder->reverse ? 
"desc" : 
"asc");
 
  122     if (sortorder->field)
 
  124       if (strlen(sortorder->field->table->alias) != 0)
 
  125         oto.add_utf8_table(sortorder->field->table);
 
  127         oto.add_alnum(
"table", 
"intermediate_tmp_table");
 
  128       oto.add_alnum(
"field", sortorder->field->field_name ?
 
  129                     sortorder->field->field_name : 
"tmp_table_column");
 
  132       oto.add(
"expression", sortorder->item);
 
  174                  bool sort_positions, ha_rows *examined_rows,
 
  178   ulong memory_available= thd->variables.sortbuff_size;
 
  181   ha_rows num_rows= HA_POS_ERROR;
 
  182   IO_CACHE tempfile, buffpek_pointers, *outfile; 
 
  184   bool multi_byte_charset;
 
  188   ha_rows max_rows= filesort->
limit;
 
  191   DBUG_ENTER(
"filesort");
 
  193   if (!(s_length= filesort->make_sortorder()))
 
  194     DBUG_RETURN(HA_POS_ERROR);  
 
  201   trace_filesort_information(trace, filesort->
sortorder, s_length);
 
  203 #ifdef SKIP_DBUG_IN_FILESORT 
  207      table->reginfo.join_tab->join->
select_lex->master_unit()->item :
 
  210   MYSQL_FILESORT_START(table->s->db.str, table->s->table_name.str);
 
  211   DEBUG_SYNC(thd, 
"filesort_start");
 
  225   table->sort.io_cache= NULL;
 
  226   DBUG_ASSERT(table_sort.record_pointers == NULL);
 
  228   outfile= table_sort.io_cache;
 
  229   my_b_clear(&tempfile);
 
  230   my_b_clear(&buffpek_pointers);
 
  235                                      &multi_byte_charset),
 
  237                           thd->variables.max_length_for_sort_data,
 
  238                           max_rows, sort_positions);
 
  240   table_sort.addon_buf= 0;
 
  241   table_sort.addon_length= param.addon_length;
 
  242   table_sort.addon_field= param.addon_field;
 
  243   table_sort.unpack= unpack_addon_fields;
 
  244   if (param.addon_field &&
 
  245       !(table_sort.addon_buf=
 
  246         (uchar *) my_malloc(param.addon_length, MYF(MY_WME))))
 
  249   if (select && select->quick)
 
  250     thd->inc_status_sort_range();
 
  252     thd->inc_status_sort_scan();
 
  257   if (multi_byte_charset &&
 
  258       !(param.tmp_buffer= (
char*) my_malloc(param.sort_length,MYF(MY_WME))))
 
  261   if (check_if_pq_applicable(trace, ¶m, &table_sort,
 
  262                              table, num_rows, memory_available))
 
  264     DBUG_PRINT(
"info", (
"filesort PQ is applicable"));
 
  265     const size_t compare_length= param.sort_length;
 
  266     if (pq.
init(param.max_rows,
 
  276       DBUG_PRINT(
"info", (
"failed to allocate PQ"));
 
  277       table_sort.free_sort_buffer();
 
  278       DBUG_ASSERT(thd->is_error());
 
  282     table_sort.init_record_pointers();
 
  287     DBUG_PRINT(
"info", (
"filesort PQ is not applicable"));
 
  289     const ulong min_sort_memory=
 
  290       max(MIN_SORT_MEMORY, param.sort_length * MERGEBUFF2);
 
  291     while (memory_available >= min_sort_memory)
 
  293       ha_rows keys= memory_available / (param.rec_length + 
sizeof(
char*));
 
  294       param.max_keys_per_buffer= (uint) min(num_rows, keys);
 
  295       if (table_sort.get_sort_keys())
 
  298         if (std::make_pair(param.max_keys_per_buffer, param.rec_length) !=
 
  299             table_sort.sort_buffer_properties())
 
  305           table_sort.free_sort_buffer();
 
  308       table_sort.alloc_sort_buffer(param.max_keys_per_buffer, param.rec_length);
 
  309       if (table_sort.get_sort_keys())
 
  311       ulong old_memory_available= memory_available;
 
  312       memory_available= memory_available/4*3;
 
  313       if (memory_available < min_sort_memory &&
 
  314           old_memory_available > min_sort_memory)
 
  315         memory_available= min_sort_memory;
 
  317     if (memory_available < min_sort_memory)
 
  319       my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR + ME_FATALERROR));
 
  324   if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
 
  325                        DISK_BUFFER_SIZE, MYF(MY_WME)))
 
  328   param.sort_form= 
table;
 
  329   param.end= (param.local_sortorder= filesort->
sortorder) + s_length;
 
  333     num_rows= find_all_keys(¶m, select,
 
  339     if (num_rows == HA_POS_ERROR)
 
  343   maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/
sizeof(*buffpek));
 
  346     .add(
"rows", num_rows)
 
  347     .add(
"examined_rows", param.examined_rows)
 
  348     .add(
"number_of_tmp_files", maxbuffer)
 
  349     .add(
"sort_buffer_size", table_sort.sort_buffer_size())
 
  350     .add_alnum(
"sort_mode",
 
  352                "<sort_key, additional_fields>" : 
"<sort_key, rowid>");
 
  356     if (save_index(¶m, (uint) num_rows, &table_sort))
 
  362     DBUG_ASSERT(param.sort_length != 0);
 
  364     if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
 
  366       my_free(table_sort.buffpek);
 
  367       table_sort.buffpek= 0;
 
  369     if (!(table_sort.buffpek=
 
  370           (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
 
  371                                  table_sort.buffpek)))
 
  373     buffpek= (
BUFFPEK *) table_sort.buffpek;
 
  374     table_sort.buffpek_len= maxbuffer;
 
  375     close_cached_file(&buffpek_pointers);
 
  377     if (! my_b_inited(outfile) &&
 
  378         open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
 
  381     if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
 
  388     param.max_keys_per_buffer= table_sort.sort_buffer_size() / param.rec_length;
 
  391                         (uchar*) table_sort.get_sort_keys(),
 
  395     if (flush_io_cache(&tempfile) ||
 
  396         reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
 
  398     if (merge_index(¶m,
 
  399                     (uchar*) table_sort.get_sort_keys(),
 
  407   if (num_rows > param.max_rows)
 
  410     num_rows= param.max_rows;
 
  415   my_free(param.tmp_buffer);
 
  416   if (!subselect || !subselect->is_uncacheable())
 
  418     table_sort.free_sort_buffer();
 
  420     table_sort.buffpek= 0;
 
  421     table_sort.buffpek_len= 0;
 
  423   close_cached_file(&tempfile);
 
  424   close_cached_file(&buffpek_pointers);
 
  425   if (my_b_inited(outfile))
 
  427     if (flush_io_cache(outfile))
 
  430       my_off_t save_pos=outfile->pos_in_file;
 
  432       if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
 
  434       outfile->end_of_file=save_pos;
 
  439     int kill_errno= thd->killed_errno();
 
  440     DBUG_ASSERT(thd->is_error() || kill_errno);
 
  441     my_printf_error(ER_FILSORT_ABORT,
 
  443                     MYF(ME_ERROR + ME_WAITTANG),
 
  444                     ER_THD(thd, ER_FILSORT_ABORT),
 
  447                     thd->get_stmt_da()->message());
 
  449     if (log_warnings > 1)
 
  451       sql_print_warning(
"%s, host: %s, user: %s, thread: %lu, query: %-.4096s",
 
  452                         ER_THD(thd, ER_FILSORT_ABORT),
 
  453                         thd->security_ctx->host_or_ip,
 
  454                         &thd->security_ctx->priv_user[0],
 
  455                         (ulong) thd->thread_id,
 
  460     thd->inc_status_sort_rows(num_rows);
 
  461   *examined_rows= param.examined_rows;
 
  462 #ifdef SKIP_DBUG_IN_FILESORT 
  467   table->sort= table_sort;
 
  470              (
"num_rows: %ld examined_rows: %ld found_rows: %ld",
 
  471               (
long) num_rows, (
long) *examined_rows, (
long) *found_rows));
 
  472   MYSQL_FILESORT_DONE(error, num_rows);
 
  473   DBUG_RETURN(error ? HA_POS_ERROR : num_rows);
 
  477 void filesort_free_buffers(
TABLE *table, 
bool full)
 
  479   DBUG_ENTER(
"filesort_free_buffers");
 
  480   my_free(table->sort.record_pointers);
 
  481   table->sort.record_pointers= NULL;
 
  485     table->sort.free_sort_buffer();
 
  486     my_free(table->sort.buffpek);
 
  487     table->sort.buffpek= NULL;
 
  488     table->sort.buffpek_len= 0;
 
  491   my_free(table->sort.addon_buf);
 
  492   my_free(table->sort.addon_field);
 
  493   table->sort.addon_buf= NULL;
 
  494   table->sort.addon_field= NULL;
 
  498 void Filesort::cleanup()
 
  507 uint Filesort::make_sortorder()
 
  510   SORT_FIELD *sort,*pos;
 
  512   DBUG_ENTER(
"make_sortorder");
 
  516   for (ord = 
order; ord; ord= ord->next)
 
  519     sortorder= (SORT_FIELD*) sql_alloc(
sizeof(SORT_FIELD) * (count + 1));
 
  525   for (ord= 
order; ord; ord= ord->next, pos++)
 
  527     Item *item= ord->item[0]->real_item();
 
  528     pos->field= 0; pos->item= 0;
 
  529     if (item->type() == Item::FIELD_ITEM)
 
  531     else if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
 
  532       pos->field= ((
Item_sum*) item)->get_tmp_table_field();
 
  533     else if (item->type() == Item::COPY_STR_ITEM)
 
  535       pos->item= ((
Item_copy*) item)->get_item();
 
  538       pos->item= *ord->item;
 
  539     pos->reverse= (ord->direction == ORDER::ORDER_DESC);
 
  540     DBUG_ASSERT(pos->field != NULL || pos->item != NULL);
 
  556 static uchar *read_buffpek_from_file(
IO_CACHE *buffpek_pointers, uint count,
 
  559   ulong length= 
sizeof(
BUFFPEK)*count;
 
  561   DBUG_ENTER(
"read_buffpek_from_file");
 
  562   if (count > UINT_MAX/
sizeof(
BUFFPEK))
 
  565     tmp= (uchar *)my_malloc(length, MYF(MY_WME));
 
  568     if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
 
  569         my_b_read(buffpek_pointers, (uchar*) tmp, length))
 
  586 static void dbug_print_record(
TABLE *table, 
bool print_rowid)
 
  590   String tmp(buff,
sizeof(buff),&my_charset_bin);
 
  593   fprintf(DBUG_FILE, 
"record (");
 
  594   for (pfield= table->field; *pfield ; pfield++)
 
  595     fprintf(DBUG_FILE, 
"%s%s", (*pfield)->field_name, (pfield[1])? 
", ":
"");
 
  596   fprintf(DBUG_FILE, 
") = ");
 
  598   fprintf(DBUG_FILE, 
"(");
 
  599   for (pfield= table->field; *pfield ; pfield++)
 
  601     Field *field=  *pfield;
 
  603     if (field->is_null())
 
  604       fwrite(
"NULL", 
sizeof(
char), 4, DBUG_FILE);
 
  606     if (field->type() == MYSQL_TYPE_BIT)
 
  609       field->val_str(&tmp);
 
  611     fwrite(tmp.ptr(),
sizeof(char),tmp.length(),DBUG_FILE);
 
  613       fwrite(
", ", 
sizeof(
char), 2, DBUG_FILE);
 
  615   fprintf(DBUG_FILE, 
")");
 
  618     fprintf(DBUG_FILE, 
" rowid ");
 
  621       fprintf(DBUG_FILE, 
"%x", (uchar)table->file->ref[
i]);
 
  624   fprintf(DBUG_FILE, 
"\n");
 
  682   int error,flag,quick_select;
 
  683   uint idx,indexpos,ref_length;
 
  684   uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
 
  687   THD *thd= current_thd;
 
  688   volatile THD::killed_state *killed= &thd->killed;
 
  690   MY_BITMAP *save_read_set, *save_write_set;
 
  693   DBUG_ENTER(
"find_all_keys");
 
  694   DBUG_PRINT(
"info",(
"using: %s",
 
  695                      (select ? select->quick ? 
"ranges" : 
"where":
 
  699   error=quick_select=0;
 
  700   sort_form=param->sort_form;
 
  701   file=sort_form->file;
 
  702   ref_length=param->ref_length;
 
  704   quick_select=select && select->quick;
 
  707   flag= ((file->
ha_table_flags() & HA_REC_NOT_IN_SEQ) || quick_select);
 
  709     ref_pos= &file->ref[0];
 
  714     DBUG_EXECUTE_IF(
"bug14365043_1",
 
  715                     DBUG_SET(
"+d,ha_rnd_init_fail"););
 
  719       DBUG_RETURN(HA_POS_ERROR);
 
  721     file->extra_opt(HA_EXTRA_CACHE,
 
  722                     current_thd->variables.read_buff_size);
 
  727     if (select->quick->reset())
 
  728       DBUG_RETURN(HA_POS_ERROR);
 
  732   save_read_set=  sort_form->read_set;
 
  733   save_write_set= sort_form->write_set;
 
  735   bitmap_clear_all(&sort_form->tmp_set);
 
  737   sort_form->read_set= &sort_form->tmp_set;
 
  739   register_used_fields(param); 
 
  742   if (select && select->cond)
 
  743     select->cond->walk(&Item::register_field_in_read_map, 1,
 
  747   if (select && select->icp_cond)
 
  748     select->icp_cond->walk(&Item::register_field_in_read_map, 1,
 
  751   sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
 
  757       if ((error= select->quick->get_next()))
 
  759       file->position(sort_form->record[0]);
 
  760       DBUG_EXECUTE_IF(
"debug_filesort", dbug_print_record(sort_form, TRUE););
 
  768           my_store_ptr(ref_pos,ref_length,record); 
 
  769           record+= sort_form->s->db_record_offset;
 
  772           file->position(sort_form->record[0]);
 
  774       if (error && error != HA_ERR_RECORD_DELETED)
 
  780       DBUG_PRINT(
"info",(
"Sort killed by user"));
 
  783         (void) file->extra(HA_EXTRA_NO_CACHE);
 
  786       DBUG_RETURN(HA_POS_ERROR);                
 
  789       param->examined_rows++;
 
  790     if (!error && (!select ||
 
  791                    (!select->skip_record(thd, &skip_record) && !skip_record)))
 
  801         if (idx == param->max_keys_per_buffer)
 
  803           if (write_keys(param, fs_info, idx, buffpek_pointers, tempfile))
 
  804              DBUG_RETURN(HA_POS_ERROR);
 
  815     else if (!thd->is_error())
 
  823     (void) file->extra(HA_EXTRA_NO_CACHE);      
 
  829     DBUG_RETURN(HA_POS_ERROR);
 
  832   sort_form->column_bitmaps_set(save_read_set, save_write_set);
 
  834   DBUG_PRINT(
"test",(
"error: %d  indexpos: %d",error,indexpos));
 
  835   if (error != HA_ERR_END_OF_FILE)
 
  837     file->
print_error(error,MYF(ME_ERROR | ME_WAITTANG)); 
 
  838     DBUG_RETURN(HA_POS_ERROR);                  
 
  840   if (indexpos && idx &&
 
  841       write_keys(param, fs_info, idx, buffpek_pointers, tempfile))
 
  842     DBUG_RETURN(HA_POS_ERROR);                  
 
  843   const ha_rows retval= 
 
  844     my_b_inited(tempfile) ?
 
  845     (ha_rows) (my_b_tell(tempfile)/param->rec_length) : idx;
 
  846   DBUG_PRINT(
"info", (
"find_all_keys return %u", (uint) retval));
 
  880   DBUG_ENTER(
"write_keys");
 
  882   rec_length= param->rec_length;
 
  883   uchar **sort_keys= fs_info->get_sort_keys();
 
  887   if (!my_b_inited(tempfile) &&
 
  888       open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
 
  892   if (my_b_tell(buffpek_pointers) + 
sizeof(
BUFFPEK) > (ulonglong)UINT_MAX)
 
  894   buffpek.file_pos= my_b_tell(tempfile);
 
  895   if ((ha_rows) count > param->max_rows)
 
  896     count=(uint) param->max_rows;               
 
  897   buffpek.count=(ha_rows) count;
 
  898   for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
 
  899     if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
 
  901   if (my_b_write(buffpek_pointers, (uchar*) &buffpek, 
sizeof(buffpek)))
 
  914 static inline void store_length(uchar *
to, uint length, uint pack_length)
 
  916   switch (pack_length) {
 
  921     mi_int2store(to, length);
 
  924     mi_int3store(to, length);
 
  927     mi_int4store(to, length);
 
  933 #ifdef WORDS_BIGENDIAN 
  934 const bool Is_big_endian= 
true;
 
  936 const bool Is_big_endian= 
false;
 
  938 void copy_native_longlong(uchar *to, 
int to_length,
 
  939                           longlong val, 
bool is_unsigned)
 
  941   copy_integer<Is_big_endian>(
to, to_length,
 
  942                               static_cast<uchar*
>(
static_cast<void*
>(&val)),
 
  952   SORT_FIELD *sort_field;
 
  954   for (sort_field= param->local_sortorder ;
 
  955        sort_field != param->end ;
 
  958     bool maybe_null= 
false;
 
  959     if (sort_field->field)
 
  961       Field *field= sort_field->field;
 
  962       if (field->maybe_null())
 
  964         if (field->is_null())
 
  966           if (sort_field->reverse)
 
  967             memset(to, 255, sort_field->length+1);
 
  969             memset(to, 0, sort_field->length+1);
 
  970           to+= sort_field->length+1;
 
  980       Item *item=sort_field->item;
 
  981       maybe_null= item->maybe_null;
 
  982       switch (sort_field->result_type) {
 
  986         char fill_char= ((cs->state & MY_CS_BINSORT) ? (
char) 0 : 
' ');
 
  988         uint sort_field_length;
 
  993         String tmp((
char*) to,sort_field->length+4,cs);
 
  994         String *res= item->str_result(&tmp);
 
  998             memset(to-1, 0, sort_field->length+1);
 
 1008             DBUG_PRINT(
"warning",
 
 1009                        (
"Got null on something that shouldn't be null"));
 
 1010             memset(to, 0, sort_field->length);  
 
 1015         uint length= res->length();
 
 1016         sort_field_length= sort_field->length - sort_field->suffix_length;
 
 1017         diff=(int) (sort_field_length - length);
 
 1021           length= sort_field_length;
 
 1023         if (sort_field->suffix_length)
 
 1026           store_length(to + sort_field_length, length,
 
 1027                        sort_field->suffix_length);
 
 1029         if (sort_field->need_strxnfrm)
 
 1031           char *from=(
char*) res->ptr();
 
 1033           if ((uchar*) from == to)
 
 1035             set_if_smaller(length,sort_field->length);
 
 1036             memcpy(param->tmp_buffer,from,length);
 
 1037             from=param->tmp_buffer;
 
 1039           tmp_length= cs->coll->strnxfrm(cs, to, sort_field->length,
 
 1040                                          item->max_char_length(),
 
 1041                                          (uchar*) from, length,
 
 1042                                          MY_STRXFRM_PAD_WITH_SPACE |
 
 1043                                          MY_STRXFRM_PAD_TO_MAXLEN);
 
 1044           DBUG_ASSERT(tmp_length == sort_field->length);
 
 1048           my_strnxfrm(cs,(uchar*)to,length,(
const uchar*)res->ptr(),length);
 
 1049           cs->cset->fill(cs, (
char *)to+length,diff,fill_char);
 
 1055           longlong value= item->field_type() == MYSQL_TYPE_TIME ?
 
 1057                           item->is_temporal_with_date() ?
 
 1059                           item->val_int_result();
 
 1063             if (item->null_value)
 
 1066                 memset(to-1, 0, sort_field->length+1);
 
 1069                 DBUG_PRINT(
"warning",
 
 1070                            (
"Got null on something that shouldn't be null"));
 
 1071                 memset(to, 0, sort_field->length);
 
 1076           copy_native_longlong(to, sort_field->length,
 
 1077                                value, item->unsigned_flag);
 
 1080       case DECIMAL_RESULT:
 
 1082           my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
 
 1085             if (item->null_value)
 
 1087               memset(to, 0, sort_field->length+1);
 
 1096             my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, buf,
 
 1097                               item->max_length - (item->decimals ? 1:0),
 
 1099             memcpy(to, buf, sort_field->length);
 
 1103             my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
 
 1104                               item->max_length - (item->decimals ? 1:0),
 
 1111           double value= item->val_result();
 
 1114             if (item->null_value)
 
 1116               memset(to, 0, sort_field->length+1);
 
 1122           if (sort_field->length < 
sizeof(
double))
 
 1124             uchar buf[
sizeof(double)];
 
 1125             change_double_for_sort(value, buf);
 
 1126             memcpy(to, buf, sort_field->length);
 
 1130             change_double_for_sort(value, (uchar*) to);
 
 1141     if (sort_field->reverse)
 
 1145       uint length= sort_field->length;
 
 1148         *to = (uchar) (~ *to);
 
 1153       to+= sort_field->length;
 
 1156   if (param->addon_field)
 
 1166     DBUG_ASSERT(addonf != 0);
 
 1167     memset(nulls, 0, addonf->offset);
 
 1168     to+= addonf->offset;
 
 1169     for (
Field* field; (field= addonf->field) ; addonf++)
 
 1171       if (addonf->null_bit && field->is_null())
 
 1173         nulls[addonf->null_offset]|= addonf->null_bit;
 
 1177         (void) field->
pack(to, field->ptr);
 
 1179       to+= addonf->length;
 
 1185     memcpy((uchar*) to, ref_pos, (
size_t) param->ref_length);
 
 1195 static void register_used_fields(
Sort_param *param)
 
 1197   reg1 SORT_FIELD *sort_field;
 
 1198   TABLE *table=param->sort_form;
 
 1201   for (sort_field= param->local_sortorder ;
 
 1202        sort_field != param->end ;
 
 1206     if ((field= sort_field->field))
 
 1208       if (field->table == table)
 
 1209       bitmap_set_bit(bitmap, field->field_index);
 
 1213       sort_field->item->walk(&Item::register_field_in_read_map, 1,
 
 1218   if (param->addon_field)
 
 1222     for ( ; (field= addonf->field) ; addonf++)
 
 1223       bitmap_set_bit(bitmap, field->field_index);
 
 1236   DBUG_ENTER(
"save_index");
 
 1239   res_length= param->res_length;
 
 1240   offset= param->rec_length-res_length;
 
 1241   if (!(to= table_sort->record_pointers= 
 
 1242         (uchar*) my_malloc(res_length*count, MYF(MY_WME))))
 
 1244   uchar **sort_keys= table_sort->get_sort_keys();
 
 1245   for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
 
 1247     memcpy(to, *sort_keys+offset, res_length);
 
 1287                             TABLE *table, ha_rows num_rows,
 
 1288                             ulong memory_available)
 
 1290   DBUG_ENTER(
"check_if_pq_applicable");
 
 1296   const double PQ_slowness= 3.0;
 
 1299                                   "filesort_priority_queue_optimization");
 
 1300   if (param->max_rows == HA_POS_ERROR)
 
 1303       .add(
"usable", 
false)
 
 1304       .add_alnum(
"cause", 
"not applicable (no LIMIT)");
 
 1309     .add(
"limit", param->max_rows)
 
 1310     .add(
"rows_estimate", num_rows)
 
 1311     .add(
"row_size", param->rec_length)
 
 1312     .add(
"memory_available", memory_available);
 
 1314   if (param->max_rows + 2 >= UINT_MAX)
 
 1316     trace_filesort.add(
"usable", 
false).add_alnum(
"cause", 
"limit too large");
 
 1320   ulong num_available_keys=
 
 1321     memory_available / (param->rec_length + 
sizeof(
char*));
 
 1323   param->max_keys_per_buffer= (uint) param->max_rows + 1;
 
 1325   if (num_rows < num_available_keys)
 
 1328     if (param->max_rows < num_rows/PQ_slowness )
 
 1330       filesort_info->alloc_sort_buffer(param->max_keys_per_buffer,
 
 1332       trace_filesort.add(
"chosen", 
true);
 
 1333       DBUG_RETURN(filesort_info->get_sort_keys() != NULL);
 
 1338       trace_filesort.add(
"chosen", 
false)
 
 1339         .add_alnum(
"cause", 
"quicksort_is_cheaper");
 
 1345   if (param->max_keys_per_buffer < num_available_keys)
 
 1347     filesort_info->alloc_sort_buffer(param->max_keys_per_buffer,
 
 1349     trace_filesort.add(
"chosen", 
true);
 
 1350     DBUG_RETURN(filesort_info->get_sort_keys() != NULL);
 
 1354   if (param->addon_field)
 
 1356     const ulong row_length=
 
 1357       param->sort_length + param->ref_length + 
sizeof(
char*);
 
 1358     num_available_keys= memory_available / row_length;
 
 1361     trace_addon.add(
"row_size", row_length);
 
 1364     if (param->max_keys_per_buffer >= num_available_keys)
 
 1366       trace_addon.add(
"chosen", 
false).add_alnum(
"cause", 
"not_enough_space");
 
 1370       const double sort_merge_cost=
 
 1371         get_merge_many_buffs_cost_fast(num_rows,
 
 1374       trace_addon.add(
"sort_merge_cost", sort_merge_cost);
 
 1384       const double pq_cpu_cost= 
 
 1385         (PQ_slowness * num_rows + param->max_keys_per_buffer) *
 
 1387       const double pq_io_cost=
 
 1388         param->max_rows * table->file->scan_time() / 2.0;
 
 1389       const double pq_cost= pq_cpu_cost + pq_io_cost;
 
 1390       trace_addon.add(
"priority_queue_cost", pq_cost);
 
 1392       if (sort_merge_cost < pq_cost)
 
 1394         trace_addon.add(
"chosen", 
false);
 
 1398       trace_addon.add(
"chosen", 
true);
 
 1399       filesort_info->alloc_sort_buffer(param->max_keys_per_buffer,
 
 1400                                        param->sort_length + param->ref_length);
 
 1401       if (filesort_info->get_sort_keys())
 
 1404         my_free(filesort_info->addon_buf);
 
 1405         my_free(filesort_info->addon_field);
 
 1406         filesort_info->addon_buf= NULL;
 
 1407         filesort_info->addon_field= NULL;
 
 1408         param->addon_field= NULL;
 
 1409         param->addon_length= 0;
 
 1411         param->res_length= param->ref_length;
 
 1412         param->sort_length+= param->ref_length;
 
 1413         param->rec_length= param->sort_length;
 
 1431   DBUG_ENTER(
"merge_many_buff");
 
 1433   if (*maxbuffer < MERGEBUFF2)
 
 1435   if (flush_io_cache(t_file) ||
 
 1436       open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
 
 1440   from_file= t_file ; to_file= &t_file2;
 
 1441   while (*maxbuffer >= MERGEBUFF2)
 
 1443     if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
 
 1445     if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
 
 1448     for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
 
 1450       if (
merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
 
 1451                         buffpek+i,buffpek+i+MERGEBUFF-1,0))
 
 1454     if (
merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
 
 1455                       buffpek+i,buffpek+ *maxbuffer,0))
 
 1457     if (flush_io_cache(to_file))
 
 1459     temp=from_file; from_file=to_file; to_file=
temp;
 
 1460     setup_io_cache(from_file);
 
 1461     setup_io_cache(to_file);
 
 1462     *maxbuffer= (uint) (lastbuff-buffpek)-1;
 
 1465   close_cached_file(to_file);                   
 
 1466   if (to_file == t_file)
 
 1469     setup_io_cache(t_file);
 
 1472   DBUG_RETURN(*maxbuffer >= MERGEBUFF2);        
 
 1486   register uint count;
 
 1489   if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
 
 1492                          (length= rec_length*count),
 
 1493                          buffpek->file_pos, MYF_RW))
 
 1495     buffpek->key=buffpek->base;
 
 1496     buffpek->file_pos+= length;                 
 
 1497     buffpek->count-=    count;
 
 1498     buffpek->mem_count= count;
 
 1500   return (count*rec_length);
 
 1517   uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
 
 1518   for (uint 
i= 0; 
i < queue->elements; ++
i)
 
 1521     if (bp->base + bp->max_keys * key_length == reuse->base)
 
 1523       bp->max_keys+= reuse->max_keys;
 
 1526     else if (bp->base == reuse_end)
 
 1528       bp->base= reuse->base;
 
 1529       bp->max_keys+= reuse->max_keys;
 
 1556                   IO_CACHE *to_file, uchar *sort_buffer,
 
 1561   uint rec_length,res_length,
offset;
 
 1564   ha_rows max_rows,org_max_rows;
 
 1565   my_off_t to_start_filepos;
 
 1570   void *first_cmp_arg;
 
 1571   volatile THD::killed_state *killed= ¤t_thd->killed;
 
 1572   THD::killed_state not_killable;
 
 1573   DBUG_ENTER(
"merge_buffers");
 
 1575   current_thd->inc_status_sort_merge_passes();
 
 1576   if (param->not_killable)
 
 1578     killed= ¬_killable;
 
 1579     not_killable= THD::NOT_KILLED;
 
 1583   rec_length= param->rec_length;
 
 1584   res_length= param->res_length;
 
 1585   sort_length= param->sort_length;
 
 1586   offset= rec_length-res_length;
 
 1587   maxcount= (ulong) (param->max_keys_per_buffer / ((uint) (Tb-Fb) +1));
 
 1588   to_start_filepos= my_b_tell(to_file);
 
 1589   strpos= (uchar*) sort_buffer;
 
 1590   org_max_rows=max_rows= param->max_rows;
 
 1593   DBUG_ASSERT(maxcount!=0);
 
 1595   if (param->unique_buff)
 
 1597     cmp= param->compare;
 
 1598     first_cmp_arg= (
void *) ¶m->cmp_context;
 
 1602     cmp= get_ptr_compare(sort_length);
 
 1603     first_cmp_arg= (
void*) &sort_length;
 
 1605   if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(
BUFFPEK,key), 0,
 
 1606                  (queue_compare) cmp, first_cmp_arg))
 
 1608   for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
 
 1610     buffpek->base= strpos;
 
 1611     buffpek->max_keys= maxcount;
 
 1613       (uint) (error= (
int)
read_to_buffer(from_file, buffpek, rec_length));
 
 1616     buffpek->max_keys= buffpek->mem_count;      
 
 1617     queue_insert(&queue, (uchar*) buffpek);
 
 1620   if (param->unique_buff)
 
 1630     buffpek= (
BUFFPEK*) queue_top(&queue);
 
 1631     memcpy(param->unique_buff, buffpek->key, rec_length);
 
 1632     if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
 
 1636     buffpek->key+= rec_length;
 
 1637     buffpek->mem_count--;
 
 1643     queue_replaced(&queue);                        
 
 1648   while (queue.elements > 1)
 
 1656       buffpek= (
BUFFPEK*) queue_top(&queue);
 
 1659         if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
 
 1660                     (uchar**) &buffpek->key))
 
 1661               goto skip_duplicate;
 
 1662             memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length);
 
 1666         if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
 
 1673         if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
 
 1685       buffpek->key+= rec_length;
 
 1686       if (! --buffpek->mem_count)
 
 1691           (void) queue_remove(&queue,0);
 
 1695         else if (error == -1)
 
 1698       queue_replaced(&queue);              
 
 1701   buffpek= (
BUFFPEK*) queue_top(&queue);
 
 1702   buffpek->base= sort_buffer;
 
 1703   buffpek->max_keys= param->max_keys_per_buffer;
 
 1711     if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
 
 1713       buffpek->key+= rec_length;         
 
 1714       --buffpek->mem_count;
 
 1720     if ((ha_rows) buffpek->mem_count > max_rows)
 
 1722       buffpek->mem_count= (uint) max_rows;
 
 1725     max_rows-= buffpek->mem_count;
 
 1728       if (my_b_write(to_file,(uchar*) buffpek->key,
 
 1729                      (rec_length*buffpek->mem_count)))
 
 1736       register uchar *end;
 
 1737       strpos= buffpek->key+
offset;
 
 1738       for (end= strpos+buffpek->mem_count*rec_length ;
 
 1740            strpos+= rec_length)
 
 1742         if (my_b_write(to_file, (uchar *) strpos, res_length))
 
 1749   while ((error=(
int) 
read_to_buffer(from_file,buffpek, rec_length))
 
 1750          != -1 && error != 0);
 
 1753   lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
 
 1754   lastbuff->file_pos= to_start_filepos;
 
 1756   delete_queue(&queue);
 
 1763 static int merge_index(
Sort_param *param, uchar *sort_buffer,
 
 1764                        BUFFPEK *buffpek, uint maxbuffer,
 
 1767   DBUG_ENTER(
"merge_index");
 
 1768   if (
merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
 
 1769                     buffpek+maxbuffer,1))
 
 1775 static uint suffix_length(ulong string_length)
 
 1777   if (string_length < 256)
 
 1779   if (string_length < 256L*256L)
 
 1781   if (string_length < 256L*256L*256L)
 
 1808            bool *multi_byte_charset)
 
 1810   uint total_length= 0;
 
 1812   *multi_byte_charset= 
false;
 
 1814   for (; s_length-- ; sortorder++)
 
 1816     sortorder->need_strxnfrm= 0;
 
 1817     sortorder->suffix_length= 0;
 
 1818     if (sortorder->field)
 
 1820       cs= sortorder->field->sort_charset();
 
 1821       sortorder->length= sortorder->field->sort_length();
 
 1823       if (use_strnxfrm((cs=sortorder->field->sort_charset())))
 
 1825         sortorder->need_strxnfrm= 1;
 
 1826         *multi_byte_charset= 1;
 
 1827         sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
 
 1829       if (sortorder->field->maybe_null())
 
 1832       if (sortorder->field->result_type() == STRING_RESULT &&
 
 1833           !sortorder->field->is_temporal())
 
 1835         set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
 1840       sortorder->result_type= sortorder->item->result_type();
 
 1841       if (sortorder->item->is_temporal())
 
 1842         sortorder->result_type= INT_RESULT;
 
 1843       switch (sortorder->result_type) {
 
 1845         sortorder->length= sortorder->item->max_length;
 
 1846         set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
 1847         if (use_strnxfrm((cs=sortorder->item->collation.collation)))
 
 1849           sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
 
 1850           sortorder->need_strxnfrm= 1;
 
 1851           *multi_byte_charset= 1;
 
 1853         else if (cs == &my_charset_bin)
 
 1856           sortorder->suffix_length= suffix_length(sortorder->length);
 
 1857           sortorder->length+= sortorder->suffix_length;
 
 1861 #if SIZEOF_LONG_LONG > 4 
 1862         sortorder->length=8;                    
 
 1864         sortorder->length=4;
 
 1867       case DECIMAL_RESULT:
 
 1869           my_decimal_get_binary_size(sortorder->item->max_length - 
 
 1870                                      (sortorder->item->decimals ? 1 : 0),
 
 1871                                      sortorder->item->decimals);
 
 1874         sortorder->length=
sizeof(double);
 
 1882       if (sortorder->item->maybe_null)
 
 1885     total_length+= sortorder->length;
 
 1887   sortorder->field= NULL;                       
 
 1888   DBUG_PRINT(
"info",(
"sort_length: %u", total_length));
 
 1889   return total_length;
 
 1921 get_addon_fields(ulong max_length_for_sort_data,
 
 1929   uint null_fields= 0;
 
 1930   MY_BITMAP *read_set= (*ptabfield)->table->read_set;
 
 1943   for (pfield= ptabfield; (field= *pfield) ; pfield++)
 
 1945     if (!bitmap_is_set(read_set, field->field_index))
 
 1947     if (field->flags & BLOB_FLAG)
 
 1949     length+= field->max_packed_col_length(field->pack_length());
 
 1950     if (field->maybe_null())
 
 1956   length+= (null_fields+7)/8;
 
 1958   if (length+sortlength > max_length_for_sort_data ||
 
 1960                                                (fields+1), MYF(MY_WME))))
 
 1964   length= (null_fields+7)/8;
 
 1966   for (pfield= ptabfield; (field= *pfield) ; pfield++)
 
 1968     if (!bitmap_is_set(read_set, field->field_index))
 
 1970     addonf->field= field;
 
 1971     addonf->offset= length;
 
 1972     if (field->maybe_null())
 
 1974       addonf->null_offset= null_fields/8;
 
 1975       addonf->null_bit= 1<<(null_fields & 7);
 
 1980       addonf->null_offset= 0;
 
 1981       addonf->null_bit= 0;
 
 1983     addonf->length= field->max_packed_col_length(field->pack_length());
 
 1984     length+= addonf->length;
 
 1989   DBUG_PRINT(
"info",(
"addon_length: %d",length));
 
 1990   return (addonf-fields);
 
 2015   for ( ; (field= addonf->field) ; addonf++)
 
 2017     if (addonf->null_bit && (addonf->null_bit & buff[addonf->null_offset]))
 
 2022     field->set_notnull();
 
 2023     field->
unpack(field->ptr, buff + addonf->offset);
 
 2032 #define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG) 
 2034 void change_double_for_sort(
double nr,uchar *to)
 
 2036   uchar *tmp=(uchar*) to;
 
 2040     memset(tmp+1, 0, 
sizeof(nr)-1);
 
 2044 #ifdef WORDS_BIGENDIAN 
 2045     memcpy(tmp, &nr, 
sizeof(nr));
 
 2048       uchar *ptr= (uchar*) &nr;
 
 2049 #if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) 
 2050       tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
 
 2051       tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
 
 2053       tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
 
 2054       tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
 
 2061       for (i=0 ; i < 
sizeof(nr); i++)
 
 2062         tmp[i]=tmp[i] ^ (uchar) 255;
 
 2066       ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
 
 2068       exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
 
 2069       tmp[0]= (uchar) (exp_part >> 8);
 
 2070       tmp[1]= (uchar) exp_part;