~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2009-03-16 16:56:48 UTC
  • mto: This revision was merged to the branch mainline in revision 938.
  • Revision ID: mordred@inaugust.com-20090316165648-0dsce73jne0qikk0
Addd -Wshadow to PROTOSKIP warnings and turned -Wstrict-aliasing off. Jumped the gun...

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