~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Jay Pipes
  • Date: 2009-02-21 16:00:06 UTC
  • mto: (907.1.1 trunk-with-temporal)
  • mto: This revision was merged to the branch mainline in revision 908.
  • Revision ID: jpipes@serialcoder-20090221160006-vnk3wt4qbcz62eru
Removes the TIME column type and related time functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
{
 
24
#include <drizzled/server_includes.h>
 
25
#include <drizzled/sql_sort.h>
 
26
#include <drizzled/error.h>
 
27
#include <drizzled/probes.h>
 
28
#include <drizzled/session.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/table_list.h>
49
31
 
50
32
/* functions defined in this file */
51
33
 
52
34
static char **make_char_array(char **old_pos, register uint32_t fields,
53
35
                              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);
 
36
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
 
37
                                     unsigned char *buf);
 
38
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
 
39
                             unsigned char * *sort_keys, IO_CACHE *buffer_file,
 
40
                             IO_CACHE *tempfile,IO_CACHE *indexfile);
 
41
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
 
42
                      uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
 
43
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
75
44
static void register_used_fields(SORTPARAM *param);
76
 
static int merge_index(SORTPARAM *param,
77
 
                       unsigned char *sort_buffer,
 
45
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
78
46
                       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,
 
47
                       uint32_t maxbuffer,IO_CACHE *tempfile,
 
48
                       IO_CACHE *outfile);
 
49
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
85
50
                       filesort_info_st *table_sort);
86
51
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);
 
52
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
 
53
                       bool *multi_byte_charset);
 
54
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
 
55
                                          uint32_t sortlength, uint32_t *plength);
95
56
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
96
57
                                unsigned char *buff);
97
58
/**
131
92
*/
132
93
 
133
94
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
134
 
                 optimizer::SqlSelect *select, ha_rows max_rows,
 
95
                 SQL_SELECT *select, ha_rows max_rows,
135
96
                 bool sort_positions, ha_rows *examined_rows)
136
97
{
137
98
  int error;
140
101
  BUFFPEK *buffpek;
141
102
  ha_rows records= HA_POS_ERROR;
142
103
  unsigned char **sort_keys= 0;
143
 
  internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
 
104
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
144
105
  SORTPARAM param;
145
106
  bool multi_byte_charset;
146
107
 
148
109
  TableList *tab= table->pos_in_table_list;
149
110
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
150
111
 
151
 
  DRIZZLE_FILESORT_START(table->s->getSchemaName(), table->s->getTableName());
 
112
  DRIZZLE_FILESORT_START();
152
113
 
153
114
  /*
154
115
   Release InnoDB's adaptive hash index latch (if holding) before
155
116
   running a sort.
156
117
  */
157
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
 
118
  ha_release_temporary_latches(session);
158
119
 
159
120
  /*
160
121
    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
 
122
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
162
123
    when index_merge select has finished with it.
163
124
  */
164
125
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
171
132
  error= 1;
172
133
  memset(&param, 0, sizeof(param));
173
134
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
174
 
  param.ref_length= table->cursor->ref_length;
 
135
  param.ref_length= table->file->ref_length;
175
136
  param.addon_field= 0;
176
137
  param.addon_length= 0;
177
 
  if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
 
138
  if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
178
139
  {
179
140
    /*
180
141
      Get the descriptors of all fields whose values are appended
218
179
#ifdef CAN_TRUST_RANGE
219
180
  if (select && select->quick && select->quick->records > 0L)
220
181
  {
221
 
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
222
 
                 table->cursor->stats.records)+EXTRA_RECORDS;
 
182
    records=cmin((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
 
183
                table->file->stats.records)+EXTRA_RECORDS;
223
184
    selected_records_file=0;
224
185
  }
225
186
  else
226
187
#endif
227
188
  {
228
 
    records= table->cursor->estimate_rows_upper_bound();
 
189
    records= table->file->estimate_rows_upper_bound();
229
190
    /*
230
191
      If number of records is not known, use as much of sort buffer
231
192
      as possible.
240
201
    goto err;
241
202
 
242
203
  memavl= session->variables.sortbuff_size;
243
 
  min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
 
204
  min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
244
205
  while (memavl >= min_sort_memory)
245
206
  {
246
207
    uint32_t old_memavl;
247
208
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
248
 
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
 
209
    param.keys=(uint32_t) cmin(records+1, keys);
249
210
    if ((table_sort.sort_keys=
250
211
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
251
212
                                            param.keys, param.rec_length)))
252
213
      break;
253
 
    old_memavl= memavl;
254
 
    if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
 
214
    old_memavl=memavl;
 
215
    if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
255
216
      memavl= min_sort_memory;
256
217
  }
257
218
  sort_keys= table_sort.sort_keys;
298
259
        open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
299
260
                          MYF(MY_WME)))
300
261
      goto err;
301
 
    if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
 
262
    if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
302
263
      goto err;
303
264
 
304
265
    /*
312
273
                        &tempfile))
313
274
      goto err;
314
275
    if (flush_io_cache(&tempfile) ||
315
 
        reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
 
276
        reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
316
277
      goto err;
317
278
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
318
279
                    outfile))
343
304
    if (flush_io_cache(outfile))
344
305
      error=1;
345
306
    {
346
 
      internal::my_off_t save_pos=outfile->pos_in_file;
 
307
      my_off_t save_pos=outfile->pos_in_file;
347
308
      /* For following reads */
348
 
      if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
 
309
      if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
349
310
        error=1;
350
311
      outfile->end_of_file=save_pos;
351
312
    }
358
319
                  (uint32_t) records, &LOCK_status);
359
320
  *examined_rows= param.examined_rows;
360
321
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
361
 
  DRIZZLE_FILESORT_DONE(error, records);
362
 
  return (error ? HA_POS_ERROR : records);
 
322
  DRIZZLE_FILESORT_END();
 
323
  return(error ? HA_POS_ERROR : records);
363
324
} /* filesort */
364
325
 
365
326
 
366
 
void Table::filesort_free_buffers(bool full)
 
327
void filesort_free_buffers(Table *table, bool full)
367
328
{
368
 
  if (sort.record_pointers)
 
329
  if (table->sort.record_pointers)
369
330
  {
370
 
    free((unsigned char*) sort.record_pointers);
371
 
    sort.record_pointers=0;
 
331
    free((unsigned char*) table->sort.record_pointers);
 
332
    table->sort.record_pointers=0;
372
333
  }
373
334
  if (full)
374
335
  {
375
 
    if (sort.sort_keys )
 
336
    if (table->sort.sort_keys )
376
337
    {
377
 
      if ((unsigned char*) sort.sort_keys)
378
 
        free((unsigned char*) sort.sort_keys);
379
 
      sort.sort_keys= 0;
 
338
      if ((unsigned char*) table->sort.sort_keys)
 
339
        free((unsigned char*) table->sort.sort_keys);
 
340
      table->sort.sort_keys= 0;
380
341
    }
381
 
    if (sort.buffpek)
 
342
    if (table->sort.buffpek)
382
343
    {
383
 
      if ((unsigned char*) sort.buffpek)
384
 
        free((unsigned char*) sort.buffpek);
385
 
      sort.buffpek= 0;
386
 
      sort.buffpek_len= 0;
 
344
      if ((unsigned char*) table->sort.buffpek)
 
345
        free((unsigned char*) table->sort.buffpek);
 
346
      table->sort.buffpek= 0;
 
347
      table->sort.buffpek_len= 0;
387
348
    }
388
349
  }
389
 
  if (sort.addon_buf)
 
350
  if (table->sort.addon_buf)
390
351
  {
391
 
    free((char *) sort.addon_buf);
392
 
    free((char *) sort.addon_field);
393
 
    sort.addon_buf=0;
394
 
    sort.addon_field=0;
 
352
    free((char *) table->sort.addon_buf);
 
353
    free((char *) table->sort.addon_field);
 
354
    table->sort.addon_buf=0;
 
355
    table->sort.addon_field=0;
395
356
  }
396
357
}
397
358
 
416
377
 
417
378
/** Read 'count' number of buffer pointers into memory. */
418
379
 
419
 
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
 
380
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
420
381
                                     unsigned char *buf)
421
382
{
422
383
  uint32_t length= sizeof(BUFFPEK)*count;
427
388
    tmp= (unsigned char *)malloc(length);
428
389
  if (tmp)
429
390
  {
430
 
    if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
 
391
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
431
392
        my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
432
393
    {
433
394
      free((char*) tmp);
475
436
    HA_POS_ERROR on error.
476
437
*/
477
438
 
478
 
static ha_rows find_all_keys(SORTPARAM *param, 
479
 
                             optimizer::SqlSelect *select,
 
439
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
480
440
                             unsigned char **sort_keys,
481
 
                             internal::IO_CACHE *buffpek_pointers,
482
 
                             internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
 
441
                             IO_CACHE *buffpek_pointers,
 
442
                             IO_CACHE *tempfile, IO_CACHE *indexfile)
483
443
{
484
444
  int error,flag,quick_select;
485
445
  uint32_t idx,indexpos,ref_length;
486
446
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
487
 
  internal::my_off_t record;
 
447
  my_off_t record;
488
448
  Table *sort_form;
489
449
  Session *session= current_session;
490
450
  volatile Session::killed_state *killed= &session->killed;
491
 
  Cursor *file;
492
 
  MyBitmap *save_read_set, *save_write_set;
 
451
  handler *file;
 
452
  MY_BITMAP *save_read_set, *save_write_set;
493
453
 
494
454
  idx=indexpos=0;
495
455
  error=quick_select=0;
496
456
  sort_form=param->sort_form;
497
 
  file= sort_form->cursor;
 
457
  file=sort_form->file;
498
458
  ref_length=param->ref_length;
499
459
  ref_pos= ref_buff;
500
460
  quick_select=select && select->quick;
501
461
  record=0;
502
 
  flag= ((!indexfile && ! file->isOrdered())
 
462
  flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
503
463
         || quick_select);
504
464
  if (indexfile || flag)
505
465
    ref_pos= &file->ref[0];
525
485
  save_read_set=  sort_form->read_set;
526
486
  save_write_set= sort_form->write_set;
527
487
  /* Set up temporary column read map for columns used by sort */
528
 
  sort_form->tmp_set.clearAll();
 
488
  bitmap_clear_all(&sort_form->tmp_set);
529
489
  /* Temporary set for register_used_fields and register_field_in_read_map */
530
490
  sort_form->read_set= &sort_form->tmp_set;
531
491
  register_used_fields(param);
549
509
    {
550
510
      if (indexfile)
551
511
      {
552
 
        if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
 
512
        if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) /* purecov: deadcode */
553
513
        {
554
 
          error= errno ? errno : -1;            /* Abort */
 
514
          error= my_errno ? my_errno : -1;              /* Abort */
555
515
          break;
556
516
        }
557
517
        error=file->rnd_pos(sort_form->record[0],next_pos);
559
519
      else
560
520
      {
561
521
        error=file->rnd_next(sort_form->record[0]);
 
522
        if (!error)
 
523
          update_virtual_fields_marked_for_write(sort_form);
562
524
 
563
525
        if (!flag)
564
526
        {
565
 
          internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
 
527
          my_store_ptr(ref_pos,ref_length,record); // Position to row
566
528
          record+= sort_form->s->db_record_offset;
567
529
        }
568
530
        else if (!error)
579
541
        (void) file->extra(HA_EXTRA_NO_CACHE);
580
542
        file->ha_rnd_end();
581
543
      }
582
 
      return(HA_POS_ERROR);
 
544
      return(HA_POS_ERROR);             /* purecov: inspected */
583
545
    }
584
546
    if (error == 0)
585
547
      param->examined_rows++;
623
585
 
624
586
  if (error != HA_ERR_END_OF_FILE)
625
587
  {
626
 
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
627
 
    return(HA_POS_ERROR);
 
588
    file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
 
589
    return(HA_POS_ERROR);                       /* purecov: inspected */
628
590
  }
629
591
  if (indexpos && idx &&
630
592
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
631
 
    return(HA_POS_ERROR);
 
593
    return(HA_POS_ERROR);                       /* purecov: inspected */
632
594
  return(my_b_inited(tempfile) ?
633
595
              (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
634
596
              idx);
659
621
 
660
622
static int
661
623
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
662
 
           internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
 
624
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
663
625
{
664
626
  size_t sort_length, rec_length;
665
627
  unsigned char **end;
667
629
 
668
630
  sort_length= param->sort_length;
669
631
  rec_length= param->rec_length;
670
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
 
632
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
671
633
  if (!my_b_inited(tempfile) &&
672
634
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
673
635
                       MYF(MY_WME)))
674
 
    goto err;
 
636
    goto err;                                   /* purecov: inspected */
675
637
  /* check we won't have more buffpeks than we can possibly keep in memory */
676
638
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
677
639
    goto err;
678
640
  buffpek.file_pos= my_b_tell(tempfile);
679
641
  if ((ha_rows) count > param->max_rows)
680
 
    count=(uint32_t) param->max_rows;
 
642
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
681
643
  buffpek.count=(ha_rows) count;
682
644
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
683
645
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
721
683
{
722
684
  register Field *field;
723
685
  register SORT_FIELD *sort_field;
724
 
  size_t length;
 
686
  register uint32_t length;
725
687
 
726
688
  for (sort_field=param->local_sortorder ;
727
689
       sort_field != param->end ;
769
731
            memset(to-1, 0, sort_field->length+1);
770
732
          else
771
733
          {
 
734
            /* purecov: begin deadcode */
772
735
            /*
773
736
              This should only happen during extreme conditions if we run out
774
737
              of memory or have an item marked not null when it can be null.
776
739
            */
777
740
            assert(0);
778
741
            memset(to, 0, sort_field->length);  // Avoid crash
 
742
            /* purecov: end */
779
743
          }
780
744
          break;
781
745
        }
819
783
          int64_t value= item->val_int_result();
820
784
          if (maybe_null)
821
785
          {
822
 
            *to++=1;
 
786
            *to++=1;                            /* purecov: inspected */
823
787
            if (item->null_value)
824
788
            {
825
789
              if (maybe_null)
954
918
{
955
919
  register SORT_FIELD *sort_field;
956
920
  Table *table=param->sort_form;
 
921
  MY_BITMAP *bitmap= table->read_set;
957
922
 
958
923
  for (sort_field= param->local_sortorder ;
959
924
       sort_field != param->end ;
963
928
    if ((field= sort_field->field))
964
929
    {
965
930
      if (field->table == table)
966
 
        table->setReadSet(field->field_index);
 
931
      bitmap_set_bit(bitmap, field->field_index);
967
932
    }
968
933
    else
969
934
    {                                           // Item
977
942
    SORT_ADDON_FIELD *addonf= param->addon_field;
978
943
    Field *field;
979
944
    for ( ; (field= addonf->field) ; addonf++)
980
 
      table->setReadSet(field->field_index);
 
945
      bitmap_set_bit(bitmap, field->field_index);
981
946
  }
982
947
  else
983
948
  {
993
958
  uint32_t offset,res_length;
994
959
  unsigned char *to;
995
960
 
996
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
 
961
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
997
962
  res_length= param->res_length;
998
963
  offset= param->rec_length-res_length;
999
964
  if ((ha_rows) count > param->max_rows)
1000
965
    count=(uint32_t) param->max_rows;
1001
966
  if (!(to= table_sort->record_pointers=
1002
967
        (unsigned char*) malloc(res_length*count)))
1003
 
    return(1);
 
968
    return(1);                 /* purecov: inspected */
1004
969
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1005
970
  {
1006
971
    memcpy(to, *sort_keys+offset, res_length);
1013
978
/** Merge buffers to make < MERGEBUFF2 buffers. */
1014
979
 
1015
980
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1016
 
                    BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
 
981
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1017
982
{
1018
983
  register uint32_t i;
1019
 
  internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
 
984
  IO_CACHE t_file2,*from_file,*to_file,*temp;
1020
985
  BUFFPEK *lastbuff;
1021
986
 
1022
987
  if (*maxbuffer < MERGEBUFF2)
1023
 
    return(0);
 
988
    return(0);                          /* purecov: inspected */
1024
989
  if (flush_io_cache(t_file) ||
1025
990
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1026
991
                        MYF(MY_WME)))
1027
 
    return(1);
 
992
    return(1);                          /* purecov: inspected */
1028
993
 
1029
994
  from_file= t_file ; to_file= &t_file2;
1030
995
  while (*maxbuffer >= MERGEBUFF2)
1031
996
  {
1032
 
    if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
 
997
    if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1033
998
      goto cleanup;
1034
 
    if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
 
999
    if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1035
1000
      goto cleanup;
1036
1001
    lastbuff=buffpek;
1037
1002
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1042
1007
    }
1043
1008
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1044
1009
                      buffpek+i,buffpek+ *maxbuffer,0))
1045
 
      break;
 
1010
      break;                                    /* purecov: inspected */
1046
1011
    if (flush_io_cache(to_file))
1047
 
      break;
 
1012
      break;                                    /* purecov: inspected */
1048
1013
    temp=from_file; from_file=to_file; to_file=temp;
1049
1014
    setup_io_cache(from_file);
1050
1015
    setup_io_cache(to_file);
1069
1034
    (uint32_t)-1 if something goes wrong
1070
1035
*/
1071
1036
 
1072
 
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
 
                        uint32_t rec_length)
 
1037
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1038
                    uint32_t rec_length)
1074
1039
{
1075
1040
  register uint32_t count;
1076
1041
  uint32_t length;
1077
1042
 
1078
 
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
 
1043
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1079
1044
  {
1080
1045
    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;
 
1046
      return((uint32_t) -1);                    /* purecov: inspected */
 
1047
    buffpek->key=buffpek->base;
1084
1048
    buffpek->file_pos+= length;                 /* New filepos */
1085
 
    buffpek->count-= count;
 
1049
    buffpek->count-=    count;
1086
1050
    buffpek->mem_count= count;
1087
1051
  }
1088
1052
  return (count*rec_length);
1089
1053
} /* read_to_buffer */
1090
1054
 
1091
1055
 
1092
 
class compare_functor
 
1056
/**
 
1057
  Put all room used by freed buffer to use in adjacent buffer.
 
1058
 
 
1059
  Note, that we can't simply distribute memory evenly between all buffers,
 
1060
  because new areas must not overlap with old ones.
 
1061
 
 
1062
  @param[in] queue      list of non-empty buffers, without freed buffer
 
1063
  @param[in] reuse      empty buffer
 
1064
  @param[in] key_length key length
 
1065
*/
 
1066
 
 
1067
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1093
1068
{
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
 
1069
  unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
 
1070
  for (uint32_t i= 0; i < queue->elements; ++i)
1100
1071
  {
1101
 
    int val= key_compare(key_compare_arg,
1102
 
                      &i->key, &j->key);
1103
 
    return (val >= 0);
 
1072
    BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
 
1073
    if (bp->base + bp->max_keys * key_length == reuse->base)
 
1074
    {
 
1075
      bp->max_keys+= reuse->max_keys;
 
1076
      return;
 
1077
    }
 
1078
    else if (bp->base == reuse_end)
 
1079
    {
 
1080
      bp->base= reuse->base;
 
1081
      bp->max_keys+= reuse->max_keys;
 
1082
      return;
 
1083
    }
1104
1084
  }
1105
 
};
 
1085
  assert(0);
 
1086
}
1106
1087
 
1107
1088
 
1108
1089
/**
1123
1104
    other  error
1124
1105
*/
1125
1106
 
1126
 
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1127
 
                  internal::IO_CACHE *to_file, unsigned char *sort_buffer,
 
1107
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
 
1108
                  IO_CACHE *to_file, unsigned char *sort_buffer,
1128
1109
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1129
1110
                  int flag)
1130
1111
{
1133
1114
  size_t sort_length;
1134
1115
  uint32_t maxcount;
1135
1116
  ha_rows max_rows,org_max_rows;
1136
 
  internal::my_off_t to_start_filepos;
 
1117
  my_off_t to_start_filepos;
1137
1118
  unsigned char *strpos;
1138
1119
  BUFFPEK *buffpek;
 
1120
  QUEUE queue;
1139
1121
  qsort2_cmp cmp;
1140
1122
  void *first_cmp_arg;
1141
1123
  volatile Session::killed_state *killed= &current_session->killed;
1168
1150
  }
1169
1151
  else
1170
1152
  {
1171
 
    cmp= internal::get_ptr_compare(sort_length);
 
1153
    cmp= get_ptr_compare(sort_length);
1172
1154
    first_cmp_arg= (void*) &sort_length;
1173
1155
  }
1174
 
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
1175
 
    queue(compare_functor(cmp, first_cmp_arg));
 
1156
  if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
 
1157
                 (queue_compare) cmp, first_cmp_arg))
 
1158
    return(1);                                /* purecov: inspected */
1176
1159
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1177
1160
  {
1178
1161
    buffpek->base= strpos;
1180
1163
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1181
1164
                                                                         rec_length));
1182
1165
    if (error == -1)
1183
 
      goto err;
 
1166
      goto err;                                 /* purecov: inspected */
1184
1167
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
1185
 
    queue.push(buffpek);
 
1168
    queue_insert(&queue, (unsigned char*) buffpek);
1186
1169
  }
1187
1170
 
1188
1171
  if (param->unique_buff)
1195
1178
       This is safe as we know that there is always more than one element
1196
1179
       in each block to merge (This is guaranteed by the Unique:: algorithm
1197
1180
    */
1198
 
    buffpek= queue.top();
 
1181
    buffpek= (BUFFPEK*) queue_top(&queue);
1199
1182
    memcpy(param->unique_buff, buffpek->key, rec_length);
1200
1183
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1201
1184
    {
1202
 
      error=1; goto err;
 
1185
      error=1; goto err;                        /* purecov: inspected */
1203
1186
    }
1204
1187
    buffpek->key+= rec_length;
1205
1188
    buffpek->mem_count--;
1206
1189
    if (!--max_rows)
1207
1190
    {
1208
 
      error= 0;
1209
 
      goto end;
 
1191
      error= 0;                                       /* purecov: inspected */
 
1192
      goto end;                                       /* purecov: inspected */
1210
1193
    }
1211
 
    /* Top element has been used */
1212
 
    queue.pop();
1213
 
    queue.push(buffpek);
 
1194
    queue_replaced(&queue);                        // Top element has been used
1214
1195
  }
1215
1196
  else
1216
1197
    cmp= 0;                                        // Not unique
1217
1198
 
1218
 
  while (queue.size() > 1)
 
1199
  while (queue.elements > 1)
1219
1200
  {
1220
1201
    if (*killed)
1221
1202
    {
1222
 
      error= 1; goto err;
 
1203
      error= 1; goto err;                        /* purecov: inspected */
1223
1204
    }
1224
1205
    for (;;)
1225
1206
    {
1226
 
      buffpek= queue.top();
 
1207
      buffpek= (BUFFPEK*) queue_top(&queue);
1227
1208
      if (cmp)                                        // Remove duplicates
1228
1209
      {
1229
1210
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1235
1216
      {
1236
1217
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1237
1218
        {
1238
 
          error=1; goto err;
 
1219
          error=1; goto err;                        /* purecov: inspected */
1239
1220
        }
1240
1221
      }
1241
1222
      else
1242
1223
      {
1243
1224
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1244
1225
        {
1245
 
          error=1; goto err;
 
1226
          error=1; goto err;                        /* purecov: inspected */
1246
1227
        }
1247
1228
      }
1248
1229
      if (!--max_rows)
1249
1230
      {
1250
 
        error= 0;
1251
 
        goto end;
 
1231
        error= 0;                               /* purecov: inspected */
 
1232
        goto end;                               /* purecov: inspected */
1252
1233
      }
1253
1234
 
1254
1235
    skip_duplicate:
1258
1239
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1259
1240
                                          rec_length)))
1260
1241
        {
1261
 
          queue.pop();
 
1242
          queue_remove(&queue,0);
 
1243
          reuse_freed_buff(&queue, buffpek, rec_length);
1262
1244
          break;                        /* One buffer have been removed */
1263
1245
        }
1264
1246
        else if (error == -1)
1265
 
          goto err;
 
1247
          goto err;                        /* purecov: inspected */
1266
1248
      }
1267
 
      /* Top element has been replaced */
1268
 
      queue.pop();
1269
 
      queue.push(buffpek);
 
1249
      queue_replaced(&queue);              /* Top element has been replaced */
1270
1250
    }
1271
1251
  }
1272
 
  buffpek= queue.top();
 
1252
  buffpek= (BUFFPEK*) queue_top(&queue);
1273
1253
  buffpek->base= sort_buffer;
1274
1254
  buffpek->max_keys= param->keys;
1275
1255
 
1299
1279
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1300
1280
                     (rec_length*buffpek->mem_count)))
1301
1281
      {
1302
 
        error= 1; goto err;
 
1282
        error= 1; goto err;                        /* purecov: inspected */
1303
1283
      }
1304
1284
    }
1305
1285
    else
1321
1301
         != -1 && error != 0);
1322
1302
 
1323
1303
end:
1324
 
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
 
1304
  lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1325
1305
  lastbuff->file_pos= to_start_filepos;
1326
1306
err:
 
1307
  delete_queue(&queue);
1327
1308
  return(error);
1328
1309
} /* merge_buffers */
1329
1310
 
1332
1313
 
1333
1314
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1334
1315
                       BUFFPEK *buffpek, uint32_t maxbuffer,
1335
 
                       internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
 
1316
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1336
1317
{
1337
1318
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1338
1319
                    buffpek+maxbuffer,1))
1339
 
    return(1);
 
1320
    return(1);                          /* purecov: inspected */
1340
1321
  return(0);
1341
1322
} /* merge_index */
1342
1323
 
1357
1338
/**
1358
1339
  Calculate length of sort key.
1359
1340
 
1360
 
  @param session                          Thread Cursor
 
1341
  @param session                          Thread handler
1361
1342
  @param sortorder                Order of items to sort
1362
1343
  @param s_length                 Number of items to sort
1363
1344
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1407
1388
      switch (sortorder->result_type) {
1408
1389
      case STRING_RESULT:
1409
1390
        sortorder->length=sortorder->item->max_length;
1410
 
        set_if_smaller(sortorder->length,
1411
 
                       session->variables.max_sort_length);
 
1391
        set_if_smaller(sortorder->length, session->variables.max_sort_length);
1412
1392
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1413
1393
        {
1414
1394
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1443
1423
      if (sortorder->item->maybe_null)
1444
1424
        length++;                               // Place for NULL marker
1445
1425
    }
1446
 
    set_if_smaller(sortorder->length,
1447
 
                   (size_t)session->variables.max_sort_length);
 
1426
    set_if_smaller(sortorder->length, session->variables.max_sort_length);
1448
1427
    length+=sortorder->length;
1449
1428
  }
1450
1429
  sortorder->field= (Field*) 0;                 // end marker
1488
1467
  uint32_t length= 0;
1489
1468
  uint32_t fields= 0;
1490
1469
  uint32_t null_fields= 0;
 
1470
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1491
1471
 
1492
1472
  /*
1493
1473
    If there is a reference to a field in the query add it
1502
1482
 
1503
1483
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1504
1484
  {
1505
 
    if (!(field->isReadSet()))
 
1485
    if (!bitmap_is_set(read_set, field->field_index))
1506
1486
      continue;
1507
1487
    if (field->flags & BLOB_FLAG)
1508
1488
      return 0;
1525
1505
  null_fields= 0;
1526
1506
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1527
1507
  {
1528
 
    if (!(field->isReadSet()))
 
1508
    if (!bitmap_is_set(read_set, field->field_index))
1529
1509
      continue;
1530
1510
    addonf->field= field;
1531
1511
    addonf->offset= length;
1630
1610
    }
1631
1611
  }
1632
1612
}
1633
 
 
1634
 
} /* namespace drizzled */