~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
Remove uint.

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(SORTPARAM *param,
60
 
                             optimizer::SqlSelect *select,
61
 
                             unsigned char * *sort_keys, 
62
 
                             internal::IO_CACHE *buffer_file,
63
 
                             internal::IO_CACHE *tempfile,
64
 
                             internal::IO_CACHE *indexfile);
65
 
 
66
 
static int write_keys(SORTPARAM *param,
67
 
                      unsigned char * *sort_keys,
68
 
                      uint32_t count,
69
 
                      internal::IO_CACHE *buffer_file,
70
 
                      internal::IO_CACHE *tempfile);
71
 
 
72
 
static void make_sortkey(SORTPARAM *param,
73
 
                         unsigned char *to,
74
 
                         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);
75
40
static void register_used_fields(SORTPARAM *param);
76
 
static int merge_index(SORTPARAM *param,
77
 
                       unsigned char *sort_buffer,
 
41
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
78
42
                       BUFFPEK *buffpek,
79
 
                       uint32_t maxbuffer,
80
 
                       internal::IO_CACHE *tempfile,
81
 
                       internal::IO_CACHE *outfile);
82
 
static bool save_index(SORTPARAM *param,
83
 
                       unsigned char **sort_keys,
84
 
                       uint32_t count,
 
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, 
85
46
                       filesort_info_st *table_sort);
86
47
static uint32_t suffix_length(uint32_t string_length);
87
 
static uint32_t sortlength(Session *session,
88
 
                           SORT_FIELD *sortorder,
89
 
                           uint32_t s_length,
90
 
                           bool *multi_byte_charset);
91
 
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
92
 
                                          Field **ptabfield,
93
 
                                          uint32_t sortlength,
94
 
                                          uint32_t *plength);
 
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);
95
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
96
53
                                unsigned char *buff);
97
54
/**
106
63
  The result set is stored in table->io_cache or
107
64
  table->record_pointers.
108
65
 
109
 
  @param session           Current thread
 
66
  @param thd           Current thread
110
67
  @param table          Table to sort
111
68
  @param sortorder      How to sort the table
112
69
  @param s_length       Number of elements in sortorder
130
87
    examined_rows       will be set to number of examined rows
131
88
*/
132
89
 
133
 
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
134
 
                 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,
135
92
                 bool sort_positions, ha_rows *examined_rows)
136
93
{
137
94
  int error;
140
97
  BUFFPEK *buffpek;
141
98
  ha_rows records= HA_POS_ERROR;
142
99
  unsigned char **sort_keys= 0;
143
 
  internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
 
100
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; 
144
101
  SORTPARAM param;
145
102
  bool multi_byte_charset;
146
103
 
148
105
  TableList *tab= table->pos_in_table_list;
149
106
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
150
107
 
151
 
  DRIZZLE_FILESORT_START(table->s->getSchemaName(), table->s->getTableName());
 
108
  DRIZZLE_FILESORT_START();
152
109
 
153
110
  /*
154
111
   Release InnoDB's adaptive hash index latch (if holding) before
155
112
   running a sort.
156
113
  */
157
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
114
  ha_release_temporary_latches(thd);
158
115
 
159
 
  /*
160
 
    Don't use table->sort in filesort as it is also used by
161
 
    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 
162
119
    when index_merge select has finished with it.
163
120
  */
164
121
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
165
122
  table->sort.io_cache= NULL;
166
 
 
 
123
  
167
124
  outfile= table_sort.io_cache;
168
125
  my_b_clear(&tempfile);
169
126
  my_b_clear(&buffpek_pointers);
170
127
  buffpek=0;
171
128
  error= 1;
172
129
  memset(&param, 0, sizeof(param));
173
 
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
174
 
  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;
175
132
  param.addon_field= 0;
176
133
  param.addon_length= 0;
177
 
  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)
178
135
  {
179
 
    /*
180
 
      Get the descriptors of all fields whose values are appended
 
136
    /* 
 
137
      Get the descriptors of all fields whose values are appended 
181
138
      to sorted fields and get its total length in param.spack_length.
182
139
    */
183
 
    param.addon_field= get_addon_fields(session, table->field,
 
140
    param.addon_field= get_addon_fields(thd, table->field, 
184
141
                                        param.sort_length,
185
142
                                        &param.addon_length);
186
143
  }
192
149
  if (param.addon_field)
193
150
  {
194
151
    param.res_length= param.addon_length;
195
 
    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))))
196
154
      goto err;
197
155
  }
198
156
  else
199
157
  {
200
158
    param.res_length= param.ref_length;
201
 
    /*
202
 
      The reference to the record is considered
 
159
    /* 
 
160
      The reference to the record is considered 
203
161
      as an additional sorted field
204
162
    */
205
163
    param.sort_length+= param.ref_length;
209
167
 
210
168
  if (select && select->quick)
211
169
  {
212
 
    status_var_increment(session->status_var.filesort_range_count);
 
170
    status_var_increment(thd->status_var.filesort_range_count);
213
171
  }
214
172
  else
215
173
  {
216
 
    status_var_increment(session->status_var.filesort_scan_count);
 
174
    status_var_increment(thd->status_var.filesort_scan_count);
217
175
  }
218
176
#ifdef CAN_TRUST_RANGE
219
177
  if (select && select->quick && select->quick->records > 0L)
220
178
  {
221
 
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
222
 
                 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;
223
181
    selected_records_file=0;
224
182
  }
225
183
  else
226
184
#endif
227
185
  {
228
 
    records= table->cursor->estimate_rows_upper_bound();
 
186
    records= table->file->estimate_rows_upper_bound();
229
187
    /*
230
 
      If number of records is not known, use as much of sort buffer
231
 
      as possible.
 
188
      If number of records is not known, use as much of sort buffer 
 
189
      as possible. 
232
190
    */
233
191
    if (records == HA_POS_ERROR)
234
192
      records--;  // we use 'records+1' below.
236
194
  }
237
195
 
238
196
  if (multi_byte_charset &&
239
 
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
 
197
      !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
240
198
    goto err;
241
199
 
242
 
  memavl= session->variables.sortbuff_size;
243
 
  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);
244
202
  while (memavl >= min_sort_memory)
245
203
  {
246
204
    uint32_t old_memavl;
247
205
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
248
 
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
 
206
    param.keys=(uint32_t) cmin(records+1, keys);
249
207
    if ((table_sort.sort_keys=
250
208
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
251
 
                                            param.keys, param.rec_length)))
 
209
                                    param.keys, param.rec_length, MYF(0))))
252
210
      break;
253
 
    old_memavl= memavl;
254
 
    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)
255
213
      memavl= min_sort_memory;
256
214
  }
257
215
  sort_keys= table_sort.sort_keys;
260
218
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
261
219
    goto err;
262
220
  }
263
 
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
 
221
  if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
264
222
                       DISK_BUFFER_SIZE, MYF(MY_WME)))
265
223
    goto err;
266
224
 
295
253
    close_cached_file(&buffpek_pointers);
296
254
        /* Open cached file if it isn't open */
297
255
    if (! my_b_inited(outfile) &&
298
 
        open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
 
256
        open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
299
257
                          MYF(MY_WME)))
300
258
      goto err;
301
 
    if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
 
259
    if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
302
260
      goto err;
303
261
 
304
262
    /*
312
270
                        &tempfile))
313
271
      goto err;
314
272
    if (flush_io_cache(&tempfile) ||
315
 
        reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
 
273
        reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
316
274
      goto err;
317
275
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
318
276
                    outfile))
343
301
    if (flush_io_cache(outfile))
344
302
      error=1;
345
303
    {
346
 
      internal::my_off_t save_pos=outfile->pos_in_file;
 
304
      my_off_t save_pos=outfile->pos_in_file;
347
305
      /* For following reads */
348
 
      if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
 
306
      if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
349
307
        error=1;
350
308
      outfile->end_of_file=save_pos;
351
309
    }
354
312
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
355
313
               MYF(ME_ERROR+ME_WAITTANG));
356
314
  else
357
 
    statistic_add(session->status_var.filesort_rows,
 
315
    statistic_add(thd->status_var.filesort_rows,
358
316
                  (uint32_t) records, &LOCK_status);
359
317
  *examined_rows= param.examined_rows;
360
318
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
361
 
  DRIZZLE_FILESORT_DONE(error, records);
362
 
  return (error ? HA_POS_ERROR : records);
 
319
  DRIZZLE_FILESORT_END();
 
320
  return(error ? HA_POS_ERROR : records);
363
321
} /* filesort */
364
322
 
365
323
 
366
 
void Table::filesort_free_buffers(bool full)
 
324
void filesort_free_buffers(Table *table, bool full)
367
325
{
368
 
  if (sort.record_pointers)
 
326
  if (table->sort.record_pointers)
369
327
  {
370
 
    free((unsigned char*) sort.record_pointers);
371
 
    sort.record_pointers=0;
 
328
    free((unsigned char*) table->sort.record_pointers);
 
329
    table->sort.record_pointers=0;
372
330
  }
373
331
  if (full)
374
332
  {
375
 
    if (sort.sort_keys )
 
333
    if (table->sort.sort_keys )
376
334
    {
377
 
      if ((unsigned char*) sort.sort_keys)
378
 
        free((unsigned char*) sort.sort_keys);
379
 
      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;
380
338
    }
381
 
    if (sort.buffpek)
 
339
    if (table->sort.buffpek)
382
340
    {
383
 
      if ((unsigned char*) sort.buffpek)
384
 
        free((unsigned char*) sort.buffpek);
385
 
      sort.buffpek= 0;
386
 
      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;
387
345
    }
388
346
  }
389
 
  if (sort.addon_buf)
 
347
  if (table->sort.addon_buf)
390
348
  {
391
 
    free((char *) sort.addon_buf);
392
 
    free((char *) sort.addon_field);
393
 
    sort.addon_buf=0;
394
 
    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;
395
353
  }
396
354
}
397
355
 
398
356
/** Make a array of string pointers. */
399
357
 
400
358
static char **make_char_array(char **old_pos, register uint32_t fields,
401
 
                              uint32_t length)
 
359
                              uint32_t length, myf my_flag)
402
360
{
403
361
  register char **pos;
404
362
  char *char_pos;
405
363
 
406
364
  if (old_pos ||
407
 
      (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)))
408
367
  {
409
368
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
410
369
    while (fields--) *(pos++) = (char_pos+= length);
416
375
 
417
376
/** Read 'count' number of buffer pointers into memory. */
418
377
 
419
 
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,
420
379
                                     unsigned char *buf)
421
380
{
422
381
  uint32_t length= sizeof(BUFFPEK)*count;
424
383
  if (count > UINT_MAX/sizeof(BUFFPEK))
425
384
    return 0; /* sizeof(BUFFPEK)*count will overflow */
426
385
  if (!tmp)
427
 
    tmp= (unsigned char *)malloc(length);
 
386
    tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
428
387
  if (tmp)
429
388
  {
430
 
    if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
 
389
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
431
390
        my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
432
391
    {
433
392
      free((char*) tmp);
475
434
    HA_POS_ERROR on error.
476
435
*/
477
436
 
478
 
static ha_rows find_all_keys(SORTPARAM *param, 
479
 
                             optimizer::SqlSelect *select,
 
437
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
480
438
                             unsigned char **sort_keys,
481
 
                             internal::IO_CACHE *buffpek_pointers,
482
 
                             internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
 
439
                             IO_CACHE *buffpek_pointers,
 
440
                             IO_CACHE *tempfile, IO_CACHE *indexfile)
483
441
{
484
442
  int error,flag,quick_select;
485
443
  uint32_t idx,indexpos,ref_length;
486
444
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
487
 
  internal::my_off_t record;
 
445
  my_off_t record;
488
446
  Table *sort_form;
489
 
  Session *session= current_session;
490
 
  volatile Session::killed_state *killed= &session->killed;
491
 
  Cursor *file;
492
 
  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;
493
451
 
494
452
  idx=indexpos=0;
495
453
  error=quick_select=0;
496
454
  sort_form=param->sort_form;
497
 
  file= sort_form->cursor;
 
455
  file=sort_form->file;
498
456
  ref_length=param->ref_length;
499
457
  ref_pos= ref_buff;
500
458
  quick_select=select && select->quick;
501
459
  record=0;
502
 
  flag= ((!indexfile && ! file->isOrdered())
 
460
  flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
503
461
         || quick_select);
504
462
  if (indexfile || flag)
505
463
    ref_pos= &file->ref[0];
509
467
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
510
468
    file->ha_rnd_init(1);
511
469
    file->extra_opt(HA_EXTRA_CACHE,
512
 
                    current_session->variables.read_buff_size);
 
470
                    current_thd->variables.read_buff_size);
513
471
  }
514
472
 
515
473
  READ_RECORD read_record_info;
517
475
  {
518
476
    if (select->quick->reset())
519
477
      return(HA_POS_ERROR);
520
 
    init_read_record(&read_record_info, current_session, select->quick->head,
 
478
    init_read_record(&read_record_info, current_thd, select->quick->head,
521
479
                     select, 1, 1);
522
480
  }
523
481
 
525
483
  save_read_set=  sort_form->read_set;
526
484
  save_write_set= sort_form->write_set;
527
485
  /* Set up temporary column read map for columns used by sort */
528
 
  sort_form->tmp_set.clearAll();
 
486
  bitmap_clear_all(&sort_form->tmp_set);
529
487
  /* Temporary set for register_used_fields and register_field_in_read_map */
530
488
  sort_form->read_set= &sort_form->tmp_set;
531
489
  register_used_fields(param);
549
507
    {
550
508
      if (indexfile)
551
509
      {
552
 
        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 */
553
511
        {
554
 
          error= errno ? errno : -1;            /* Abort */
 
512
          error= my_errno ? my_errno : -1;              /* Abort */
555
513
          break;
556
514
        }
557
515
        error=file->rnd_pos(sort_form->record[0],next_pos);
559
517
      else
560
518
      {
561
519
        error=file->rnd_next(sort_form->record[0]);
562
 
 
563
520
        if (!flag)
564
521
        {
565
 
          internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
 
522
          my_store_ptr(ref_pos,ref_length,record); // Position to row
566
523
          record+= sort_form->s->db_record_offset;
567
524
        }
568
525
        else if (!error)
579
536
        (void) file->extra(HA_EXTRA_NO_CACHE);
580
537
        file->ha_rnd_end();
581
538
      }
582
 
      return(HA_POS_ERROR);
 
539
      return(HA_POS_ERROR);             /* purecov: inspected */
583
540
    }
584
541
    if (error == 0)
585
542
      param->examined_rows++;
597
554
    else
598
555
      file->unlock_row();
599
556
    /* It does not make sense to read more keys in case of a fatal error */
600
 
    if (session->is_error())
 
557
    if (thd->is_error())
601
558
      break;
602
559
  }
603
560
  if (quick_select)
615
572
      file->ha_rnd_end();
616
573
  }
617
574
 
618
 
  if (session->is_error())
 
575
  if (thd->is_error())
619
576
    return(HA_POS_ERROR);
620
 
 
 
577
  
621
578
  /* Signal we should use orignal column read and write maps */
622
579
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
623
580
 
624
581
  if (error != HA_ERR_END_OF_FILE)
625
582
  {
626
 
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
627
 
    return(HA_POS_ERROR);
 
583
    file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
 
584
    return(HA_POS_ERROR);                       /* purecov: inspected */
628
585
  }
629
586
  if (indexpos && idx &&
630
587
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
631
 
    return(HA_POS_ERROR);
 
588
    return(HA_POS_ERROR);                       /* purecov: inspected */
632
589
  return(my_b_inited(tempfile) ?
633
590
              (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
634
591
              idx);
659
616
 
660
617
static int
661
618
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
662
 
           internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
 
619
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
663
620
{
664
621
  size_t sort_length, rec_length;
665
622
  unsigned char **end;
667
624
 
668
625
  sort_length= param->sort_length;
669
626
  rec_length= param->rec_length;
670
 
  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);
671
628
  if (!my_b_inited(tempfile) &&
672
 
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
 
629
      open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
673
630
                       MYF(MY_WME)))
674
 
    goto err;
 
631
    goto err;                                   /* purecov: inspected */
675
632
  /* check we won't have more buffpeks than we can possibly keep in memory */
676
633
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
677
634
    goto err;
678
635
  buffpek.file_pos= my_b_tell(tempfile);
679
636
  if ((ha_rows) count > param->max_rows)
680
 
    count=(uint32_t) param->max_rows;
 
637
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
681
638
  buffpek.count=(ha_rows) count;
682
639
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
683
640
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
721
678
{
722
679
  register Field *field;
723
680
  register SORT_FIELD *sort_field;
724
 
  size_t length;
 
681
  register uint32_t length;
725
682
 
726
683
  for (sort_field=param->local_sortorder ;
727
684
       sort_field != param->end ;
769
726
            memset(to-1, 0, sort_field->length+1);
770
727
          else
771
728
          {
 
729
            /* purecov: begin deadcode */
772
730
            /*
773
731
              This should only happen during extreme conditions if we run out
774
732
              of memory or have an item marked not null when it can be null.
776
734
            */
777
735
            assert(0);
778
736
            memset(to, 0, sort_field->length);  // Avoid crash
 
737
            /* purecov: end */
779
738
          }
780
739
          break;
781
740
        }
819
778
          int64_t value= item->val_int_result();
820
779
          if (maybe_null)
821
780
          {
822
 
            *to++=1;
 
781
            *to++=1;                            /* purecov: inspected */
823
782
            if (item->null_value)
824
783
            {
825
784
              if (maybe_null)
831
790
              break;
832
791
            }
833
792
          }
 
793
#if SIZEOF_LONG_LONG > 4
834
794
          to[7]= (unsigned char) value;
835
795
          to[6]= (unsigned char) (value >> 8);
836
796
          to[5]= (unsigned char) (value >> 16);
842
802
            to[0]= (unsigned char) (value >> 56);
843
803
          else
844
804
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
 
805
#else
 
806
          to[3]= (unsigned char) value;
 
807
          to[2]= (unsigned char) (value >> 8);
 
808
          to[1]= (unsigned char) (value >> 16);
 
809
          if (item->unsigned_flag)                    /* Fix sign */
 
810
            to[0]= (unsigned char) (value >> 24);
 
811
          else
 
812
            to[0]= (unsigned char) (value >> 24) ^ 128; /* Reverse signbit */
 
813
#endif
845
814
          break;
846
815
        }
847
816
      case DECIMAL_RESULT:
850
819
          if (maybe_null)
851
820
          {
852
821
            if (item->null_value)
853
 
            {
 
822
            { 
854
823
              memset(to, 0, sort_field->length+1);
855
824
              to++;
856
825
              break;
879
848
          break;
880
849
        }
881
850
      case ROW_RESULT:
882
 
      default:
 
851
      default: 
883
852
        // This case should never be choosen
884
853
        assert(0);
885
854
        break;
902
871
 
903
872
  if (param->addon_field)
904
873
  {
905
 
    /*
 
874
    /* 
906
875
      Save field values appended to sorted fields.
907
876
      First null bit indicators are appended then field values follow.
908
877
      In this implementation we use fixed layout for field values -
954
923
{
955
924
  register SORT_FIELD *sort_field;
956
925
  Table *table=param->sort_form;
 
926
  MY_BITMAP *bitmap= table->read_set;
957
927
 
958
928
  for (sort_field= param->local_sortorder ;
959
929
       sort_field != param->end ;
963
933
    if ((field= sort_field->field))
964
934
    {
965
935
      if (field->table == table)
966
 
        table->setReadSet(field->field_index);
 
936
      bitmap_set_bit(bitmap, field->field_index);
967
937
    }
968
938
    else
969
939
    {                                           // Item
977
947
    SORT_ADDON_FIELD *addonf= param->addon_field;
978
948
    Field *field;
979
949
    for ( ; (field= addonf->field) ; addonf++)
980
 
      table->setReadSet(field->field_index);
 
950
      bitmap_set_bit(bitmap, field->field_index);
981
951
  }
982
952
  else
983
953
  {
987
957
}
988
958
 
989
959
 
990
 
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
 
960
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count, 
991
961
                       filesort_info_st *table_sort)
992
962
{
993
963
  uint32_t offset,res_length;
994
964
  unsigned char *to;
995
965
 
996
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
 
966
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
997
967
  res_length= param->res_length;
998
968
  offset= param->rec_length-res_length;
999
969
  if ((ha_rows) count > param->max_rows)
1000
970
    count=(uint32_t) param->max_rows;
1001
 
  if (!(to= table_sort->record_pointers=
1002
 
        (unsigned char*) malloc(res_length*count)))
1003
 
    return(1);
 
971
  if (!(to= table_sort->record_pointers= 
 
972
        (unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
 
973
    return(1);                 /* purecov: inspected */
1004
974
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1005
975
  {
1006
976
    memcpy(to, *sort_keys+offset, res_length);
1013
983
/** Merge buffers to make < MERGEBUFF2 buffers. */
1014
984
 
1015
985
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1016
 
                    BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
 
986
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1017
987
{
1018
988
  register uint32_t i;
1019
 
  internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
 
989
  IO_CACHE t_file2,*from_file,*to_file,*temp;
1020
990
  BUFFPEK *lastbuff;
1021
991
 
1022
992
  if (*maxbuffer < MERGEBUFF2)
1023
 
    return(0);
 
993
    return(0);                          /* purecov: inspected */
1024
994
  if (flush_io_cache(t_file) ||
1025
 
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
 
995
      open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1026
996
                        MYF(MY_WME)))
1027
 
    return(1);
 
997
    return(1);                          /* purecov: inspected */
1028
998
 
1029
999
  from_file= t_file ; to_file= &t_file2;
1030
1000
  while (*maxbuffer >= MERGEBUFF2)
1031
1001
  {
1032
 
    if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
 
1002
    if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1033
1003
      goto cleanup;
1034
 
    if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
 
1004
    if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1035
1005
      goto cleanup;
1036
1006
    lastbuff=buffpek;
1037
1007
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1042
1012
    }
1043
1013
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1044
1014
                      buffpek+i,buffpek+ *maxbuffer,0))
1045
 
      break;
 
1015
      break;                                    /* purecov: inspected */
1046
1016
    if (flush_io_cache(to_file))
1047
 
      break;
 
1017
      break;                                    /* purecov: inspected */
1048
1018
    temp=from_file; from_file=to_file; to_file=temp;
1049
1019
    setup_io_cache(from_file);
1050
1020
    setup_io_cache(to_file);
1069
1039
    (uint32_t)-1 if something goes wrong
1070
1040
*/
1071
1041
 
1072
 
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
 
                        uint32_t rec_length)
 
1042
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1043
                    uint32_t rec_length)
1074
1044
{
1075
1045
  register uint32_t count;
1076
1046
  uint32_t length;
1077
1047
 
1078
 
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
 
1048
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1079
1049
  {
1080
1050
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1081
 
      return((uint32_t) -1);
1082
 
 
1083
 
    buffpek->key= buffpek->base;
 
1051
      return((uint32_t) -1);                    /* purecov: inspected */
 
1052
    buffpek->key=buffpek->base;
1084
1053
    buffpek->file_pos+= length;                 /* New filepos */
1085
 
    buffpek->count-= count;
 
1054
    buffpek->count-=    count;
1086
1055
    buffpek->mem_count= count;
1087
1056
  }
1088
1057
  return (count*rec_length);
1089
1058
} /* read_to_buffer */
1090
1059
 
1091
1060
 
1092
 
class compare_functor
 
1061
/**
 
1062
  Put all room used by freed buffer to use in adjacent buffer.
 
1063
 
 
1064
  Note, that we can't simply distribute memory evenly between all buffers,
 
1065
  because new areas must not overlap with old ones.
 
1066
 
 
1067
  @param[in] queue      list of non-empty buffers, without freed buffer
 
1068
  @param[in] reuse      empty buffer
 
1069
  @param[in] key_length key length
 
1070
*/
 
1071
 
 
1072
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1093
1073
{
1094
 
  qsort2_cmp key_compare;
1095
 
  void *key_compare_arg;
1096
 
  public:
1097
 
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1098
 
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1099
 
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
 
1074
  unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
 
1075
  for (uint32_t i= 0; i < queue->elements; ++i)
1100
1076
  {
1101
 
    int val= key_compare(key_compare_arg,
1102
 
                      &i->key, &j->key);
1103
 
    return (val >= 0);
 
1077
    BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
 
1078
    if (bp->base + bp->max_keys * key_length == reuse->base)
 
1079
    {
 
1080
      bp->max_keys+= reuse->max_keys;
 
1081
      return;
 
1082
    }
 
1083
    else if (bp->base == reuse_end)
 
1084
    {
 
1085
      bp->base= reuse->base;
 
1086
      bp->max_keys+= reuse->max_keys;
 
1087
      return;
 
1088
    }
1104
1089
  }
1105
 
};
 
1090
  assert(0);
 
1091
}
1106
1092
 
1107
1093
 
1108
1094
/**
1123
1109
    other  error
1124
1110
*/
1125
1111
 
1126
 
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1127
 
                  internal::IO_CACHE *to_file, unsigned char *sort_buffer,
 
1112
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
 
1113
                  IO_CACHE *to_file, unsigned char *sort_buffer,
1128
1114
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1129
1115
                  int flag)
1130
1116
{
1133
1119
  size_t sort_length;
1134
1120
  uint32_t maxcount;
1135
1121
  ha_rows max_rows,org_max_rows;
1136
 
  internal::my_off_t to_start_filepos;
 
1122
  my_off_t to_start_filepos;
1137
1123
  unsigned char *strpos;
1138
1124
  BUFFPEK *buffpek;
 
1125
  QUEUE queue;
1139
1126
  qsort2_cmp cmp;
1140
1127
  void *first_cmp_arg;
1141
 
  volatile Session::killed_state *killed= &current_session->killed;
1142
 
  Session::killed_state not_killable;
 
1128
  volatile THD::killed_state *killed= &current_thd->killed;
 
1129
  THD::killed_state not_killable;
1143
1130
 
1144
 
  status_var_increment(current_session->status_var.filesort_merge_passes);
 
1131
  status_var_increment(current_thd->status_var.filesort_merge_passes);
1145
1132
  if (param->not_killable)
1146
1133
  {
1147
1134
    killed= &not_killable;
1148
 
    not_killable= Session::NOT_KILLED;
 
1135
    not_killable= THD::NOT_KILLED;
1149
1136
  }
1150
1137
 
1151
1138
  error=0;
1160
1147
 
1161
1148
  /* The following will fire if there is not enough space in sort_buffer */
1162
1149
  assert(maxcount!=0);
1163
 
 
 
1150
  
1164
1151
  if (param->unique_buff)
1165
1152
  {
1166
1153
    cmp= param->compare;
1168
1155
  }
1169
1156
  else
1170
1157
  {
1171
 
    cmp= internal::get_ptr_compare(sort_length);
 
1158
    cmp= get_ptr_compare(sort_length);
1172
1159
    first_cmp_arg= (void*) &sort_length;
1173
1160
  }
1174
 
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
1175
 
    queue(compare_functor(cmp, first_cmp_arg));
 
1161
  if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
 
1162
                 (queue_compare) cmp, first_cmp_arg))
 
1163
    return(1);                                /* purecov: inspected */
1176
1164
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1177
1165
  {
1178
1166
    buffpek->base= strpos;
1180
1168
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1181
1169
                                                                         rec_length));
1182
1170
    if (error == -1)
1183
 
      goto err;
 
1171
      goto err;                                 /* purecov: inspected */
1184
1172
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
1185
 
    queue.push(buffpek);
 
1173
    queue_insert(&queue, (unsigned char*) buffpek);
1186
1174
  }
1187
1175
 
1188
1176
  if (param->unique_buff)
1189
1177
  {
1190
 
    /*
 
1178
    /* 
1191
1179
       Called by Unique::get()
1192
1180
       Copy the first argument to param->unique_buff for unique removal.
1193
1181
       Store it also in 'to_file'.
1195
1183
       This is safe as we know that there is always more than one element
1196
1184
       in each block to merge (This is guaranteed by the Unique:: algorithm
1197
1185
    */
1198
 
    buffpek= queue.top();
 
1186
    buffpek= (BUFFPEK*) queue_top(&queue);
1199
1187
    memcpy(param->unique_buff, buffpek->key, rec_length);
1200
1188
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1201
1189
    {
1202
 
      error=1; goto err;
 
1190
      error=1; goto err;                        /* purecov: inspected */
1203
1191
    }
1204
1192
    buffpek->key+= rec_length;
1205
1193
    buffpek->mem_count--;
1206
1194
    if (!--max_rows)
1207
1195
    {
1208
 
      error= 0;
1209
 
      goto end;
 
1196
      error= 0;                                       /* purecov: inspected */
 
1197
      goto end;                                       /* purecov: inspected */
1210
1198
    }
1211
 
    /* Top element has been used */
1212
 
    queue.pop();
1213
 
    queue.push(buffpek);
 
1199
    queue_replaced(&queue);                        // Top element has been used
1214
1200
  }
1215
1201
  else
1216
1202
    cmp= 0;                                        // Not unique
1217
1203
 
1218
 
  while (queue.size() > 1)
 
1204
  while (queue.elements > 1)
1219
1205
  {
1220
1206
    if (*killed)
1221
1207
    {
1222
 
      error= 1; goto err;
 
1208
      error= 1; goto err;                        /* purecov: inspected */
1223
1209
    }
1224
1210
    for (;;)
1225
1211
    {
1226
 
      buffpek= queue.top();
 
1212
      buffpek= (BUFFPEK*) queue_top(&queue);
1227
1213
      if (cmp)                                        // Remove duplicates
1228
1214
      {
1229
1215
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1235
1221
      {
1236
1222
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1237
1223
        {
1238
 
          error=1; goto err;
 
1224
          error=1; goto err;                        /* purecov: inspected */
1239
1225
        }
1240
1226
      }
1241
1227
      else
1242
1228
      {
1243
1229
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1244
1230
        {
1245
 
          error=1; goto err;
 
1231
          error=1; goto err;                        /* purecov: inspected */
1246
1232
        }
1247
1233
      }
1248
1234
      if (!--max_rows)
1249
1235
      {
1250
 
        error= 0;
1251
 
        goto end;
 
1236
        error= 0;                               /* purecov: inspected */
 
1237
        goto end;                               /* purecov: inspected */
1252
1238
      }
1253
1239
 
1254
1240
    skip_duplicate:
1258
1244
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1259
1245
                                          rec_length)))
1260
1246
        {
1261
 
          queue.pop();
 
1247
          queue_remove(&queue,0);
 
1248
          reuse_freed_buff(&queue, buffpek, rec_length);
1262
1249
          break;                        /* One buffer have been removed */
1263
1250
        }
1264
1251
        else if (error == -1)
1265
 
          goto err;
 
1252
          goto err;                        /* purecov: inspected */
1266
1253
      }
1267
 
      /* Top element has been replaced */
1268
 
      queue.pop();
1269
 
      queue.push(buffpek);
 
1254
      queue_replaced(&queue);              /* Top element has been replaced */
1270
1255
    }
1271
1256
  }
1272
 
  buffpek= queue.top();
 
1257
  buffpek= (BUFFPEK*) queue_top(&queue);
1273
1258
  buffpek->base= sort_buffer;
1274
1259
  buffpek->max_keys= param->keys;
1275
1260
 
1299
1284
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1300
1285
                     (rec_length*buffpek->mem_count)))
1301
1286
      {
1302
 
        error= 1; goto err;
 
1287
        error= 1; goto err;                        /* purecov: inspected */
1303
1288
      }
1304
1289
    }
1305
1290
    else
1309
1294
      for (end= strpos+buffpek->mem_count*rec_length ;
1310
1295
           strpos != end ;
1311
1296
           strpos+= rec_length)
1312
 
      {
 
1297
      {     
1313
1298
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1314
1299
        {
1315
 
          error=1; goto err;
 
1300
          error=1; goto err;                        
1316
1301
        }
1317
1302
      }
1318
1303
    }
1321
1306
         != -1 && error != 0);
1322
1307
 
1323
1308
end:
1324
 
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
 
1309
  lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1325
1310
  lastbuff->file_pos= to_start_filepos;
1326
1311
err:
 
1312
  delete_queue(&queue);
1327
1313
  return(error);
1328
1314
} /* merge_buffers */
1329
1315
 
1332
1318
 
1333
1319
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1334
1320
                       BUFFPEK *buffpek, uint32_t maxbuffer,
1335
 
                       internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
 
1321
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1336
1322
{
1337
1323
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1338
1324
                    buffpek+maxbuffer,1))
1339
 
    return(1);
 
1325
    return(1);                          /* purecov: inspected */
1340
1326
  return(0);
1341
1327
} /* merge_index */
1342
1328
 
1357
1343
/**
1358
1344
  Calculate length of sort key.
1359
1345
 
1360
 
  @param session                          Thread Cursor
 
1346
  @param thd                      Thread handler
1361
1347
  @param sortorder                Order of items to sort
1362
1348
  @param s_length                 Number of items to sort
1363
1349
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1373
1359
*/
1374
1360
 
1375
1361
static uint32_t
1376
 
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
 
1362
sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
1377
1363
           bool *multi_byte_charset)
1378
1364
{
1379
1365
  register uint32_t length;
1407
1393
      switch (sortorder->result_type) {
1408
1394
      case STRING_RESULT:
1409
1395
        sortorder->length=sortorder->item->max_length;
1410
 
        set_if_smaller(sortorder->length,
1411
 
                       session->variables.max_sort_length);
 
1396
        set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1412
1397
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1413
 
        {
 
1398
        { 
1414
1399
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1415
1400
          sortorder->need_strxnfrm= 1;
1416
1401
          *multi_byte_charset= 1;
1423
1408
        }
1424
1409
        break;
1425
1410
      case INT_RESULT:
 
1411
#if SIZEOF_LONG_LONG > 4
1426
1412
        sortorder->length=8;                    // Size of intern int64_t
 
1413
#else
 
1414
        sortorder->length=4;
 
1415
#endif
1427
1416
        break;
1428
1417
      case DECIMAL_RESULT:
1429
1418
        sortorder->length=
1430
 
          my_decimal_get_binary_size(sortorder->item->max_length -
 
1419
          my_decimal_get_binary_size(sortorder->item->max_length - 
1431
1420
                                     (sortorder->item->decimals ? 1 : 0),
1432
1421
                                     sortorder->item->decimals);
1433
1422
        break;
1435
1424
        sortorder->length=sizeof(double);
1436
1425
        break;
1437
1426
      case ROW_RESULT:
1438
 
      default:
 
1427
      default: 
1439
1428
        // This case should never be choosen
1440
1429
        assert(0);
1441
1430
        break;
1443
1432
      if (sortorder->item->maybe_null)
1444
1433
        length++;                               // Place for NULL marker
1445
1434
    }
1446
 
    set_if_smaller(sortorder->length,
1447
 
                   (size_t)session->variables.max_sort_length);
 
1435
    set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1448
1436
    length+=sortorder->length;
1449
1437
  }
1450
1438
  sortorder->field= (Field*) 0;                 // end marker
1458
1446
 
1459
1447
  The function first finds out what fields are used in the result set.
1460
1448
  Then it calculates the length of the buffer to store the values of
1461
 
  these fields together with the value of sort values.
 
1449
  these fields together with the value of sort values. 
1462
1450
  If the calculated length is not greater than max_length_for_sort_data
1463
1451
  the function allocates memory for an array of descriptors containing
1464
1452
  layouts for the values of the non-sorted fields in the buffer and
1465
1453
  fills them.
1466
1454
 
1467
 
  @param session                 Current thread
 
1455
  @param thd                 Current thread
1468
1456
  @param ptabfield           Array of references to the table fields
1469
1457
  @param sortlength          Total length of sorted fields
1470
1458
  @param[out] plength        Total length of appended fields
1480
1468
*/
1481
1469
 
1482
1470
static SORT_ADDON_FIELD *
1483
 
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
 
1471
get_addon_fields(THD *thd, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1484
1472
{
1485
1473
  Field **pfield;
1486
1474
  Field *field;
1488
1476
  uint32_t length= 0;
1489
1477
  uint32_t fields= 0;
1490
1478
  uint32_t null_fields= 0;
 
1479
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1491
1480
 
1492
1481
  /*
1493
1482
    If there is a reference to a field in the query add it
1495
1484
    Note for future refinement:
1496
1485
    This this a too strong condition.
1497
1486
    Actually we need only the fields referred in the
1498
 
    result set. And for some of them it makes sense to use
 
1487
    result set. And for some of them it makes sense to use 
1499
1488
    the values directly from sorted fields.
1500
1489
  */
1501
1490
  *plength= 0;
1502
1491
 
1503
1492
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1504
1493
  {
1505
 
    if (!(field->isReadSet()))
 
1494
    if (!bitmap_is_set(read_set, field->field_index))
1506
1495
      continue;
1507
1496
    if (field->flags & BLOB_FLAG)
1508
1497
      return 0;
1510
1499
    if (field->maybe_null())
1511
1500
      null_fields++;
1512
1501
    fields++;
1513
 
  }
 
1502
  } 
1514
1503
  if (!fields)
1515
1504
    return 0;
1516
1505
  length+= (null_fields+7)/8;
1517
1506
 
1518
 
  if (length+sortlength > session->variables.max_length_for_sort_data ||
1519
 
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
1520
 
                                            (fields+1))))
 
1507
  if (length+sortlength > thd->variables.max_length_for_sort_data ||
 
1508
      !(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)*
 
1509
                                               (fields+1), MYF(MY_WME))))
1521
1510
    return 0;
1522
1511
 
1523
1512
  *plength= length;
1525
1514
  null_fields= 0;
1526
1515
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1527
1516
  {
1528
 
    if (!(field->isReadSet()))
 
1517
    if (!bitmap_is_set(read_set, field->field_index))
1529
1518
      continue;
1530
1519
    addonf->field= field;
1531
1520
    addonf->offset= length;
1545
1534
    addonf++;
1546
1535
  }
1547
1536
  addonf->field= 0;     // Put end marker
1548
 
 
 
1537
  
1549
1538
  return (addonf-fields);
1550
1539
}
1551
1540
 
1565
1554
    void.
1566
1555
*/
1567
1556
 
1568
 
static void
 
1557
static void 
1569
1558
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1570
1559
{
1571
1560
  Field *field;
1630
1619
    }
1631
1620
  }
1632
1621
}
1633
 
 
1634
 
} /* namespace drizzled */