~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2009-12-25 08:50:15 UTC
  • mto: This revision was merged to the branch mainline in revision 1255.
  • Revision ID: mordred@inaugust.com-20091225085015-83sux5qsvy312gew
MEM_ROOT == memory::Root

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