~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2008-12-18 07:24:54 UTC
  • mto: This revision was merged to the branch mainline in revision 714.
  • Revision ID: monty@bitters-20081218072454-8pnep622damjgqli
Fixed one more my_time thing.

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