~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2008-10-06 04:45:56 UTC
  • mfrom: (438.1.13 drizzle)
  • Revision ID: monty@inaugust.com-20081006044556-5urk8k3yhnnl3o1p
Merged in from trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
        /* functions defined in this file */
29
29
 
30
 
static char **make_char_array(char **old_pos, register uint fields,
31
 
                              uint length, myf my_flag);
32
 
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
 
30
static char **make_char_array(char **old_pos, register uint32_t fields,
 
31
                              uint32_t length, myf my_flag);
 
32
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
33
33
                                     uchar *buf);
34
34
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
35
35
                             uchar * *sort_keys, IO_CACHE *buffer_file,
36
36
                             IO_CACHE *tempfile,IO_CACHE *indexfile);
37
37
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
38
 
                      uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
 
38
                      uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
39
39
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
40
40
static void register_used_fields(SORTPARAM *param);
41
41
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
42
42
                       BUFFPEK *buffpek,
43
 
                       uint maxbuffer,IO_CACHE *tempfile,
 
43
                       uint32_t maxbuffer,IO_CACHE *tempfile,
44
44
                       IO_CACHE *outfile);
45
 
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count, 
 
45
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint32_t count, 
46
46
                       filesort_info_st *table_sort);
47
 
static uint suffix_length(uint32_t string_length);
48
 
static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
 
47
static uint32_t suffix_length(uint32_t string_length);
 
48
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
49
49
                       bool *multi_byte_charset);
50
50
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
51
 
                                          uint sortlength, uint *plength);
 
51
                                          uint32_t sortlength, uint32_t *plength);
52
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
53
53
                                uchar *buff);
54
54
/**
87
87
    examined_rows       will be set to number of examined rows
88
88
*/
89
89
 
90
 
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint s_length,
 
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
91
91
                 SQL_SELECT *select, ha_rows max_rows,
92
92
                 bool sort_positions, ha_rows *examined_rows)
93
93
{
94
94
  int error;
95
95
  uint32_t memavl, min_sort_memory;
96
 
  uint maxbuffer;
 
96
  uint32_t maxbuffer;
97
97
  BUFFPEK *buffpek;
98
98
  ha_rows records= HA_POS_ERROR;
99
99
  uchar **sort_keys= 0;
198
198
    goto err;
199
199
 
200
200
  memavl= thd->variables.sortbuff_size;
201
 
  min_sort_memory= cmax((uint)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
 
201
  min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
202
202
  while (memavl >= min_sort_memory)
203
203
  {
204
204
    uint32_t old_memavl;
205
205
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
206
 
    param.keys=(uint) cmin(records+1, keys);
 
206
    param.keys=(uint32_t) cmin(records+1, keys);
207
207
    if ((table_sort.sort_keys=
208
208
         (uchar **) make_char_array((char **) table_sort.sort_keys,
209
209
                                    param.keys, param.rec_length, MYF(0))))
229
229
                             &tempfile, selected_records_file)) ==
230
230
      HA_POS_ERROR)
231
231
    goto err;
232
 
  maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
 
232
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
233
233
 
234
234
  if (maxbuffer == 0)                   // The whole set is in memory
235
235
  {
236
 
    if (save_index(&param,sort_keys,(uint) records, &table_sort))
 
236
    if (save_index(&param,sort_keys,(uint32_t) records, &table_sort))
237
237
      goto err;
238
238
  }
239
239
  else
355
355
 
356
356
/** Make a array of string pointers. */
357
357
 
358
 
static char **make_char_array(char **old_pos, register uint fields,
359
 
                              uint length, myf my_flag)
 
358
static char **make_char_array(char **old_pos, register uint32_t fields,
 
359
                              uint32_t length, myf my_flag)
360
360
{
361
361
  register char **pos;
362
362
  char *char_pos;
363
363
 
364
364
  if (old_pos ||
365
 
      (old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
 
365
      (old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
366
366
                                   my_flag)))
367
367
  {
368
368
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
375
375
 
376
376
/** Read 'count' number of buffer pointers into memory. */
377
377
 
378
 
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
 
378
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
379
379
                                     uchar *buf)
380
380
{
381
381
  uint32_t length= sizeof(BUFFPEK)*count;
440
440
                             IO_CACHE *tempfile, IO_CACHE *indexfile)
441
441
{
442
442
  int error,flag,quick_select;
443
 
  uint idx,indexpos,ref_length;
 
443
  uint32_t idx,indexpos,ref_length;
444
444
  uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
445
445
  my_off_t record;
446
446
  Table *sort_form;
615
615
*/
616
616
 
617
617
static int
618
 
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
 
618
write_keys(SORTPARAM *param, register uchar **sort_keys, uint32_t count,
619
619
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
620
620
{
621
621
  size_t sort_length, rec_length;
624
624
 
625
625
  sort_length= param->sort_length;
626
626
  rec_length= param->rec_length;
627
 
  my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
 
627
  my_string_ptr_sort((uchar*) sort_keys, (uint32_t) count, sort_length);
628
628
  if (!my_b_inited(tempfile) &&
629
629
      open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
630
630
                       MYF(MY_WME)))
634
634
    goto err;
635
635
  buffpek.file_pos= my_b_tell(tempfile);
636
636
  if ((ha_rows) count > param->max_rows)
637
 
    count=(uint) param->max_rows;               /* purecov: inspected */
 
637
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
638
638
  buffpek.count=(ha_rows) count;
639
639
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
640
 
    if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
 
640
    if (my_b_write(tempfile, (uchar*) *sort_keys, (uint32_t) rec_length))
641
641
      goto err;
642
642
  if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
643
643
    goto err;
652
652
  Store length as suffix in high-byte-first order.
653
653
*/
654
654
 
655
 
static inline void store_length(uchar *to, uint length, uint pack_length)
 
655
static inline void store_length(uchar *to, uint32_t length, uint32_t pack_length)
656
656
{
657
657
  switch (pack_length) {
658
658
  case 1:
678
678
{
679
679
  register Field *field;
680
680
  register SORT_FIELD *sort_field;
681
 
  register uint length;
 
681
  register uint32_t length;
682
682
 
683
683
  for (sort_field=param->local_sortorder ;
684
684
       sort_field != param->end ;
713
713
        const CHARSET_INFO * const cs=item->collation.collation;
714
714
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
715
715
        int diff;
716
 
        uint sort_field_length;
 
716
        uint32_t sort_field_length;
717
717
 
718
718
        if (maybe_null)
719
719
          *to++=1;
755
755
        if (sort_field->need_strxnfrm)
756
756
        {
757
757
          char *from=(char*) res->ptr();
758
 
          uint tmp_length;
 
758
          uint32_t tmp_length;
759
759
          if ((uchar*) from == to)
760
760
          {
761
761
            set_if_smaller(length,sort_field->length);
895
895
      {
896
896
#ifdef HAVE_purify
897
897
        uchar *end= field->pack(to, field->ptr);
898
 
        uint length= (uint) ((to + addonf->length) - end);
 
898
        uint32_t length= (uint32_t) ((to + addonf->length) - end);
899
899
        assert((int) length >= 0);
900
900
        if (length)
901
901
          memset(end, 0, length);
957
957
}
958
958
 
959
959
 
960
 
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, 
 
960
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint32_t count, 
961
961
                       filesort_info_st *table_sort)
962
962
{
963
 
  uint offset,res_length;
 
963
  uint32_t offset,res_length;
964
964
  uchar *to;
965
965
 
966
 
  my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
 
966
  my_string_ptr_sort((uchar*) sort_keys, (uint32_t) count, param->sort_length);
967
967
  res_length= param->res_length;
968
968
  offset= param->rec_length-res_length;
969
969
  if ((ha_rows) count > param->max_rows)
970
 
    count=(uint) param->max_rows;
 
970
    count=(uint32_t) param->max_rows;
971
971
  if (!(to= table_sort->record_pointers= 
972
972
        (uchar*) my_malloc(res_length*count, MYF(MY_WME))))
973
973
    return(1);                 /* purecov: inspected */
983
983
/** Merge buffers to make < MERGEBUFF2 buffers. */
984
984
 
985
985
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
986
 
                    BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
 
986
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
987
987
{
988
 
  register uint i;
 
988
  register uint32_t i;
989
989
  IO_CACHE t_file2,*from_file,*to_file,*temp;
990
990
  BUFFPEK *lastbuff;
991
991
 
1018
1018
    temp=from_file; from_file=to_file; to_file=temp;
1019
1019
    setup_io_cache(from_file);
1020
1020
    setup_io_cache(to_file);
1021
 
    *maxbuffer= (uint) (lastbuff-buffpek)-1;
 
1021
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1022
1022
  }
1023
1023
cleanup:
1024
1024
  close_cached_file(to_file);                   // This holds old result
1036
1036
  Read data to buffer.
1037
1037
 
1038
1038
  @retval
1039
 
    (uint)-1 if something goes wrong
 
1039
    (uint32_t)-1 if something goes wrong
1040
1040
*/
1041
1041
 
1042
 
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1043
 
                    uint rec_length)
 
1042
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1043
                    uint32_t rec_length)
1044
1044
{
1045
 
  register uint count;
1046
 
  uint length;
 
1045
  register uint32_t count;
 
1046
  uint32_t length;
1047
1047
 
1048
 
  if ((count=(uint) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
 
1048
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1049
1049
  {
1050
1050
    if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1051
 
      return((uint) -1);                        /* purecov: inspected */
 
1051
      return((uint32_t) -1);                    /* purecov: inspected */
1052
1052
    buffpek->key=buffpek->base;
1053
1053
    buffpek->file_pos+= length;                 /* New filepos */
1054
1054
    buffpek->count-=    count;
1069
1069
  @param[in] key_length key length
1070
1070
*/
1071
1071
 
1072
 
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
 
1072
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1073
1073
{
1074
1074
  uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
 
  for (uint i= 0; i < queue->elements; ++i)
 
1075
  for (uint32_t i= 0; i < queue->elements; ++i)
1076
1076
  {
1077
1077
    BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1078
1078
    if (bp->base + bp->max_keys * key_length == reuse->base)
1115
1115
                  int flag)
1116
1116
{
1117
1117
  int error;
1118
 
  uint rec_length,res_length,offset;
 
1118
  uint32_t rec_length,res_length,offset;
1119
1119
  size_t sort_length;
1120
1120
  uint32_t maxcount;
1121
1121
  ha_rows max_rows,org_max_rows;
1140
1140
  res_length= param->res_length;
1141
1141
  sort_length= param->sort_length;
1142
1142
  offset= rec_length-res_length;
1143
 
  maxcount= (uint32_t) (param->keys/((uint) (Tb-Fb) +1));
 
1143
  maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1144
1144
  to_start_filepos= my_b_tell(to_file);
1145
1145
  strpos= (uchar*) sort_buffer;
1146
1146
  org_max_rows=max_rows= param->max_rows;
1158
1158
    cmp= get_ptr_compare(sort_length);
1159
1159
    first_cmp_arg= (void*) &sort_length;
1160
1160
  }
1161
 
  if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
 
1161
  if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1162
1162
                 (queue_compare) cmp, first_cmp_arg))
1163
1163
    return(1);                                /* purecov: inspected */
1164
1164
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1165
1165
  {
1166
1166
    buffpek->base= strpos;
1167
1167
    buffpek->max_keys= maxcount;
1168
 
    strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
 
1168
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1169
1169
                                                                         rec_length));
1170
1170
    if (error == -1)
1171
1171
      goto err;                                 /* purecov: inspected */
1275
1275
  {
1276
1276
    if ((ha_rows) buffpek->mem_count > max_rows)
1277
1277
    {                                        /* Don't write too many records */
1278
 
      buffpek->mem_count= (uint) max_rows;
 
1278
      buffpek->mem_count= (uint32_t) max_rows;
1279
1279
      buffpek->count= 0;                        /* Don't read more */
1280
1280
    }
1281
1281
    max_rows-= buffpek->mem_count;
1317
1317
        /* Do a merge to output-file (save only positions) */
1318
1318
 
1319
1319
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1320
 
                       BUFFPEK *buffpek, uint maxbuffer,
 
1320
                       BUFFPEK *buffpek, uint32_t maxbuffer,
1321
1321
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1322
1322
{
1323
1323
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1327
1327
} /* merge_index */
1328
1328
 
1329
1329
 
1330
 
static uint suffix_length(uint32_t string_length)
 
1330
static uint32_t suffix_length(uint32_t string_length)
1331
1331
{
1332
1332
  if (string_length < 256)
1333
1333
    return 1;
1358
1358
    Total length of sort buffer in bytes
1359
1359
*/
1360
1360
 
1361
 
static uint
1362
 
sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
 
1361
static uint32_t
 
1362
sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
1363
1363
           bool *multi_byte_charset)
1364
1364
{
1365
 
  register uint length;
 
1365
  register uint32_t length;
1366
1366
  const CHARSET_INFO *cs;
1367
1367
  *multi_byte_charset= 0;
1368
1368
 
1468
1468
*/
1469
1469
 
1470
1470
static SORT_ADDON_FIELD *
1471
 
get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength)
 
1471
get_addon_fields(THD *thd, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1472
1472
{
1473
1473
  Field **pfield;
1474
1474
  Field *field;
1475
1475
  SORT_ADDON_FIELD *addonf;
1476
 
  uint length= 0;
1477
 
  uint fields= 0;
1478
 
  uint null_fields= 0;
 
1476
  uint32_t length= 0;
 
1477
  uint32_t fields= 0;
 
1478
  uint32_t null_fields= 0;
1479
1479
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1480
1480
 
1481
1481
  /*
1605
1605
#endif
1606
1606
    if (tmp[0] & 128)                           /* Negative */
1607
1607
    {                                           /* make complement */
1608
 
      uint i;
 
1608
      uint32_t i;
1609
1609
      for (i=0 ; i < sizeof(nr); i++)
1610
1610
        tmp[i]=tmp[i] ^ (uchar) 255;
1611
1611
    }
1612
1612
    else
1613
1613
    {                                   /* Set high and move exponent one up */
1614
 
      ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
1615
 
                       (ushort) 32768);
1616
 
      exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
 
1614
      uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
 
1615
                       (uint16_t) 32768);
 
1616
      exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
1617
1617
      tmp[0]= (uchar) (exp_part >> 8);
1618
1618
      tmp[1]= (uchar) exp_part;
1619
1619
    }