~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2008-10-07 19:30:18 UTC
  • mfrom: (322.2.8 stdize-code)
  • mto: This revision was merged to the branch mainline in revision 491.
  • Revision ID: monty@inaugust.com-20081007193018-22fhaywc990akeqa
Merged code from Mats that I should have merged a while ago.

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