~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

Merge Joe, plus I updated the tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
 
17
17
/**
28
28
 
29
29
#include <queue>
30
30
#include <algorithm>
31
 
#include <iostream>
32
31
 
33
 
#include "drizzled/drizzled.h"
34
32
#include "drizzled/sql_sort.h"
35
 
#include "drizzled/filesort.h"
36
33
#include "drizzled/error.h"
37
34
#include "drizzled/probes.h"
38
35
#include "drizzled/session.h"
44
41
#include "drizzled/internal/my_sys.h"
45
42
#include "plugin/myisam/myisam.h"
46
43
#include "drizzled/plugin/transactional_storage_engine.h"
47
 
#include "drizzled/atomics.h"
48
 
#include "drizzled/global_buffer.h"
49
 
 
50
44
 
51
45
using namespace std;
52
46
 
53
47
namespace drizzled
54
48
{
55
49
 
56
 
/* Defines used by filesort and uniques */
57
 
#define MERGEBUFF               7
58
 
#define MERGEBUFF2              15
59
 
 
60
 
class BufferCompareContext
61
 
{
62
 
public:
63
 
  qsort_cmp2 key_compare;
64
 
  void *key_compare_arg;
65
 
 
66
 
  BufferCompareContext() :
67
 
    key_compare(0),
68
 
    key_compare_arg(0)
69
 
  { }
70
 
 
71
 
};
72
 
 
73
 
class SortParam {
74
 
public:
75
 
  uint32_t rec_length;          /* Length of sorted records */
76
 
  uint32_t sort_length;                 /* Length of sorted columns */
77
 
  uint32_t ref_length;                  /* Length of record ref. */
78
 
  uint32_t addon_length;        /* Length of added packed fields */
79
 
  uint32_t res_length;          /* Length of records in final sorted file/buffer */
80
 
  uint32_t keys;                                /* Max keys / buffer */
81
 
  ha_rows max_rows,examined_rows;
82
 
  Table *sort_form;                     /* For quicker make_sortkey */
83
 
  SortField *local_sortorder;
84
 
  SortField *end;
85
 
  sort_addon_field *addon_field; /* Descriptors for companion fields */
86
 
  unsigned char *unique_buff;
87
 
  bool not_killable;
88
 
  char *tmp_buffer;
89
 
  /* The fields below are used only by Unique class */
90
 
  qsort2_cmp compare;
91
 
  BufferCompareContext cmp_context;
92
 
 
93
 
  SortParam() :
94
 
    rec_length(0),
95
 
    sort_length(0),
96
 
    ref_length(0),
97
 
    addon_length(0),
98
 
    res_length(0),
99
 
    keys(0),
100
 
    max_rows(0),
101
 
    examined_rows(0),
102
 
    sort_form(0),
103
 
    local_sortorder(0),
104
 
    end(0),
105
 
    addon_field(0),
106
 
    unique_buff(0),
107
 
    not_killable(0),
108
 
    tmp_buffer(0),
109
 
    compare(0)
110
 
  {
111
 
  }
112
 
 
113
 
  ~SortParam()
114
 
  {
115
 
    if (tmp_buffer)
116
 
      free(tmp_buffer);
117
 
  }
118
 
 
119
 
  int write_keys(unsigned char * *sort_keys,
120
 
                 uint32_t count,
121
 
                 internal::IO_CACHE *buffer_file,
122
 
                 internal::IO_CACHE *tempfile);
123
 
 
124
 
  void make_sortkey(unsigned char *to,
125
 
                    unsigned char *ref_pos);
126
 
  void register_used_fields();
127
 
  bool save_index(unsigned char **sort_keys,
128
 
                  uint32_t count,
129
 
                  filesort_info *table_sort);
130
 
 
131
 
};
132
 
 
133
50
/* functions defined in this file */
134
51
 
135
52
static char **make_char_array(char **old_pos, register uint32_t fields,
139
56
                                             uint32_t count,
140
57
                                             unsigned char *buf);
141
58
 
 
59
static ha_rows find_all_keys(Session *session,
 
60
                             SORTPARAM *param,
 
61
                             optimizer::SqlSelect *select,
 
62
                             unsigned char * *sort_keys, 
 
63
                             internal::IO_CACHE *buffer_file,
 
64
                             internal::IO_CACHE *tempfile,
 
65
                             internal::IO_CACHE *indexfile);
 
66
 
 
67
static int write_keys(SORTPARAM *param,
 
68
                      unsigned char * *sort_keys,
 
69
                      uint32_t count,
 
70
                      internal::IO_CACHE *buffer_file,
 
71
                      internal::IO_CACHE *tempfile);
 
72
 
 
73
static void make_sortkey(SORTPARAM *param,
 
74
                         unsigned char *to,
 
75
                         unsigned char *ref_pos);
 
76
static void register_used_fields(SORTPARAM *param);
 
77
static int merge_index(SORTPARAM *param,
 
78
                       unsigned char *sort_buffer,
 
79
                       BUFFPEK *buffpek,
 
80
                       uint32_t maxbuffer,
 
81
                       internal::IO_CACHE *tempfile,
 
82
                       internal::IO_CACHE *outfile);
 
83
static bool save_index(SORTPARAM *param,
 
84
                       unsigned char **sort_keys,
 
85
                       uint32_t count,
 
86
                       filesort_info_st *table_sort);
142
87
static uint32_t suffix_length(uint32_t string_length);
143
 
static void unpack_addon_fields(sort_addon_field *addon_field,
 
88
static uint32_t sortlength(Session *session,
 
89
                           SORT_FIELD *sortorder,
 
90
                           uint32_t s_length,
 
91
                           bool *multi_byte_charset);
 
92
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
 
93
                                          Field **ptabfield,
 
94
                                          uint32_t sortlength,
 
95
                                          uint32_t *plength);
 
96
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
144
97
                                unsigned char *buff);
145
 
 
146
 
FileSort::FileSort(Session &arg) :
147
 
  _session(arg)
148
 
149
 
}
150
 
 
151
98
/**
152
99
  Sort a table.
153
100
  Creates a set of pointers that can be used to read the rows
160
107
  The result set is stored in table->io_cache or
161
108
  table->record_pointers.
162
109
 
 
110
  @param session           Current thread
163
111
  @param table          Table to sort
164
112
  @param sortorder      How to sort the table
165
113
  @param s_length       Number of elements in sortorder
183
131
    examined_rows       will be set to number of examined rows
184
132
*/
185
133
 
186
 
ha_rows FileSort::run(Table *table, SortField *sortorder, uint32_t s_length,
187
 
                      optimizer::SqlSelect *select, ha_rows max_rows,
188
 
                      bool sort_positions, ha_rows &examined_rows)
 
134
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
 
135
                 optimizer::SqlSelect *select, ha_rows max_rows,
 
136
                 bool sort_positions, ha_rows *examined_rows)
189
137
{
190
 
  int error= 1;
191
 
  uint32_t memavl= 0, min_sort_memory;
 
138
  int error;
 
139
  uint32_t memavl, min_sort_memory;
192
140
  uint32_t maxbuffer;
193
 
  size_t allocated_sort_memory= 0;
194
 
  buffpek *buffpek_inst= 0;
 
141
  BUFFPEK *buffpek;
195
142
  ha_rows records= HA_POS_ERROR;
196
143
  unsigned char **sort_keys= 0;
197
 
  internal::IO_CACHE tempfile;
198
 
  internal::IO_CACHE buffpek_pointers;
199
 
  internal::IO_CACHE *selected_records_file;
200
 
  internal::IO_CACHE *outfile;
201
 
  SortParam param;
 
144
  internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
 
145
  SORTPARAM param;
202
146
  bool multi_byte_charset;
203
147
 
204
 
  /*
205
 
    Don't use table->sort in filesort as it is also used by
206
 
    QuickIndexMergeSelect. Work with a copy and put it back at the end
207
 
    when index_merge select has finished with it.
208
 
  */
209
 
  filesort_info table_sort(table->sort);
210
 
  table->sort.io_cache= NULL;
211
 
 
 
148
  filesort_info_st table_sort;
212
149
  TableList *tab= table->pos_in_table_list;
213
150
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
214
151
 
218
155
   Release InnoDB's adaptive hash index latch (if holding) before
219
156
   running a sort.
220
157
  */
221
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
 
158
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
222
159
 
 
160
  /*
 
161
    Don't use table->sort in filesort as it is also used by
 
162
    QuickIndexMergeSelect. Work with a copy and put it back at the end
 
163
    when index_merge select has finished with it.
 
164
  */
 
165
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
 
166
  table->sort.io_cache= NULL;
223
167
 
224
168
  outfile= table_sort.io_cache;
225
 
  assert(tempfile.buffer == 0);
226
 
  assert(buffpek_pointers.buffer == 0);
227
 
 
228
 
  param.sort_length= sortlength(sortorder, s_length, &multi_byte_charset);
 
169
  my_b_clear(&tempfile);
 
170
  my_b_clear(&buffpek_pointers);
 
171
  buffpek=0;
 
172
  error= 1;
 
173
  memset(&param, 0, sizeof(param));
 
174
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
229
175
  param.ref_length= table->cursor->ref_length;
230
 
 
 
176
  param.addon_field= 0;
 
177
  param.addon_length= 0;
231
178
  if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
232
179
  {
233
180
    /*
234
181
      Get the descriptors of all fields whose values are appended
235
182
      to sorted fields and get its total length in param.spack_length.
236
183
    */
237
 
    param.addon_field= get_addon_fields(table->getFields(),
 
184
    param.addon_field= get_addon_fields(session, table->getFields(),
238
185
                                        param.sort_length,
239
186
                                        &param.addon_length);
240
187
  }
247
194
  {
248
195
    param.res_length= param.addon_length;
249
196
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
250
 
    {
251
197
      goto err;
252
 
    }
253
198
  }
254
199
  else
255
200
  {
265
210
 
266
211
  if (select && select->quick)
267
212
  {
268
 
    getSession().status_var.filesort_range_count++;
 
213
    status_var_increment(session->status_var.filesort_range_count);
269
214
  }
270
215
  else
271
216
  {
272
 
    getSession().status_var.filesort_scan_count++;
 
217
    status_var_increment(session->status_var.filesort_scan_count);
273
218
  }
274
219
#ifdef CAN_TRUST_RANGE
275
220
  if (select && select->quick && select->quick->records > 0L)
291
236
    selected_records_file= 0;
292
237
  }
293
238
 
294
 
  if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
295
 
  {
 
239
  if (multi_byte_charset &&
 
240
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
296
241
    goto err;
297
 
  }
298
242
 
299
 
  memavl= getSession().variables.sortbuff_size;
 
243
  memavl= session->variables.sortbuff_size;
300
244
  min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
245
  while (memavl >= min_sort_memory)
302
246
  {
303
247
    uint32_t old_memavl;
304
248
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
249
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
306
 
 
307
 
    allocated_sort_memory= param.keys * param.rec_length;
308
 
    if (not global_sort_buffer.add(allocated_sort_memory))
309
 
    {
310
 
      my_error(ER_OUT_OF_GLOBAL_SORTMEMORY, MYF(ME_ERROR+ME_WAITTANG));
311
 
      goto err;
312
 
    }
313
 
 
314
250
    if ((table_sort.sort_keys=
315
251
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
252
                                            param.keys, param.rec_length)))
317
253
      break;
318
 
 
319
 
    global_sort_buffer.sub(allocated_sort_memory);
320
254
    old_memavl= memavl;
321
255
    if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
256
      memavl= min_sort_memory;
327
261
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
328
262
    goto err;
329
263
  }
330
 
 
331
 
  if (buffpek_pointers.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
332
 
  {
 
264
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
 
265
                       DISK_BUFFER_SIZE, MYF(MY_WME)))
333
266
    goto err;
334
 
  }
335
267
 
336
268
  param.keys--;                         /* TODO: check why we do this */
337
269
  param.sort_form= table;
338
270
  param.end=(param.local_sortorder=sortorder)+s_length;
339
 
  if ((records= find_all_keys(&param,select,sort_keys, &buffpek_pointers,
340
 
                              &tempfile, selected_records_file)) == HA_POS_ERROR)
341
 
  {
 
271
  if ((records=find_all_keys(session, &param,select,sort_keys, &buffpek_pointers,
 
272
                             &tempfile, selected_records_file)) ==
 
273
      HA_POS_ERROR)
342
274
    goto err;
343
 
  }
344
 
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
 
275
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
345
276
 
346
277
  if (maxbuffer == 0)                   // The whole set is in memory
347
278
  {
348
 
    if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
349
 
    {
 
279
    if (save_index(&param,sort_keys,(uint32_t) records, &table_sort))
350
280
      goto err;
351
 
    }
352
281
  }
353
282
  else
354
283
  {
356
285
    {
357
286
      if (table_sort.buffpek)
358
287
        free(table_sort.buffpek);
359
 
      table_sort.buffpek = 0;
 
288
      table_sort.buffpek= 0;
360
289
    }
361
290
    if (!(table_sort.buffpek=
362
 
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
363
 
    {
 
291
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
 
292
                                 table_sort.buffpek)))
364
293
      goto err;
365
 
    }
366
 
    buffpek_inst= (buffpek *) table_sort.buffpek;
 
294
    buffpek= (BUFFPEK *) table_sort.buffpek;
367
295
    table_sort.buffpek_len= maxbuffer;
368
 
    buffpek_pointers.close_cached_file();
 
296
    close_cached_file(&buffpek_pointers);
369
297
        /* Open cached file if it isn't open */
370
 
    if (! my_b_inited(outfile) && outfile->open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME)))
371
 
    {
372
 
      goto err;
373
 
    }
374
 
 
375
 
    if (outfile->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
376
 
    {
377
 
      goto err;
378
 
    }
 
298
    if (! my_b_inited(outfile) &&
 
299
        open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
 
300
                          MYF(MY_WME)))
 
301
      goto err;
 
302
    if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
 
303
      goto err;
379
304
 
380
305
    /*
381
306
      Use also the space previously used by string pointers in sort_buffer
382
307
      for temporary key storage.
383
308
    */
384
 
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
385
 
 
 
309
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
 
310
                param.rec_length-1);
386
311
    maxbuffer--;                                // Offset from 0
387
 
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
388
 
    {
389
 
      goto err;
390
 
    }
391
 
 
392
 
    if (flush_io_cache(&tempfile) || tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
393
 
    {
394
 
      goto err;
395
 
    }
396
 
 
397
 
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek_inst,maxbuffer,&tempfile, outfile))
398
 
    {
399
 
      goto err;
400
 
    }
 
312
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek,&maxbuffer,
 
313
                        &tempfile))
 
314
      goto err;
 
315
    if (flush_io_cache(&tempfile) ||
 
316
        reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
 
317
      goto err;
 
318
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
 
319
                    outfile))
 
320
      goto err;
401
321
  }
402
 
 
403
322
  if (records > param.max_rows)
404
 
  {
405
 
    records= param.max_rows;
406
 
  }
 
323
    records=param.max_rows;
407
324
  error =0;
408
325
 
409
326
 err:
410
 
  if (not subselect || not subselect->is_uncacheable())
 
327
  if (param.tmp_buffer)
 
328
    if (param.tmp_buffer)
 
329
      free(param.tmp_buffer);
 
330
  if (!subselect || !subselect->is_uncacheable())
411
331
  {
412
332
    free(sort_keys);
413
333
    table_sort.sort_keys= 0;
414
 
    free(buffpek_inst);
 
334
    free(buffpek);
415
335
    table_sort.buffpek= 0;
416
336
    table_sort.buffpek_len= 0;
417
337
  }
418
 
 
419
 
  tempfile.close_cached_file();
420
 
  buffpek_pointers.close_cached_file();
421
 
 
 
338
  close_cached_file(&tempfile);
 
339
  close_cached_file(&buffpek_pointers);
422
340
  if (my_b_inited(outfile))
423
341
  {
424
342
    if (flush_io_cache(outfile))
425
 
    {
426
343
      error=1;
427
 
    }
428
344
    {
429
 
      internal::my_off_t save_pos= outfile->pos_in_file;
 
345
      internal::my_off_t save_pos=outfile->pos_in_file;
430
346
      /* For following reads */
431
 
      if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
432
 
      {
 
347
      if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
433
348
        error=1;
434
 
      }
435
349
      outfile->end_of_file=save_pos;
436
350
    }
437
351
  }
438
 
 
439
352
  if (error)
440
 
  {
441
353
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
354
               MYF(ME_ERROR+ME_WAITTANG));
443
 
  }
444
355
  else
445
 
  {
446
 
    getSession().status_var.filesort_rows+= (uint32_t) records;
447
 
  }
448
 
  examined_rows= param.examined_rows;
449
 
  global_sort_buffer.sub(allocated_sort_memory);
450
 
  table->sort= table_sort;
 
356
    statistic_add(session->status_var.filesort_rows,
 
357
                  (uint32_t) records, &LOCK_status);
 
358
  *examined_rows= param.examined_rows;
 
359
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
451
360
  DRIZZLE_FILESORT_DONE(error, records);
452
361
  return (error ? HA_POS_ERROR : records);
453
362
} /* filesort */
454
363
 
 
364
 
 
365
void Table::filesort_free_buffers(bool full)
 
366
{
 
367
  if (sort.record_pointers)
 
368
  {
 
369
    free((unsigned char*) sort.record_pointers);
 
370
    sort.record_pointers=0;
 
371
  }
 
372
  if (full)
 
373
  {
 
374
    if (sort.sort_keys )
 
375
    {
 
376
      if ((unsigned char*) sort.sort_keys)
 
377
        free((unsigned char*) sort.sort_keys);
 
378
      sort.sort_keys= 0;
 
379
    }
 
380
    if (sort.buffpek)
 
381
    {
 
382
      if ((unsigned char*) sort.buffpek)
 
383
        free((unsigned char*) sort.buffpek);
 
384
      sort.buffpek= 0;
 
385
      sort.buffpek_len= 0;
 
386
    }
 
387
  }
 
388
  if (sort.addon_buf)
 
389
  {
 
390
    free((char *) sort.addon_buf);
 
391
    free((char *) sort.addon_field);
 
392
    sort.addon_buf=0;
 
393
    sort.addon_field=0;
 
394
  }
 
395
}
 
396
 
455
397
/** Make a array of string pointers. */
456
398
 
457
399
static char **make_char_array(char **old_pos, register uint32_t fields,
476
418
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
477
419
                                     unsigned char *buf)
478
420
{
479
 
  uint32_t length= sizeof(buffpek)*count;
 
421
  uint32_t length= sizeof(BUFFPEK)*count;
480
422
  unsigned char *tmp= buf;
481
 
  if (count > UINT_MAX/sizeof(buffpek))
482
 
    return 0; /* sizeof(buffpek)*count will overflow */
 
423
  if (count > UINT_MAX/sizeof(BUFFPEK))
 
424
    return 0; /* sizeof(BUFFPEK)*count will overflow */
483
425
  if (!tmp)
484
426
    tmp= (unsigned char *)malloc(length);
485
427
  if (tmp)
486
428
  {
487
 
    if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
 
429
    if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
488
430
        my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
489
431
    {
490
432
      free((char*) tmp);
502
444
  @param param             Sorting parameter
503
445
  @param select            Use this to get source data
504
446
  @param sort_keys         Array of pointers to sort key + addon buffers.
505
 
  @param buffpek_pointers  File to write buffpeks describing sorted segments
 
447
  @param buffpek_pointers  File to write BUFFPEKs describing sorted segments
506
448
                           in tempfile.
507
449
  @param tempfile          File to write sorted sequences of sortkeys to.
508
450
  @param indexfile         If !NULL, use it for source data (contains rowids)
516
458
       {
517
459
         sort sort_keys buffer;
518
460
         dump sorted sequence to 'tempfile';
519
 
         dump buffpek describing sequence location into 'buffpek_pointers';
 
461
         dump BUFFPEK describing sequence location into 'buffpek_pointers';
520
462
       }
521
463
       put sort key into 'sort_keys';
522
464
     }
532
474
    HA_POS_ERROR on error.
533
475
*/
534
476
 
535
 
ha_rows FileSort::find_all_keys(SortParam *param, 
536
 
                                optimizer::SqlSelect *select,
537
 
                                unsigned char **sort_keys,
538
 
                                internal::IO_CACHE *buffpek_pointers,
539
 
                                internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
 
477
static ha_rows find_all_keys(Session *session,
 
478
                             SORTPARAM *param, 
 
479
                             optimizer::SqlSelect *select,
 
480
                             unsigned char **sort_keys,
 
481
                             internal::IO_CACHE *buffpek_pointers,
 
482
                             internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
540
483
{
541
484
  int error,flag,quick_select;
542
485
  uint32_t idx,indexpos,ref_length;
543
486
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
487
  internal::my_off_t record;
545
488
  Table *sort_form;
546
 
  volatile Session::killed_state_t *killed= getSession().getKilledPtr();
 
489
  volatile Session::killed_state *killed= &session->killed;
547
490
  Cursor *file;
548
 
  boost::dynamic_bitset<> *save_read_set= NULL;
549
 
  boost::dynamic_bitset<> *save_write_set= NULL;
 
491
  MyBitmap *save_read_set, *save_write_set;
550
492
 
551
493
  idx=indexpos=0;
552
494
  error=quick_select=0;
564
506
  if (! indexfile && ! quick_select)
565
507
  {
566
508
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
567
 
    if (file->startTableScan(1))
568
 
      return(HA_POS_ERROR);
569
 
    file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
 
509
    file->startTableScan(1);
 
510
    file->extra_opt(HA_EXTRA_CACHE,
 
511
                    session->variables.read_buff_size);
570
512
  }
571
513
 
572
514
  ReadRecord read_record_info;
575
517
    if (select->quick->reset())
576
518
      return(HA_POS_ERROR);
577
519
 
578
 
    if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
 
      return(HA_POS_ERROR);
 
520
    read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
580
521
  }
581
522
 
582
523
  /* Remember original bitmaps */
583
524
  save_read_set=  sort_form->read_set;
584
525
  save_write_set= sort_form->write_set;
585
526
  /* Set up temporary column read map for columns used by sort */
586
 
  sort_form->tmp_set.reset();
 
527
  sort_form->tmp_set.clearAll();
587
528
  /* Temporary set for register_used_fields and register_field_in_read_map */
588
529
  sort_form->read_set= &sort_form->tmp_set;
589
 
  param->register_used_fields();
 
530
  register_used_fields(param);
590
531
  if (select && select->cond)
591
532
    select->cond->walk(&Item::register_field_in_read_map, 1,
592
533
                       (unsigned char*) sort_form);
593
 
  sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
 
534
  sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
594
535
 
595
536
  for (;;)
596
537
  {
601
542
        error= HA_ERR_END_OF_FILE;
602
543
        break;
603
544
      }
604
 
      file->position(sort_form->getInsertRecord());
 
545
      file->position(sort_form->record[0]);
605
546
    }
606
547
    else                                        /* Not quick-select */
607
548
    {
612
553
          error= errno ? errno : -1;            /* Abort */
613
554
          break;
614
555
        }
615
 
        error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
 
556
        error=file->rnd_pos(sort_form->record[0],next_pos);
616
557
      }
617
558
      else
618
559
      {
619
 
        error=file->rnd_next(sort_form->getInsertRecord());
 
560
        error=file->rnd_next(sort_form->record[0]);
620
561
 
621
562
        if (!flag)
622
563
        {
624
565
          record+= sort_form->getShare()->db_record_offset;
625
566
        }
626
567
        else if (!error)
627
 
          file->position(sort_form->getInsertRecord());
 
568
          file->position(sort_form->record[0]);
628
569
      }
629
570
      if (error && error != HA_ERR_RECORD_DELETED)
630
571
        break;
645
586
    {
646
587
      if (idx == param->keys)
647
588
      {
648
 
        if (param->write_keys(sort_keys, idx, buffpek_pointers, tempfile))
 
589
        if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
649
590
          return(HA_POS_ERROR);
650
591
        idx=0;
651
592
        indexpos++;
652
593
      }
653
 
      param->make_sortkey(sort_keys[idx++], ref_pos);
 
594
      make_sortkey(param,sort_keys[idx++],ref_pos);
654
595
    }
655
596
    else
656
 
    {
657
597
      file->unlock_row();
658
 
    }
659
 
 
660
598
    /* It does not make sense to read more keys in case of a fatal error */
661
 
    if (getSession().is_error())
 
599
    if (session->is_error())
662
600
      break;
663
601
  }
664
602
  if (quick_select)
676
614
      file->endTableScan();
677
615
  }
678
616
 
679
 
  if (getSession().is_error())
 
617
  if (session->is_error())
680
618
    return(HA_POS_ERROR);
681
619
 
682
620
  /* Signal we should use orignal column read and write maps */
683
 
  sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
 
621
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
684
622
 
685
623
  if (error != HA_ERR_END_OF_FILE)
686
624
  {
687
625
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
626
    return(HA_POS_ERROR);
689
627
  }
690
 
 
691
 
  if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
692
 
  {
 
628
  if (indexpos && idx &&
 
629
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
693
630
    return(HA_POS_ERROR);
694
 
  }
695
 
 
696
631
  return(my_b_inited(tempfile) ?
697
632
              (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
698
633
              idx);
703
638
  @details
704
639
  Sort the buffer and write:
705
640
  -# the sorted sequence to tempfile
706
 
  -# a buffpek describing the sorted sequence position to buffpek_pointers
 
641
  -# a BUFFPEK describing the sorted sequence position to buffpek_pointers
707
642
 
708
643
    (was: Skriver en buffert med nycklar till filen)
709
644
 
710
645
  @param param             Sort parameters
711
646
  @param sort_keys         Array of pointers to keys to sort
712
647
  @param count             Number of elements in sort_keys array
713
 
  @param buffpek_pointers  One 'buffpek' struct will be written into this file.
714
 
                           The buffpek::{file_pos, count} will indicate where
 
648
  @param buffpek_pointers  One 'BUFFPEK' struct will be written into this file.
 
649
                           The BUFFPEK::{file_pos, count} will indicate where
715
650
                           the sorted data was stored.
716
651
  @param tempfile          The sorted sequence will be written into this file.
717
652
 
721
656
    1 Error
722
657
*/
723
658
 
724
 
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
725
 
                          internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
 
659
static int
 
660
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
 
661
           internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
726
662
{
727
 
  buffpek buffpek;
 
663
  size_t sort_length, rec_length;
 
664
  unsigned char **end;
 
665
  BUFFPEK buffpek;
728
666
 
 
667
  sort_length= param->sort_length;
 
668
  rec_length= param->rec_length;
729
669
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
670
  if (!my_b_inited(tempfile) &&
731
 
      tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
732
 
  {
733
 
    return 1;
734
 
  }
 
671
      open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
 
672
                       MYF(MY_WME)))
 
673
    goto err;
735
674
  /* check we won't have more buffpeks than we can possibly keep in memory */
736
 
  if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
737
 
  {
738
 
    return 1;
739
 
  }
740
 
 
 
675
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
 
676
    goto err;
741
677
  buffpek.file_pos= my_b_tell(tempfile);
742
 
  if ((ha_rows) count > max_rows)
743
 
    count=(uint32_t) max_rows;
744
 
 
 
678
  if ((ha_rows) count > param->max_rows)
 
679
    count=(uint32_t) param->max_rows;
745
680
  buffpek.count=(ha_rows) count;
746
 
 
747
 
  for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
748
 
  {
 
681
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
682
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
750
 
    {
751
 
      return 1;
752
 
    }
753
 
  }
754
 
 
 
683
      goto err;
755
684
  if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
756
 
  {
757
 
    return 1;
758
 
  }
 
685
    goto err;
 
686
  return(0);
759
687
 
760
 
  return 0;
 
688
err:
 
689
  return(1);
761
690
} /* write_keys */
762
691
 
763
692
 
786
715
 
787
716
/** Make a sort-key from record. */
788
717
 
789
 
void SortParam::make_sortkey(register unsigned char *to, unsigned char *ref_pos)
 
718
static void make_sortkey(register SORTPARAM *param,
 
719
                         register unsigned char *to, unsigned char *ref_pos)
790
720
{
791
 
  Field *field;
792
 
  SortField *sort_field;
 
721
  register Field *field;
 
722
  register SORT_FIELD *sort_field;
793
723
  size_t length;
794
724
 
795
 
  for (sort_field= local_sortorder ;
796
 
       sort_field != end ;
 
725
  for (sort_field=param->local_sortorder ;
 
726
       sort_field != param->end ;
797
727
       sort_field++)
798
728
  {
799
729
    bool maybe_null=0;
819
749
    {                                           // Item
820
750
      Item *item=sort_field->item;
821
751
      maybe_null= item->maybe_null;
822
 
 
823
752
      switch (sort_field->result_type) {
824
753
      case STRING_RESULT:
825
 
        {
826
 
          const CHARSET_INFO * const cs=item->collation.collation;
827
 
          char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
828
 
          int diff;
829
 
          uint32_t sort_field_length;
 
754
      {
 
755
        const CHARSET_INFO * const cs=item->collation.collation;
 
756
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
 
757
        int diff;
 
758
        uint32_t sort_field_length;
830
759
 
 
760
        if (maybe_null)
 
761
          *to++=1;
 
762
        /* All item->str() to use some extra byte for end null.. */
 
763
        String tmp((char*) to,sort_field->length+4,cs);
 
764
        String *res= item->str_result(&tmp);
 
765
        if (!res)
 
766
        {
831
767
          if (maybe_null)
832
 
            *to++=1;
833
 
          /* All item->str() to use some extra byte for end null.. */
834
 
          String tmp((char*) to,sort_field->length+4,cs);
835
 
          String *res= item->str_result(&tmp);
836
 
          if (!res)
837
 
          {
838
 
            if (maybe_null)
839
 
              memset(to-1, 0, sort_field->length+1);
840
 
            else
841
 
            {
842
 
              /*
843
 
                This should only happen during extreme conditions if we run out
844
 
                of memory or have an item marked not null when it can be null.
845
 
                This code is here mainly to avoid a hard crash in this case.
846
 
              */
847
 
              assert(0);
848
 
              memset(to, 0, sort_field->length);        // Avoid crash
849
 
            }
850
 
            break;
851
 
          }
852
 
          length= res->length();
853
 
          sort_field_length= sort_field->length - sort_field->suffix_length;
854
 
          diff=(int) (sort_field_length - length);
855
 
          if (diff < 0)
856
 
          {
857
 
            diff=0;
858
 
            length= sort_field_length;
859
 
          }
860
 
          if (sort_field->suffix_length)
861
 
          {
862
 
            /* Store length last in result_string */
863
 
            store_length(to + sort_field_length, length,
864
 
                         sort_field->suffix_length);
865
 
          }
866
 
          if (sort_field->need_strxnfrm)
867
 
          {
868
 
            char *from=(char*) res->ptr();
869
 
            uint32_t tmp_length;
870
 
            if ((unsigned char*) from == to)
871
 
            {
872
 
              set_if_smaller(length,sort_field->length);
873
 
              memcpy(tmp_buffer,from,length);
874
 
              from= tmp_buffer;
875
 
            }
876
 
            tmp_length= my_strnxfrm(cs,to,sort_field->length,
877
 
                                    (unsigned char*) from, length);
878
 
            assert(tmp_length == sort_field->length);
879
 
          }
 
768
            memset(to-1, 0, sort_field->length+1);
880
769
          else
881
770
          {
882
 
            my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
883
 
            cs->cset->fill(cs, (char *)to+length,diff,fill_char);
 
771
            /*
 
772
              This should only happen during extreme conditions if we run out
 
773
              of memory or have an item marked not null when it can be null.
 
774
              This code is here mainly to avoid a hard crash in this case.
 
775
            */
 
776
            assert(0);
 
777
            memset(to, 0, sort_field->length);  // Avoid crash
884
778
          }
885
779
          break;
886
780
        }
 
781
        length= res->length();
 
782
        sort_field_length= sort_field->length - sort_field->suffix_length;
 
783
        diff=(int) (sort_field_length - length);
 
784
        if (diff < 0)
 
785
        {
 
786
          diff=0;
 
787
          length= sort_field_length;
 
788
        }
 
789
        if (sort_field->suffix_length)
 
790
        {
 
791
          /* Store length last in result_string */
 
792
          store_length(to + sort_field_length, length,
 
793
                       sort_field->suffix_length);
 
794
        }
 
795
        if (sort_field->need_strxnfrm)
 
796
        {
 
797
          char *from=(char*) res->ptr();
 
798
          uint32_t tmp_length;
 
799
          if ((unsigned char*) from == to)
 
800
          {
 
801
            set_if_smaller(length,sort_field->length);
 
802
            memcpy(param->tmp_buffer,from,length);
 
803
            from=param->tmp_buffer;
 
804
          }
 
805
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
 
806
                                  (unsigned char*) from, length);
 
807
          assert(tmp_length == sort_field->length);
 
808
        }
 
809
        else
 
810
        {
 
811
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
 
812
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
 
813
        }
 
814
        break;
 
815
      }
887
816
      case INT_RESULT:
888
 
        {
 
817
        {
889
818
          int64_t value= item->val_int_result();
890
819
          if (maybe_null)
891
820
          {
892
 
            *to++=1;
 
821
            *to++=1;
893
822
            if (item->null_value)
894
823
            {
895
824
              if (maybe_null)
901
830
              break;
902
831
            }
903
832
          }
904
 
          to[7]= (unsigned char) value;
905
 
          to[6]= (unsigned char) (value >> 8);
906
 
          to[5]= (unsigned char) (value >> 16);
907
 
          to[4]= (unsigned char) (value >> 24);
908
 
          to[3]= (unsigned char) (value >> 32);
909
 
          to[2]= (unsigned char) (value >> 40);
910
 
          to[1]= (unsigned char) (value >> 48);
 
833
          to[7]= (unsigned char) value;
 
834
          to[6]= (unsigned char) (value >> 8);
 
835
          to[5]= (unsigned char) (value >> 16);
 
836
          to[4]= (unsigned char) (value >> 24);
 
837
          to[3]= (unsigned char) (value >> 32);
 
838
          to[2]= (unsigned char) (value >> 40);
 
839
          to[1]= (unsigned char) (value >> 48);
911
840
          if (item->unsigned_flag)                    /* Fix sign */
912
841
            to[0]= (unsigned char) (value >> 56);
913
842
          else
914
843
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
915
 
          break;
916
 
        }
 
844
          break;
 
845
        }
917
846
      case DECIMAL_RESULT:
918
847
        {
919
 
          type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
 
848
          my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
920
849
          if (maybe_null)
921
850
          {
922
851
            if (item->null_value)
927
856
            }
928
857
            *to++=1;
929
858
          }
930
 
          dec_val->val_binary(E_DEC_FATAL_ERROR, to,
931
 
                              item->max_length - (item->decimals ? 1:0),
932
 
                              item->decimals);
933
 
          break;
 
859
          my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
 
860
                            item->max_length - (item->decimals ? 1:0),
 
861
                            item->decimals);
 
862
         break;
934
863
        }
935
864
      case REAL_RESULT:
936
 
        {
 
865
        {
937
866
          double value= item->val_result();
938
 
          if (maybe_null)
 
867
          if (maybe_null)
939
868
          {
940
869
            if (item->null_value)
941
870
            {
943
872
              to++;
944
873
              break;
945
874
            }
946
 
            *to++=1;
 
875
            *to++=1;
947
876
          }
948
 
          change_double_for_sort(value,(unsigned char*) to);
949
 
          break;
950
 
        }
 
877
          change_double_for_sort(value,(unsigned char*) to);
 
878
          break;
 
879
        }
951
880
      case ROW_RESULT:
952
881
      default:
953
 
        // This case should never be choosen
954
 
        assert(0);
955
 
        break;
 
882
        // This case should never be choosen
 
883
        assert(0);
 
884
        break;
956
885
      }
957
886
    }
958
 
 
959
887
    if (sort_field->reverse)
960
888
    {                                                   /* Revers key */
961
889
      if (maybe_null)
968
896
      }
969
897
    }
970
898
    else
971
 
    {
972
899
      to+= sort_field->length;
973
 
    }
974
900
  }
975
901
 
976
 
  if (addon_field)
 
902
  if (param->addon_field)
977
903
  {
978
904
    /*
979
905
      Save field values appended to sorted fields.
981
907
      In this implementation we use fixed layout for field values -
982
908
      the same for all records.
983
909
    */
984
 
    sort_addon_field *addonf= addon_field;
 
910
    SORT_ADDON_FIELD *addonf= param->addon_field;
985
911
    unsigned char *nulls= to;
986
912
    assert(addonf != 0);
987
913
    memset(nulls, 0, addonf->offset);
991
917
      if (addonf->null_bit && field->is_null())
992
918
      {
993
919
        nulls[addonf->null_offset]|= addonf->null_bit;
994
 
#ifdef HAVE_VALGRIND
 
920
#ifdef HAVE_purify
995
921
        memset(to, 0, addonf->length);
996
922
#endif
997
923
      }
998
924
      else
999
925
      {
1000
 
#ifdef HAVE_VALGRIND
 
926
#ifdef HAVE_purify
1001
927
        unsigned char *end= field->pack(to, field->ptr);
1002
 
        uint32_t local_length= (uint32_t) ((to + addonf->length) - end);
1003
 
        assert((int) local_length >= 0);
1004
 
        if (local_length)
1005
 
          memset(end, 0, local_length);
 
928
        uint32_t length= (uint32_t) ((to + addonf->length) - end);
 
929
        assert((int) length >= 0);
 
930
        if (length)
 
931
          memset(end, 0, length);
1006
932
#else
1007
933
        (void) field->pack(to, field->ptr);
1008
934
#endif
1013
939
  else
1014
940
  {
1015
941
    /* Save filepos last */
1016
 
    memcpy(to, ref_pos, (size_t) ref_length);
 
942
    memcpy(to, ref_pos, (size_t) param->ref_length);
1017
943
  }
 
944
  return;
1018
945
}
1019
946
 
1020
947
 
1022
949
  Register fields used by sorting in the sorted table's read set
1023
950
*/
1024
951
 
1025
 
void SortParam::register_used_fields()
 
952
static void register_used_fields(SORTPARAM *param)
1026
953
{
1027
 
  SortField *sort_field;
1028
 
  Table *table= sort_form;
 
954
  register SORT_FIELD *sort_field;
 
955
  Table *table=param->sort_form;
1029
956
 
1030
 
  for (sort_field= local_sortorder ;
1031
 
       sort_field != end ;
 
957
  for (sort_field= param->local_sortorder ;
 
958
       sort_field != param->end ;
1032
959
       sort_field++)
1033
960
  {
1034
961
    Field *field;
1035
962
    if ((field= sort_field->field))
1036
963
    {
1037
 
      if (field->getTable() == table)
1038
 
        table->setReadSet(field->position());
 
964
      if (field->table == table)
 
965
        table->setReadSet(field->field_index);
1039
966
    }
1040
967
    else
1041
968
    {                                           // Item
1044
971
    }
1045
972
  }
1046
973
 
1047
 
  if (addon_field)
 
974
  if (param->addon_field)
1048
975
  {
1049
 
    sort_addon_field *addonf= addon_field;
 
976
    SORT_ADDON_FIELD *addonf= param->addon_field;
1050
977
    Field *field;
1051
978
    for ( ; (field= addonf->field) ; addonf++)
1052
 
      table->setReadSet(field->position());
 
979
      table->setReadSet(field->field_index);
1053
980
  }
1054
981
  else
1055
982
  {
1059
986
}
1060
987
 
1061
988
 
1062
 
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
 
989
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
 
990
                       filesort_info_st *table_sort)
1063
991
{
1064
 
  uint32_t offset;
 
992
  uint32_t offset,res_length;
1065
993
  unsigned char *to;
1066
994
 
1067
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1068
 
  offset= rec_length - res_length;
1069
 
 
1070
 
  if ((ha_rows) count > max_rows)
1071
 
    count=(uint32_t) max_rows;
1072
 
 
1073
 
  if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1074
 
    return true;
1075
 
 
1076
 
  for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
 
995
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
 
996
  res_length= param->res_length;
 
997
  offset= param->rec_length-res_length;
 
998
  if ((ha_rows) count > param->max_rows)
 
999
    count=(uint32_t) param->max_rows;
 
1000
  if (!(to= table_sort->record_pointers=
 
1001
        (unsigned char*) malloc(res_length*count)))
 
1002
    return(1);
 
1003
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1077
1004
  {
1078
1005
    memcpy(to, *sort_keys+offset, res_length);
1079
1006
    to+= res_length;
1080
1007
  }
1081
 
 
1082
 
  return false;
 
1008
  return(0);
1083
1009
}
1084
1010
 
1085
1011
 
1086
1012
/** Merge buffers to make < MERGEBUFF2 buffers. */
1087
1013
 
1088
 
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1089
 
                              buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
 
1014
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
 
1015
                    BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1090
1016
{
 
1017
  register uint32_t i;
1091
1018
  internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1092
 
  buffpek *lastbuff;
 
1019
  BUFFPEK *lastbuff;
1093
1020
 
1094
1021
  if (*maxbuffer < MERGEBUFF2)
1095
 
    return 0;
 
1022
    return(0);
1096
1023
  if (flush_io_cache(t_file) ||
1097
 
      t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1098
 
  {
1099
 
    return 1;
1100
 
  }
 
1024
      open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
 
1025
                        MYF(MY_WME)))
 
1026
    return(1);
1101
1027
 
1102
1028
  from_file= t_file ; to_file= &t_file2;
1103
1029
  while (*maxbuffer >= MERGEBUFF2)
1104
1030
  {
1105
 
    register uint32_t i;
1106
 
 
1107
 
    if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1108
 
    {
1109
 
      break;
1110
 
    }
1111
 
 
1112
 
    if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1113
 
    {
1114
 
      break;
1115
 
    }
1116
 
 
1117
 
    lastbuff=buffpek_inst;
 
1031
    if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
 
1032
      goto cleanup;
 
1033
    if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
 
1034
      goto cleanup;
 
1035
    lastbuff=buffpek;
1118
1036
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1119
1037
    {
1120
1038
      if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
 
                        buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1122
 
      {
1123
 
        goto cleanup;
1124
 
      }
 
1039
                        buffpek+i,buffpek+i+MERGEBUFF-1,0))
 
1040
      goto cleanup;
1125
1041
    }
1126
 
 
1127
1042
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
 
                      buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1129
 
    {
 
1043
                      buffpek+i,buffpek+ *maxbuffer,0))
1130
1044
      break;
1131
 
    }
1132
 
 
1133
1045
    if (flush_io_cache(to_file))
1134
 
    {
1135
1046
      break;
1136
 
    }
1137
 
 
1138
1047
    temp=from_file; from_file=to_file; to_file=temp;
1139
 
    from_file->setup_io_cache();
1140
 
    to_file->setup_io_cache();
1141
 
    *maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
 
1048
    setup_io_cache(from_file);
 
1049
    setup_io_cache(to_file);
 
1050
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1142
1051
  }
1143
 
 
1144
1052
cleanup:
1145
 
  to_file->close_cached_file();                 // This holds old result
 
1053
  close_cached_file(to_file);                   // This holds old result
1146
1054
  if (to_file == t_file)
1147
1055
  {
1148
1056
    *t_file=t_file2;                            // Copy result file
1149
 
    t_file->setup_io_cache();
 
1057
    setup_io_cache(t_file);
1150
1058
  }
1151
1059
 
1152
1060
  return(*maxbuffer >= MERGEBUFF2);     /* Return 1 if interrupted */
1160
1068
    (uint32_t)-1 if something goes wrong
1161
1069
*/
1162
1070
 
1163
 
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
 
1071
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1072
                        uint32_t rec_length)
1164
1073
{
1165
1074
  register uint32_t count;
1166
1075
  uint32_t length;
1167
1076
 
1168
 
  if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
 
1077
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1169
1078
  {
1170
 
    if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
 
1079
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1171
1080
      return((uint32_t) -1);
1172
1081
 
1173
 
    buffpek_inst->key= buffpek_inst->base;
1174
 
    buffpek_inst->file_pos+= length;                    /* New filepos */
1175
 
    buffpek_inst->count-= count;
1176
 
    buffpek_inst->mem_count= count;
 
1082
    buffpek->key= buffpek->base;
 
1083
    buffpek->file_pos+= length;                 /* New filepos */
 
1084
    buffpek->count-= count;
 
1085
    buffpek->mem_count= count;
1177
1086
  }
1178
1087
  return (count*rec_length);
1179
1088
} /* read_to_buffer */
1183
1092
{
1184
1093
  qsort2_cmp key_compare;
1185
1094
  void *key_compare_arg;
1186
 
 
1187
1095
  public:
1188
 
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1189
 
    key_compare(in_key_compare),
1190
 
    key_compare_arg(in_compare_arg)
1191
 
  { }
1192
 
  
1193
 
  inline bool operator()(const buffpek *i, const buffpek *j) const
 
1096
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
 
1097
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
 
1098
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1194
1099
  {
1195
 
    int val= key_compare(key_compare_arg, &i->key, &j->key);
1196
 
 
 
1100
    int val= key_compare(key_compare_arg,
 
1101
                      &i->key, &j->key);
1197
1102
    return (val >= 0);
1198
1103
  }
1199
1104
};
1203
1108
  Merge buffers to one buffer.
1204
1109
 
1205
1110
  @param param        Sort parameter
1206
 
  @param from_file    File with source data (buffpeks point to this file)
 
1111
  @param from_file    File with source data (BUFFPEKs point to this file)
1207
1112
  @param to_file      File to write the sorted result data.
1208
1113
  @param sort_buffer  Buffer for data to store up to MERGEBUFF2 sort keys.
1209
 
  @param lastbuff     OUT Store here buffpek describing data written to to_file
1210
 
  @param Fb           First element in source buffpeks array
1211
 
  @param Tb           Last element in source buffpeks array
 
1114
  @param lastbuff     OUT Store here BUFFPEK describing data written to to_file
 
1115
  @param Fb           First element in source BUFFPEKs array
 
1116
  @param Tb           Last element in source BUFFPEKs array
1212
1117
  @param flag
1213
1118
 
1214
1119
  @retval
1217
1122
    other  error
1218
1123
*/
1219
1124
 
1220
 
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1221
 
                            internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1222
 
                            buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1223
 
                            int flag)
 
1125
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
 
1126
                  internal::IO_CACHE *to_file, unsigned char *sort_buffer,
 
1127
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
 
1128
                  int flag)
1224
1129
{
1225
1130
  int error;
1226
1131
  uint32_t rec_length,res_length,offset;
1229
1134
  ha_rows max_rows,org_max_rows;
1230
1135
  internal::my_off_t to_start_filepos;
1231
1136
  unsigned char *strpos;
1232
 
  buffpek *buffpek_inst;
 
1137
  BUFFPEK *buffpek;
1233
1138
  qsort2_cmp cmp;
1234
1139
  void *first_cmp_arg;
1235
 
  volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1236
 
  Session::killed_state_t not_killable;
 
1140
  volatile Session::killed_state *killed= &current_session->killed;
 
1141
  Session::killed_state not_killable;
1237
1142
 
1238
 
  getSession().status_var.filesort_merge_passes++;
 
1143
  status_var_increment(current_session->status_var.filesort_merge_passes);
1239
1144
  if (param->not_killable)
1240
1145
  {
1241
1146
    killed= &not_killable;
1265
1170
    cmp= internal::get_ptr_compare(sort_length);
1266
1171
    first_cmp_arg= (void*) &sort_length;
1267
1172
  }
1268
 
  priority_queue<buffpek *, vector<buffpek *>, compare_functor >
 
1173
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
1269
1174
    queue(compare_functor(cmp, first_cmp_arg));
1270
 
  for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
 
1175
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1271
1176
  {
1272
 
    buffpek_inst->base= strpos;
1273
 
    buffpek_inst->max_keys= maxcount;
1274
 
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
 
1177
    buffpek->base= strpos;
 
1178
    buffpek->max_keys= maxcount;
 
1179
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1275
1180
                                                                         rec_length));
1276
1181
    if (error == -1)
1277
 
      return -1;
1278
 
 
1279
 
    buffpek_inst->max_keys= buffpek_inst->mem_count;    // If less data in buffers than expected
1280
 
    queue.push(buffpek_inst);
 
1182
      goto err;
 
1183
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
 
1184
    queue.push(buffpek);
1281
1185
  }
1282
1186
 
1283
1187
  if (param->unique_buff)
1290
1194
       This is safe as we know that there is always more than one element
1291
1195
       in each block to merge (This is guaranteed by the Unique:: algorithm
1292
1196
    */
1293
 
    buffpek_inst= queue.top();
1294
 
    memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1295
 
    if (my_b_write(to_file, (unsigned char*) buffpek_inst->key, rec_length))
 
1197
    buffpek= queue.top();
 
1198
    memcpy(param->unique_buff, buffpek->key, rec_length);
 
1199
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1296
1200
    {
1297
 
      return 1;
 
1201
      error=1; goto err;
1298
1202
    }
1299
 
    buffpek_inst->key+= rec_length;
1300
 
    buffpek_inst->mem_count--;
 
1203
    buffpek->key+= rec_length;
 
1204
    buffpek->mem_count--;
1301
1205
    if (!--max_rows)
1302
1206
    {
1303
1207
      error= 0;
1305
1209
    }
1306
1210
    /* Top element has been used */
1307
1211
    queue.pop();
1308
 
    queue.push(buffpek_inst);
 
1212
    queue.push(buffpek);
1309
1213
  }
1310
1214
  else
1311
 
  {
1312
1215
    cmp= 0;                                        // Not unique
1313
 
  }
1314
1216
 
1315
1217
  while (queue.size() > 1)
1316
1218
  {
1317
1219
    if (*killed)
1318
1220
    {
1319
 
      return 1;
 
1221
      error= 1; goto err;
1320
1222
    }
1321
1223
    for (;;)
1322
1224
    {
1323
 
      buffpek_inst= queue.top();
 
1225
      buffpek= queue.top();
1324
1226
      if (cmp)                                        // Remove duplicates
1325
1227
      {
1326
1228
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
 
                    (unsigned char**) &buffpek_inst->key))
 
1229
                    (unsigned char**) &buffpek->key))
1328
1230
              goto skip_duplicate;
1329
 
            memcpy(param->unique_buff, buffpek_inst->key, rec_length);
 
1231
            memcpy(param->unique_buff, buffpek->key, rec_length);
1330
1232
      }
1331
1233
      if (flag == 0)
1332
1234
      {
1333
 
        if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
 
1235
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1334
1236
        {
1335
 
          return 1;
 
1237
          error=1; goto err;
1336
1238
        }
1337
1239
      }
1338
1240
      else
1339
1241
      {
1340
 
        if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
 
1242
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1341
1243
        {
1342
 
          return 1;
 
1244
          error=1; goto err;
1343
1245
        }
1344
1246
      }
1345
1247
      if (!--max_rows)
1349
1251
      }
1350
1252
 
1351
1253
    skip_duplicate:
1352
 
      buffpek_inst->key+= rec_length;
1353
 
      if (! --buffpek_inst->mem_count)
 
1254
      buffpek->key+= rec_length;
 
1255
      if (! --buffpek->mem_count)
1354
1256
      {
1355
 
        if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
 
1257
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1356
1258
                                          rec_length)))
1357
1259
        {
1358
1260
          queue.pop();
1359
1261
          break;                        /* One buffer have been removed */
1360
1262
        }
1361
1263
        else if (error == -1)
1362
 
        {
1363
 
          return -1;
1364
 
        }
 
1264
          goto err;
1365
1265
      }
1366
1266
      /* Top element has been replaced */
1367
1267
      queue.pop();
1368
 
      queue.push(buffpek_inst);
 
1268
      queue.push(buffpek);
1369
1269
    }
1370
1270
  }
1371
 
  buffpek_inst= queue.top();
1372
 
  buffpek_inst->base= sort_buffer;
1373
 
  buffpek_inst->max_keys= param->keys;
 
1271
  buffpek= queue.top();
 
1272
  buffpek->base= sort_buffer;
 
1273
  buffpek->max_keys= param->keys;
1374
1274
 
1375
1275
  /*
1376
1276
    As we know all entries in the buffer are unique, we only have to
1378
1278
  */
1379
1279
  if (cmp)
1380
1280
  {
1381
 
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
 
1281
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1382
1282
    {
1383
 
      buffpek_inst->key+= rec_length;         // Remove duplicate
1384
 
      --buffpek_inst->mem_count;
 
1283
      buffpek->key+= rec_length;         // Remove duplicate
 
1284
      --buffpek->mem_count;
1385
1285
    }
1386
1286
  }
1387
1287
 
1388
1288
  do
1389
1289
  {
1390
 
    if ((ha_rows) buffpek_inst->mem_count > max_rows)
 
1290
    if ((ha_rows) buffpek->mem_count > max_rows)
1391
1291
    {                                        /* Don't write too many records */
1392
 
      buffpek_inst->mem_count= (uint32_t) max_rows;
1393
 
      buffpek_inst->count= 0;                        /* Don't read more */
 
1292
      buffpek->mem_count= (uint32_t) max_rows;
 
1293
      buffpek->count= 0;                        /* Don't read more */
1394
1294
    }
1395
 
    max_rows-= buffpek_inst->mem_count;
 
1295
    max_rows-= buffpek->mem_count;
1396
1296
    if (flag == 0)
1397
1297
    {
1398
 
      if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
 
                     (rec_length*buffpek_inst->mem_count)))
 
1298
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
 
1299
                     (rec_length*buffpek->mem_count)))
1400
1300
      {
1401
 
        return 1;
 
1301
        error= 1; goto err;
1402
1302
      }
1403
1303
    }
1404
1304
    else
1405
1305
    {
1406
1306
      register unsigned char *end;
1407
 
      strpos= buffpek_inst->key+offset;
1408
 
      for (end= strpos+buffpek_inst->mem_count*rec_length ;
 
1307
      strpos= buffpek->key+offset;
 
1308
      for (end= strpos+buffpek->mem_count*rec_length ;
1409
1309
           strpos != end ;
1410
1310
           strpos+= rec_length)
1411
1311
      {
1412
1312
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1413
1313
        {
1414
 
          return 1;
 
1314
          error=1; goto err;
1415
1315
        }
1416
1316
      }
1417
1317
    }
1418
1318
  }
1419
 
 
1420
 
  while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
 
1319
  while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1320
         != -1 && error != 0);
1422
1321
 
1423
1322
end:
1424
1323
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1425
1324
  lastbuff->file_pos= to_start_filepos;
1426
 
 
1427
 
  return error;
 
1325
err:
 
1326
  return(error);
1428
1327
} /* merge_buffers */
1429
1328
 
1430
1329
 
1431
1330
        /* Do a merge to output-file (save only positions) */
1432
1331
 
1433
 
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1434
 
                          buffpek *buffpek_inst, uint32_t maxbuffer,
1435
 
                          internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
 
1332
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
 
1333
                       BUFFPEK *buffpek, uint32_t maxbuffer,
 
1334
                       internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1436
1335
{
1437
 
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
 
                    buffpek_inst+maxbuffer,1))
1439
 
    return 1;
1440
 
 
1441
 
  return 0;
 
1336
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
 
1337
                    buffpek+maxbuffer,1))
 
1338
    return(1);
 
1339
  return(0);
1442
1340
} /* merge_index */
1443
1341
 
1444
1342
 
1458
1356
/**
1459
1357
  Calculate length of sort key.
1460
1358
 
 
1359
  @param session                          Thread Cursor
1461
1360
  @param sortorder                Order of items to sort
1462
1361
  @param s_length                 Number of items to sort
1463
1362
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1472
1371
    Total length of sort buffer in bytes
1473
1372
*/
1474
1373
 
1475
 
uint32_t FileSort::sortlength(SortField *sortorder, uint32_t s_length, bool *multi_byte_charset)
 
1374
static uint32_t
 
1375
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
 
1376
           bool *multi_byte_charset)
1476
1377
{
1477
1378
  register uint32_t length;
1478
1379
  const CHARSET_INFO *cs;
1502
1403
      sortorder->result_type= sortorder->item->result_type();
1503
1404
      if (sortorder->item->result_as_int64_t())
1504
1405
        sortorder->result_type= INT_RESULT;
1505
 
 
1506
1406
      switch (sortorder->result_type) {
1507
1407
      case STRING_RESULT:
1508
 
        sortorder->length=sortorder->item->max_length;
 
1408
        sortorder->length=sortorder->item->max_length;
1509
1409
        set_if_smaller(sortorder->length,
1510
 
                       getSession().variables.max_sort_length);
1511
 
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1512
 
        {
 
1410
                       session->variables.max_sort_length);
 
1411
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
 
1412
        {
1513
1413
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
 
          sortorder->need_strxnfrm= 1;
1515
 
          *multi_byte_charset= 1;
1516
 
        }
 
1414
          sortorder->need_strxnfrm= 1;
 
1415
          *multi_byte_charset= 1;
 
1416
        }
1517
1417
        else if (cs == &my_charset_bin)
1518
1418
        {
1519
1419
          /* Store length last to be able to sort blob/varbinary */
1520
1420
          sortorder->suffix_length= suffix_length(sortorder->length);
1521
1421
          sortorder->length+= sortorder->suffix_length;
1522
1422
        }
1523
 
        break;
 
1423
        break;
1524
1424
      case INT_RESULT:
1525
 
        sortorder->length=8;                    // Size of intern int64_t
1526
 
        break;
 
1425
        sortorder->length=8;                    // Size of intern int64_t
 
1426
        break;
1527
1427
      case DECIMAL_RESULT:
1528
1428
        sortorder->length=
1529
 
          class_decimal_get_binary_size(sortorder->item->max_length -
 
1429
          my_decimal_get_binary_size(sortorder->item->max_length -
1530
1430
                                     (sortorder->item->decimals ? 1 : 0),
1531
1431
                                     sortorder->item->decimals);
1532
1432
        break;
1533
1433
      case REAL_RESULT:
1534
 
        sortorder->length=sizeof(double);
1535
 
        break;
 
1434
        sortorder->length=sizeof(double);
 
1435
        break;
1536
1436
      case ROW_RESULT:
1537
 
        // This case should never be choosen
1538
 
        assert(0);
1539
 
        break;
 
1437
      default:
 
1438
        // This case should never be choosen
 
1439
        assert(0);
 
1440
        break;
1540
1441
      }
1541
1442
      if (sortorder->item->maybe_null)
1542
 
        length++;                               // Place for NULL marker
 
1443
        length++;                               // Place for NULL marker
1543
1444
    }
1544
 
    set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
 
1445
    set_if_smaller(sortorder->length,
 
1446
                   (size_t)session->variables.max_sort_length);
1545
1447
    length+=sortorder->length;
1546
1448
  }
1547
1449
  sortorder->field= (Field*) 0;                 // end marker
1561
1463
  layouts for the values of the non-sorted fields in the buffer and
1562
1464
  fills them.
1563
1465
 
 
1466
  @param session                 Current thread
1564
1467
  @param ptabfield           Array of references to the table fields
1565
1468
  @param sortlength          Total length of sorted fields
1566
1469
  @param[out] plength        Total length of appended fields
1575
1478
    NULL   if we do not store field values with sort data.
1576
1479
*/
1577
1480
 
1578
 
sort_addon_field *FileSort::get_addon_fields(Field **ptabfield, uint32_t sortlength_arg, uint32_t *plength)
 
1481
static SORT_ADDON_FIELD *
 
1482
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1579
1483
{
1580
1484
  Field **pfield;
1581
1485
  Field *field;
1582
 
  sort_addon_field *addonf;
 
1486
  SORT_ADDON_FIELD *addonf;
1583
1487
  uint32_t length= 0;
1584
1488
  uint32_t fields= 0;
1585
1489
  uint32_t null_fields= 0;
1610
1514
    return 0;
1611
1515
  length+= (null_fields+7)/8;
1612
1516
 
1613
 
  if (length+sortlength_arg > getSession().variables.max_length_for_sort_data ||
1614
 
      !(addonf= (sort_addon_field *) malloc(sizeof(sort_addon_field)*
 
1517
  if (length+sortlength > session->variables.max_length_for_sort_data ||
 
1518
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
1615
1519
                                            (fields+1))))
1616
1520
    return 0;
1617
1521
 
1661
1565
*/
1662
1566
 
1663
1567
static void
1664
 
unpack_addon_fields(sort_addon_field *addon_field, unsigned char *buff)
 
1568
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1665
1569
{
1666
1570
  Field *field;
1667
 
  sort_addon_field *addonf= addon_field;
 
1571
  SORT_ADDON_FIELD *addonf= addon_field;
1668
1572
 
1669
1573
  for ( ; (field= addonf->field) ; addonf++)
1670
1574
  {