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;
575
520
if (select->quick->reset())
576
521
return(HA_POS_ERROR);
578
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
return(HA_POS_ERROR);
523
read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
582
526
/* Remember original bitmaps */
583
527
save_read_set= sort_form->read_set;
584
528
save_write_set= sort_form->write_set;
585
529
/* Set up temporary column read map for columns used by sort */
586
sort_form->tmp_set.reset();
530
sort_form->tmp_set.clearAll();
587
531
/* Temporary set for register_used_fields and register_field_in_read_map */
588
532
sort_form->read_set= &sort_form->tmp_set;
589
param->register_used_fields();
533
register_used_fields(param);
590
534
if (select && select->cond)
591
535
select->cond->walk(&Item::register_field_in_read_map, 1,
592
536
(unsigned char*) sort_form);
593
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);
676
617
file->endTableScan();
679
if (getSession().is_error())
620
if (session->is_error())
680
621
return(HA_POS_ERROR);
682
623
/* Signal we should use orignal column read and write maps */
683
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
624
sort_form->column_bitmaps_set(save_read_set, save_write_set);
685
626
if (error != HA_ERR_END_OF_FILE)
687
628
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
629
return(HA_POS_ERROR);
691
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))
693
633
return(HA_POS_ERROR);
696
634
return(my_b_inited(tempfile) ?
697
635
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
704
642
Sort the buffer and write:
705
643
-# the sorted sequence to tempfile
706
-# a buffpek describing the sorted sequence position to buffpek_pointers
644
-# a buffpek_st describing the sorted sequence position to buffpek_pointers
708
646
(was: Skriver en buffert med nycklar till filen)
710
648
@param param Sort parameters
711
649
@param sort_keys Array of pointers to keys to sort
712
650
@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
651
@param buffpek_pointers One 'buffpek_st' struct will be written into this file.
652
The buffpek_st::{file_pos, count} will indicate where
715
653
the sorted data was stored.
716
654
@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)
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;
729
672
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
673
if (!my_b_inited(tempfile) &&
731
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,
735
677
/* 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)
678
if (my_b_tell(buffpek_pointers) + sizeof(buffpek_st) > (uint64_t)UINT_MAX)
741
680
buffpek.file_pos= my_b_tell(tempfile);
742
if ((ha_rows) count > max_rows)
743
count=(uint32_t) max_rows;
681
if ((ha_rows) count > param->max_rows)
682
count=(uint32_t) param->max_rows;
745
683
buffpek.count=(ha_rows) count;
747
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
684
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
685
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
755
687
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
761
693
} /* write_keys */
820
753
Item *item=sort_field->item;
821
754
maybe_null= item->maybe_null;
823
755
switch (sort_field->result_type) {
824
756
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;
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);
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);
771
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);
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);
889
821
int64_t value= item->val_int_result();
893
825
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);
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);
911
843
if (item->unsigned_flag) /* Fix sign */
912
844
to[0]= (unsigned char) (value >> 56);
914
846
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
849
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
851
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
854
if (item->null_value)
1062
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;
1065
996
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++)
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++)
1078
1008
memcpy(to, *sort_keys+offset, res_length);
1079
1009
to+= res_length;
1086
1015
/** 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)
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;
1091
1021
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1022
buffpek_st *lastbuff;
1094
1024
if (*maxbuffer < MERGEBUFF2)
1096
1026
if (flush_io_cache(t_file) ||
1097
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,
1102
1031
from_file= t_file ; to_file= &t_file2;
1103
1032
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;
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))
1118
1039
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1120
1041
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1042
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1127
1045
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1046
buffpek+i,buffpek+ *maxbuffer,0))
1133
1048
if (flush_io_cache(to_file))
1138
1050
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;
1051
setup_io_cache(from_file);
1052
setup_io_cache(to_file);
1053
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1145
to_file->close_cached_file(); // This holds old result
1056
close_cached_file(to_file); // This holds old result
1146
1057
if (to_file == t_file)
1148
1059
*t_file=t_file2; // Copy result file
1149
t_file->setup_io_cache();
1060
setup_io_cache(t_file);
1152
1063
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1160
1071
(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)
1074
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, buffpek_st *buffpek,
1075
uint32_t rec_length)
1165
1077
register uint32_t count;
1166
1078
uint32_t length;
1168
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)))
1170
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)
1171
1083
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;
1085
buffpek->key= buffpek->base;
1086
buffpek->file_pos+= length; /* New filepos */
1087
buffpek->count-= count;
1088
buffpek->mem_count= count;
1178
1090
return (count*rec_length);
1179
1091
} /* read_to_buffer */
1184
1096
qsort2_cmp key_compare;
1185
1097
void *key_compare_arg;
1188
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1189
key_compare(in_key_compare),
1190
key_compare_arg(in_compare_arg)
1193
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
1195
int val= key_compare(key_compare_arg, &i->key, &j->key);
1103
int val= key_compare(key_compare_arg,
1197
1105
return (val >= 0);
1220
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1221
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1222
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,
1226
1134
uint32_t rec_length,res_length,offset;
1265
1173
cmp= internal::get_ptr_compare(sort_length);
1266
1174
first_cmp_arg= (void*) &sort_length;
1268
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1176
priority_queue<buffpek_st *, vector<buffpek_st *>, compare_functor >
1269
1177
queue(compare_functor(cmp, first_cmp_arg));
1270
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1178
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,
1180
buffpek->base= strpos;
1181
buffpek->max_keys= maxcount;
1182
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1276
1184
if (error == -1)
1279
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1280
queue.push(buffpek_inst);
1186
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1187
queue.push(buffpek);
1283
1190
if (param->unique_buff)
1290
1197
This is safe as we know that there is always more than one element
1291
1198
in each block to merge (This is guaranteed by the Unique:: algorithm
1293
buffpek_inst= queue.top();
1294
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1295
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))
1299
buffpek_inst->key+= rec_length;
1300
buffpek_inst->mem_count--;
1206
buffpek->key+= rec_length;
1207
buffpek->mem_count--;
1301
1208
if (!--max_rows)
1306
1213
/* Top element has been used */
1308
queue.push(buffpek_inst);
1215
queue.push(buffpek);
1312
1218
cmp= 0; // Not unique
1315
1220
while (queue.size() > 1)
1323
buffpek_inst= queue.top();
1228
buffpek= queue.top();
1324
1229
if (cmp) // Remove duplicates
1326
1231
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
(unsigned char**) &buffpek_inst->key))
1232
(unsigned char**) &buffpek->key))
1328
1233
goto skip_duplicate;
1329
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1234
memcpy(param->unique_buff, buffpek->key, rec_length);
1333
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))
1340
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))
1345
1250
if (!--max_rows)
1351
1256
skip_duplicate:
1352
buffpek_inst->key+= rec_length;
1353
if (! --buffpek_inst->mem_count)
1257
buffpek->key+= rec_length;
1258
if (! --buffpek->mem_count)
1355
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1260
if (!(error= (int) read_to_buffer(from_file,buffpek,
1359
1264
break; /* One buffer have been removed */
1361
1266
else if (error == -1)
1366
1269
/* Top element has been replaced */
1368
queue.push(buffpek_inst);
1271
queue.push(buffpek);
1371
buffpek_inst= queue.top();
1372
buffpek_inst->base= sort_buffer;
1373
buffpek_inst->max_keys= param->keys;
1274
buffpek= queue.top();
1275
buffpek->base= sort_buffer;
1276
buffpek->max_keys= param->keys;
1376
1279
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))
1284
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;
1286
buffpek->key+= rec_length; // Remove duplicate
1287
--buffpek->mem_count;
1390
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1293
if ((ha_rows) buffpek->mem_count > max_rows)
1391
1294
{ /* Don't write too many records */
1392
buffpek_inst->mem_count= (uint32_t) max_rows;
1393
buffpek_inst->count= 0; /* Don't read more */
1295
buffpek->mem_count= (uint32_t) max_rows;
1296
buffpek->count= 0; /* Don't read more */
1395
max_rows-= buffpek_inst->mem_count;
1298
max_rows-= buffpek->mem_count;
1398
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
(rec_length*buffpek_inst->mem_count)))
1301
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1302
(rec_length*buffpek->mem_count)))
1406
1309
register unsigned char *end;
1407
strpos= buffpek_inst->key+offset;
1408
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1310
strpos= buffpek->key+offset;
1311
for (end= strpos+buffpek->mem_count*rec_length ;
1409
1312
strpos != end ;
1410
1313
strpos+= rec_length)
1412
1315
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1420
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1322
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1323
!= -1 && error != 0);
1424
1326
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1425
1327
lastbuff->file_pos= to_start_filepos;
1428
1330
} /* merge_buffers */
1431
1333
/* 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)
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)
1437
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
buffpek_inst+maxbuffer,1))
1339
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1340
buffpek+maxbuffer,1))
1442
1343
} /* merge_index */
1502
1406
sortorder->result_type= sortorder->item->result_type();
1503
1407
if (sortorder->item->result_as_int64_t())
1504
1408
sortorder->result_type= INT_RESULT;
1506
1409
switch (sortorder->result_type) {
1507
1410
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1411
sortorder->length=sortorder->item->max_length;
1509
1412
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1413
session->variables.max_sort_length);
1414
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1416
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1417
sortorder->need_strxnfrm= 1;
1418
*multi_byte_charset= 1;
1517
1420
else if (cs == &my_charset_bin)
1519
1422
/* Store length last to be able to sort blob/varbinary */
1520
1423
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1424
sortorder->length+= sortorder->suffix_length;
1524
1427
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1428
sortorder->length=8; // Size of intern int64_t
1527
1430
case DECIMAL_RESULT:
1528
1431
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1432
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1433
(sortorder->item->decimals ? 1 : 0),
1531
1434
sortorder->item->decimals);
1533
1436
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1437
sortorder->length=sizeof(double);
1536
1439
case ROW_RESULT:
1537
// This case should never be choosen
1441
// This case should never be choosen
1541
1445
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1446
length++; // Place for NULL marker
1544
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);
1545
1450
length+=sortorder->length;
1547
1452
sortorder->field= (Field*) 0; // end marker