~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2009-08-18 07:19:56 UTC
  • mfrom: (1116.1.3 stewart)
  • mto: This revision was merged to the branch mainline in revision 1118.
  • Revision ID: brian@gaz-20090818071956-nfpoe9rp3i7p50kx
Merge my branch from Stewart into one branch

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