~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2010-10-15 01:23:36 UTC
  • mfrom: (1835.1.7 staging)
  • Revision ID: brian@tangent.org-20101015012336-8w5lox9kj0hkv0a1
MergeĀ inĀ mutable/execute

Show diffs side-by-side

added added

removed removed

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