~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2010-08-12 17:19:46 UTC
  • mfrom: (1701.1.1 turn-off-csv)
  • Revision ID: brian@tangent.org-20100812171946-n44naaqhg27gehlh
MErge Monty, remove CSV from auto-build

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