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;
147
filesort_info_st table_sort;
148
TableList *tab= table->pos_in_table_list;
149
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
151
DRIZZLE_FILESORT_START(table->s->getSchemaName(), table->s->getTableName());
154
Release InnoDB's adaptive hash index latch (if holding) before
157
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
205
160
Don't use table->sort in filesort as it is also used by
206
161
QuickIndexMergeSelect. Work with a copy and put it back at the end
207
162
when index_merge select has finished with it.
209
filesort_info table_sort(table->sort);
164
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
210
165
table->sort.io_cache= NULL;
212
TableList *tab= table->pos_in_table_list;
213
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
215
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
218
Release InnoDB's adaptive hash index latch (if holding) before
221
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
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,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,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())
331
if ((unsigned char*) sort_keys)
332
free((unsigned char*) sort_keys);
413
333
table_sort.sort_keys= 0;
334
if ((unsigned char*) buffpek)
335
free((unsigned char*) buffpek);
415
336
table_sort.buffpek= 0;
416
337
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
339
close_cached_file(&tempfile);
340
close_cached_file(&buffpek_pointers);
422
341
if (my_b_inited(outfile))
424
343
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
346
internal::my_off_t save_pos=outfile->pos_in_file;
430
347
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
348
if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
435
350
outfile->end_of_file=save_pos;
441
354
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
355
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;
357
statistic_add(session->status_var.filesort_rows,
358
(uint32_t) records, &LOCK_status);
359
*examined_rows= param.examined_rows;
360
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
451
361
DRIZZLE_FILESORT_DONE(error, records);
452
362
return (error ? HA_POS_ERROR : records);
366
void Table::filesort_free_buffers(bool full)
368
if (sort.record_pointers)
370
free((unsigned char*) sort.record_pointers);
371
sort.record_pointers=0;
377
if ((unsigned char*) sort.sort_keys)
378
free((unsigned char*) sort.sort_keys);
383
if ((unsigned char*) sort.buffpek)
384
free((unsigned char*) sort.buffpek);
391
free((char *) sort.addon_buf);
392
free((char *) sort.addon_field);
455
398
/** Make a array of string pointers. */
457
400
static char **make_char_array(char **old_pos, register uint32_t fields,
476
419
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
477
420
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
422
uint32_t length= sizeof(BUFFPEK)*count;
480
423
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
424
if (count > UINT_MAX/sizeof(BUFFPEK))
425
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
427
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
430
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
488
431
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
433
free((char*) tmp);
532
475
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)
478
static ha_rows find_all_keys(SORTPARAM *param,
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
Session *session= current_session;
490
volatile Session::killed_state *killed= &session->killed;
548
boost::dynamic_bitset<> *save_read_set= NULL;
549
boost::dynamic_bitset<> *save_write_set= NULL;
492
MyBitmap *save_read_set, *save_write_set;
552
495
error=quick_select=0;
564
507
if (! indexfile && ! quick_select)
566
509
next_pos=(unsigned char*) 0; /* Find records in sequence */
567
file->startTableScan(1);
568
file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
510
file->ha_rnd_init(1);
511
file->extra_opt(HA_EXTRA_CACHE,
512
current_session->variables.read_buff_size);
571
ReadRecord read_record_info;
515
READ_RECORD read_record_info;
572
516
if (quick_select)
574
518
if (select->quick->reset())
575
519
return(HA_POS_ERROR);
577
read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1);
520
init_read_record(&read_record_info, current_session, select->quick->head,
580
524
/* Remember original bitmaps */
581
525
save_read_set= sort_form->read_set;
582
526
save_write_set= sort_form->write_set;
583
527
/* Set up temporary column read map for columns used by sort */
584
sort_form->tmp_set.reset();
528
sort_form->tmp_set.clearAll();
585
529
/* Temporary set for register_used_fields and register_field_in_read_map */
586
530
sort_form->read_set= &sort_form->tmp_set;
587
param->register_used_fields();
531
register_used_fields(param);
588
532
if (select && select->cond)
589
533
select->cond->walk(&Item::register_field_in_read_map, 1,
590
534
(unsigned char*) sort_form);
591
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
535
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
665
606
index_merge quick select uses table->sort when retrieving rows, so free
666
607
resoures it has allocated.
668
read_record_info.end_read_record();
609
end_read_record(&read_record_info);
672
613
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
674
file->endTableScan();
677
if (getSession().is_error())
618
if (session->is_error())
678
619
return(HA_POS_ERROR);
680
621
/* Signal we should use orignal column read and write maps */
681
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
622
sort_form->column_bitmaps_set(save_read_set, save_write_set);
683
624
if (error != HA_ERR_END_OF_FILE)
685
626
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
686
627
return(HA_POS_ERROR);
689
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
629
if (indexpos && idx &&
630
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
691
631
return(HA_POS_ERROR);
694
632
return(my_b_inited(tempfile) ?
695
633
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
722
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
723
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
661
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
662
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
664
size_t sort_length, rec_length;
668
sort_length= param->sort_length;
669
rec_length= param->rec_length;
727
670
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
728
671
if (!my_b_inited(tempfile) &&
729
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
672
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
733
675
/* 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)
676
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
739
678
buffpek.file_pos= my_b_tell(tempfile);
740
if ((ha_rows) count > max_rows)
741
count=(uint32_t) max_rows;
679
if ((ha_rows) count > param->max_rows)
680
count=(uint32_t) param->max_rows;
743
681
buffpek.count=(ha_rows) count;
745
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
682
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
747
683
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
753
685
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
759
691
} /* write_keys */
818
751
Item *item=sort_field->item;
819
752
maybe_null= item->maybe_null;
821
753
switch (sort_field->result_type) {
822
754
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;
756
const CHARSET_INFO * const cs=item->collation.collation;
757
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
759
uint32_t sort_field_length;
763
/* All item->str() to use some extra byte for end null.. */
764
String tmp((char*) to,sort_field->length+4,cs);
765
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);
769
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);
773
This should only happen during extreme conditions if we run out
774
of memory or have an item marked not null when it can be null.
775
This code is here mainly to avoid a hard crash in this case.
778
memset(to, 0, sort_field->length); // Avoid crash
782
length= res->length();
783
sort_field_length= sort_field->length - sort_field->suffix_length;
784
diff=(int) (sort_field_length - length);
788
length= sort_field_length;
790
if (sort_field->suffix_length)
792
/* Store length last in result_string */
793
store_length(to + sort_field_length, length,
794
sort_field->suffix_length);
796
if (sort_field->need_strxnfrm)
798
char *from=(char*) res->ptr();
800
if ((unsigned char*) from == to)
802
set_if_smaller(length,sort_field->length);
803
memcpy(param->tmp_buffer,from,length);
804
from=param->tmp_buffer;
806
tmp_length= my_strnxfrm(cs,to,sort_field->length,
807
(unsigned char*) from, length);
808
assert(tmp_length == sort_field->length);
812
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
813
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
887
819
int64_t value= item->val_int_result();
891
823
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);
834
to[7]= (unsigned char) value;
835
to[6]= (unsigned char) (value >> 8);
836
to[5]= (unsigned char) (value >> 16);
837
to[4]= (unsigned char) (value >> 24);
838
to[3]= (unsigned char) (value >> 32);
839
to[2]= (unsigned char) (value >> 40);
840
to[1]= (unsigned char) (value >> 48);
909
841
if (item->unsigned_flag) /* Fix sign */
910
842
to[0]= (unsigned char) (value >> 56);
912
844
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
915
847
case DECIMAL_RESULT:
917
849
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)
990
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
991
filesort_info_st *table_sort)
993
uint32_t offset,res_length;
1063
994
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++)
996
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
997
res_length= param->res_length;
998
offset= param->rec_length-res_length;
999
if ((ha_rows) count > param->max_rows)
1000
count=(uint32_t) param->max_rows;
1001
if (!(to= table_sort->record_pointers=
1002
(unsigned char*) malloc(res_length*count)))
1004
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1076
1006
memcpy(to, *sort_keys+offset, res_length);
1077
1007
to+= res_length;
1084
1013
/** 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)
1015
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1016
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1018
register uint32_t i;
1089
1019
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1092
1022
if (*maxbuffer < MERGEBUFF2)
1094
1024
if (flush_io_cache(t_file) ||
1095
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1025
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1100
1029
from_file= t_file ; to_file= &t_file2;
1101
1030
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;
1032
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1034
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1116
1037
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1118
1039
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1119
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1040
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1125
1043
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1126
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1044
buffpek+i,buffpek+ *maxbuffer,0))
1131
1046
if (flush_io_cache(to_file))
1136
1048
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;
1049
setup_io_cache(from_file);
1050
setup_io_cache(to_file);
1051
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1143
to_file->close_cached_file(); // This holds old result
1054
close_cached_file(to_file); // This holds old result
1144
1055
if (to_file == t_file)
1146
1057
*t_file=t_file2; // Copy result file
1147
t_file->setup_io_cache();
1058
setup_io_cache(t_file);
1150
1061
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1158
1069
(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)
1072
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
uint32_t rec_length)
1163
1075
register uint32_t count;
1164
1076
uint32_t length;
1166
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1078
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)
1080
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1169
1081
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;
1083
buffpek->key= buffpek->base;
1084
buffpek->file_pos+= length; /* New filepos */
1085
buffpek->count-= count;
1086
buffpek->mem_count= count;
1176
1088
return (count*rec_length);
1177
1089
} /* read_to_buffer */
1263
1171
cmp= internal::get_ptr_compare(sort_length);
1264
1172
first_cmp_arg= (void*) &sort_length;
1266
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1174
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1267
1175
queue(compare_functor(cmp, first_cmp_arg));
1268
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1176
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,
1178
buffpek->base= strpos;
1179
buffpek->max_keys= maxcount;
1180
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1274
1182
if (error == -1)
1277
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1278
queue.push(buffpek_inst);
1184
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1185
queue.push(buffpek);
1281
1188
if (param->unique_buff)
1304
1211
/* Top element has been used */
1306
queue.push(buffpek_inst);
1213
queue.push(buffpek);
1310
1216
cmp= 0; // Not unique
1313
1218
while (queue.size() > 1)
1321
buffpek_inst= queue.top();
1226
buffpek= queue.top();
1322
1227
if (cmp) // Remove duplicates
1324
1229
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1325
(unsigned char**) &buffpek_inst->key))
1230
(unsigned char**) &buffpek->key))
1326
1231
goto skip_duplicate;
1327
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1232
memcpy(param->unique_buff, buffpek->key, rec_length);
1331
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1236
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))
1243
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1343
1248
if (!--max_rows)
1349
1254
skip_duplicate:
1350
buffpek_inst->key+= rec_length;
1351
if (! --buffpek_inst->mem_count)
1255
buffpek->key+= rec_length;
1256
if (! --buffpek->mem_count)
1353
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1258
if (!(error= (int) read_to_buffer(from_file,buffpek,
1357
1262
break; /* One buffer have been removed */
1359
1264
else if (error == -1)
1364
1267
/* Top element has been replaced */
1366
queue.push(buffpek_inst);
1269
queue.push(buffpek);
1369
buffpek_inst= queue.top();
1370
buffpek_inst->base= sort_buffer;
1371
buffpek_inst->max_keys= param->keys;
1272
buffpek= queue.top();
1273
buffpek->base= sort_buffer;
1274
buffpek->max_keys= param->keys;
1374
1277
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))
1282
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;
1284
buffpek->key+= rec_length; // Remove duplicate
1285
--buffpek->mem_count;
1388
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1291
if ((ha_rows) buffpek->mem_count > max_rows)
1389
1292
{ /* Don't write too many records */
1390
buffpek_inst->mem_count= (uint32_t) max_rows;
1391
buffpek_inst->count= 0; /* Don't read more */
1293
buffpek->mem_count= (uint32_t) max_rows;
1294
buffpek->count= 0; /* Don't read more */
1393
max_rows-= buffpek_inst->mem_count;
1296
max_rows-= buffpek->mem_count;
1396
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1397
(rec_length*buffpek_inst->mem_count)))
1299
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1300
(rec_length*buffpek->mem_count)))
1404
1307
register unsigned char *end;
1405
strpos= buffpek_inst->key+offset;
1406
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1308
strpos= buffpek->key+offset;
1309
for (end= strpos+buffpek->mem_count*rec_length ;
1407
1310
strpos != end ;
1408
1311
strpos+= rec_length)
1410
1313
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1418
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1320
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1419
1321
!= -1 && error != 0);
1422
1324
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1423
1325
lastbuff->file_pos= to_start_filepos;
1426
1328
} /* merge_buffers */
1429
1331
/* 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)
1333
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1334
BUFFPEK *buffpek, uint32_t maxbuffer,
1335
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))
1337
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1338
buffpek+maxbuffer,1))
1440
1341
} /* merge_index */
1500
1404
sortorder->result_type= sortorder->item->result_type();
1501
1405
if (sortorder->item->result_as_int64_t())
1502
1406
sortorder->result_type= INT_RESULT;
1504
1407
switch (sortorder->result_type) {
1505
1408
case STRING_RESULT:
1506
sortorder->length=sortorder->item->max_length;
1409
sortorder->length=sortorder->item->max_length;
1507
1410
set_if_smaller(sortorder->length,
1508
getSession().variables.max_sort_length);
1509
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1411
session->variables.max_sort_length);
1412
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1511
1414
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1512
sortorder->need_strxnfrm= 1;
1513
*multi_byte_charset= 1;
1415
sortorder->need_strxnfrm= 1;
1416
*multi_byte_charset= 1;
1515
1418
else if (cs == &my_charset_bin)
1517
1420
/* Store length last to be able to sort blob/varbinary */
1518
1421
sortorder->suffix_length= suffix_length(sortorder->length);
1519
1422
sortorder->length+= sortorder->suffix_length;
1522
1425
case INT_RESULT:
1523
sortorder->length=8; // Size of intern int64_t
1426
sortorder->length=8; // Size of intern int64_t
1525
1428
case DECIMAL_RESULT:
1526
1429
sortorder->length=
1527
1430
my_decimal_get_binary_size(sortorder->item->max_length -