~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

Merge Stewart.

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