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,
89
SORT_FIELD *sortorder,
91
bool *multi_byte_charset);
92
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
96
static void unpack_addon_fields(struct st_sort_addon_field *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, SORT_FIELD *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 *) 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
353
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
354
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;
356
statistic_add(session->status_var.filesort_rows,
357
(uint32_t) records, &LOCK_status);
358
*examined_rows= param.examined_rows;
359
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
451
360
DRIZZLE_FILESORT_DONE(error, records);
452
361
return (error ? HA_POS_ERROR : records);
365
void Table::filesort_free_buffers(bool full)
367
if (sort.record_pointers)
369
free((unsigned char*) sort.record_pointers);
370
sort.record_pointers=0;
376
if ((unsigned char*) sort.sort_keys)
377
free((unsigned char*) sort.sort_keys);
382
if ((unsigned char*) sort.buffpek)
383
free((unsigned char*) sort.buffpek);
390
free((char *) sort.addon_buf);
391
free((char *) sort.addon_field);
455
397
/** Make a array of string pointers. */
457
399
static char **make_char_array(char **old_pos, register uint32_t fields,
476
418
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
477
419
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
421
uint32_t length= sizeof(BUFFPEK)*count;
480
422
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
423
if (count > UINT_MAX/sizeof(BUFFPEK))
424
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
426
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
429
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
488
430
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
432
free((char*) tmp);
532
474
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)
477
static ha_rows find_all_keys(Session *session,
479
optimizer::SqlSelect *select,
480
unsigned char **sort_keys,
481
internal::IO_CACHE *buffpek_pointers,
482
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
541
484
int error,flag,quick_select;
542
485
uint32_t idx,indexpos,ref_length;
543
486
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
487
internal::my_off_t record;
545
488
Table *sort_form;
546
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
489
volatile Session::killed_state *killed= &session->killed;
548
boost::dynamic_bitset<> *save_read_set= NULL;
549
boost::dynamic_bitset<> *save_write_set= NULL;
491
MyBitmap *save_read_set, *save_write_set;
552
494
error=quick_select=0;
575
517
if (select->quick->reset())
576
518
return(HA_POS_ERROR);
578
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
return(HA_POS_ERROR);
520
read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
582
523
/* Remember original bitmaps */
583
524
save_read_set= sort_form->read_set;
584
525
save_write_set= sort_form->write_set;
585
526
/* Set up temporary column read map for columns used by sort */
586
sort_form->tmp_set.reset();
527
sort_form->tmp_set.clearAll();
587
528
/* Temporary set for register_used_fields and register_field_in_read_map */
588
529
sort_form->read_set= &sort_form->tmp_set;
589
param->register_used_fields();
530
register_used_fields(param);
590
531
if (select && select->cond)
591
532
select->cond->walk(&Item::register_field_in_read_map, 1,
592
533
(unsigned char*) sort_form);
593
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
534
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
704
639
Sort the buffer and write:
705
640
-# the sorted sequence to tempfile
706
-# a buffpek describing the sorted sequence position to buffpek_pointers
641
-# a BUFFPEK describing the sorted sequence position to buffpek_pointers
708
643
(was: Skriver en buffert med nycklar till filen)
710
645
@param param Sort parameters
711
646
@param sort_keys Array of pointers to keys to sort
712
647
@param count Number of elements in sort_keys array
713
@param buffpek_pointers One 'buffpek' struct will be written into this file.
714
The buffpek::{file_pos, count} will indicate where
648
@param buffpek_pointers One 'BUFFPEK' struct will be written into this file.
649
The BUFFPEK::{file_pos, count} will indicate where
715
650
the sorted data was stored.
716
651
@param tempfile The sorted sequence will be written into this file.
724
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
725
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
660
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
661
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
663
size_t sort_length, rec_length;
667
sort_length= param->sort_length;
668
rec_length= param->rec_length;
729
669
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
670
if (!my_b_inited(tempfile) &&
731
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
671
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
735
674
/* check we won't have more buffpeks than we can possibly keep in memory */
736
if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
675
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
741
677
buffpek.file_pos= my_b_tell(tempfile);
742
if ((ha_rows) count > max_rows)
743
count=(uint32_t) max_rows;
678
if ((ha_rows) count > param->max_rows)
679
count=(uint32_t) param->max_rows;
745
680
buffpek.count=(ha_rows) count;
747
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
681
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
682
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
755
684
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
761
690
} /* write_keys */
820
750
Item *item=sort_field->item;
821
751
maybe_null= item->maybe_null;
823
752
switch (sort_field->result_type) {
824
753
case STRING_RESULT:
826
const CHARSET_INFO * const cs=item->collation.collation;
827
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
829
uint32_t sort_field_length;
755
const CHARSET_INFO * const cs=item->collation.collation;
756
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
758
uint32_t sort_field_length;
762
/* All item->str() to use some extra byte for end null.. */
763
String tmp((char*) to,sort_field->length+4,cs);
764
String *res= item->str_result(&tmp);
833
/* All item->str() to use some extra byte for end null.. */
834
String tmp((char*) to,sort_field->length+4,cs);
835
String *res= item->str_result(&tmp);
839
memset(to-1, 0, sort_field->length+1);
843
This should only happen during extreme conditions if we run out
844
of memory or have an item marked not null when it can be null.
845
This code is here mainly to avoid a hard crash in this case.
848
memset(to, 0, sort_field->length); // Avoid crash
852
length= res->length();
853
sort_field_length= sort_field->length - sort_field->suffix_length;
854
diff=(int) (sort_field_length - length);
858
length= sort_field_length;
860
if (sort_field->suffix_length)
862
/* Store length last in result_string */
863
store_length(to + sort_field_length, length,
864
sort_field->suffix_length);
866
if (sort_field->need_strxnfrm)
868
char *from=(char*) res->ptr();
870
if ((unsigned char*) from == to)
872
set_if_smaller(length,sort_field->length);
873
memcpy(tmp_buffer,from,length);
876
tmp_length= my_strnxfrm(cs,to,sort_field->length,
877
(unsigned char*) from, length);
878
assert(tmp_length == sort_field->length);
768
memset(to-1, 0, sort_field->length+1);
882
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
883
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
772
This should only happen during extreme conditions if we run out
773
of memory or have an item marked not null when it can be null.
774
This code is here mainly to avoid a hard crash in this case.
777
memset(to, 0, sort_field->length); // Avoid crash
781
length= res->length();
782
sort_field_length= sort_field->length - sort_field->suffix_length;
783
diff=(int) (sort_field_length - length);
787
length= sort_field_length;
789
if (sort_field->suffix_length)
791
/* Store length last in result_string */
792
store_length(to + sort_field_length, length,
793
sort_field->suffix_length);
795
if (sort_field->need_strxnfrm)
797
char *from=(char*) res->ptr();
799
if ((unsigned char*) from == to)
801
set_if_smaller(length,sort_field->length);
802
memcpy(param->tmp_buffer,from,length);
803
from=param->tmp_buffer;
805
tmp_length= my_strnxfrm(cs,to,sort_field->length,
806
(unsigned char*) from, length);
807
assert(tmp_length == sort_field->length);
811
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
812
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
889
818
int64_t value= item->val_int_result();
893
822
if (item->null_value)
904
to[7]= (unsigned char) value;
905
to[6]= (unsigned char) (value >> 8);
906
to[5]= (unsigned char) (value >> 16);
907
to[4]= (unsigned char) (value >> 24);
908
to[3]= (unsigned char) (value >> 32);
909
to[2]= (unsigned char) (value >> 40);
910
to[1]= (unsigned char) (value >> 48);
833
to[7]= (unsigned char) value;
834
to[6]= (unsigned char) (value >> 8);
835
to[5]= (unsigned char) (value >> 16);
836
to[4]= (unsigned char) (value >> 24);
837
to[3]= (unsigned char) (value >> 32);
838
to[2]= (unsigned char) (value >> 40);
839
to[1]= (unsigned char) (value >> 48);
911
840
if (item->unsigned_flag) /* Fix sign */
912
841
to[0]= (unsigned char) (value >> 56);
914
843
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
846
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
848
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
851
if (item->null_value)
1062
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
989
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
990
filesort_info_st *table_sort)
992
uint32_t offset,res_length;
1065
993
unsigned char *to;
1067
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1068
offset= rec_length - res_length;
1070
if ((ha_rows) count > max_rows)
1071
count=(uint32_t) max_rows;
1073
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1076
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
995
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
996
res_length= param->res_length;
997
offset= param->rec_length-res_length;
998
if ((ha_rows) count > param->max_rows)
999
count=(uint32_t) param->max_rows;
1000
if (!(to= table_sort->record_pointers=
1001
(unsigned char*) malloc(res_length*count)))
1003
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1078
1005
memcpy(to, *sort_keys+offset, res_length);
1079
1006
to+= res_length;
1086
1012
/** Merge buffers to make < MERGEBUFF2 buffers. */
1088
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1089
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1014
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1015
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1017
register uint32_t i;
1091
1018
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1094
1021
if (*maxbuffer < MERGEBUFF2)
1096
1023
if (flush_io_cache(t_file) ||
1097
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1024
open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
1102
1028
from_file= t_file ; to_file= &t_file2;
1103
1029
while (*maxbuffer >= MERGEBUFF2)
1105
register uint32_t i;
1107
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1112
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1117
lastbuff=buffpek_inst;
1031
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1033
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1118
1036
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1120
1038
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1039
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1127
1042
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1043
buffpek+i,buffpek+ *maxbuffer,0))
1133
1045
if (flush_io_cache(to_file))
1138
1047
temp=from_file; from_file=to_file; to_file=temp;
1139
from_file->setup_io_cache();
1140
to_file->setup_io_cache();
1141
*maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
1048
setup_io_cache(from_file);
1049
setup_io_cache(to_file);
1050
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1145
to_file->close_cached_file(); // This holds old result
1053
close_cached_file(to_file); // This holds old result
1146
1054
if (to_file == t_file)
1148
1056
*t_file=t_file2; // Copy result file
1149
t_file->setup_io_cache();
1057
setup_io_cache(t_file);
1152
1060
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1160
1068
(uint32_t)-1 if something goes wrong
1163
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
1071
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1072
uint32_t rec_length)
1165
1074
register uint32_t count;
1166
1075
uint32_t length;
1168
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1077
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1170
if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
1079
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1171
1080
return((uint32_t) -1);
1173
buffpek_inst->key= buffpek_inst->base;
1174
buffpek_inst->file_pos+= length; /* New filepos */
1175
buffpek_inst->count-= count;
1176
buffpek_inst->mem_count= count;
1082
buffpek->key= buffpek->base;
1083
buffpek->file_pos+= length; /* New filepos */
1084
buffpek->count-= count;
1085
buffpek->mem_count= count;
1178
1087
return (count*rec_length);
1179
1088
} /* read_to_buffer */
1265
1170
cmp= internal::get_ptr_compare(sort_length);
1266
1171
first_cmp_arg= (void*) &sort_length;
1268
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1173
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1269
1174
queue(compare_functor(cmp, first_cmp_arg));
1270
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1175
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1272
buffpek_inst->base= strpos;
1273
buffpek_inst->max_keys= maxcount;
1274
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
1177
buffpek->base= strpos;
1178
buffpek->max_keys= maxcount;
1179
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1276
1181
if (error == -1)
1279
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1280
queue.push(buffpek_inst);
1183
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1184
queue.push(buffpek);
1283
1187
if (param->unique_buff)
1306
1210
/* Top element has been used */
1308
queue.push(buffpek_inst);
1212
queue.push(buffpek);
1312
1215
cmp= 0; // Not unique
1315
1217
while (queue.size() > 1)
1323
buffpek_inst= queue.top();
1225
buffpek= queue.top();
1324
1226
if (cmp) // Remove duplicates
1326
1228
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
(unsigned char**) &buffpek_inst->key))
1229
(unsigned char**) &buffpek->key))
1328
1230
goto skip_duplicate;
1329
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1231
memcpy(param->unique_buff, buffpek->key, rec_length);
1333
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1235
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1340
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1242
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1345
1247
if (!--max_rows)
1351
1253
skip_duplicate:
1352
buffpek_inst->key+= rec_length;
1353
if (! --buffpek_inst->mem_count)
1254
buffpek->key+= rec_length;
1255
if (! --buffpek->mem_count)
1355
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1257
if (!(error= (int) read_to_buffer(from_file,buffpek,
1359
1261
break; /* One buffer have been removed */
1361
1263
else if (error == -1)
1366
1266
/* Top element has been replaced */
1368
queue.push(buffpek_inst);
1268
queue.push(buffpek);
1371
buffpek_inst= queue.top();
1372
buffpek_inst->base= sort_buffer;
1373
buffpek_inst->max_keys= param->keys;
1271
buffpek= queue.top();
1272
buffpek->base= sort_buffer;
1273
buffpek->max_keys= param->keys;
1376
1276
As we know all entries in the buffer are unique, we only have to
1381
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
1281
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1383
buffpek_inst->key+= rec_length; // Remove duplicate
1384
--buffpek_inst->mem_count;
1283
buffpek->key+= rec_length; // Remove duplicate
1284
--buffpek->mem_count;
1390
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1290
if ((ha_rows) buffpek->mem_count > max_rows)
1391
1291
{ /* Don't write too many records */
1392
buffpek_inst->mem_count= (uint32_t) max_rows;
1393
buffpek_inst->count= 0; /* Don't read more */
1292
buffpek->mem_count= (uint32_t) max_rows;
1293
buffpek->count= 0; /* Don't read more */
1395
max_rows-= buffpek_inst->mem_count;
1295
max_rows-= buffpek->mem_count;
1398
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
(rec_length*buffpek_inst->mem_count)))
1298
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1299
(rec_length*buffpek->mem_count)))
1406
1306
register unsigned char *end;
1407
strpos= buffpek_inst->key+offset;
1408
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1307
strpos= buffpek->key+offset;
1308
for (end= strpos+buffpek->mem_count*rec_length ;
1409
1309
strpos != end ;
1410
1310
strpos+= rec_length)
1412
1312
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1420
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1319
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1320
!= -1 && error != 0);
1424
1323
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1425
1324
lastbuff->file_pos= to_start_filepos;
1428
1327
} /* merge_buffers */
1431
1330
/* Do a merge to output-file (save only positions) */
1433
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1434
buffpek *buffpek_inst, uint32_t maxbuffer,
1435
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1332
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1333
BUFFPEK *buffpek, uint32_t maxbuffer,
1334
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1437
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
buffpek_inst+maxbuffer,1))
1336
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1337
buffpek+maxbuffer,1))
1442
1340
} /* merge_index */
1502
1403
sortorder->result_type= sortorder->item->result_type();
1503
1404
if (sortorder->item->result_as_int64_t())
1504
1405
sortorder->result_type= INT_RESULT;
1506
1406
switch (sortorder->result_type) {
1507
1407
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1408
sortorder->length=sortorder->item->max_length;
1509
1409
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1410
session->variables.max_sort_length);
1411
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1413
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1414
sortorder->need_strxnfrm= 1;
1415
*multi_byte_charset= 1;
1517
1417
else if (cs == &my_charset_bin)
1519
1419
/* Store length last to be able to sort blob/varbinary */
1520
1420
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1421
sortorder->length+= sortorder->suffix_length;
1524
1424
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1425
sortorder->length=8; // Size of intern int64_t
1527
1427
case DECIMAL_RESULT:
1528
1428
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1429
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1430
(sortorder->item->decimals ? 1 : 0),
1531
1431
sortorder->item->decimals);
1533
1433
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1434
sortorder->length=sizeof(double);
1536
1436
case ROW_RESULT:
1537
// This case should never be choosen
1438
// This case should never be choosen
1541
1442
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1443
length++; // Place for NULL marker
1544
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1445
set_if_smaller(sortorder->length,
1446
(size_t)session->variables.max_sort_length);
1545
1447
length+=sortorder->length;
1547
1449
sortorder->field= (Field*) 0; // end marker