~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2009-03-08 23:45:12 UTC
  • mto: (923.2.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 921.
  • Revision ID: mordred@inaugust.com-20090308234512-tqkygxtu1iaig23s
Removed C99 isnan() usage, which allows us to remove the util/math.{cc,h} workarounds. Yay for standards!

Show diffs side-by-side

added added

removed removed

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