~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

Merged vcol stuff.

Show diffs side-by-side

added added

removed removed

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