~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

Moved the last of the libdrizzleclient calls into Protocol.

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