~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2008-10-09 22:38:27 UTC
  • mto: This revision was merged to the branch mainline in revision 497.
  • Revision ID: monty@inaugust.com-20081009223827-bc9gvpiplsmvpwyq
Moved test() to its own file.
Made a new function to possibly replace int10_to_str.

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
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
 
 
32
 
#include "drizzled/sql_sort.h"
33
 
#include "drizzled/error.h"
34
 
#include "drizzled/probes.h"
35
 
#include "drizzled/session.h"
36
 
#include "drizzled/table.h"
37
 
#include "drizzled/table_list.h"
38
 
#include "drizzled/optimizer/range.h"
39
 
#include "drizzled/records.h"
40
 
#include "drizzled/internal/iocache.h"
41
 
#include "drizzled/internal/my_sys.h"
42
 
#include "plugin/myisam/myisam.h"
43
 
#include "drizzled/plugin/transactional_storage_engine.h"
44
 
 
45
 
using namespace std;
46
 
 
47
 
namespace drizzled
48
 
{
49
 
 
50
 
/* functions defined in this file */
 
24
#include <drizzled/server_includes.h>
 
25
#include "sql_sort.h"
 
26
#include <drizzled/drizzled_error_messages.h>
 
27
 
 
28
        /* functions defined in this file */
51
29
 
52
30
static char **make_char_array(char **old_pos, register uint32_t fields,
53
 
                              uint32_t length);
54
 
 
55
 
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
56
 
                                             uint32_t count,
57
 
                                             unsigned char *buf);
58
 
 
59
 
static ha_rows find_all_keys(Session *session,
60
 
                             SORTPARAM *param,
61
 
                             optimizer::SqlSelect *select,
62
 
                             unsigned char * *sort_keys, 
63
 
                             internal::IO_CACHE *buffer_file,
64
 
                             internal::IO_CACHE *tempfile,
65
 
                             internal::IO_CACHE *indexfile);
66
 
 
67
 
static int write_keys(SORTPARAM *param,
68
 
                      unsigned char * *sort_keys,
69
 
                      uint32_t count,
70
 
                      internal::IO_CACHE *buffer_file,
71
 
                      internal::IO_CACHE *tempfile);
72
 
 
73
 
static void make_sortkey(SORTPARAM *param,
74
 
                         unsigned char *to,
75
 
                         unsigned char *ref_pos);
 
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);
76
40
static void register_used_fields(SORTPARAM *param);
77
 
static int merge_index(SORTPARAM *param,
78
 
                       unsigned char *sort_buffer,
79
 
                       buffpek_st *buffpek,
80
 
                       uint32_t maxbuffer,
81
 
                       internal::IO_CACHE *tempfile,
82
 
                       internal::IO_CACHE *outfile);
83
 
static bool save_index(SORTPARAM *param,
84
 
                       unsigned char **sort_keys,
85
 
                       uint32_t count,
 
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, 
86
46
                       filesort_info_st *table_sort);
87
47
static uint32_t suffix_length(uint32_t string_length);
88
 
static uint32_t sortlength(Session *session,
89
 
                           SortField *sortorder,
90
 
                           uint32_t s_length,
91
 
                           bool *multi_byte_charset);
92
 
static sort_addon_field_st *get_addon_fields(Session *session,
93
 
                                             Field **ptabfield,
94
 
                                             uint32_t sortlength,
95
 
                                             uint32_t *plength);
96
 
static void unpack_addon_fields(sort_addon_field_st *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,
97
53
                                unsigned char *buff);
98
54
/**
99
55
  Sort a table.
107
63
  The result set is stored in table->io_cache or
108
64
  table->record_pointers.
109
65
 
110
 
  @param session           Current thread
 
66
  @param thd           Current thread
111
67
  @param table          Table to sort
112
68
  @param sortorder      How to sort the table
113
69
  @param s_length       Number of elements in sortorder
131
87
    examined_rows       will be set to number of examined rows
132
88
*/
133
89
 
134
 
ha_rows filesort(Session *session, Table *table, SortField *sortorder, uint32_t s_length,
135
 
                 optimizer::SqlSelect *select, ha_rows max_rows,
 
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
 
91
                 SQL_SELECT *select, ha_rows max_rows,
136
92
                 bool sort_positions, ha_rows *examined_rows)
137
93
{
138
94
  int error;
139
95
  uint32_t memavl, min_sort_memory;
140
96
  uint32_t maxbuffer;
141
 
  buffpek_st *buffpek;
 
97
  BUFFPEK *buffpek;
142
98
  ha_rows records= HA_POS_ERROR;
143
99
  unsigned char **sort_keys= 0;
144
 
  internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
 
100
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; 
145
101
  SORTPARAM param;
146
102
  bool multi_byte_charset;
147
103
 
149
105
  TableList *tab= table->pos_in_table_list;
150
106
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
151
107
 
152
 
  DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
108
  DRIZZLE_FILESORT_START();
153
109
 
154
110
  /*
155
111
   Release InnoDB's adaptive hash index latch (if holding) before
156
112
   running a sort.
157
113
  */
158
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
114
  ha_release_temporary_latches(thd);
159
115
 
160
 
  /*
161
 
    Don't use table->sort in filesort as it is also used by
162
 
    QuickIndexMergeSelect. Work with a copy and put it back at the end
 
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 
163
119
    when index_merge select has finished with it.
164
120
  */
165
121
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
166
122
  table->sort.io_cache= NULL;
167
 
 
 
123
  
168
124
  outfile= table_sort.io_cache;
169
125
  my_b_clear(&tempfile);
170
126
  my_b_clear(&buffpek_pointers);
171
127
  buffpek=0;
172
128
  error= 1;
173
129
  memset(&param, 0, sizeof(param));
174
 
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
175
 
  param.ref_length= table->cursor->ref_length;
 
130
  param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
 
131
  param.ref_length= table->file->ref_length;
176
132
  param.addon_field= 0;
177
133
  param.addon_length= 0;
178
 
  if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
 
134
  if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
179
135
  {
180
 
    /*
181
 
      Get the descriptors of all fields whose values are appended
 
136
    /* 
 
137
      Get the descriptors of all fields whose values are appended 
182
138
      to sorted fields and get its total length in param.spack_length.
183
139
    */
184
 
    param.addon_field= get_addon_fields(session, table->getFields(),
 
140
    param.addon_field= get_addon_fields(thd, table->field, 
185
141
                                        param.sort_length,
186
142
                                        &param.addon_length);
187
143
  }
193
149
  if (param.addon_field)
194
150
  {
195
151
    param.res_length= param.addon_length;
196
 
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
 
152
    if (!(table_sort.addon_buf= (unsigned char *) my_malloc(param.addon_length,
 
153
                                                    MYF(MY_WME))))
197
154
      goto err;
198
155
  }
199
156
  else
200
157
  {
201
158
    param.res_length= param.ref_length;
202
 
    /*
203
 
      The reference to the record is considered
 
159
    /* 
 
160
      The reference to the record is considered 
204
161
      as an additional sorted field
205
162
    */
206
163
    param.sort_length+= param.ref_length;
210
167
 
211
168
  if (select && select->quick)
212
169
  {
213
 
    session->status_var.filesort_range_count++;
 
170
    status_var_increment(thd->status_var.filesort_range_count);
214
171
  }
215
172
  else
216
173
  {
217
 
    session->status_var.filesort_scan_count++;
 
174
    status_var_increment(thd->status_var.filesort_scan_count);
218
175
  }
219
176
#ifdef CAN_TRUST_RANGE
220
177
  if (select && select->quick && select->quick->records > 0L)
221
178
  {
222
 
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
223
 
                 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;
224
181
    selected_records_file=0;
225
182
  }
226
183
  else
227
184
#endif
228
185
  {
229
 
    records= table->cursor->estimate_rows_upper_bound();
 
186
    records= table->file->estimate_rows_upper_bound();
230
187
    /*
231
 
      If number of records is not known, use as much of sort buffer
232
 
      as possible.
 
188
      If number of records is not known, use as much of sort buffer 
 
189
      as possible. 
233
190
    */
234
191
    if (records == HA_POS_ERROR)
235
192
      records--;  // we use 'records+1' below.
237
194
  }
238
195
 
239
196
  if (multi_byte_charset &&
240
 
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
 
197
      !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
241
198
    goto err;
242
199
 
243
 
  memavl= session->variables.sortbuff_size;
244
 
  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);
245
202
  while (memavl >= min_sort_memory)
246
203
  {
247
204
    uint32_t old_memavl;
248
205
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
249
 
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
 
206
    param.keys=(uint32_t) cmin(records+1, keys);
250
207
    if ((table_sort.sort_keys=
251
208
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
252
 
                                            param.keys, param.rec_length)))
 
209
                                    param.keys, param.rec_length, MYF(0))))
253
210
      break;
254
 
    old_memavl= memavl;
255
 
    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)
256
213
      memavl= min_sort_memory;
257
214
  }
258
215
  sort_keys= table_sort.sort_keys;
261
218
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
262
219
    goto err;
263
220
  }
264
 
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
 
221
  if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
265
222
                       DISK_BUFFER_SIZE, MYF(MY_WME)))
266
223
    goto err;
267
224
 
268
225
  param.keys--;                         /* TODO: check why we do this */
269
226
  param.sort_form= table;
270
227
  param.end=(param.local_sortorder=sortorder)+s_length;
271
 
  if ((records=find_all_keys(session, &param,select,sort_keys, &buffpek_pointers,
 
228
  if ((records=find_all_keys(&param,select,sort_keys, &buffpek_pointers,
272
229
                             &tempfile, selected_records_file)) ==
273
230
      HA_POS_ERROR)
274
231
    goto err;
291
248
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
292
249
                                 table_sort.buffpek)))
293
250
      goto err;
294
 
    buffpek= (buffpek_st *) table_sort.buffpek;
 
251
    buffpek= (BUFFPEK *) table_sort.buffpek;
295
252
    table_sort.buffpek_len= maxbuffer;
296
253
    close_cached_file(&buffpek_pointers);
297
254
        /* Open cached file if it isn't open */
298
255
    if (! my_b_inited(outfile) &&
299
 
        open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
 
256
        open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
300
257
                          MYF(MY_WME)))
301
258
      goto err;
302
 
    if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
 
259
    if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
303
260
      goto err;
304
261
 
305
262
    /*
313
270
                        &tempfile))
314
271
      goto err;
315
272
    if (flush_io_cache(&tempfile) ||
316
 
        reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
 
273
        reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
317
274
      goto err;
318
275
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
319
276
                    outfile))
329
286
      free(param.tmp_buffer);
330
287
  if (!subselect || !subselect->is_uncacheable())
331
288
  {
332
 
    free(sort_keys);
 
289
    if ((unsigned char*) sort_keys)
 
290
      free((unsigned char*) sort_keys);
333
291
    table_sort.sort_keys= 0;
334
 
    free(buffpek);
 
292
    if ((unsigned char*) buffpek)
 
293
      free((unsigned char*) buffpek);
335
294
    table_sort.buffpek= 0;
336
295
    table_sort.buffpek_len= 0;
337
296
  }
342
301
    if (flush_io_cache(outfile))
343
302
      error=1;
344
303
    {
345
 
      internal::my_off_t save_pos=outfile->pos_in_file;
 
304
      my_off_t save_pos=outfile->pos_in_file;
346
305
      /* For following reads */
347
 
      if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
 
306
      if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
348
307
        error=1;
349
308
      outfile->end_of_file=save_pos;
350
309
    }
351
310
  }
352
311
  if (error)
353
 
  {
354
312
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
355
313
               MYF(ME_ERROR+ME_WAITTANG));
356
 
  }
357
314
  else
358
 
  {
359
 
    session->status_var.filesort_rows+= (uint32_t) records;
360
 
  }
 
315
    statistic_add(thd->status_var.filesort_rows,
 
316
                  (uint32_t) records, &LOCK_status);
361
317
  *examined_rows= param.examined_rows;
362
318
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
363
 
  DRIZZLE_FILESORT_DONE(error, records);
364
 
  return (error ? HA_POS_ERROR : records);
 
319
  DRIZZLE_FILESORT_END();
 
320
  return(error ? HA_POS_ERROR : records);
365
321
} /* filesort */
366
322
 
367
323
 
368
 
void Table::filesort_free_buffers(bool full)
 
324
void filesort_free_buffers(Table *table, bool full)
369
325
{
370
 
  if (sort.record_pointers)
 
326
  if (table->sort.record_pointers)
371
327
  {
372
 
    free((unsigned char*) sort.record_pointers);
373
 
    sort.record_pointers=0;
 
328
    free((unsigned char*) table->sort.record_pointers);
 
329
    table->sort.record_pointers=0;
374
330
  }
375
331
  if (full)
376
332
  {
377
 
    if (sort.sort_keys )
 
333
    if (table->sort.sort_keys )
378
334
    {
379
 
      if ((unsigned char*) sort.sort_keys)
380
 
        free((unsigned char*) sort.sort_keys);
381
 
      sort.sort_keys= 0;
 
335
      if ((unsigned char*) table->sort.sort_keys)
 
336
        free((unsigned char*) table->sort.sort_keys);
 
337
      table->sort.sort_keys= 0;
382
338
    }
383
 
    if (sort.buffpek)
 
339
    if (table->sort.buffpek)
384
340
    {
385
 
      if ((unsigned char*) sort.buffpek)
386
 
        free((unsigned char*) sort.buffpek);
387
 
      sort.buffpek= 0;
388
 
      sort.buffpek_len= 0;
 
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;
389
345
    }
390
346
  }
391
 
  if (sort.addon_buf)
 
347
  if (table->sort.addon_buf)
392
348
  {
393
 
    free((char *) sort.addon_buf);
394
 
    free((char *) sort.addon_field);
395
 
    sort.addon_buf=0;
396
 
    sort.addon_field=0;
 
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;
397
353
  }
398
354
}
399
355
 
400
356
/** Make a array of string pointers. */
401
357
 
402
358
static char **make_char_array(char **old_pos, register uint32_t fields,
403
 
                              uint32_t length)
 
359
                              uint32_t length, myf my_flag)
404
360
{
405
361
  register char **pos;
406
362
  char *char_pos;
407
363
 
408
364
  if (old_pos ||
409
 
      (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)))
410
367
  {
411
368
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
412
369
    while (fields--) *(pos++) = (char_pos+= length);
418
375
 
419
376
/** Read 'count' number of buffer pointers into memory. */
420
377
 
421
 
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,
422
379
                                     unsigned char *buf)
423
380
{
424
 
  uint32_t length= sizeof(buffpek_st)*count;
 
381
  uint32_t length= sizeof(BUFFPEK)*count;
425
382
  unsigned char *tmp= buf;
426
 
  if (count > UINT_MAX/sizeof(buffpek_st))
427
 
    return 0; /* sizeof(buffpek_st)*count will overflow */
 
383
  if (count > UINT_MAX/sizeof(BUFFPEK))
 
384
    return 0; /* sizeof(BUFFPEK)*count will overflow */
428
385
  if (!tmp)
429
 
    tmp= (unsigned char *)malloc(length);
 
386
    tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
430
387
  if (tmp)
431
388
  {
432
 
    if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
 
389
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
433
390
        my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
434
391
    {
435
392
      free((char*) tmp);
447
404
  @param param             Sorting parameter
448
405
  @param select            Use this to get source data
449
406
  @param sort_keys         Array of pointers to sort key + addon buffers.
450
 
  @param buffpek_pointers  File to write buffpek_sts describing sorted segments
 
407
  @param buffpek_pointers  File to write BUFFPEKs describing sorted segments
451
408
                           in tempfile.
452
409
  @param tempfile          File to write sorted sequences of sortkeys to.
453
410
  @param indexfile         If !NULL, use it for source data (contains rowids)
461
418
       {
462
419
         sort sort_keys buffer;
463
420
         dump sorted sequence to 'tempfile';
464
 
         dump buffpek_st describing sequence location into 'buffpek_pointers';
 
421
         dump BUFFPEK describing sequence location into 'buffpek_pointers';
465
422
       }
466
423
       put sort key into 'sort_keys';
467
424
     }
477
434
    HA_POS_ERROR on error.
478
435
*/
479
436
 
480
 
static ha_rows find_all_keys(Session *session,
481
 
                             SORTPARAM *param, 
482
 
                             optimizer::SqlSelect *select,
 
437
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
483
438
                             unsigned char **sort_keys,
484
 
                             internal::IO_CACHE *buffpek_pointers,
485
 
                             internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
 
439
                             IO_CACHE *buffpek_pointers,
 
440
                             IO_CACHE *tempfile, IO_CACHE *indexfile)
486
441
{
487
442
  int error,flag,quick_select;
488
443
  uint32_t idx,indexpos,ref_length;
489
444
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
490
 
  internal::my_off_t record;
 
445
  my_off_t record;
491
446
  Table *sort_form;
492
 
  volatile Session::killed_state *killed= &session->killed;
493
 
  Cursor *file;
494
 
  MyBitmap *save_read_set, *save_write_set;
 
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;
495
451
 
496
452
  idx=indexpos=0;
497
453
  error=quick_select=0;
498
454
  sort_form=param->sort_form;
499
 
  file= sort_form->cursor;
 
455
  file=sort_form->file;
500
456
  ref_length=param->ref_length;
501
457
  ref_pos= ref_buff;
502
458
  quick_select=select && select->quick;
503
459
  record=0;
504
 
  flag= ((!indexfile && ! file->isOrdered())
 
460
  flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
505
461
         || quick_select);
506
462
  if (indexfile || flag)
507
463
    ref_pos= &file->ref[0];
509
465
  if (! indexfile && ! quick_select)
510
466
  {
511
467
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
512
 
    file->startTableScan(1);
 
468
    file->ha_rnd_init(1);
513
469
    file->extra_opt(HA_EXTRA_CACHE,
514
 
                    session->variables.read_buff_size);
 
470
                    current_thd->variables.read_buff_size);
515
471
  }
516
472
 
517
 
  ReadRecord read_record_info;
 
473
  READ_RECORD read_record_info;
518
474
  if (quick_select)
519
475
  {
520
476
    if (select->quick->reset())
521
477
      return(HA_POS_ERROR);
522
 
 
523
 
    read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
 
478
    init_read_record(&read_record_info, current_thd, select->quick->head,
 
479
                     select, 1, 1);
524
480
  }
525
481
 
526
482
  /* Remember original bitmaps */
527
483
  save_read_set=  sort_form->read_set;
528
484
  save_write_set= sort_form->write_set;
529
485
  /* Set up temporary column read map for columns used by sort */
530
 
  sort_form->tmp_set.clearAll();
 
486
  bitmap_clear_all(&sort_form->tmp_set);
531
487
  /* Temporary set for register_used_fields and register_field_in_read_map */
532
488
  sort_form->read_set= &sort_form->tmp_set;
533
489
  register_used_fields(param);
545
501
        error= HA_ERR_END_OF_FILE;
546
502
        break;
547
503
      }
548
 
      file->position(sort_form->getInsertRecord());
 
504
      file->position(sort_form->record[0]);
549
505
    }
550
506
    else                                        /* Not quick-select */
551
507
    {
552
508
      if (indexfile)
553
509
      {
554
 
        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 */
555
511
        {
556
 
          error= errno ? errno : -1;            /* Abort */
 
512
          error= my_errno ? my_errno : -1;              /* Abort */
557
513
          break;
558
514
        }
559
 
        error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
 
515
        error=file->rnd_pos(sort_form->record[0],next_pos);
560
516
      }
561
517
      else
562
518
      {
563
 
        error=file->rnd_next(sort_form->getInsertRecord());
564
 
 
 
519
        error=file->rnd_next(sort_form->record[0]);
565
520
        if (!flag)
566
521
        {
567
 
          internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
568
 
          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;
569
524
        }
570
525
        else if (!error)
571
 
          file->position(sort_form->getInsertRecord());
 
526
          file->position(sort_form->record[0]);
572
527
      }
573
528
      if (error && error != HA_ERR_RECORD_DELETED)
574
529
        break;
579
534
      if (!indexfile && !quick_select)
580
535
      {
581
536
        (void) file->extra(HA_EXTRA_NO_CACHE);
582
 
        file->endTableScan();
 
537
        file->ha_rnd_end();
583
538
      }
584
 
      return(HA_POS_ERROR);
 
539
      return(HA_POS_ERROR);             /* purecov: inspected */
585
540
    }
586
541
    if (error == 0)
587
542
      param->examined_rows++;
599
554
    else
600
555
      file->unlock_row();
601
556
    /* It does not make sense to read more keys in case of a fatal error */
602
 
    if (session->is_error())
 
557
    if (thd->is_error())
603
558
      break;
604
559
  }
605
560
  if (quick_select)
608
563
      index_merge quick select uses table->sort when retrieving rows, so free
609
564
      resoures it has allocated.
610
565
    */
611
 
    read_record_info.end_read_record();
 
566
    end_read_record(&read_record_info);
612
567
  }
613
568
  else
614
569
  {
615
570
    (void) file->extra(HA_EXTRA_NO_CACHE);      /* End cacheing of records */
616
571
    if (!next_pos)
617
 
      file->endTableScan();
 
572
      file->ha_rnd_end();
618
573
  }
619
574
 
620
 
  if (session->is_error())
 
575
  if (thd->is_error())
621
576
    return(HA_POS_ERROR);
622
 
 
 
577
  
623
578
  /* Signal we should use orignal column read and write maps */
624
579
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
625
580
 
626
581
  if (error != HA_ERR_END_OF_FILE)
627
582
  {
628
 
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
629
 
    return(HA_POS_ERROR);
 
583
    file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
 
584
    return(HA_POS_ERROR);                       /* purecov: inspected */
630
585
  }
631
586
  if (indexpos && idx &&
632
587
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
633
 
    return(HA_POS_ERROR);
 
588
    return(HA_POS_ERROR);                       /* purecov: inspected */
634
589
  return(my_b_inited(tempfile) ?
635
590
              (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
636
591
              idx);
641
596
  @details
642
597
  Sort the buffer and write:
643
598
  -# the sorted sequence to tempfile
644
 
  -# a buffpek_st describing the sorted sequence position to buffpek_pointers
 
599
  -# a BUFFPEK describing the sorted sequence position to buffpek_pointers
645
600
 
646
601
    (was: Skriver en buffert med nycklar till filen)
647
602
 
648
603
  @param param             Sort parameters
649
604
  @param sort_keys         Array of pointers to keys to sort
650
605
  @param count             Number of elements in sort_keys array
651
 
  @param buffpek_pointers  One 'buffpek_st' struct will be written into this file.
652
 
                           The buffpek_st::{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
653
608
                           the sorted data was stored.
654
609
  @param tempfile          The sorted sequence will be written into this file.
655
610
 
661
616
 
662
617
static int
663
618
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
664
 
           internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
 
619
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
665
620
{
666
621
  size_t sort_length, rec_length;
667
622
  unsigned char **end;
668
 
  buffpek_st buffpek;
 
623
  BUFFPEK buffpek;
669
624
 
670
625
  sort_length= param->sort_length;
671
626
  rec_length= param->rec_length;
672
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
 
627
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
673
628
  if (!my_b_inited(tempfile) &&
674
 
      open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
 
629
      open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
675
630
                       MYF(MY_WME)))
676
 
    goto err;
 
631
    goto err;                                   /* purecov: inspected */
677
632
  /* check we won't have more buffpeks than we can possibly keep in memory */
678
 
  if (my_b_tell(buffpek_pointers) + sizeof(buffpek_st) > (uint64_t)UINT_MAX)
 
633
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
679
634
    goto err;
680
635
  buffpek.file_pos= my_b_tell(tempfile);
681
636
  if ((ha_rows) count > param->max_rows)
682
 
    count=(uint32_t) param->max_rows;
 
637
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
683
638
  buffpek.count=(ha_rows) count;
684
639
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
685
640
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
721
676
static void make_sortkey(register SORTPARAM *param,
722
677
                         register unsigned char *to, unsigned char *ref_pos)
723
678
{
724
 
  Field *field;
725
 
  SortField *sort_field;
726
 
  size_t length;
 
679
  register Field *field;
 
680
  register SORT_FIELD *sort_field;
 
681
  register uint32_t length;
727
682
 
728
683
  for (sort_field=param->local_sortorder ;
729
684
       sort_field != param->end ;
771
726
            memset(to-1, 0, sort_field->length+1);
772
727
          else
773
728
          {
 
729
            /* purecov: begin deadcode */
774
730
            /*
775
731
              This should only happen during extreme conditions if we run out
776
732
              of memory or have an item marked not null when it can be null.
778
734
            */
779
735
            assert(0);
780
736
            memset(to, 0, sort_field->length);  // Avoid crash
 
737
            /* purecov: end */
781
738
          }
782
739
          break;
783
740
        }
821
778
          int64_t value= item->val_int_result();
822
779
          if (maybe_null)
823
780
          {
824
 
            *to++=1;
 
781
            *to++=1;                            /* purecov: inspected */
825
782
            if (item->null_value)
826
783
            {
827
784
              if (maybe_null)
852
809
          if (maybe_null)
853
810
          {
854
811
            if (item->null_value)
855
 
            {
 
812
            { 
856
813
              memset(to, 0, sort_field->length+1);
857
814
              to++;
858
815
              break;
881
838
          break;
882
839
        }
883
840
      case ROW_RESULT:
884
 
      default:
 
841
      default: 
885
842
        // This case should never be choosen
886
843
        assert(0);
887
844
        break;
904
861
 
905
862
  if (param->addon_field)
906
863
  {
907
 
    /*
 
864
    /* 
908
865
      Save field values appended to sorted fields.
909
866
      First null bit indicators are appended then field values follow.
910
867
      In this implementation we use fixed layout for field values -
911
868
      the same for all records.
912
869
    */
913
 
    sort_addon_field_st *addonf= param->addon_field;
 
870
    SORT_ADDON_FIELD *addonf= param->addon_field;
914
871
    unsigned char *nulls= to;
915
872
    assert(addonf != 0);
916
873
    memset(nulls, 0, addonf->offset);
954
911
 
955
912
static void register_used_fields(SORTPARAM *param)
956
913
{
957
 
  SortField *sort_field;
 
914
  register SORT_FIELD *sort_field;
958
915
  Table *table=param->sort_form;
 
916
  MY_BITMAP *bitmap= table->read_set;
959
917
 
960
918
  for (sort_field= param->local_sortorder ;
961
919
       sort_field != param->end ;
964
922
    Field *field;
965
923
    if ((field= sort_field->field))
966
924
    {
967
 
      if (field->getTable() == table)
968
 
        table->setReadSet(field->field_index);
 
925
      if (field->table == table)
 
926
      bitmap_set_bit(bitmap, field->field_index);
969
927
    }
970
928
    else
971
929
    {                                           // Item
976
934
 
977
935
  if (param->addon_field)
978
936
  {
979
 
    sort_addon_field_st *addonf= param->addon_field;
 
937
    SORT_ADDON_FIELD *addonf= param->addon_field;
980
938
    Field *field;
981
939
    for ( ; (field= addonf->field) ; addonf++)
982
 
      table->setReadSet(field->field_index);
 
940
      bitmap_set_bit(bitmap, field->field_index);
983
941
  }
984
942
  else
985
943
  {
989
947
}
990
948
 
991
949
 
992
 
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
 
950
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count, 
993
951
                       filesort_info_st *table_sort)
994
952
{
995
953
  uint32_t offset,res_length;
996
954
  unsigned char *to;
997
955
 
998
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
 
956
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
999
957
  res_length= param->res_length;
1000
958
  offset= param->rec_length-res_length;
1001
959
  if ((ha_rows) count > param->max_rows)
1002
960
    count=(uint32_t) param->max_rows;
1003
 
  if (!(to= table_sort->record_pointers=
1004
 
        (unsigned char*) malloc(res_length*count)))
1005
 
    return(1);
 
961
  if (!(to= table_sort->record_pointers= 
 
962
        (unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
 
963
    return(1);                 /* purecov: inspected */
1006
964
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1007
965
  {
1008
966
    memcpy(to, *sort_keys+offset, res_length);
1015
973
/** Merge buffers to make < MERGEBUFF2 buffers. */
1016
974
 
1017
975
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1018
 
                    buffpek_st *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
 
976
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1019
977
{
1020
978
  register uint32_t i;
1021
 
  internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1022
 
  buffpek_st *lastbuff;
 
979
  IO_CACHE t_file2,*from_file,*to_file,*temp;
 
980
  BUFFPEK *lastbuff;
1023
981
 
1024
982
  if (*maxbuffer < MERGEBUFF2)
1025
 
    return(0);
 
983
    return(0);                          /* purecov: inspected */
1026
984
  if (flush_io_cache(t_file) ||
1027
 
      open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
 
985
      open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1028
986
                        MYF(MY_WME)))
1029
 
    return(1);
 
987
    return(1);                          /* purecov: inspected */
1030
988
 
1031
989
  from_file= t_file ; to_file= &t_file2;
1032
990
  while (*maxbuffer >= MERGEBUFF2)
1033
991
  {
1034
 
    if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
 
992
    if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1035
993
      goto cleanup;
1036
 
    if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
 
994
    if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1037
995
      goto cleanup;
1038
996
    lastbuff=buffpek;
1039
997
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1044
1002
    }
1045
1003
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1046
1004
                      buffpek+i,buffpek+ *maxbuffer,0))
1047
 
      break;
 
1005
      break;                                    /* purecov: inspected */
1048
1006
    if (flush_io_cache(to_file))
1049
 
      break;
 
1007
      break;                                    /* purecov: inspected */
1050
1008
    temp=from_file; from_file=to_file; to_file=temp;
1051
1009
    setup_io_cache(from_file);
1052
1010
    setup_io_cache(to_file);
1071
1029
    (uint32_t)-1 if something goes wrong
1072
1030
*/
1073
1031
 
1074
 
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, buffpek_st *buffpek,
1075
 
                        uint32_t rec_length)
 
1032
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1033
                    uint32_t rec_length)
1076
1034
{
1077
1035
  register uint32_t count;
1078
1036
  uint32_t length;
1079
1037
 
1080
 
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
 
1038
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1081
1039
  {
1082
1040
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1083
 
      return((uint32_t) -1);
1084
 
 
1085
 
    buffpek->key= buffpek->base;
 
1041
      return((uint32_t) -1);                    /* purecov: inspected */
 
1042
    buffpek->key=buffpek->base;
1086
1043
    buffpek->file_pos+= length;                 /* New filepos */
1087
 
    buffpek->count-= count;
 
1044
    buffpek->count-=    count;
1088
1045
    buffpek->mem_count= count;
1089
1046
  }
1090
1047
  return (count*rec_length);
1091
1048
} /* read_to_buffer */
1092
1049
 
1093
1050
 
1094
 
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)
1095
1063
{
1096
 
  qsort2_cmp key_compare;
1097
 
  void *key_compare_arg;
1098
 
  public:
1099
 
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1100
 
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1101
 
  inline bool operator()(const buffpek_st *i, const buffpek_st *j) const
 
1064
  unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
 
1065
  for (uint32_t i= 0; i < queue->elements; ++i)
1102
1066
  {
1103
 
    int val= key_compare(key_compare_arg,
1104
 
                      &i->key, &j->key);
1105
 
    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
    }
1106
1079
  }
1107
 
};
 
1080
  assert(0);
 
1081
}
1108
1082
 
1109
1083
 
1110
1084
/**
1111
1085
  Merge buffers to one buffer.
1112
1086
 
1113
1087
  @param param        Sort parameter
1114
 
  @param from_file    File with source data (buffpek_sts point to this file)
 
1088
  @param from_file    File with source data (BUFFPEKs point to this file)
1115
1089
  @param to_file      File to write the sorted result data.
1116
1090
  @param sort_buffer  Buffer for data to store up to MERGEBUFF2 sort keys.
1117
 
  @param lastbuff     OUT Store here buffpek_st describing data written to to_file
1118
 
  @param Fb           First element in source buffpek_sts array
1119
 
  @param Tb           Last element in source buffpek_sts 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
1120
1094
  @param flag
1121
1095
 
1122
1096
  @retval
1125
1099
    other  error
1126
1100
*/
1127
1101
 
1128
 
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1129
 
                  internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1130
 
                  buffpek_st *lastbuff, buffpek_st *Fb, buffpek_st *Tb,
 
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,
1131
1105
                  int flag)
1132
1106
{
1133
1107
  int error;
1135
1109
  size_t sort_length;
1136
1110
  uint32_t maxcount;
1137
1111
  ha_rows max_rows,org_max_rows;
1138
 
  internal::my_off_t to_start_filepos;
 
1112
  my_off_t to_start_filepos;
1139
1113
  unsigned char *strpos;
1140
 
  buffpek_st *buffpek;
 
1114
  BUFFPEK *buffpek;
 
1115
  QUEUE queue;
1141
1116
  qsort2_cmp cmp;
1142
1117
  void *first_cmp_arg;
1143
 
  volatile Session::killed_state *killed= &current_session->killed;
1144
 
  Session::killed_state not_killable;
 
1118
  volatile THD::killed_state *killed= &current_thd->killed;
 
1119
  THD::killed_state not_killable;
1145
1120
 
1146
 
  current_session->status_var.filesort_merge_passes++;
 
1121
  status_var_increment(current_thd->status_var.filesort_merge_passes);
1147
1122
  if (param->not_killable)
1148
1123
  {
1149
1124
    killed= &not_killable;
1150
 
    not_killable= Session::NOT_KILLED;
 
1125
    not_killable= THD::NOT_KILLED;
1151
1126
  }
1152
1127
 
1153
1128
  error=0;
1162
1137
 
1163
1138
  /* The following will fire if there is not enough space in sort_buffer */
1164
1139
  assert(maxcount!=0);
1165
 
 
 
1140
  
1166
1141
  if (param->unique_buff)
1167
1142
  {
1168
1143
    cmp= param->compare;
1170
1145
  }
1171
1146
  else
1172
1147
  {
1173
 
    cmp= internal::get_ptr_compare(sort_length);
 
1148
    cmp= get_ptr_compare(sort_length);
1174
1149
    first_cmp_arg= (void*) &sort_length;
1175
1150
  }
1176
 
  priority_queue<buffpek_st *, vector<buffpek_st *>, compare_functor > 
1177
 
    queue(compare_functor(cmp, first_cmp_arg));
 
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 */
1178
1154
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1179
1155
  {
1180
1156
    buffpek->base= strpos;
1182
1158
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1183
1159
                                                                         rec_length));
1184
1160
    if (error == -1)
1185
 
      goto err;
 
1161
      goto err;                                 /* purecov: inspected */
1186
1162
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
1187
 
    queue.push(buffpek);
 
1163
    queue_insert(&queue, (unsigned char*) buffpek);
1188
1164
  }
1189
1165
 
1190
1166
  if (param->unique_buff)
1191
1167
  {
1192
 
    /*
 
1168
    /* 
1193
1169
       Called by Unique::get()
1194
1170
       Copy the first argument to param->unique_buff for unique removal.
1195
1171
       Store it also in 'to_file'.
1197
1173
       This is safe as we know that there is always more than one element
1198
1174
       in each block to merge (This is guaranteed by the Unique:: algorithm
1199
1175
    */
1200
 
    buffpek= queue.top();
 
1176
    buffpek= (BUFFPEK*) queue_top(&queue);
1201
1177
    memcpy(param->unique_buff, buffpek->key, rec_length);
1202
1178
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1203
1179
    {
1204
 
      error=1; goto err;
 
1180
      error=1; goto err;                        /* purecov: inspected */
1205
1181
    }
1206
1182
    buffpek->key+= rec_length;
1207
1183
    buffpek->mem_count--;
1208
1184
    if (!--max_rows)
1209
1185
    {
1210
 
      error= 0;
1211
 
      goto end;
 
1186
      error= 0;                                       /* purecov: inspected */
 
1187
      goto end;                                       /* purecov: inspected */
1212
1188
    }
1213
 
    /* Top element has been used */
1214
 
    queue.pop();
1215
 
    queue.push(buffpek);
 
1189
    queue_replaced(&queue);                        // Top element has been used
1216
1190
  }
1217
1191
  else
1218
1192
    cmp= 0;                                        // Not unique
1219
1193
 
1220
 
  while (queue.size() > 1)
 
1194
  while (queue.elements > 1)
1221
1195
  {
1222
1196
    if (*killed)
1223
1197
    {
1224
 
      error= 1; goto err;
 
1198
      error= 1; goto err;                        /* purecov: inspected */
1225
1199
    }
1226
1200
    for (;;)
1227
1201
    {
1228
 
      buffpek= queue.top();
 
1202
      buffpek= (BUFFPEK*) queue_top(&queue);
1229
1203
      if (cmp)                                        // Remove duplicates
1230
1204
      {
1231
1205
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1237
1211
      {
1238
1212
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1239
1213
        {
1240
 
          error=1; goto err;
 
1214
          error=1; goto err;                        /* purecov: inspected */
1241
1215
        }
1242
1216
      }
1243
1217
      else
1244
1218
      {
1245
1219
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1246
1220
        {
1247
 
          error=1; goto err;
 
1221
          error=1; goto err;                        /* purecov: inspected */
1248
1222
        }
1249
1223
      }
1250
1224
      if (!--max_rows)
1251
1225
      {
1252
 
        error= 0;
1253
 
        goto end;
 
1226
        error= 0;                               /* purecov: inspected */
 
1227
        goto end;                               /* purecov: inspected */
1254
1228
      }
1255
1229
 
1256
1230
    skip_duplicate:
1260
1234
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1261
1235
                                          rec_length)))
1262
1236
        {
1263
 
          queue.pop();
 
1237
          queue_remove(&queue,0);
 
1238
          reuse_freed_buff(&queue, buffpek, rec_length);
1264
1239
          break;                        /* One buffer have been removed */
1265
1240
        }
1266
1241
        else if (error == -1)
1267
 
          goto err;
 
1242
          goto err;                        /* purecov: inspected */
1268
1243
      }
1269
 
      /* Top element has been replaced */
1270
 
      queue.pop();
1271
 
      queue.push(buffpek);
 
1244
      queue_replaced(&queue);              /* Top element has been replaced */
1272
1245
    }
1273
1246
  }
1274
 
  buffpek= queue.top();
 
1247
  buffpek= (BUFFPEK*) queue_top(&queue);
1275
1248
  buffpek->base= sort_buffer;
1276
1249
  buffpek->max_keys= param->keys;
1277
1250
 
1301
1274
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1302
1275
                     (rec_length*buffpek->mem_count)))
1303
1276
      {
1304
 
        error= 1; goto err;
 
1277
        error= 1; goto err;                        /* purecov: inspected */
1305
1278
      }
1306
1279
    }
1307
1280
    else
1311
1284
      for (end= strpos+buffpek->mem_count*rec_length ;
1312
1285
           strpos != end ;
1313
1286
           strpos+= rec_length)
1314
 
      {
 
1287
      {     
1315
1288
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1316
1289
        {
1317
 
          error=1; goto err;
 
1290
          error=1; goto err;                        
1318
1291
        }
1319
1292
      }
1320
1293
    }
1323
1296
         != -1 && error != 0);
1324
1297
 
1325
1298
end:
1326
 
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
 
1299
  lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1327
1300
  lastbuff->file_pos= to_start_filepos;
1328
1301
err:
 
1302
  delete_queue(&queue);
1329
1303
  return(error);
1330
1304
} /* merge_buffers */
1331
1305
 
1333
1307
        /* Do a merge to output-file (save only positions) */
1334
1308
 
1335
1309
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1336
 
                       buffpek_st *buffpek, uint32_t maxbuffer,
1337
 
                       internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
 
1310
                       BUFFPEK *buffpek, uint32_t maxbuffer,
 
1311
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1338
1312
{
1339
1313
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1340
1314
                    buffpek+maxbuffer,1))
1341
 
    return(1);
 
1315
    return(1);                          /* purecov: inspected */
1342
1316
  return(0);
1343
1317
} /* merge_index */
1344
1318
 
1359
1333
/**
1360
1334
  Calculate length of sort key.
1361
1335
 
1362
 
  @param session                          Thread Cursor
 
1336
  @param thd                      Thread handler
1363
1337
  @param sortorder                Order of items to sort
1364
1338
  @param s_length                 Number of items to sort
1365
1339
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1375
1349
*/
1376
1350
 
1377
1351
static uint32_t
1378
 
sortlength(Session *session, SortField *sortorder, uint32_t s_length,
 
1352
sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
1379
1353
           bool *multi_byte_charset)
1380
1354
{
1381
1355
  register uint32_t length;
1409
1383
      switch (sortorder->result_type) {
1410
1384
      case STRING_RESULT:
1411
1385
        sortorder->length=sortorder->item->max_length;
1412
 
        set_if_smaller(sortorder->length,
1413
 
                       session->variables.max_sort_length);
 
1386
        set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1414
1387
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1415
 
        {
 
1388
        { 
1416
1389
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1417
1390
          sortorder->need_strxnfrm= 1;
1418
1391
          *multi_byte_charset= 1;
1429
1402
        break;
1430
1403
      case DECIMAL_RESULT:
1431
1404
        sortorder->length=
1432
 
          my_decimal_get_binary_size(sortorder->item->max_length -
 
1405
          my_decimal_get_binary_size(sortorder->item->max_length - 
1433
1406
                                     (sortorder->item->decimals ? 1 : 0),
1434
1407
                                     sortorder->item->decimals);
1435
1408
        break;
1437
1410
        sortorder->length=sizeof(double);
1438
1411
        break;
1439
1412
      case ROW_RESULT:
1440
 
      default:
 
1413
      default: 
1441
1414
        // This case should never be choosen
1442
1415
        assert(0);
1443
1416
        break;
1445
1418
      if (sortorder->item->maybe_null)
1446
1419
        length++;                               // Place for NULL marker
1447
1420
    }
1448
 
    set_if_smaller(sortorder->length,
1449
 
                   (size_t)session->variables.max_sort_length);
 
1421
    set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1450
1422
    length+=sortorder->length;
1451
1423
  }
1452
1424
  sortorder->field= (Field*) 0;                 // end marker
1460
1432
 
1461
1433
  The function first finds out what fields are used in the result set.
1462
1434
  Then it calculates the length of the buffer to store the values of
1463
 
  these fields together with the value of sort values.
 
1435
  these fields together with the value of sort values. 
1464
1436
  If the calculated length is not greater than max_length_for_sort_data
1465
1437
  the function allocates memory for an array of descriptors containing
1466
1438
  layouts for the values of the non-sorted fields in the buffer and
1467
1439
  fills them.
1468
1440
 
1469
 
  @param session                 Current thread
 
1441
  @param thd                 Current thread
1470
1442
  @param ptabfield           Array of references to the table fields
1471
1443
  @param sortlength          Total length of sorted fields
1472
1444
  @param[out] plength        Total length of appended fields
1481
1453
    NULL   if we do not store field values with sort data.
1482
1454
*/
1483
1455
 
1484
 
static sort_addon_field_st *
1485
 
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
 
1456
static SORT_ADDON_FIELD *
 
1457
get_addon_fields(THD *thd, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1486
1458
{
1487
1459
  Field **pfield;
1488
1460
  Field *field;
1489
 
  sort_addon_field_st *addonf;
 
1461
  SORT_ADDON_FIELD *addonf;
1490
1462
  uint32_t length= 0;
1491
1463
  uint32_t fields= 0;
1492
1464
  uint32_t null_fields= 0;
 
1465
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1493
1466
 
1494
1467
  /*
1495
1468
    If there is a reference to a field in the query add it
1497
1470
    Note for future refinement:
1498
1471
    This this a too strong condition.
1499
1472
    Actually we need only the fields referred in the
1500
 
    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 
1501
1474
    the values directly from sorted fields.
1502
1475
  */
1503
1476
  *plength= 0;
1504
1477
 
1505
1478
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1506
1479
  {
1507
 
    if (!(field->isReadSet()))
 
1480
    if (!bitmap_is_set(read_set, field->field_index))
1508
1481
      continue;
1509
1482
    if (field->flags & BLOB_FLAG)
1510
1483
      return 0;
1512
1485
    if (field->maybe_null())
1513
1486
      null_fields++;
1514
1487
    fields++;
1515
 
  }
 
1488
  } 
1516
1489
  if (!fields)
1517
1490
    return 0;
1518
1491
  length+= (null_fields+7)/8;
1519
1492
 
1520
 
  if (length+sortlength > session->variables.max_length_for_sort_data ||
1521
 
      !(addonf= (sort_addon_field_st *) malloc(sizeof(sort_addon_field_st)*
1522
 
                                            (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))))
1523
1496
    return 0;
1524
1497
 
1525
1498
  *plength= length;
1527
1500
  null_fields= 0;
1528
1501
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1529
1502
  {
1530
 
    if (!(field->isReadSet()))
 
1503
    if (!bitmap_is_set(read_set, field->field_index))
1531
1504
      continue;
1532
1505
    addonf->field= field;
1533
1506
    addonf->offset= length;
1547
1520
    addonf++;
1548
1521
  }
1549
1522
  addonf->field= 0;     // Put end marker
1550
 
 
 
1523
  
1551
1524
  return (addonf-fields);
1552
1525
}
1553
1526
 
1567
1540
    void.
1568
1541
*/
1569
1542
 
1570
 
static void
1571
 
unpack_addon_fields(struct sort_addon_field_st *addon_field, unsigned char *buff)
 
1543
static void 
 
1544
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1572
1545
{
1573
1546
  Field *field;
1574
 
  sort_addon_field_st *addonf= addon_field;
 
1547
  SORT_ADDON_FIELD *addonf= addon_field;
1575
1548
 
1576
1549
  for ( ; (field= addonf->field) ; addonf++)
1577
1550
  {
1632
1605
    }
1633
1606
  }
1634
1607
}
1635
 
 
1636
 
} /* namespace drizzled */