~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-08-07 14:14:58 UTC
  • mfrom: (1112 staging)
  • mto: (1115.3.4 captain)
  • mto: This revision was merged to the branch mainline in revision 1117.
  • Revision ID: osullivan.padraig@gmail.com-20090807141458-qrc3don58s304ore
MergeĀ fromĀ trunk.

Show diffs side-by-side

added added

removed removed

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