~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Nathan Williams
  • Date: 2009-06-25 00:01:26 UTC
  • mto: This revision was merged to the branch mainline in revision 1082.
  • Revision ID: nathanlws@gmail.com-20090625000126-fv99nqpec4edrchc
Converted last usage of cmin to std::min.

Removed cmin and cmax defines from global.h

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB  
 
1
/* Copyright (C) 2000-2006 MySQL AB
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
22
22
*/
23
23
 
24
24
#include <drizzled/server_includes.h>
25
 
#include "sql_sort.h"
26
 
#include <drizzled/drizzled_error_messages.h>
27
 
 
28
 
        /* functions defined in this file */
 
25
#include <drizzled/sql_sort.h>
 
26
#include <drizzled/error.h>
 
27
#include <drizzled/probes.h>
 
28
#include <drizzled/session.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/table_list.h>
 
31
 
 
32
#include <queue>
 
33
#include <algorithm>
 
34
 
 
35
using namespace std;
 
36
 
 
37
/* functions defined in this file */
29
38
 
30
39
static char **make_char_array(char **old_pos, register uint32_t fields,
31
 
                              uint32_t length, myf my_flag);
 
40
                              uint32_t length);
32
41
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
33
42
                                     unsigned char *buf);
34
43
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
42
51
                       BUFFPEK *buffpek,
43
52
                       uint32_t maxbuffer,IO_CACHE *tempfile,
44
53
                       IO_CACHE *outfile);
45
 
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count, 
 
54
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
46
55
                       filesort_info_st *table_sort);
47
56
static uint32_t suffix_length(uint32_t string_length);
48
 
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
 
57
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
49
58
                       bool *multi_byte_charset);
50
 
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
 
59
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
51
60
                                          uint32_t sortlength, uint32_t *plength);
52
61
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
53
62
                                unsigned char *buff);
63
72
  The result set is stored in table->io_cache or
64
73
  table->record_pointers.
65
74
 
66
 
  @param thd           Current thread
 
75
  @param session           Current thread
67
76
  @param table          Table to sort
68
77
  @param sortorder      How to sort the table
69
78
  @param s_length       Number of elements in sortorder
87
96
    examined_rows       will be set to number of examined rows
88
97
*/
89
98
 
90
 
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
 
99
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
91
100
                 SQL_SELECT *select, ha_rows max_rows,
92
101
                 bool sort_positions, ha_rows *examined_rows)
93
102
{
97
106
  BUFFPEK *buffpek;
98
107
  ha_rows records= HA_POS_ERROR;
99
108
  unsigned char **sort_keys= 0;
100
 
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; 
 
109
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
101
110
  SORTPARAM param;
102
111
  bool multi_byte_charset;
103
112
 
111
120
   Release InnoDB's adaptive hash index latch (if holding) before
112
121
   running a sort.
113
122
  */
114
 
  ha_release_temporary_latches(thd);
 
123
  ha_release_temporary_latches(session);
115
124
 
116
 
  /* 
117
 
    Don't use table->sort in filesort as it is also used by 
118
 
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end 
 
125
  /*
 
126
    Don't use table->sort in filesort as it is also used by
 
127
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
119
128
    when index_merge select has finished with it.
120
129
  */
121
130
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
122
131
  table->sort.io_cache= NULL;
123
 
  
 
132
 
124
133
  outfile= table_sort.io_cache;
125
134
  my_b_clear(&tempfile);
126
135
  my_b_clear(&buffpek_pointers);
127
136
  buffpek=0;
128
137
  error= 1;
129
138
  memset(&param, 0, sizeof(param));
130
 
  param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
 
139
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
131
140
  param.ref_length= table->file->ref_length;
132
141
  param.addon_field= 0;
133
142
  param.addon_length= 0;
134
143
  if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
135
144
  {
136
 
    /* 
137
 
      Get the descriptors of all fields whose values are appended 
 
145
    /*
 
146
      Get the descriptors of all fields whose values are appended
138
147
      to sorted fields and get its total length in param.spack_length.
139
148
    */
140
 
    param.addon_field= get_addon_fields(thd, table->field, 
 
149
    param.addon_field= get_addon_fields(session, table->field,
141
150
                                        param.sort_length,
142
151
                                        &param.addon_length);
143
152
  }
149
158
  if (param.addon_field)
150
159
  {
151
160
    param.res_length= param.addon_length;
152
 
    if (!(table_sort.addon_buf= (unsigned char *) my_malloc(param.addon_length,
153
 
                                                    MYF(MY_WME))))
 
161
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
154
162
      goto err;
155
163
  }
156
164
  else
157
165
  {
158
166
    param.res_length= param.ref_length;
159
 
    /* 
160
 
      The reference to the record is considered 
 
167
    /*
 
168
      The reference to the record is considered
161
169
      as an additional sorted field
162
170
    */
163
171
    param.sort_length+= param.ref_length;
167
175
 
168
176
  if (select && select->quick)
169
177
  {
170
 
    status_var_increment(thd->status_var.filesort_range_count);
 
178
    status_var_increment(session->status_var.filesort_range_count);
171
179
  }
172
180
  else
173
181
  {
174
 
    status_var_increment(thd->status_var.filesort_scan_count);
 
182
    status_var_increment(session->status_var.filesort_scan_count);
175
183
  }
176
184
#ifdef CAN_TRUST_RANGE
177
185
  if (select && select->quick && select->quick->records > 0L)
178
186
  {
179
 
    records=cmin((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
180
 
                table->file->stats.records)+EXTRA_RECORDS;
 
187
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
 
188
                 table->file->stats.records)+EXTRA_RECORDS;
181
189
    selected_records_file=0;
182
190
  }
183
191
  else
185
193
  {
186
194
    records= table->file->estimate_rows_upper_bound();
187
195
    /*
188
 
      If number of records is not known, use as much of sort buffer 
189
 
      as possible. 
 
196
      If number of records is not known, use as much of sort buffer
 
197
      as possible.
190
198
    */
191
199
    if (records == HA_POS_ERROR)
192
200
      records--;  // we use 'records+1' below.
194
202
  }
195
203
 
196
204
  if (multi_byte_charset &&
197
 
      !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
 
205
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
198
206
    goto err;
199
207
 
200
 
  memavl= thd->variables.sortbuff_size;
201
 
  min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
 
208
  memavl= session->variables.sortbuff_size;
 
209
  min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
202
210
  while (memavl >= min_sort_memory)
203
211
  {
204
212
    uint32_t old_memavl;
205
213
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
206
 
    param.keys=(uint32_t) cmin(records+1, keys);
 
214
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
207
215
    if ((table_sort.sort_keys=
208
216
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
209
 
                                    param.keys, param.rec_length, MYF(0))))
 
217
                                            param.keys, param.rec_length)))
210
218
      break;
211
 
    old_memavl=memavl;
212
 
    if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
 
219
    old_memavl= memavl;
 
220
    if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
213
221
      memavl= min_sort_memory;
214
222
  }
215
223
  sort_keys= table_sort.sort_keys;
218
226
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
219
227
    goto err;
220
228
  }
221
 
  if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
 
229
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
222
230
                       DISK_BUFFER_SIZE, MYF(MY_WME)))
223
231
    goto err;
224
232
 
253
261
    close_cached_file(&buffpek_pointers);
254
262
        /* Open cached file if it isn't open */
255
263
    if (! my_b_inited(outfile) &&
256
 
        open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
 
264
        open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
257
265
                          MYF(MY_WME)))
258
266
      goto err;
259
267
    if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
312
320
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
313
321
               MYF(ME_ERROR+ME_WAITTANG));
314
322
  else
315
 
    statistic_add(thd->status_var.filesort_rows,
 
323
    statistic_add(session->status_var.filesort_rows,
316
324
                  (uint32_t) records, &LOCK_status);
317
325
  *examined_rows= param.examined_rows;
318
326
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
356
364
/** Make a array of string pointers. */
357
365
 
358
366
static char **make_char_array(char **old_pos, register uint32_t fields,
359
 
                              uint32_t length, myf my_flag)
 
367
                              uint32_t length)
360
368
{
361
369
  register char **pos;
362
370
  char *char_pos;
363
371
 
364
372
  if (old_pos ||
365
 
      (old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
366
 
                                   my_flag)))
 
373
      (old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
367
374
  {
368
375
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
369
376
    while (fields--) *(pos++) = (char_pos+= length);
383
390
  if (count > UINT_MAX/sizeof(BUFFPEK))
384
391
    return 0; /* sizeof(BUFFPEK)*count will overflow */
385
392
  if (!tmp)
386
 
    tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
 
393
    tmp= (unsigned char *)malloc(length);
387
394
  if (tmp)
388
395
  {
389
396
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
444
451
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
445
452
  my_off_t record;
446
453
  Table *sort_form;
447
 
  THD *thd= current_thd;
448
 
  volatile THD::killed_state *killed= &thd->killed;
 
454
  Session *session= current_session;
 
455
  volatile Session::killed_state *killed= &session->killed;
449
456
  handler *file;
450
457
  MY_BITMAP *save_read_set, *save_write_set;
451
458
 
467
474
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
468
475
    file->ha_rnd_init(1);
469
476
    file->extra_opt(HA_EXTRA_CACHE,
470
 
                    current_thd->variables.read_buff_size);
 
477
                    current_session->variables.read_buff_size);
471
478
  }
472
479
 
473
480
  READ_RECORD read_record_info;
475
482
  {
476
483
    if (select->quick->reset())
477
484
      return(HA_POS_ERROR);
478
 
    init_read_record(&read_record_info, current_thd, select->quick->head,
 
485
    init_read_record(&read_record_info, current_session, select->quick->head,
479
486
                     select, 1, 1);
480
487
  }
481
488
 
517
524
      else
518
525
      {
519
526
        error=file->rnd_next(sort_form->record[0]);
 
527
 
520
528
        if (!flag)
521
529
        {
522
530
          my_store_ptr(ref_pos,ref_length,record); // Position to row
554
562
    else
555
563
      file->unlock_row();
556
564
    /* It does not make sense to read more keys in case of a fatal error */
557
 
    if (thd->is_error())
 
565
    if (session->is_error())
558
566
      break;
559
567
  }
560
568
  if (quick_select)
572
580
      file->ha_rnd_end();
573
581
  }
574
582
 
575
 
  if (thd->is_error())
 
583
  if (session->is_error())
576
584
    return(HA_POS_ERROR);
577
 
  
 
585
 
578
586
  /* Signal we should use orignal column read and write maps */
579
587
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
580
588
 
626
634
  rec_length= param->rec_length;
627
635
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
628
636
  if (!my_b_inited(tempfile) &&
629
 
      open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
 
637
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
630
638
                       MYF(MY_WME)))
631
639
    goto err;                                   /* purecov: inspected */
632
640
  /* check we won't have more buffpeks than we can possibly keep in memory */
678
686
{
679
687
  register Field *field;
680
688
  register SORT_FIELD *sort_field;
681
 
  register uint32_t length;
 
689
  size_t length;
682
690
 
683
691
  for (sort_field=param->local_sortorder ;
684
692
       sort_field != param->end ;
790
798
              break;
791
799
            }
792
800
          }
793
 
#if SIZEOF_LONG_LONG > 4
794
801
          to[7]= (unsigned char) value;
795
802
          to[6]= (unsigned char) (value >> 8);
796
803
          to[5]= (unsigned char) (value >> 16);
802
809
            to[0]= (unsigned char) (value >> 56);
803
810
          else
804
811
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
805
 
#else
806
 
          to[3]= (unsigned char) value;
807
 
          to[2]= (unsigned char) (value >> 8);
808
 
          to[1]= (unsigned char) (value >> 16);
809
 
          if (item->unsigned_flag)                    /* Fix sign */
810
 
            to[0]= (unsigned char) (value >> 24);
811
 
          else
812
 
            to[0]= (unsigned char) (value >> 24) ^ 128; /* Reverse signbit */
813
 
#endif
814
812
          break;
815
813
        }
816
814
      case DECIMAL_RESULT:
819
817
          if (maybe_null)
820
818
          {
821
819
            if (item->null_value)
822
 
            { 
 
820
            {
823
821
              memset(to, 0, sort_field->length+1);
824
822
              to++;
825
823
              break;
848
846
          break;
849
847
        }
850
848
      case ROW_RESULT:
851
 
      default: 
 
849
      default:
852
850
        // This case should never be choosen
853
851
        assert(0);
854
852
        break;
871
869
 
872
870
  if (param->addon_field)
873
871
  {
874
 
    /* 
 
872
    /*
875
873
      Save field values appended to sorted fields.
876
874
      First null bit indicators are appended then field values follow.
877
875
      In this implementation we use fixed layout for field values -
923
921
{
924
922
  register SORT_FIELD *sort_field;
925
923
  Table *table=param->sort_form;
926
 
  MY_BITMAP *bitmap= table->read_set;
927
924
 
928
925
  for (sort_field= param->local_sortorder ;
929
926
       sort_field != param->end ;
933
930
    if ((field= sort_field->field))
934
931
    {
935
932
      if (field->table == table)
936
 
      bitmap_set_bit(bitmap, field->field_index);
 
933
        table->setReadSet(field->field_index);
937
934
    }
938
935
    else
939
936
    {                                           // Item
947
944
    SORT_ADDON_FIELD *addonf= param->addon_field;
948
945
    Field *field;
949
946
    for ( ; (field= addonf->field) ; addonf++)
950
 
      bitmap_set_bit(bitmap, field->field_index);
 
947
      table->setReadSet(field->field_index);
951
948
  }
952
949
  else
953
950
  {
957
954
}
958
955
 
959
956
 
960
 
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count, 
 
957
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
961
958
                       filesort_info_st *table_sort)
962
959
{
963
960
  uint32_t offset,res_length;
968
965
  offset= param->rec_length-res_length;
969
966
  if ((ha_rows) count > param->max_rows)
970
967
    count=(uint32_t) param->max_rows;
971
 
  if (!(to= table_sort->record_pointers= 
972
 
        (unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
 
968
  if (!(to= table_sort->record_pointers=
 
969
        (unsigned char*) malloc(res_length*count)))
973
970
    return(1);                 /* purecov: inspected */
974
971
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
975
972
  {
992
989
  if (*maxbuffer < MERGEBUFF2)
993
990
    return(0);                          /* purecov: inspected */
994
991
  if (flush_io_cache(t_file) ||
995
 
      open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
 
992
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
996
993
                        MYF(MY_WME)))
997
994
    return(1);                          /* purecov: inspected */
998
995
 
1040
1037
*/
1041
1038
 
1042
1039
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1043
 
                    uint32_t rec_length)
 
1040
                        uint32_t rec_length)
1044
1041
{
1045
1042
  register uint32_t count;
1046
1043
  uint32_t length;
1047
1044
 
1048
 
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
 
1045
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1049
1046
  {
1050
1047
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1051
1048
      return((uint32_t) -1);                    /* purecov: inspected */
1052
 
    buffpek->key=buffpek->base;
 
1049
 
 
1050
    buffpek->key= buffpek->base;
1053
1051
    buffpek->file_pos+= length;                 /* New filepos */
1054
 
    buffpek->count-=    count;
 
1052
    buffpek->count-= count;
1055
1053
    buffpek->mem_count= count;
1056
1054
  }
1057
1055
  return (count*rec_length);
1058
1056
} /* read_to_buffer */
1059
1057
 
1060
1058
 
1061
 
/**
1062
 
  Put all room used by freed buffer to use in adjacent buffer.
1063
 
 
1064
 
  Note, that we can't simply distribute memory evenly between all buffers,
1065
 
  because new areas must not overlap with old ones.
1066
 
 
1067
 
  @param[in] queue      list of non-empty buffers, without freed buffer
1068
 
  @param[in] reuse      empty buffer
1069
 
  @param[in] key_length key length
1070
 
*/
1071
 
 
1072
 
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
 
1059
class compare_functor
1073
1060
{
1074
 
  unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
 
  for (uint32_t i= 0; i < queue->elements; ++i)
 
1061
  qsort2_cmp key_compare;
 
1062
  void *key_compare_arg;
 
1063
  public:
 
1064
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
 
1065
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
 
1066
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1076
1067
  {
1077
 
    BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1078
 
    if (bp->base + bp->max_keys * key_length == reuse->base)
1079
 
    {
1080
 
      bp->max_keys+= reuse->max_keys;
1081
 
      return;
1082
 
    }
1083
 
    else if (bp->base == reuse_end)
1084
 
    {
1085
 
      bp->base= reuse->base;
1086
 
      bp->max_keys+= reuse->max_keys;
1087
 
      return;
1088
 
    }
 
1068
    int val= key_compare(key_compare_arg,
 
1069
                      &i->key, &j->key);
 
1070
    return (val >= 0);
1089
1071
  }
1090
 
  assert(0);
1091
 
}
 
1072
};
1092
1073
 
1093
1074
 
1094
1075
/**
1122
1103
  my_off_t to_start_filepos;
1123
1104
  unsigned char *strpos;
1124
1105
  BUFFPEK *buffpek;
1125
 
  QUEUE queue;
1126
1106
  qsort2_cmp cmp;
1127
1107
  void *first_cmp_arg;
1128
 
  volatile THD::killed_state *killed= &current_thd->killed;
1129
 
  THD::killed_state not_killable;
 
1108
  volatile Session::killed_state *killed= &current_session->killed;
 
1109
  Session::killed_state not_killable;
1130
1110
 
1131
 
  status_var_increment(current_thd->status_var.filesort_merge_passes);
 
1111
  status_var_increment(current_session->status_var.filesort_merge_passes);
1132
1112
  if (param->not_killable)
1133
1113
  {
1134
1114
    killed= &not_killable;
1135
 
    not_killable= THD::NOT_KILLED;
 
1115
    not_killable= Session::NOT_KILLED;
1136
1116
  }
1137
1117
 
1138
1118
  error=0;
1147
1127
 
1148
1128
  /* The following will fire if there is not enough space in sort_buffer */
1149
1129
  assert(maxcount!=0);
1150
 
  
 
1130
 
1151
1131
  if (param->unique_buff)
1152
1132
  {
1153
1133
    cmp= param->compare;
1158
1138
    cmp= get_ptr_compare(sort_length);
1159
1139
    first_cmp_arg= (void*) &sort_length;
1160
1140
  }
1161
 
  if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1162
 
                 (queue_compare) cmp, first_cmp_arg))
1163
 
    return(1);                                /* purecov: inspected */
 
1141
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
 
1142
    queue(compare_functor(cmp, first_cmp_arg));
1164
1143
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1165
1144
  {
1166
1145
    buffpek->base= strpos;
1170
1149
    if (error == -1)
1171
1150
      goto err;                                 /* purecov: inspected */
1172
1151
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
1173
 
    queue_insert(&queue, (unsigned char*) buffpek);
 
1152
    queue.push(buffpek);
1174
1153
  }
1175
1154
 
1176
1155
  if (param->unique_buff)
1177
1156
  {
1178
 
    /* 
 
1157
    /*
1179
1158
       Called by Unique::get()
1180
1159
       Copy the first argument to param->unique_buff for unique removal.
1181
1160
       Store it also in 'to_file'.
1183
1162
       This is safe as we know that there is always more than one element
1184
1163
       in each block to merge (This is guaranteed by the Unique:: algorithm
1185
1164
    */
1186
 
    buffpek= (BUFFPEK*) queue_top(&queue);
 
1165
    buffpek= queue.top();
1187
1166
    memcpy(param->unique_buff, buffpek->key, rec_length);
1188
1167
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1189
1168
    {
1196
1175
      error= 0;                                       /* purecov: inspected */
1197
1176
      goto end;                                       /* purecov: inspected */
1198
1177
    }
1199
 
    queue_replaced(&queue);                        // Top element has been used
 
1178
    /* Top element has been used */
 
1179
    queue.pop();
 
1180
    queue.push(buffpek);
1200
1181
  }
1201
1182
  else
1202
1183
    cmp= 0;                                        // Not unique
1203
1184
 
1204
 
  while (queue.elements > 1)
 
1185
  while (queue.size() > 1)
1205
1186
  {
1206
1187
    if (*killed)
1207
1188
    {
1209
1190
    }
1210
1191
    for (;;)
1211
1192
    {
1212
 
      buffpek= (BUFFPEK*) queue_top(&queue);
 
1193
      buffpek= queue.top();
1213
1194
      if (cmp)                                        // Remove duplicates
1214
1195
      {
1215
1196
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1244
1225
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1245
1226
                                          rec_length)))
1246
1227
        {
1247
 
          queue_remove(&queue,0);
1248
 
          reuse_freed_buff(&queue, buffpek, rec_length);
 
1228
          queue.pop();
1249
1229
          break;                        /* One buffer have been removed */
1250
1230
        }
1251
1231
        else if (error == -1)
1252
1232
          goto err;                        /* purecov: inspected */
1253
1233
      }
1254
 
      queue_replaced(&queue);              /* Top element has been replaced */
 
1234
      /* Top element has been replaced */
 
1235
      queue.pop();
 
1236
      queue.push(buffpek);
1255
1237
    }
1256
1238
  }
1257
 
  buffpek= (BUFFPEK*) queue_top(&queue);
 
1239
  buffpek= queue.top();
1258
1240
  buffpek->base= sort_buffer;
1259
1241
  buffpek->max_keys= param->keys;
1260
1242
 
1294
1276
      for (end= strpos+buffpek->mem_count*rec_length ;
1295
1277
           strpos != end ;
1296
1278
           strpos+= rec_length)
1297
 
      {     
 
1279
      {
1298
1280
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1299
1281
        {
1300
 
          error=1; goto err;                        
 
1282
          error=1; goto err;
1301
1283
        }
1302
1284
      }
1303
1285
    }
1306
1288
         != -1 && error != 0);
1307
1289
 
1308
1290
end:
1309
 
  lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
 
1291
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1310
1292
  lastbuff->file_pos= to_start_filepos;
1311
1293
err:
1312
 
  delete_queue(&queue);
1313
1294
  return(error);
1314
1295
} /* merge_buffers */
1315
1296
 
1343
1324
/**
1344
1325
  Calculate length of sort key.
1345
1326
 
1346
 
  @param thd                      Thread handler
 
1327
  @param session                          Thread handler
1347
1328
  @param sortorder                Order of items to sort
1348
1329
  @param s_length                 Number of items to sort
1349
1330
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1359
1340
*/
1360
1341
 
1361
1342
static uint32_t
1362
 
sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
 
1343
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
1363
1344
           bool *multi_byte_charset)
1364
1345
{
1365
1346
  register uint32_t length;
1393
1374
      switch (sortorder->result_type) {
1394
1375
      case STRING_RESULT:
1395
1376
        sortorder->length=sortorder->item->max_length;
1396
 
        set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
1377
        set_if_smaller(sortorder->length,
 
1378
                       session->variables.max_sort_length);
1397
1379
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1398
 
        { 
 
1380
        {
1399
1381
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1400
1382
          sortorder->need_strxnfrm= 1;
1401
1383
          *multi_byte_charset= 1;
1408
1390
        }
1409
1391
        break;
1410
1392
      case INT_RESULT:
1411
 
#if SIZEOF_LONG_LONG > 4
1412
1393
        sortorder->length=8;                    // Size of intern int64_t
1413
 
#else
1414
 
        sortorder->length=4;
1415
 
#endif
1416
1394
        break;
1417
1395
      case DECIMAL_RESULT:
1418
1396
        sortorder->length=
1419
 
          my_decimal_get_binary_size(sortorder->item->max_length - 
 
1397
          my_decimal_get_binary_size(sortorder->item->max_length -
1420
1398
                                     (sortorder->item->decimals ? 1 : 0),
1421
1399
                                     sortorder->item->decimals);
1422
1400
        break;
1424
1402
        sortorder->length=sizeof(double);
1425
1403
        break;
1426
1404
      case ROW_RESULT:
1427
 
      default: 
 
1405
      default:
1428
1406
        // This case should never be choosen
1429
1407
        assert(0);
1430
1408
        break;
1432
1410
      if (sortorder->item->maybe_null)
1433
1411
        length++;                               // Place for NULL marker
1434
1412
    }
1435
 
    set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
1413
    set_if_smaller(sortorder->length,
 
1414
                   (size_t)session->variables.max_sort_length);
1436
1415
    length+=sortorder->length;
1437
1416
  }
1438
1417
  sortorder->field= (Field*) 0;                 // end marker
1446
1425
 
1447
1426
  The function first finds out what fields are used in the result set.
1448
1427
  Then it calculates the length of the buffer to store the values of
1449
 
  these fields together with the value of sort values. 
 
1428
  these fields together with the value of sort values.
1450
1429
  If the calculated length is not greater than max_length_for_sort_data
1451
1430
  the function allocates memory for an array of descriptors containing
1452
1431
  layouts for the values of the non-sorted fields in the buffer and
1453
1432
  fills them.
1454
1433
 
1455
 
  @param thd                 Current thread
 
1434
  @param session                 Current thread
1456
1435
  @param ptabfield           Array of references to the table fields
1457
1436
  @param sortlength          Total length of sorted fields
1458
1437
  @param[out] plength        Total length of appended fields
1468
1447
*/
1469
1448
 
1470
1449
static SORT_ADDON_FIELD *
1471
 
get_addon_fields(THD *thd, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
 
1450
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1472
1451
{
1473
1452
  Field **pfield;
1474
1453
  Field *field;
1476
1455
  uint32_t length= 0;
1477
1456
  uint32_t fields= 0;
1478
1457
  uint32_t null_fields= 0;
1479
 
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1480
1458
 
1481
1459
  /*
1482
1460
    If there is a reference to a field in the query add it
1484
1462
    Note for future refinement:
1485
1463
    This this a too strong condition.
1486
1464
    Actually we need only the fields referred in the
1487
 
    result set. And for some of them it makes sense to use 
 
1465
    result set. And for some of them it makes sense to use
1488
1466
    the values directly from sorted fields.
1489
1467
  */
1490
1468
  *plength= 0;
1491
1469
 
1492
1470
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1493
1471
  {
1494
 
    if (!bitmap_is_set(read_set, field->field_index))
 
1472
    if (!(field->isReadSet()))
1495
1473
      continue;
1496
1474
    if (field->flags & BLOB_FLAG)
1497
1475
      return 0;
1499
1477
    if (field->maybe_null())
1500
1478
      null_fields++;
1501
1479
    fields++;
1502
 
  } 
 
1480
  }
1503
1481
  if (!fields)
1504
1482
    return 0;
1505
1483
  length+= (null_fields+7)/8;
1506
1484
 
1507
 
  if (length+sortlength > thd->variables.max_length_for_sort_data ||
1508
 
      !(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)*
1509
 
                                               (fields+1), MYF(MY_WME))))
 
1485
  if (length+sortlength > session->variables.max_length_for_sort_data ||
 
1486
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
 
1487
                                            (fields+1))))
1510
1488
    return 0;
1511
1489
 
1512
1490
  *plength= length;
1514
1492
  null_fields= 0;
1515
1493
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1516
1494
  {
1517
 
    if (!bitmap_is_set(read_set, field->field_index))
 
1495
    if (!(field->isReadSet()))
1518
1496
      continue;
1519
1497
    addonf->field= field;
1520
1498
    addonf->offset= length;
1534
1512
    addonf++;
1535
1513
  }
1536
1514
  addonf->field= 0;     // Put end marker
1537
 
  
 
1515
 
1538
1516
  return (addonf-fields);
1539
1517
}
1540
1518
 
1554
1532
    void.
1555
1533
*/
1556
1534
 
1557
 
static void 
 
1535
static void
1558
1536
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1559
1537
{
1560
1538
  Field *field;