~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2010-10-29 01:13:40 UTC
  • mto: (1890.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1891.
  • Revision ID: brian@tangent.org-20101029011340-y9ixm180v9daypqr
Remove warnings for c++

Show diffs side-by-side

added added

removed removed

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