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(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);
66
static int write_keys(SORTPARAM *param,
67
unsigned char * *sort_keys,
69
internal::IO_CACHE *buffer_file,
70
internal::IO_CACHE *tempfile);
72
static void make_sortkey(SORTPARAM *param,
74
unsigned char *ref_pos);
75
static void register_used_fields(SORTPARAM *param);
76
static int merge_index(SORTPARAM *param,
77
unsigned char *sort_buffer,
80
internal::IO_CACHE *tempfile,
81
internal::IO_CACHE *outfile);
82
static bool save_index(SORTPARAM *param,
83
unsigned char **sort_keys,
85
filesort_info_st *table_sort);
142
86
static uint32_t suffix_length(uint32_t string_length);
143
static void unpack_addon_fields(sort_addon_field *addon_field,
87
static uint32_t sortlength(Session *session,
88
SORT_FIELD *sortorder,
90
bool *multi_byte_charset);
91
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
95
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
144
96
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
99
Creates a set of pointers that can be used to read the rows
183
130
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)
133
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
134
optimizer::SqlSelect *select, ha_rows max_rows,
135
bool sort_positions, ha_rows *examined_rows)
191
uint32_t memavl= 0, min_sort_memory;
138
uint32_t memavl, min_sort_memory;
192
139
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
195
141
ha_rows records= HA_POS_ERROR;
196
142
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;
143
internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
145
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;
147
filesort_info_st table_sort;
212
148
TableList *tab= table->pos_in_table_list;
213
149
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
218
154
Release InnoDB's adaptive hash index latch (if holding) before
221
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
157
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
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
162
when index_merge select has finished with it.
164
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
165
table->sort.io_cache= NULL;
224
167
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);
168
my_b_clear(&tempfile);
169
my_b_clear(&buffpek_pointers);
172
memset(¶m, 0, sizeof(param));
173
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
229
174
param.ref_length= table->cursor->ref_length;
175
param.addon_field= 0;
176
param.addon_length= 0;
231
177
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
234
180
Get the descriptors of all fields whose values are appended
235
181
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
183
param.addon_field= get_addon_fields(session, table->field,
238
184
param.sort_length,
239
185
¶m.addon_length);
291
235
selected_records_file= 0;
294
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
238
if (multi_byte_charset &&
239
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
299
memavl= getSession().variables.sortbuff_size;
242
memavl= session->variables.sortbuff_size;
300
243
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
244
while (memavl >= min_sort_memory)
303
246
uint32_t old_memavl;
304
247
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
248
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
249
if ((table_sort.sort_keys=
315
250
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
251
param.keys, param.rec_length)))
319
global_sort_buffer.sub(allocated_sort_memory);
320
253
old_memavl= memavl;
321
254
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
255
memavl= min_sort_memory;
327
260
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)))
263
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
264
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
267
param.keys--; /* TODO: check why we do this */
337
268
param.sort_form= table;
338
269
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)
270
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
271
&tempfile, selected_records_file)) ==
344
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
274
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
346
276
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
278
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
357
285
if (table_sort.buffpek)
358
286
free(table_sort.buffpek);
359
table_sort.buffpek = 0;
287
table_sort.buffpek= 0;
361
289
if (!(table_sort.buffpek=
362
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
290
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
291
table_sort.buffpek)))
366
buffpek_inst= (buffpek *) table_sort.buffpek;
293
buffpek= (BUFFPEK *) table_sort.buffpek;
367
294
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
295
close_cached_file(&buffpek_pointers);
369
296
/* 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))
297
if (! my_b_inited(outfile) &&
298
open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
301
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
381
305
Use also the space previously used by string pointers in sort_buffer
382
306
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
308
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
310
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))
311
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
314
if (flush_io_cache(&tempfile) ||
315
reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
317
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
403
321
if (records > param.max_rows)
405
records= param.max_rows;
322
records=param.max_rows;
410
if (not subselect || not subselect->is_uncacheable())
326
if (param.tmp_buffer)
327
if (param.tmp_buffer)
328
free(param.tmp_buffer);
329
if (!subselect || !subselect->is_uncacheable())
413
332
table_sort.sort_keys= 0;
415
334
table_sort.buffpek= 0;
416
335
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
337
close_cached_file(&tempfile);
338
close_cached_file(&buffpek_pointers);
422
339
if (my_b_inited(outfile))
424
341
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
344
internal::my_off_t save_pos=outfile->pos_in_file;
430
345
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
346
if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
435
348
outfile->end_of_file=save_pos;
441
352
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
353
MYF(ME_ERROR+ME_WAITTANG));
446
getSession().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;
355
statistic_add(session->status_var.filesort_rows,
356
(uint32_t) records, &LOCK_status);
357
*examined_rows= param.examined_rows;
358
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
451
359
DRIZZLE_FILESORT_DONE(error, records);
452
360
return (error ? HA_POS_ERROR : records);
364
void Table::filesort_free_buffers(bool full)
366
if (sort.record_pointers)
368
free((unsigned char*) sort.record_pointers);
369
sort.record_pointers=0;
375
if ((unsigned char*) sort.sort_keys)
376
free((unsigned char*) sort.sort_keys);
381
if ((unsigned char*) sort.buffpek)
382
free((unsigned char*) sort.buffpek);
389
free((char *) sort.addon_buf);
390
free((char *) sort.addon_field);
455
396
/** Make a array of string pointers. */
457
398
static char **make_char_array(char **old_pos, register uint32_t fields,
476
417
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
477
418
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
420
uint32_t length= sizeof(BUFFPEK)*count;
480
421
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
422
if (count > UINT_MAX/sizeof(BUFFPEK))
423
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
425
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
428
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
488
429
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
431
free((char*) tmp);
532
473
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)
476
static ha_rows find_all_keys(SORTPARAM *param,
477
optimizer::SqlSelect *select,
478
unsigned char **sort_keys,
479
internal::IO_CACHE *buffpek_pointers,
480
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
541
482
int error,flag,quick_select;
542
483
uint32_t idx,indexpos,ref_length;
543
484
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
485
internal::my_off_t record;
545
486
Table *sort_form;
546
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
487
Session *session= current_session;
488
volatile Session::killed_state *killed= &session->killed;
548
boost::dynamic_bitset<> *save_read_set= NULL;
549
boost::dynamic_bitset<> *save_write_set= NULL;
490
MyBitmap *save_read_set, *save_write_set;
552
493
error=quick_select=0;
574
516
if (select->quick->reset())
575
517
return(HA_POS_ERROR);
577
read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1);
519
read_record_info.init_read_record(current_session, select->quick->head, select, 1, 1);
580
522
/* Remember original bitmaps */
581
523
save_read_set= sort_form->read_set;
582
524
save_write_set= sort_form->write_set;
583
525
/* Set up temporary column read map for columns used by sort */
584
sort_form->tmp_set.reset();
526
sort_form->tmp_set.clearAll();
585
527
/* Temporary set for register_used_fields and register_field_in_read_map */
586
528
sort_form->read_set= &sort_form->tmp_set;
587
param->register_used_fields();
529
register_used_fields(param);
588
530
if (select && select->cond)
589
531
select->cond->walk(&Item::register_field_in_read_map, 1,
590
532
(unsigned char*) sort_form);
591
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
533
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
702
638
Sort the buffer and write:
703
639
-# the sorted sequence to tempfile
704
-# a buffpek describing the sorted sequence position to buffpek_pointers
640
-# a BUFFPEK describing the sorted sequence position to buffpek_pointers
706
642
(was: Skriver en buffert med nycklar till filen)
708
644
@param param Sort parameters
709
645
@param sort_keys Array of pointers to keys to sort
710
646
@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
647
@param buffpek_pointers One 'BUFFPEK' struct will be written into this file.
648
The BUFFPEK::{file_pos, count} will indicate where
713
649
the sorted data was stored.
714
650
@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)
659
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
660
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
662
size_t sort_length, rec_length;
666
sort_length= param->sort_length;
667
rec_length= param->rec_length;
727
668
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
728
669
if (!my_b_inited(tempfile) &&
729
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
670
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
733
673
/* 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)
674
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
739
676
buffpek.file_pos= my_b_tell(tempfile);
740
if ((ha_rows) count > max_rows)
741
count=(uint32_t) max_rows;
677
if ((ha_rows) count > param->max_rows)
678
count=(uint32_t) param->max_rows;
743
679
buffpek.count=(ha_rows) count;
745
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
680
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
747
681
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
753
683
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
759
689
} /* write_keys */
818
749
Item *item=sort_field->item;
819
750
maybe_null= item->maybe_null;
821
751
switch (sort_field->result_type) {
822
752
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;
754
const CHARSET_INFO * const cs=item->collation.collation;
755
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
757
uint32_t sort_field_length;
761
/* All item->str() to use some extra byte for end null.. */
762
String tmp((char*) to,sort_field->length+4,cs);
763
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);
767
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);
771
This should only happen during extreme conditions if we run out
772
of memory or have an item marked not null when it can be null.
773
This code is here mainly to avoid a hard crash in this case.
776
memset(to, 0, sort_field->length); // Avoid crash
780
length= res->length();
781
sort_field_length= sort_field->length - sort_field->suffix_length;
782
diff=(int) (sort_field_length - length);
786
length= sort_field_length;
788
if (sort_field->suffix_length)
790
/* Store length last in result_string */
791
store_length(to + sort_field_length, length,
792
sort_field->suffix_length);
794
if (sort_field->need_strxnfrm)
796
char *from=(char*) res->ptr();
798
if ((unsigned char*) from == to)
800
set_if_smaller(length,sort_field->length);
801
memcpy(param->tmp_buffer,from,length);
802
from=param->tmp_buffer;
804
tmp_length= my_strnxfrm(cs,to,sort_field->length,
805
(unsigned char*) from, length);
806
assert(tmp_length == sort_field->length);
810
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
811
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
887
817
int64_t value= item->val_int_result();
891
821
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);
832
to[7]= (unsigned char) value;
833
to[6]= (unsigned char) (value >> 8);
834
to[5]= (unsigned char) (value >> 16);
835
to[4]= (unsigned char) (value >> 24);
836
to[3]= (unsigned char) (value >> 32);
837
to[2]= (unsigned char) (value >> 40);
838
to[1]= (unsigned char) (value >> 48);
909
839
if (item->unsigned_flag) /* Fix sign */
910
840
to[0]= (unsigned char) (value >> 56);
912
842
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
915
845
case DECIMAL_RESULT:
917
847
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)
988
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
989
filesort_info_st *table_sort)
991
uint32_t offset,res_length;
1063
992
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++)
994
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
995
res_length= param->res_length;
996
offset= param->rec_length-res_length;
997
if ((ha_rows) count > param->max_rows)
998
count=(uint32_t) param->max_rows;
999
if (!(to= table_sort->record_pointers=
1000
(unsigned char*) malloc(res_length*count)))
1002
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1076
1004
memcpy(to, *sort_keys+offset, res_length);
1077
1005
to+= res_length;
1084
1011
/** 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)
1013
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1014
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1016
register uint32_t i;
1089
1017
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1092
1020
if (*maxbuffer < MERGEBUFF2)
1094
1022
if (flush_io_cache(t_file) ||
1095
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1023
open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
1100
1027
from_file= t_file ; to_file= &t_file2;
1101
1028
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;
1030
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1032
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1116
1035
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1118
1037
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1119
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1038
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1125
1041
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1126
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1042
buffpek+i,buffpek+ *maxbuffer,0))
1131
1044
if (flush_io_cache(to_file))
1136
1046
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;
1047
setup_io_cache(from_file);
1048
setup_io_cache(to_file);
1049
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1143
to_file->close_cached_file(); // This holds old result
1052
close_cached_file(to_file); // This holds old result
1144
1053
if (to_file == t_file)
1146
1055
*t_file=t_file2; // Copy result file
1147
t_file->setup_io_cache();
1056
setup_io_cache(t_file);
1150
1059
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1158
1067
(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)
1070
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1071
uint32_t rec_length)
1163
1073
register uint32_t count;
1164
1074
uint32_t length;
1166
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1076
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)
1078
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1169
1079
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;
1081
buffpek->key= buffpek->base;
1082
buffpek->file_pos+= length; /* New filepos */
1083
buffpek->count-= count;
1084
buffpek->mem_count= count;
1176
1086
return (count*rec_length);
1177
1087
} /* read_to_buffer */
1263
1169
cmp= internal::get_ptr_compare(sort_length);
1264
1170
first_cmp_arg= (void*) &sort_length;
1266
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1172
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1267
1173
queue(compare_functor(cmp, first_cmp_arg));
1268
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1174
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,
1176
buffpek->base= strpos;
1177
buffpek->max_keys= maxcount;
1178
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1274
1180
if (error == -1)
1277
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1278
queue.push(buffpek_inst);
1182
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1183
queue.push(buffpek);
1281
1186
if (param->unique_buff)
1304
1209
/* Top element has been used */
1306
queue.push(buffpek_inst);
1211
queue.push(buffpek);
1310
1214
cmp= 0; // Not unique
1313
1216
while (queue.size() > 1)
1321
buffpek_inst= queue.top();
1224
buffpek= queue.top();
1322
1225
if (cmp) // Remove duplicates
1324
1227
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1325
(unsigned char**) &buffpek_inst->key))
1228
(unsigned char**) &buffpek->key))
1326
1229
goto skip_duplicate;
1327
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1230
memcpy(param->unique_buff, buffpek->key, rec_length);
1331
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1234
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))
1241
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1343
1246
if (!--max_rows)
1349
1252
skip_duplicate:
1350
buffpek_inst->key+= rec_length;
1351
if (! --buffpek_inst->mem_count)
1253
buffpek->key+= rec_length;
1254
if (! --buffpek->mem_count)
1353
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1256
if (!(error= (int) read_to_buffer(from_file,buffpek,
1357
1260
break; /* One buffer have been removed */
1359
1262
else if (error == -1)
1364
1265
/* Top element has been replaced */
1366
queue.push(buffpek_inst);
1267
queue.push(buffpek);
1369
buffpek_inst= queue.top();
1370
buffpek_inst->base= sort_buffer;
1371
buffpek_inst->max_keys= param->keys;
1270
buffpek= queue.top();
1271
buffpek->base= sort_buffer;
1272
buffpek->max_keys= param->keys;
1374
1275
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))
1280
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;
1282
buffpek->key+= rec_length; // Remove duplicate
1283
--buffpek->mem_count;
1388
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1289
if ((ha_rows) buffpek->mem_count > max_rows)
1389
1290
{ /* Don't write too many records */
1390
buffpek_inst->mem_count= (uint32_t) max_rows;
1391
buffpek_inst->count= 0; /* Don't read more */
1291
buffpek->mem_count= (uint32_t) max_rows;
1292
buffpek->count= 0; /* Don't read more */
1393
max_rows-= buffpek_inst->mem_count;
1294
max_rows-= buffpek->mem_count;
1396
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1397
(rec_length*buffpek_inst->mem_count)))
1297
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1298
(rec_length*buffpek->mem_count)))
1404
1305
register unsigned char *end;
1405
strpos= buffpek_inst->key+offset;
1406
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1306
strpos= buffpek->key+offset;
1307
for (end= strpos+buffpek->mem_count*rec_length ;
1407
1308
strpos != end ;
1408
1309
strpos+= rec_length)
1410
1311
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1418
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1318
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1419
1319
!= -1 && error != 0);
1422
1322
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1423
1323
lastbuff->file_pos= to_start_filepos;
1426
1326
} /* merge_buffers */
1429
1329
/* 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)
1331
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1332
BUFFPEK *buffpek, uint32_t maxbuffer,
1333
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))
1335
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1336
buffpek+maxbuffer,1))
1440
1339
} /* merge_index */
1500
1402
sortorder->result_type= sortorder->item->result_type();
1501
1403
if (sortorder->item->result_as_int64_t())
1502
1404
sortorder->result_type= INT_RESULT;
1504
1405
switch (sortorder->result_type) {
1505
1406
case STRING_RESULT:
1506
sortorder->length=sortorder->item->max_length;
1407
sortorder->length=sortorder->item->max_length;
1507
1408
set_if_smaller(sortorder->length,
1508
getSession().variables.max_sort_length);
1509
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1409
session->variables.max_sort_length);
1410
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1511
1412
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1512
sortorder->need_strxnfrm= 1;
1513
*multi_byte_charset= 1;
1413
sortorder->need_strxnfrm= 1;
1414
*multi_byte_charset= 1;
1515
1416
else if (cs == &my_charset_bin)
1517
1418
/* Store length last to be able to sort blob/varbinary */
1518
1419
sortorder->suffix_length= suffix_length(sortorder->length);
1519
1420
sortorder->length+= sortorder->suffix_length;
1522
1423
case INT_RESULT:
1523
sortorder->length=8; // Size of intern int64_t
1424
sortorder->length=8; // Size of intern int64_t
1525
1426
case DECIMAL_RESULT:
1526
1427
sortorder->length=
1527
1428
my_decimal_get_binary_size(sortorder->item->max_length -