filesort.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:27k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* Sorts a database */
  14. #include "mysql_priv.h"
  15. #ifdef HAVE_STDDEF_H
  16. #include <stddef.h> /* for macro offsetof */
  17. #endif
  18. #include <m_ctype.h>
  19. #ifndef THREAD
  20. #define SKIPP_DBUG_IN_FILESORT
  21. #endif
  22. /* static variabels */
  23. #define MERGEBUFF  7
  24. #define MERGEBUFF2 15
  25. /* How to write record_ref. */
  26. #define WRITE_REF(file,from) 
  27. if (my_b_write((file),(byte*) (from),param->ref_length)) 
  28.   DBUG_RETURN(1);
  29. typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
  30.   my_off_t file_pos; /* Where we are in the sort file */
  31.   uchar *base,*key; /* key pointers */
  32.   ha_rows count; /* Number of rows in table */
  33.   ulong mem_count; /* numbers of keys in memory */
  34.   ulong max_keys; /* Max keys in buffert */
  35. } BUFFPEK;
  36. typedef struct st_sort_param {
  37.   uint sort_length; /* Length of sortarg */
  38.   uint keys; /* Max antal nycklar / buffert */
  39.   uint ref_length; /* Length of record ref. */
  40.   ha_rows max_rows;
  41.   TABLE *sort_form; /* For quicker make_sortkey */
  42.   SORT_FIELD *local_sortorder;
  43.   SORT_FIELD *end;
  44. #ifdef USE_STRCOLL
  45.   char* tmp_buffer;
  46. #endif
  47. } SORTPARAM;
  48. /* functions defined in this file */
  49. static char **make_char_array(register uint fields, uint length, myf my_flag);
  50. static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
  51.      uchar * *sort_keys,
  52.      BUFFPEK *buffpek,uint *maxbuffer,
  53.      IO_CACHE *tempfile,IO_CACHE *indexfile);
  54. static int write_keys(SORTPARAM *param,uchar * *sort_keys,
  55.       uint count,BUFFPEK *buffpek,
  56.       IO_CACHE *tempfile);
  57. static void make_sortkey(SORTPARAM *param,uchar *to,
  58.  byte *ref_pos);
  59. static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count);
  60. static int merge_many_buff(SORTPARAM *param,uchar * *sort_keys,
  61.    BUFFPEK *buffpek,
  62.    uint *maxbuffer, IO_CACHE *t_file);
  63. static uint read_to_buffer(IO_CACHE *fromfile,BUFFPEK *buffpek,
  64.    uint sort_length);
  65. static int merge_buffers(SORTPARAM *param,IO_CACHE *from_file,
  66.  IO_CACHE *to_file,uchar * *sort_keys,
  67.  BUFFPEK *lastbuff,BUFFPEK *Fb,
  68.  BUFFPEK *Tb,int flag);
  69. static int merge_index(SORTPARAM *param,uchar * *sort_keys,
  70.        BUFFPEK *buffpek,
  71.        uint maxbuffer,IO_CACHE *tempfile,
  72.        IO_CACHE *outfile);
  73. static uint sortlength(SORT_FIELD *sortorder,uint length);
  74. /* Makes a indexfil of recordnumbers of a sorted database */
  75. /* outfile is reset before data is written to it, if it wasn't
  76.  open a new file is opened */
  77. ha_rows filesort(TABLE **table, SORT_FIELD *sortorder, uint s_length,
  78.  SQL_SELECT *select, ha_rows special, ha_rows max_rows)
  79. {
  80.   int error;
  81.   uint memavl,old_memavl,maxbuffer,skr;
  82.   BUFFPEK *buffpek;
  83.   ha_rows records;
  84.   uchar **sort_keys;
  85.   IO_CACHE tempfile,*selected_records_file,*outfile;
  86.   SORTPARAM param;
  87.   DBUG_ENTER("filesort");
  88.   DBUG_EXECUTE("info",TEST_filesort(table,sortorder,s_length,special););
  89. #ifdef SKIPP_DBUG_IN_FILESORT
  90.   DBUG_PUSH(""); /* No DBUG here */
  91. #endif
  92.   outfile= table[0]->io_cache;
  93.   my_b_clear(&tempfile);
  94.   buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
  95.   maxbuffer=1;
  96.   param.ref_length= table[0]->file->ref_length;
  97.   param.sort_length=sortlength(sortorder,s_length)+ param.ref_length;
  98.   param.max_rows= max_rows;
  99.   if (select && select->quick)
  100.   {
  101.     statistic_increment(filesort_range_count, &LOCK_status);
  102.   }
  103.   else
  104.   {
  105.     statistic_increment(filesort_scan_count, &LOCK_status);
  106.   }
  107.   if (select && my_b_inited(&select->file))
  108.   {
  109.     records=special=select->records; /* purecov: deadcode */
  110.     selected_records_file= &select->file; /* purecov: deadcode */
  111.     reinit_io_cache(selected_records_file,READ_CACHE,0L,0,0); /* purecov: deadcode */
  112.   }
  113.   else if (special)
  114.   {
  115.     records=special; /* purecov: deadcode */
  116.     selected_records_file= outfile; /* purecov: deadcode */
  117.     reinit_io_cache(selected_records_file,READ_CACHE,0L,0,0); /* purecov: deadcode */
  118.   }
  119. #ifdef CAN_TRUST_RANGE
  120.   else if (select && select->quick && select->quick->records > 0L)
  121.   {
  122.     /* Get record-count */
  123.     table[0]->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  124.     records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
  125. table[0]->file->records)+EXTRA_RECORDS;
  126.     selected_records_file=0;
  127.   }
  128. #endif
  129.   else
  130.   {
  131.     table[0]->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);/* Get record-count */
  132.     records=table[0]->file->estimate_number_of_rows();
  133.     selected_records_file= 0;
  134.   }
  135.   if (param.sort_length == param.ref_length && records > param.max_rows)
  136.     records=param.max_rows; /* purecov: inspected */
  137. #ifdef USE_STRCOLL
  138.   if (use_strcoll(default_charset_info) &&
  139.       !(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME))))
  140.     goto err;
  141. #endif
  142.   memavl=sortbuff_size;
  143.   while (memavl >= MIN_SORT_MEMORY)
  144.   {
  145.     if ((ulonglong) (records+1)*(param.sort_length+sizeof(char*))+sizeof(BUFFPEK)*10 <
  146. (ulonglong) memavl)
  147.       param.keys=(uint) records+1;
  148.     else
  149.     {
  150.       maxbuffer=1;
  151.       do
  152.       {
  153. skr=maxbuffer;
  154. if (memavl < sizeof(BUFFPEK)*maxbuffer)
  155. {
  156.   my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
  157.   goto err;
  158. }
  159. param.keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
  160.   (param.sort_length+sizeof(char*));
  161.       }
  162.       while ((maxbuffer= (uint) (records/param.keys+1)) != skr);
  163.     }
  164.     if ((sort_keys= (uchar **) make_char_array(param.keys,param.sort_length,
  165.        MYF(0))))
  166.       if ((buffpek = (BUFFPEK*) my_malloc((uint) sizeof(BUFFPEK)*
  167.   (maxbuffer+10),
  168.   MYF(0))))
  169. break;
  170.       else
  171. my_free((gptr) sort_keys,MYF(0));
  172.     old_memavl=memavl;
  173.     if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
  174.       memavl=MIN_SORT_MEMORY;
  175.   }
  176.   param.keys--;
  177.   maxbuffer+=10; /* Some extra range */
  178.   if (memavl < MIN_SORT_MEMORY)
  179.   {
  180.     my_error(ER_OUTOFMEMORY,MYF(ME_ERROR+ME_WAITTANG),sortbuff_size);
  181.     goto err;
  182.   }
  183.   param.sort_form= table[0];
  184.   param.end=(param.local_sortorder=sortorder)+s_length;
  185.   if ((records=find_all_keys(&param,select,sort_keys,buffpek,&maxbuffer,
  186.      &tempfile, selected_records_file)) ==
  187.       HA_POS_ERROR)
  188.     goto err;
  189.   if (maxbuffer == 0) // The whole set is in memory
  190.   {
  191.     if (save_index(&param,sort_keys,(uint) records))
  192.       goto err;
  193.   }
  194.   else
  195.   {
  196. /* Open cached file if it isn't open */
  197.     if (! my_b_inited(outfile) &&
  198. open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
  199.   MYF(MY_WME)))
  200.       goto err;
  201.     reinit_io_cache(outfile,WRITE_CACHE,0L,0,0);
  202.     param.keys=((param.keys*(param.sort_length+sizeof(char*))) /
  203. param.sort_length-1);
  204.     if (merge_many_buff(&param,sort_keys,buffpek,&maxbuffer,&tempfile))
  205.       goto err;
  206.     if (flush_io_cache(&tempfile) ||
  207. reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
  208.       goto err;
  209.     if (merge_index(&param,sort_keys,buffpek,maxbuffer,&tempfile,outfile))
  210.       goto err;
  211.   }
  212.   if (records > param.max_rows)
  213.     records=param.max_rows;
  214.   error =0;
  215.  err:
  216. #ifdef USE_STRCOLL
  217.   if (use_strcoll(default_charset_info))
  218.     x_free(param.tmp_buffer);
  219. #endif
  220.   x_free((gptr) sort_keys);
  221.   x_free((gptr) buffpek);
  222.   close_cached_file(&tempfile);
  223.   if (my_b_inited(outfile))
  224.   {
  225.     if (flush_io_cache(outfile))
  226.       error=1;
  227.     {
  228.       my_off_t save_pos=outfile->pos_in_file;
  229.       /* For following reads */
  230.       if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
  231. error=1;
  232.       outfile->end_of_file=save_pos;
  233.     }
  234.   }
  235.   if (error)
  236.     my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
  237.   else
  238.     statistic_add(filesort_rows, records, &LOCK_status);
  239. #ifdef SKIPP_DBUG_IN_FILESORT
  240.   DBUG_POP(); /* Ok to DBUG */
  241. #endif
  242.   DBUG_PRINT("exit",("records: %ld",records));
  243.   DBUG_RETURN(error ? HA_POS_ERROR : records);
  244. } /* filesort */
  245. /* Make a array of string pointers */
  246. static char **make_char_array(register uint fields, uint length, myf my_flag)
  247. {
  248.   register char **pos;
  249.   char **old_pos,*char_pos;
  250.   DBUG_ENTER("make_char_array");
  251.   if ((old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
  252.     my_flag)))
  253.   {
  254.     pos=old_pos; char_pos=((char*) (pos+fields)) -length;
  255.     while (fields--) *(pos++) = (char_pos+= length);
  256.   }
  257.   DBUG_RETURN(old_pos);
  258. } /* make_char_array */
  259. /* Search after sort_keys and place them in a temp. file */
  260. static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
  261.      uchar **sort_keys,
  262.      BUFFPEK *buffpek, uint *maxbuffer,
  263.      IO_CACHE *tempfile, IO_CACHE *indexfile)
  264. {
  265.   int error,flag,quick_select;
  266.   uint idx,indexpos,ref_length;
  267.   byte *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
  268.   my_off_t record;
  269.   TABLE *sort_form;
  270.   volatile bool *killed= &current_thd->killed;
  271.   handler *file;
  272.   DBUG_ENTER("find_all_keys");
  273.   DBUG_PRINT("info",("using: %s",(select?select->quick?"ranges":"where":"every row")));
  274.   idx=indexpos=0;
  275.   error=quick_select=0;
  276.   sort_form=param->sort_form;
  277.   file=sort_form->file;
  278.   ref_length=param->ref_length;
  279.   ref_pos= ref_buff;
  280.   quick_select=select && select->quick;
  281.   record=0;
  282.   flag= ((!indexfile && file->option_flag() & HA_REC_NOT_IN_SEQ)
  283.  || quick_select);
  284.   if (indexfile || flag)
  285.     ref_pos= &file->ref[0];
  286.   next_pos=ref_pos;
  287.   if (! indexfile && ! quick_select)
  288.   {
  289.     file->reset(); // QQ; Shouldn't be needed
  290.     if (sort_form->key_read) // QQ Can be removed after the reset
  291.       file->extra(HA_EXTRA_KEYREAD); // QQ is removed
  292.     next_pos=(byte*) 0; /* Find records in sequence */
  293.     file->rnd_init();
  294.     file->extra(HA_EXTRA_CACHE); /* Quicker reads */
  295.   }
  296.   for (;;)
  297.   {
  298.     if (quick_select)
  299.     {
  300.       if ((error=select->quick->get_next()))
  301. break;
  302.       file->position(sort_form->record[0]);
  303.     }
  304.     else /* Not quick-select */
  305.     {
  306.       if (indexfile)
  307.       {
  308. if (my_b_read(indexfile,(byte*) ref_pos,ref_length)) /* purecov: deadcode */
  309. {
  310.   error= my_errno ? my_errno : -1; /* Abort */
  311.   break;
  312. }
  313. error=file->rnd_pos(sort_form->record[0],next_pos);
  314.       }
  315.       else
  316.       {
  317. error=file->rnd_next(sort_form->record[0]);
  318. if (!flag)
  319. {
  320.   ha_store_ptr(ref_pos,ref_length,record); // Position to row
  321.   record+=sort_form->db_record_offset;
  322. }
  323. else
  324.   file->position(sort_form->record[0]);
  325.       }
  326.       if (error && error != HA_ERR_RECORD_DELETED)
  327. break;
  328.     }
  329.     if (*killed)
  330.     {
  331.       DBUG_PRINT("info",("Sort killed by user"));
  332.       (void) file->extra(HA_EXTRA_NO_CACHE);
  333.       file->rnd_end();
  334.       DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
  335.     }
  336.     if (error == 0 && (!select || select->skipp_record() == 0))
  337.     {
  338.       if (idx == param->keys)
  339.       {
  340. if (indexpos >= *maxbuffer ||
  341.     write_keys(param,sort_keys,idx,buffpek+indexpos,tempfile))
  342.       DBUG_RETURN(HA_POS_ERROR);
  343. idx=0; indexpos++;
  344. if (param->ref_length == param->sort_length &&
  345.     my_b_tell(tempfile)/param->sort_length >= param->max_rows)
  346. {
  347.   error=HA_ERR_END_OF_FILE;
  348.   break; /* Found enough records */
  349. }
  350.       }
  351.       make_sortkey(param,sort_keys[idx++],ref_pos);
  352.     }
  353.   }
  354.   (void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
  355.   file->rnd_end();
  356.   DBUG_PRINT("test",("error: %d  indexpos: %d",error,indexpos));
  357.   if (error != HA_ERR_END_OF_FILE)
  358.   {
  359.     file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
  360.     DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
  361.   }
  362.   if (indexpos)
  363.     if (indexpos >= *maxbuffer ||
  364. write_keys(param,sort_keys,idx,buffpek+indexpos,tempfile))
  365.       DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
  366.   *maxbuffer=indexpos;
  367.   DBUG_RETURN(my_b_inited(tempfile) ?
  368.       (ha_rows) (my_b_tell(tempfile)/param->sort_length) :
  369.       idx);
  370. } /* find_all_keys */
  371. /* Skriver en buffert med nycklar till filen */
  372. static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
  373.       BUFFPEK *buffpek, IO_CACHE *tempfile)
  374. {
  375.   uint sort_length;
  376.   DBUG_ENTER("write_keys");
  377.   sort_length=param->sort_length;
  378. #ifdef MC68000
  379.   quicksort(sort_keys,count,sort_length);
  380. #else
  381.   my_string_ptr_sort((gptr) sort_keys,(uint) count,sort_length);
  382. #endif
  383.   if (!my_b_inited(tempfile) &&
  384.       open_cached_file(tempfile,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
  385. MYF(MY_WME)))
  386.     DBUG_RETURN(1); /* purecov: inspected */
  387.   buffpek->file_pos=my_b_tell(tempfile);
  388.   if ((ha_rows) count > param->max_rows)
  389.     count=(uint) param->max_rows; /* purecov: inspected */
  390.   buffpek->count=(ha_rows) count;
  391.   for (uchar **end=sort_keys+count ; sort_keys != end ; sort_keys++)
  392.     if (my_b_write(tempfile,(byte*) *sort_keys,(uint) sort_length))
  393.       DBUG_RETURN(1);
  394.   DBUG_RETURN(0);
  395. } /* write_keys */
  396. /* makes a sort-key from record */
  397. static void make_sortkey(register SORTPARAM *param,
  398.  register uchar *to, byte *ref_pos)
  399. {
  400.   reg3 Field *field;
  401.   reg1 SORT_FIELD *sort_field;
  402.   reg5 uint length;
  403.   for (sort_field=param->local_sortorder ;
  404.        sort_field != param->end ;
  405.        sort_field++)
  406.   {
  407.     if ((field=sort_field->field))
  408.     { // Field
  409.       if (field->maybe_null())
  410.       {
  411. if (field->is_null())
  412. {
  413.   if (sort_field->reverse)
  414.     bfill(to,sort_field->length+1,(char) 255);
  415.   else
  416.     bzero((char*) to,sort_field->length+1);
  417.   to+= sort_field->length+1;
  418.   continue;
  419. }
  420. else
  421.   *to++=1;
  422.       }
  423.       field->sort_string((char*) to,sort_field->length);
  424.     }
  425.     else
  426.     { // Item
  427.       Item *item=sort_field->item;
  428.       switch (sort_field->result_type) {
  429.       case STRING_RESULT:
  430. {
  431.   if (item->maybe_null)
  432.     *to++=1;
  433.   /* All item->str() to use some extra byte for end null.. */
  434.   String tmp((char*) to,sort_field->length+4);
  435.   String *res=item->val_str(&tmp);
  436.   if (!res)
  437.   {
  438.     if (item->maybe_null)
  439.       bzero((char*) to-1,sort_field->length+1);
  440.     else
  441.     {
  442.       DBUG_PRINT("warning",
  443.  ("Got null on something that shouldn't be null"));
  444.       bzero((char*) to,sort_field->length); // Avoid crash
  445.     }
  446.     break;
  447.   }
  448.   length=res->length();
  449.   int diff=(int) (sort_field->length-length);
  450.   if (diff < 0)
  451.   {
  452.     diff=0; /* purecov: inspected */
  453.     length=sort_field->length;
  454.   }
  455. #ifdef USE_STRCOLL
  456.           if (use_strcoll(default_charset_info))
  457.           {
  458.             if (item->binary)
  459.             {
  460.               if (res->ptr() != (char*) to)
  461.                 memcpy(to,res->ptr(),length);
  462.               bzero((char*) to+length,diff);
  463.             }
  464.             else
  465.             {
  466.               char *from=(char*) res->ptr();
  467.               if ((unsigned char *)from == to)
  468.               {
  469.                 set_if_smaller(length,sort_field->length);
  470.                 memcpy(param->tmp_buffer,from,length);
  471.                 from=param->tmp_buffer;
  472.               }
  473.               uint tmp_length=my_strnxfrm(default_charset_info,
  474.                                           to,(unsigned char *) from,
  475.                                           sort_field->length,
  476.                                           length);
  477.               if (tmp_length < sort_field->length)
  478.                 bzero((char*) to+tmp_length,sort_field->length-tmp_length);
  479.             }
  480.           }
  481.           else
  482.           {
  483. #endif
  484.             if (res->ptr() != (char*) to)
  485.               memcpy(to,res->ptr(),length);
  486.             bzero((char *)to+length,diff);
  487.             if (!item->binary)
  488.               case_sort((char*) to,length);
  489. #ifdef USE_STRCOLL
  490.           }
  491. #endif
  492.   break;
  493. }
  494.       case INT_RESULT:
  495. {
  496.   longlong value=item->val_int();
  497.   if (item->maybe_null)
  498.     *to++=1; /* purecov: inspected */
  499.   if (item->null_value)
  500.   {
  501.     if (item->maybe_null)
  502.       bzero((char*) to-1,sort_field->length+1);
  503.     else
  504.     {
  505.       DBUG_PRINT("warning",
  506.  ("Got null on something that shouldn't be null"));
  507.       bzero((char*) to,sort_field->length);
  508.     }
  509.     break;
  510.   }
  511. #if SIZEOF_LONG_LONG > 4
  512.   to[7]= (uchar) value;
  513.   to[6]= (uchar) (value >> 8);
  514.   to[5]= (uchar) (value >> 16);
  515.   to[4]= (uchar) (value >> 24);
  516.   to[3]= (uchar) (value >> 32);
  517.   to[2]= (uchar) (value >> 40);
  518.   to[1]= (uchar) (value >> 48);
  519.   to[0]= (uchar) (value >> 56) ^ 128; // Fix sign
  520. #else
  521.   to[3]= (uchar) value;
  522.   to[2]= (uchar) (value >> 8);
  523.   to[1]= (uchar) (value >> 16);
  524.   to[0]= (uchar) (value >> 24) ^ 128; // Fix sign
  525. #endif
  526.   break;
  527. }
  528.       case REAL_RESULT:
  529. {
  530.   double value=item->val();
  531.   if (item->null_value)
  532.   {
  533.     bzero((char*) to,sort_field->length+1);
  534.     to++;
  535.     break;
  536.   }
  537.   if (item->maybe_null)
  538.     *to++=1;
  539.   change_double_for_sort(value,(byte*) to);
  540.   break;
  541. }
  542.       }
  543.     }
  544.     if (sort_field->reverse)
  545.     { /* Revers key */
  546.       length=sort_field->length;
  547.       while (length--)
  548.       {
  549. *to = (uchar) (~ *to);
  550. to++;
  551.       }
  552.     }
  553.     else
  554.       to+= sort_field->length;
  555.   }
  556.   memcpy((byte*) to,ref_pos,(size_s) param->ref_length);/* Save filepos last */
  557.   return;
  558. }
  559. static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count)
  560. {
  561.   uint offset,ref_length;
  562.   byte *to;
  563.   DBUG_ENTER("save_index");
  564.   my_string_ptr_sort((gptr) sort_keys,(uint) count,param->sort_length);
  565.   ref_length=param->ref_length;
  566.   offset=param->sort_length-ref_length;
  567.   if ((ha_rows) count > param->max_rows)
  568.     count=(uint) param->max_rows;
  569.   if (!(to=param->sort_form->record_pointers=
  570. (byte*) my_malloc(ref_length*count,MYF(MY_WME))))
  571.     DBUG_RETURN(1); /* purecov: inspected */
  572.   for (uchar **end=sort_keys+count ; sort_keys != end ; sort_keys++)
  573.   {
  574.     memcpy(to,*sort_keys+offset,ref_length);
  575.     to+=ref_length;
  576.   }
  577.   DBUG_RETURN(0);
  578. }
  579. /* Merge buffers to make < MERGEBUFF2 buffers */
  580. static int merge_many_buff(SORTPARAM *param, uchar **sort_keys,
  581.    BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
  582. {
  583.   register int i;
  584.   IO_CACHE t_file2,*from_file,*to_file,*temp;
  585.   BUFFPEK *lastbuff;
  586.   DBUG_ENTER("merge_many_buff");
  587.   if (*maxbuffer < MERGEBUFF2)
  588.     DBUG_RETURN(0); /* purecov: inspected */
  589.   if (flush_io_cache(t_file) ||
  590.       open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
  591. MYF(MY_WME)))
  592.     DBUG_RETURN(1); /* purecov: inspected */
  593.   from_file= t_file ; to_file= &t_file2;
  594.   while (*maxbuffer >= MERGEBUFF2)
  595.   {
  596.     reinit_io_cache(from_file,READ_CACHE,0L,0,0);
  597.     reinit_io_cache(to_file,WRITE_CACHE,0L,0,0);
  598.     lastbuff=buffpek;
  599.     for (i=0 ; i <= (int) *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
  600.     {
  601.       if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++,
  602. buffpek+i,buffpek+i+MERGEBUFF-1,0))
  603. break; /* purecov: inspected */
  604.     }
  605.     if (merge_buffers(param,from_file,to_file,sort_keys,lastbuff++,
  606.       buffpek+i,buffpek+ *maxbuffer,0))
  607.       break; /* purecov: inspected */
  608.     if (flush_io_cache(to_file))
  609.       break; /* purecov: inspected */
  610.     temp=from_file; from_file=to_file; to_file=temp;
  611.     *maxbuffer= (uint) (lastbuff-buffpek)-1;
  612.   }
  613.   close_cached_file(to_file); // This holds old result
  614.   if (to_file == t_file)
  615.     *t_file=t_file2; // Copy result file
  616.   DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
  617. } /* merge_many_buff */
  618. /* Read data to buffer */
  619. /* This returns (uint) -1 if something goes wrong */
  620. static uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
  621.    uint sort_length)
  622. {
  623.   register uint count;
  624.   uint length;
  625.   if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
  626.   {
  627.     if (my_pread(fromfile->file,(byte*) buffpek->base,
  628.  (length= sort_length*count),buffpek->file_pos,MYF_RW))
  629.       return((uint) -1); /* purecov: inspected */
  630.     buffpek->key=buffpek->base;
  631.     buffpek->file_pos+= length; /* New filepos */
  632.     buffpek->count-= count;
  633.     buffpek->mem_count= count;
  634.   }
  635.   return (count*sort_length);
  636. } /* read_to_buffer */
  637. /* Merge buffers to one buffer */
  638. static int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
  639.  IO_CACHE *to_file, uchar **sort_keys,
  640.  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
  641.  int flag)
  642. {
  643.   int error;
  644.   uint sort_length,offset;
  645.   ulong maxcount;
  646.   ha_rows count,max_rows;
  647.   my_off_t to_start_filepos;
  648.   uchar *strpos;
  649.   BUFFPEK *buffpek,**refpek;
  650.   QUEUE queue;
  651.   volatile bool *killed= &current_thd->killed;
  652.   DBUG_ENTER("merge_buffers");
  653.   statistic_increment(filesort_merge_passes, &LOCK_status);
  654.   count=error=0;
  655.   offset=param->sort_length-param->ref_length;
  656.   maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1));
  657.   to_start_filepos=my_b_tell(to_file);
  658.   strpos=(uchar*) sort_keys;
  659.   sort_length=param->sort_length;
  660.   max_rows=param->max_rows;
  661.   if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
  662.  (int (*) (void *, byte *,byte*))
  663.  get_ptr_compare(sort_length),(void*) &sort_length))
  664.     DBUG_RETURN(1); /* purecov: inspected */
  665.   for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
  666.   {
  667.     count+= buffpek->count;
  668.     buffpek->base= strpos;
  669.     buffpek->max_keys=maxcount;
  670.     strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
  671. sort_length));
  672.     if (error == -1)
  673.       goto err; /* purecov: inspected */
  674.     queue_insert(&queue,(byte*) buffpek);
  675.   }
  676.   while (queue.elements > 1)
  677.   {
  678.     if (*killed)
  679.     {
  680.       error=1; goto err; /* purecov: inspected */
  681.     }
  682.     for (;;)
  683.     {
  684.       buffpek=(BUFFPEK*) queue_top(&queue);
  685.       if (flag == 0)
  686.       {
  687. if (my_b_write(to_file,(byte*) buffpek->key, sort_length))
  688. {
  689.   error=1; goto err; /* purecov: inspected */
  690. }
  691.       }
  692.       else
  693.       {
  694. WRITE_REF(to_file,(byte*) buffpek->key+offset);
  695.       }
  696.       if (!--max_rows)
  697.       {
  698. error=0; /* purecov: inspected */
  699. goto end; /* purecov: inspected */
  700.       }
  701.       buffpek->key+=sort_length;
  702.       if (! --buffpek->mem_count)
  703.       {
  704. if (!(error=(int) read_to_buffer(from_file,buffpek,
  705.  sort_length)))
  706. {
  707.   uchar *base=buffpek->base;
  708.   ulong max_keys=buffpek->max_keys;
  709.   VOID(queue_remove(&queue,0));
  710.   /* Put room used by buffer to use in other buffer */
  711.   for (refpek= (BUFFPEK**) &queue_top(&queue);
  712.        refpek <= (BUFFPEK**) &queue_end(&queue);
  713.        refpek++)
  714.   {
  715.     buffpek= *refpek;
  716.     if (buffpek->base+buffpek->max_keys*sort_length == base)
  717.     {
  718.       buffpek->max_keys+=max_keys;
  719.       break;
  720.     }
  721.     else if (base+max_keys*sort_length == buffpek->base)
  722.     {
  723.       buffpek->base=base;
  724.       buffpek->max_keys+=max_keys;
  725.       break;
  726.     }
  727.   }
  728.   break; /* One buffer have been removed */
  729. }
  730. else if (error == -1)
  731.   goto err; /* purecov: inspected */
  732.       }
  733.       queue_replaced(&queue); /* Top element has been replaced */
  734.     }
  735.   }
  736.   buffpek=(BUFFPEK*) queue_top(&queue);
  737.   buffpek->base=(uchar *) sort_keys;
  738.   buffpek->max_keys=param->keys;
  739.   do
  740.   {
  741.     if ((ha_rows) buffpek->mem_count > max_rows)
  742.     { /* Don't write too many records */
  743.       buffpek->mem_count=(uint) max_rows;
  744.       buffpek->count=0; /* Don't read more */
  745.     }
  746.     if (flag == 0)
  747.     {
  748.       if (my_b_write(to_file,(byte*) buffpek->key,
  749.      (sort_length*buffpek->mem_count)))
  750.       {
  751. error=1; goto err; /* purecov: inspected */
  752.       }
  753.     }
  754.     else
  755.     {
  756.       register uchar *end;
  757.       strpos= buffpek->key+offset;
  758.       for (end=strpos+buffpek->mem_count*sort_length;
  759.    strpos != end ;
  760.    strpos+=sort_length)
  761.       {
  762. WRITE_REF(to_file,strpos);
  763.       }
  764.     }
  765.   }
  766.   while ((error=(int) read_to_buffer(from_file,buffpek,sort_length))
  767.  != -1 && error != 0);
  768. end:
  769.   lastbuff->count=min(count,param->max_rows);
  770.   lastbuff->file_pos=to_start_filepos;
  771. err:
  772.   delete_queue(&queue);
  773.   DBUG_RETURN(error);
  774. } /* merge_buffers */
  775. /* Do a merge to output-file (save only positions) */
  776. static int merge_index(SORTPARAM *param, uchar **sort_keys,
  777.        BUFFPEK *buffpek, uint maxbuffer,
  778.        IO_CACHE *tempfile, IO_CACHE *outfile)
  779. {
  780.   DBUG_ENTER("merge_index");
  781.   if (merge_buffers(param,tempfile,outfile,sort_keys,buffpek,buffpek,
  782.     buffpek+maxbuffer,1))
  783.     DBUG_RETURN(1); /* purecov: inspected */
  784.   DBUG_RETURN(0);
  785. } /* merge_index */
  786. /* Calculate length of sort key */
  787. static uint
  788. sortlength(SORT_FIELD *sortorder, uint s_length)
  789. {
  790.   reg2 uint length;
  791.   length=0;
  792.   for (; s_length-- ; sortorder++)
  793.   {
  794.     if (sortorder->field)
  795.     {
  796.       if (sortorder->field->type() == FIELD_TYPE_BLOB)
  797. sortorder->length=max_item_sort_length;
  798.       else
  799.       {
  800. sortorder->length=sortorder->field->pack_length();
  801. #ifdef USE_STRCOLL
  802. if (use_strcoll(default_charset_info) && !sortorder->field->binary())
  803.   sortorder->length= sortorder->length*MY_STRXFRM_MULTIPLY;
  804. #endif
  805.       }
  806.       if (sortorder->field->maybe_null())
  807. length++; // Place for NULL marker
  808.     }
  809.     else
  810.     {
  811.       switch ((sortorder->result_type=sortorder->item->result_type())) {
  812.       case STRING_RESULT:
  813. sortorder->length=sortorder->item->max_length;
  814. #ifdef USE_STRCOLL
  815. if (use_strcoll(default_charset_info) && !sortorder->item->binary)
  816.   sortorder->length= sortorder->length*MY_STRXFRM_MULTIPLY;
  817. #endif
  818. break;
  819.       case INT_RESULT:
  820. #if SIZEOF_LONG_LONG > 4
  821. sortorder->length=8; // Size of intern longlong
  822. #else
  823. sortorder->length=4;
  824. #endif
  825. break;
  826.       case REAL_RESULT:
  827. sortorder->length=sizeof(double);
  828. break;
  829.       }
  830.       if (sortorder->item->maybe_null)
  831. length++; // Place for NULL marker
  832.     }
  833.     set_if_smaller(sortorder->length,max_item_sort_length);
  834.     length+=sortorder->length;
  835.   }
  836.   sortorder->field= (Field*) 0; // end marker
  837.   DBUG_PRINT("info",("sort_length: %d",length));
  838.   return length;
  839. }
  840. /*
  841. ** functions to change a double or float to a sortable string
  842. ** The following should work for IEEE
  843. */
  844. #define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
  845. void change_double_for_sort(double nr,byte *to)
  846. {
  847.   uchar *tmp=(uchar*) to;
  848.   if (nr == 0.0)
  849.   { /* Change to zero string */
  850.     tmp[0]=(uchar) 128;
  851.     bzero((char*) tmp+1,sizeof(nr)-1);
  852.   }
  853.   else
  854.   {
  855. #ifdef WORDS_BIGENDIAN
  856.     memcpy_fixed(tmp,&nr,sizeof(nr));
  857. #else
  858.     {
  859.       uchar *ptr= (uchar*) &nr;
  860. #if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
  861.       tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
  862.       tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
  863. #else
  864.       tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
  865.       tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
  866. #endif
  867.     }
  868. #endif
  869.     if (tmp[0] & 128) /* Negative */
  870.     { /* make complement */
  871.       uint i;
  872.       for (i=0 ; i < sizeof(nr); i++)
  873. tmp[i]=tmp[i] ^ (uchar) 255;
  874.     }
  875.     else
  876.     { /* Set high and move exponent one up */
  877.       ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
  878.        (ushort) 32768);
  879.       exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
  880.       tmp[0]= (uchar) (exp_part >> 8);
  881.       tmp[1]= (uchar) exp_part;
  882.     }
  883.   }
  884. }