44
41
#include "drizzled/internal/my_sys.h"
45
42
#include "plugin/myisam/myisam.h"
46
43
#include "drizzled/plugin/transactional_storage_engine.h"
47
#include "drizzled/atomics.h"
48
#include "drizzled/global_buffer.h"
51
45
using namespace std;
56
/* Defines used by filesort and uniques */
60
class BufferCompareContext
63
qsort_cmp2 key_compare;
64
void *key_compare_arg;
66
BufferCompareContext() :
75
uint32_t rec_length; /* Length of sorted records */
76
uint32_t sort_length; /* Length of sorted columns */
77
uint32_t ref_length; /* Length of record ref. */
78
uint32_t addon_length; /* Length of added packed fields */
79
uint32_t res_length; /* Length of records in final sorted file/buffer */
80
uint32_t keys; /* Max keys / buffer */
81
ha_rows max_rows,examined_rows;
82
Table *sort_form; /* For quicker make_sortkey */
83
SortField *local_sortorder;
85
sort_addon_field *addon_field; /* Descriptors for companion fields */
86
unsigned char *unique_buff;
89
/* The fields below are used only by Unique class */
91
BufferCompareContext cmp_context;
119
int write_keys(unsigned char * *sort_keys,
121
internal::IO_CACHE *buffer_file,
122
internal::IO_CACHE *tempfile);
124
void make_sortkey(unsigned char *to,
125
unsigned char *ref_pos);
126
void register_used_fields();
127
bool save_index(unsigned char **sort_keys,
129
filesort_info *table_sort);
133
50
/* functions defined in this file */
135
52
static char **make_char_array(char **old_pos, register uint32_t fields,
140
57
unsigned char *buf);
59
static ha_rows find_all_keys(Session *session,
61
optimizer::SqlSelect *select,
62
unsigned char * *sort_keys,
63
internal::IO_CACHE *buffer_file,
64
internal::IO_CACHE *tempfile,
65
internal::IO_CACHE *indexfile);
67
static int write_keys(SORTPARAM *param,
68
unsigned char * *sort_keys,
70
internal::IO_CACHE *buffer_file,
71
internal::IO_CACHE *tempfile);
73
static void make_sortkey(SORTPARAM *param,
75
unsigned char *ref_pos);
76
static void register_used_fields(SORTPARAM *param);
77
static int merge_index(SORTPARAM *param,
78
unsigned char *sort_buffer,
81
internal::IO_CACHE *tempfile,
82
internal::IO_CACHE *outfile);
83
static bool save_index(SORTPARAM *param,
84
unsigned char **sort_keys,
86
filesort_info_st *table_sort);
142
87
static uint32_t suffix_length(uint32_t string_length);
143
static void unpack_addon_fields(sort_addon_field *addon_field,
88
static uint32_t sortlength(Session *session,
91
bool *multi_byte_charset);
92
static sort_addon_field_st *get_addon_fields(Session *session,
96
static void unpack_addon_fields(sort_addon_field_st *addon_field,
144
97
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
100
Creates a set of pointers that can be used to read the rows
183
131
examined_rows will be set to number of examined rows
186
ha_rows FileSort::run(Table *table, SortField *sortorder, uint32_t s_length,
187
optimizer::SqlSelect *select, ha_rows max_rows,
188
bool sort_positions, ha_rows &examined_rows)
134
ha_rows filesort(Session *session, Table *table, SortField *sortorder, uint32_t s_length,
135
optimizer::SqlSelect *select, ha_rows max_rows,
136
bool sort_positions, ha_rows *examined_rows)
191
uint32_t memavl= 0, min_sort_memory;
139
uint32_t memavl, min_sort_memory;
192
140
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
195
142
ha_rows records= HA_POS_ERROR;
196
143
unsigned char **sort_keys= 0;
197
internal::IO_CACHE tempfile;
198
internal::IO_CACHE buffpek_pointers;
199
internal::IO_CACHE *selected_records_file;
200
internal::IO_CACHE *outfile;
144
internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
146
bool multi_byte_charset;
205
Don't use table->sort in filesort as it is also used by
206
QuickIndexMergeSelect. Work with a copy and put it back at the end
207
when index_merge select has finished with it.
209
filesort_info table_sort(table->sort);
210
table->sort.io_cache= NULL;
148
filesort_info_st table_sort;
212
149
TableList *tab= table->pos_in_table_list;
213
150
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
218
155
Release InnoDB's adaptive hash index latch (if holding) before
221
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
158
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
161
Don't use table->sort in filesort as it is also used by
162
QuickIndexMergeSelect. Work with a copy and put it back at the end
163
when index_merge select has finished with it.
165
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
166
table->sort.io_cache= NULL;
224
168
outfile= table_sort.io_cache;
225
assert(tempfile.buffer == 0);
226
assert(buffpek_pointers.buffer == 0);
228
param.sort_length= sortlength(sortorder, s_length, &multi_byte_charset);
169
my_b_clear(&tempfile);
170
my_b_clear(&buffpek_pointers);
173
memset(¶m, 0, sizeof(param));
174
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
229
175
param.ref_length= table->cursor->ref_length;
176
param.addon_field= 0;
177
param.addon_length= 0;
231
178
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
234
181
Get the descriptors of all fields whose values are appended
235
182
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
184
param.addon_field= get_addon_fields(session, table->getFields(),
238
185
param.sort_length,
239
186
¶m.addon_length);
291
236
selected_records_file= 0;
294
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
239
if (multi_byte_charset &&
240
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
299
memavl= getSession().variables.sortbuff_size;
243
memavl= session->variables.sortbuff_size;
300
244
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
245
while (memavl >= min_sort_memory)
303
247
uint32_t old_memavl;
304
248
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
249
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
307
allocated_sort_memory= param.keys * param.rec_length;
308
if (not global_sort_buffer.add(allocated_sort_memory))
310
my_error(ER_OUT_OF_GLOBAL_SORTMEMORY, MYF(ME_ERROR+ME_WAITTANG));
314
250
if ((table_sort.sort_keys=
315
251
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
252
param.keys, param.rec_length)))
319
global_sort_buffer.sub(allocated_sort_memory);
320
254
old_memavl= memavl;
321
255
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
256
memavl= min_sort_memory;
327
261
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
331
if (buffpek_pointers.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
264
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
265
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
268
param.keys--; /* TODO: check why we do this */
337
269
param.sort_form= table;
338
270
param.end=(param.local_sortorder=sortorder)+s_length;
339
if ((records= find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
340
&tempfile, selected_records_file)) == HA_POS_ERROR)
271
if ((records=find_all_keys(session, ¶m,select,sort_keys, &buffpek_pointers,
272
&tempfile, selected_records_file)) ==
344
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
275
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
346
277
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
279
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
357
286
if (table_sort.buffpek)
358
287
free(table_sort.buffpek);
359
table_sort.buffpek = 0;
288
table_sort.buffpek= 0;
361
290
if (!(table_sort.buffpek=
362
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
291
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
292
table_sort.buffpek)))
366
buffpek_inst= (buffpek *) table_sort.buffpek;
294
buffpek= (buffpek_st *) table_sort.buffpek;
367
295
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
296
close_cached_file(&buffpek_pointers);
369
297
/* Open cached file if it isn't open */
370
if (! my_b_inited(outfile) && outfile->open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME)))
375
if (outfile->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
298
if (! my_b_inited(outfile) &&
299
open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
302
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
381
306
Use also the space previously used by string pointers in sort_buffer
382
307
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
309
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
311
maxbuffer--; // Offset from 0
387
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
392
if (flush_io_cache(&tempfile) || tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
397
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek_inst,maxbuffer,&tempfile, outfile))
312
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
315
if (flush_io_cache(&tempfile) ||
316
reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
318
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
403
322
if (records > param.max_rows)
405
records= param.max_rows;
323
records=param.max_rows;
410
if (not subselect || not subselect->is_uncacheable())
327
if (param.tmp_buffer)
328
if (param.tmp_buffer)
329
free(param.tmp_buffer);
330
if (!subselect || !subselect->is_uncacheable())
413
333
table_sort.sort_keys= 0;
415
335
table_sort.buffpek= 0;
416
336
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
338
close_cached_file(&tempfile);
339
close_cached_file(&buffpek_pointers);
422
340
if (my_b_inited(outfile))
424
342
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
345
internal::my_off_t save_pos=outfile->pos_in_file;
430
346
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
347
if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
435
349
outfile->end_of_file=save_pos;
441
354
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
446
getSession().status_var.filesort_rows+= (uint32_t) records;
359
session->status_var.filesort_rows+= (uint32_t) records;
448
examined_rows= param.examined_rows;
449
global_sort_buffer.sub(allocated_sort_memory);
450
table->sort= table_sort;
361
*examined_rows= param.examined_rows;
362
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
451
363
DRIZZLE_FILESORT_DONE(error, records);
452
364
return (error ? HA_POS_ERROR : records);
368
void Table::filesort_free_buffers(bool full)
370
if (sort.record_pointers)
372
free((unsigned char*) sort.record_pointers);
373
sort.record_pointers=0;
379
if ((unsigned char*) sort.sort_keys)
380
free((unsigned char*) sort.sort_keys);
385
if ((unsigned char*) sort.buffpek)
386
free((unsigned char*) sort.buffpek);
393
free((char *) sort.addon_buf);
394
free((char *) sort.addon_field);
455
400
/** Make a array of string pointers. */
457
402
static char **make_char_array(char **old_pos, register uint32_t fields,
476
421
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
477
422
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
424
uint32_t length= sizeof(buffpek_st)*count;
480
425
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
426
if (count > UINT_MAX/sizeof(buffpek_st))
427
return 0; /* sizeof(buffpek_st)*count will overflow */
484
429
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
432
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
488
433
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
435
free((char*) tmp);
532
477
HA_POS_ERROR on error.
535
ha_rows FileSort::find_all_keys(SortParam *param,
536
optimizer::SqlSelect *select,
537
unsigned char **sort_keys,
538
internal::IO_CACHE *buffpek_pointers,
539
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
480
static ha_rows find_all_keys(Session *session,
482
optimizer::SqlSelect *select,
483
unsigned char **sort_keys,
484
internal::IO_CACHE *buffpek_pointers,
485
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
541
487
int error,flag,quick_select;
542
488
uint32_t idx,indexpos,ref_length;
543
489
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
490
internal::my_off_t record;
545
491
Table *sort_form;
546
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
492
volatile Session::killed_state *killed= &session->killed;
548
boost::dynamic_bitset<> *save_read_set= NULL;
549
boost::dynamic_bitset<> *save_write_set= NULL;
494
MyBitmap *save_read_set, *save_write_set;
552
497
error=quick_select=0;
574
520
if (select->quick->reset())
575
521
return(HA_POS_ERROR);
577
read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1);
523
read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
580
526
/* Remember original bitmaps */
581
527
save_read_set= sort_form->read_set;
582
528
save_write_set= sort_form->write_set;
583
529
/* Set up temporary column read map for columns used by sort */
584
sort_form->tmp_set.reset();
530
sort_form->tmp_set.clearAll();
585
531
/* Temporary set for register_used_fields and register_field_in_read_map */
586
532
sort_form->read_set= &sort_form->tmp_set;
587
param->register_used_fields();
533
register_used_fields(param);
588
534
if (select && select->cond)
589
535
select->cond->walk(&Item::register_field_in_read_map, 1,
590
536
(unsigned char*) sort_form);
591
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
537
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
674
617
file->endTableScan();
677
if (getSession().is_error())
620
if (session->is_error())
678
621
return(HA_POS_ERROR);
680
623
/* Signal we should use orignal column read and write maps */
681
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
624
sort_form->column_bitmaps_set(save_read_set, save_write_set);
683
626
if (error != HA_ERR_END_OF_FILE)
685
628
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
686
629
return(HA_POS_ERROR);
689
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
631
if (indexpos && idx &&
632
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
691
633
return(HA_POS_ERROR);
694
634
return(my_b_inited(tempfile) ?
695
635
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
702
642
Sort the buffer and write:
703
643
-# the sorted sequence to tempfile
704
-# a buffpek describing the sorted sequence position to buffpek_pointers
644
-# a buffpek_st describing the sorted sequence position to buffpek_pointers
706
646
(was: Skriver en buffert med nycklar till filen)
708
648
@param param Sort parameters
709
649
@param sort_keys Array of pointers to keys to sort
710
650
@param count Number of elements in sort_keys array
711
@param buffpek_pointers One 'buffpek' struct will be written into this file.
712
The buffpek::{file_pos, count} will indicate where
651
@param buffpek_pointers One 'buffpek_st' struct will be written into this file.
652
The buffpek_st::{file_pos, count} will indicate where
713
653
the sorted data was stored.
714
654
@param tempfile The sorted sequence will be written into this file.
722
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
723
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
663
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
664
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
666
size_t sort_length, rec_length;
670
sort_length= param->sort_length;
671
rec_length= param->rec_length;
727
672
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
728
673
if (!my_b_inited(tempfile) &&
729
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
674
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
733
677
/* check we won't have more buffpeks than we can possibly keep in memory */
734
if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
678
if (my_b_tell(buffpek_pointers) + sizeof(buffpek_st) > (uint64_t)UINT_MAX)
739
680
buffpek.file_pos= my_b_tell(tempfile);
740
if ((ha_rows) count > max_rows)
741
count=(uint32_t) max_rows;
681
if ((ha_rows) count > param->max_rows)
682
count=(uint32_t) param->max_rows;
743
683
buffpek.count=(ha_rows) count;
745
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
684
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
747
685
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
753
687
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
759
693
} /* write_keys */
818
753
Item *item=sort_field->item;
819
754
maybe_null= item->maybe_null;
821
755
switch (sort_field->result_type) {
822
756
case STRING_RESULT:
824
const CHARSET_INFO * const cs=item->collation.collation;
825
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
827
uint32_t sort_field_length;
758
const CHARSET_INFO * const cs=item->collation.collation;
759
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
761
uint32_t sort_field_length;
765
/* All item->str() to use some extra byte for end null.. */
766
String tmp((char*) to,sort_field->length+4,cs);
767
String *res= item->str_result(&tmp);
831
/* All item->str() to use some extra byte for end null.. */
832
String tmp((char*) to,sort_field->length+4,cs);
833
String *res= item->str_result(&tmp);
837
memset(to-1, 0, sort_field->length+1);
841
This should only happen during extreme conditions if we run out
842
of memory or have an item marked not null when it can be null.
843
This code is here mainly to avoid a hard crash in this case.
846
memset(to, 0, sort_field->length); // Avoid crash
850
length= res->length();
851
sort_field_length= sort_field->length - sort_field->suffix_length;
852
diff=(int) (sort_field_length - length);
856
length= sort_field_length;
858
if (sort_field->suffix_length)
860
/* Store length last in result_string */
861
store_length(to + sort_field_length, length,
862
sort_field->suffix_length);
864
if (sort_field->need_strxnfrm)
866
char *from=(char*) res->ptr();
868
if ((unsigned char*) from == to)
870
set_if_smaller(length,sort_field->length);
871
memcpy(tmp_buffer,from,length);
874
tmp_length= my_strnxfrm(cs,to,sort_field->length,
875
(unsigned char*) from, length);
876
assert(tmp_length == sort_field->length);
771
memset(to-1, 0, sort_field->length+1);
880
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
881
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
775
This should only happen during extreme conditions if we run out
776
of memory or have an item marked not null when it can be null.
777
This code is here mainly to avoid a hard crash in this case.
780
memset(to, 0, sort_field->length); // Avoid crash
784
length= res->length();
785
sort_field_length= sort_field->length - sort_field->suffix_length;
786
diff=(int) (sort_field_length - length);
790
length= sort_field_length;
792
if (sort_field->suffix_length)
794
/* Store length last in result_string */
795
store_length(to + sort_field_length, length,
796
sort_field->suffix_length);
798
if (sort_field->need_strxnfrm)
800
char *from=(char*) res->ptr();
802
if ((unsigned char*) from == to)
804
set_if_smaller(length,sort_field->length);
805
memcpy(param->tmp_buffer,from,length);
806
from=param->tmp_buffer;
808
tmp_length= my_strnxfrm(cs,to,sort_field->length,
809
(unsigned char*) from, length);
810
assert(tmp_length == sort_field->length);
814
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
815
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
887
821
int64_t value= item->val_int_result();
891
825
if (item->null_value)
902
to[7]= (unsigned char) value;
903
to[6]= (unsigned char) (value >> 8);
904
to[5]= (unsigned char) (value >> 16);
905
to[4]= (unsigned char) (value >> 24);
906
to[3]= (unsigned char) (value >> 32);
907
to[2]= (unsigned char) (value >> 40);
908
to[1]= (unsigned char) (value >> 48);
836
to[7]= (unsigned char) value;
837
to[6]= (unsigned char) (value >> 8);
838
to[5]= (unsigned char) (value >> 16);
839
to[4]= (unsigned char) (value >> 24);
840
to[3]= (unsigned char) (value >> 32);
841
to[2]= (unsigned char) (value >> 40);
842
to[1]= (unsigned char) (value >> 48);
909
843
if (item->unsigned_flag) /* Fix sign */
910
844
to[0]= (unsigned char) (value >> 56);
912
846
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
915
849
case DECIMAL_RESULT:
917
851
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
1060
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
992
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
993
filesort_info_st *table_sort)
995
uint32_t offset,res_length;
1063
996
unsigned char *to;
1065
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1066
offset= rec_length - res_length;
1068
if ((ha_rows) count > max_rows)
1069
count=(uint32_t) max_rows;
1071
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1074
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
998
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
999
res_length= param->res_length;
1000
offset= param->rec_length-res_length;
1001
if ((ha_rows) count > param->max_rows)
1002
count=(uint32_t) param->max_rows;
1003
if (!(to= table_sort->record_pointers=
1004
(unsigned char*) malloc(res_length*count)))
1006
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1076
1008
memcpy(to, *sort_keys+offset, res_length);
1077
1009
to+= res_length;
1084
1015
/** Merge buffers to make < MERGEBUFF2 buffers. */
1086
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1087
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1017
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1018
buffpek_st *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1020
register uint32_t i;
1089
1021
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1022
buffpek_st *lastbuff;
1092
1024
if (*maxbuffer < MERGEBUFF2)
1094
1026
if (flush_io_cache(t_file) ||
1095
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1027
open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
1100
1031
from_file= t_file ; to_file= &t_file2;
1101
1032
while (*maxbuffer >= MERGEBUFF2)
1103
register uint32_t i;
1105
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1110
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1115
lastbuff=buffpek_inst;
1034
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1036
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1116
1039
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1118
1041
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1119
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1042
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1125
1045
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1126
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1046
buffpek+i,buffpek+ *maxbuffer,0))
1131
1048
if (flush_io_cache(to_file))
1136
1050
temp=from_file; from_file=to_file; to_file=temp;
1137
from_file->setup_io_cache();
1138
to_file->setup_io_cache();
1139
*maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
1051
setup_io_cache(from_file);
1052
setup_io_cache(to_file);
1053
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1143
to_file->close_cached_file(); // This holds old result
1056
close_cached_file(to_file); // This holds old result
1144
1057
if (to_file == t_file)
1146
1059
*t_file=t_file2; // Copy result file
1147
t_file->setup_io_cache();
1060
setup_io_cache(t_file);
1150
1063
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1158
1071
(uint32_t)-1 if something goes wrong
1161
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
1074
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, buffpek_st *buffpek,
1075
uint32_t rec_length)
1163
1077
register uint32_t count;
1164
1078
uint32_t length;
1166
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1080
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1168
if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
1082
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1169
1083
return((uint32_t) -1);
1171
buffpek_inst->key= buffpek_inst->base;
1172
buffpek_inst->file_pos+= length; /* New filepos */
1173
buffpek_inst->count-= count;
1174
buffpek_inst->mem_count= count;
1085
buffpek->key= buffpek->base;
1086
buffpek->file_pos+= length; /* New filepos */
1087
buffpek->count-= count;
1088
buffpek->mem_count= count;
1176
1090
return (count*rec_length);
1177
1091
} /* read_to_buffer */
1182
1096
qsort2_cmp key_compare;
1183
1097
void *key_compare_arg;
1186
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1187
key_compare(in_key_compare),
1188
key_compare_arg(in_compare_arg)
1191
inline bool operator()(const buffpek *i, const buffpek *j) const
1099
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1100
: key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1101
inline bool operator()(const buffpek_st *i, const buffpek_st *j) const
1193
int val= key_compare(key_compare_arg, &i->key, &j->key);
1103
int val= key_compare(key_compare_arg,
1195
1105
return (val >= 0);
1218
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1219
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1220
buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1128
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1129
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1130
buffpek_st *lastbuff, buffpek_st *Fb, buffpek_st *Tb,
1224
1134
uint32_t rec_length,res_length,offset;
1263
1173
cmp= internal::get_ptr_compare(sort_length);
1264
1174
first_cmp_arg= (void*) &sort_length;
1266
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1176
priority_queue<buffpek_st *, vector<buffpek_st *>, compare_functor >
1267
1177
queue(compare_functor(cmp, first_cmp_arg));
1268
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1178
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1270
buffpek_inst->base= strpos;
1271
buffpek_inst->max_keys= maxcount;
1272
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
1180
buffpek->base= strpos;
1181
buffpek->max_keys= maxcount;
1182
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1274
1184
if (error == -1)
1277
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1278
queue.push(buffpek_inst);
1186
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1187
queue.push(buffpek);
1281
1190
if (param->unique_buff)
1288
1197
This is safe as we know that there is always more than one element
1289
1198
in each block to merge (This is guaranteed by the Unique:: algorithm
1291
buffpek_inst= queue.top();
1292
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1293
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key, rec_length))
1200
buffpek= queue.top();
1201
memcpy(param->unique_buff, buffpek->key, rec_length);
1202
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1297
buffpek_inst->key+= rec_length;
1298
buffpek_inst->mem_count--;
1206
buffpek->key+= rec_length;
1207
buffpek->mem_count--;
1299
1208
if (!--max_rows)
1304
1213
/* Top element has been used */
1306
queue.push(buffpek_inst);
1215
queue.push(buffpek);
1310
1218
cmp= 0; // Not unique
1313
1220
while (queue.size() > 1)
1321
buffpek_inst= queue.top();
1228
buffpek= queue.top();
1322
1229
if (cmp) // Remove duplicates
1324
1231
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1325
(unsigned char**) &buffpek_inst->key))
1232
(unsigned char**) &buffpek->key))
1326
1233
goto skip_duplicate;
1327
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1234
memcpy(param->unique_buff, buffpek->key, rec_length);
1331
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1238
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1338
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1245
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1343
1250
if (!--max_rows)
1349
1256
skip_duplicate:
1350
buffpek_inst->key+= rec_length;
1351
if (! --buffpek_inst->mem_count)
1257
buffpek->key+= rec_length;
1258
if (! --buffpek->mem_count)
1353
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1260
if (!(error= (int) read_to_buffer(from_file,buffpek,
1357
1264
break; /* One buffer have been removed */
1359
1266
else if (error == -1)
1364
1269
/* Top element has been replaced */
1366
queue.push(buffpek_inst);
1271
queue.push(buffpek);
1369
buffpek_inst= queue.top();
1370
buffpek_inst->base= sort_buffer;
1371
buffpek_inst->max_keys= param->keys;
1274
buffpek= queue.top();
1275
buffpek->base= sort_buffer;
1276
buffpek->max_keys= param->keys;
1374
1279
As we know all entries in the buffer are unique, we only have to
1379
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
1284
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1381
buffpek_inst->key+= rec_length; // Remove duplicate
1382
--buffpek_inst->mem_count;
1286
buffpek->key+= rec_length; // Remove duplicate
1287
--buffpek->mem_count;
1388
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1293
if ((ha_rows) buffpek->mem_count > max_rows)
1389
1294
{ /* Don't write too many records */
1390
buffpek_inst->mem_count= (uint32_t) max_rows;
1391
buffpek_inst->count= 0; /* Don't read more */
1295
buffpek->mem_count= (uint32_t) max_rows;
1296
buffpek->count= 0; /* Don't read more */
1393
max_rows-= buffpek_inst->mem_count;
1298
max_rows-= buffpek->mem_count;
1396
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1397
(rec_length*buffpek_inst->mem_count)))
1301
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1302
(rec_length*buffpek->mem_count)))
1404
1309
register unsigned char *end;
1405
strpos= buffpek_inst->key+offset;
1406
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1310
strpos= buffpek->key+offset;
1311
for (end= strpos+buffpek->mem_count*rec_length ;
1407
1312
strpos != end ;
1408
1313
strpos+= rec_length)
1410
1315
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1418
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1322
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1419
1323
!= -1 && error != 0);
1422
1326
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1423
1327
lastbuff->file_pos= to_start_filepos;
1426
1330
} /* merge_buffers */
1429
1333
/* Do a merge to output-file (save only positions) */
1431
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1432
buffpek *buffpek_inst, uint32_t maxbuffer,
1433
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1335
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1336
buffpek_st *buffpek, uint32_t maxbuffer,
1337
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1435
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1436
buffpek_inst+maxbuffer,1))
1339
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1340
buffpek+maxbuffer,1))
1440
1343
} /* merge_index */
1500
1406
sortorder->result_type= sortorder->item->result_type();
1501
1407
if (sortorder->item->result_as_int64_t())
1502
1408
sortorder->result_type= INT_RESULT;
1504
1409
switch (sortorder->result_type) {
1505
1410
case STRING_RESULT:
1506
sortorder->length=sortorder->item->max_length;
1411
sortorder->length=sortorder->item->max_length;
1507
1412
set_if_smaller(sortorder->length,
1508
getSession().variables.max_sort_length);
1509
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1413
session->variables.max_sort_length);
1414
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1511
1416
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1512
sortorder->need_strxnfrm= 1;
1513
*multi_byte_charset= 1;
1417
sortorder->need_strxnfrm= 1;
1418
*multi_byte_charset= 1;
1515
1420
else if (cs == &my_charset_bin)
1517
1422
/* Store length last to be able to sort blob/varbinary */
1518
1423
sortorder->suffix_length= suffix_length(sortorder->length);
1519
1424
sortorder->length+= sortorder->suffix_length;
1522
1427
case INT_RESULT:
1523
sortorder->length=8; // Size of intern int64_t
1428
sortorder->length=8; // Size of intern int64_t
1525
1430
case DECIMAL_RESULT:
1526
1431
sortorder->length=
1527
1432
my_decimal_get_binary_size(sortorder->item->max_length -
1529
1434
sortorder->item->decimals);
1531
1436
case REAL_RESULT:
1532
sortorder->length=sizeof(double);
1437
sortorder->length=sizeof(double);
1534
1439
case ROW_RESULT:
1535
// This case should never be choosen
1441
// This case should never be choosen
1539
1445
if (sortorder->item->maybe_null)
1540
length++; // Place for NULL marker
1446
length++; // Place for NULL marker
1542
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1448
set_if_smaller(sortorder->length,
1449
(size_t)session->variables.max_sort_length);
1543
1450
length+=sortorder->length;
1545
1452
sortorder->field= (Field*) 0; // end marker