43
40
#include "drizzled/internal/iocache.h"
44
41
#include "drizzled/internal/my_sys.h"
45
42
#include "plugin/myisam/myisam.h"
46
#include "drizzled/plugin/transactional_storage_engine.h"
47
#include "drizzled/atomics.h"
48
#include "drizzled/global_buffer.h"
51
44
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);
45
using namespace drizzled;
133
47
/* functions defined in this file */
135
49
static char **make_char_array(char **old_pos, register uint32_t fields,
138
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
52
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
55
static ha_rows find_all_keys(SORTPARAM *param,
56
optimizer::SqlSelect *select,
57
unsigned char * *sort_keys,
58
IO_CACHE *buffer_file,
62
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
63
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
65
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
66
static void register_used_fields(SORTPARAM *param);
67
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
69
uint32_t maxbuffer,IO_CACHE *tempfile,
71
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
72
filesort_info_st *table_sort);
142
73
static uint32_t suffix_length(uint32_t string_length);
143
static void unpack_addon_fields(sort_addon_field *addon_field,
74
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
75
bool *multi_byte_charset);
76
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
77
uint32_t sortlength, uint32_t *plength);
78
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
144
79
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
82
Creates a set of pointers that can be used to read the rows
183
113
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)
116
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
117
optimizer::SqlSelect *select, ha_rows max_rows,
118
bool sort_positions, ha_rows *examined_rows)
191
uint32_t memavl= 0, min_sort_memory;
121
uint32_t memavl, min_sort_memory;
192
122
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
195
124
ha_rows records= HA_POS_ERROR;
196
125
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;
126
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
128
bool multi_byte_charset;
130
filesort_info_st table_sort;
131
TableList *tab= table->pos_in_table_list;
132
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
134
DRIZZLE_FILESORT_START(table->s->db.str, table->s->table_name.str);
137
Release InnoDB's adaptive hash index latch (if holding) before
140
plugin::StorageEngine::releaseTemporaryLatches(session);
205
143
Don't use table->sort in filesort as it is also used by
206
144
QuickIndexMergeSelect. Work with a copy and put it back at the end
207
145
when index_merge select has finished with it.
209
filesort_info table_sort(table->sort);
147
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
210
148
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
150
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);
151
my_b_clear(&tempfile);
152
my_b_clear(&buffpek_pointers);
155
memset(¶m, 0, sizeof(param));
156
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
229
157
param.ref_length= table->cursor->ref_length;
158
param.addon_field= 0;
159
param.addon_length= 0;
231
160
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
234
163
Get the descriptors of all fields whose values are appended
235
164
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
166
param.addon_field= get_addon_fields(session, table->field,
238
167
param.sort_length,
239
168
¶m.addon_length);
291
218
selected_records_file= 0;
294
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
221
if (multi_byte_charset &&
222
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
299
memavl= getSession().variables.sortbuff_size;
225
memavl= session->variables.sortbuff_size;
300
226
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
227
while (memavl >= min_sort_memory)
303
229
uint32_t old_memavl;
304
230
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
231
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
232
if ((table_sort.sort_keys=
315
233
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
234
param.keys, param.rec_length)))
319
global_sort_buffer.sub(allocated_sort_memory);
320
236
old_memavl= memavl;
321
237
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
238
memavl= min_sort_memory;
327
243
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)))
246
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
247
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
250
param.keys--; /* TODO: check why we do this */
337
251
param.sort_form= table;
338
252
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)
253
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
254
&tempfile, selected_records_file)) ==
344
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
257
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
346
259
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
261
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
357
268
if (table_sort.buffpek)
358
269
free(table_sort.buffpek);
359
table_sort.buffpek = 0;
270
table_sort.buffpek= 0;
361
272
if (!(table_sort.buffpek=
362
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
273
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
274
table_sort.buffpek)))
366
buffpek_inst= (buffpek *) table_sort.buffpek;
276
buffpek= (BUFFPEK *) table_sort.buffpek;
367
277
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
278
close_cached_file(&buffpek_pointers);
369
279
/* 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))
280
if (! my_b_inited(outfile) &&
281
open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
284
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
381
288
Use also the space previously used by string pointers in sort_buffer
382
289
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
291
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
293
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))
294
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
297
if (flush_io_cache(&tempfile) ||
298
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
300
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
403
304
if (records > param.max_rows)
405
records= param.max_rows;
305
records=param.max_rows;
410
if (not subselect || not subselect->is_uncacheable())
309
if (param.tmp_buffer)
310
if (param.tmp_buffer)
311
free(param.tmp_buffer);
312
if (!subselect || !subselect->is_uncacheable())
314
if ((unsigned char*) sort_keys)
315
free((unsigned char*) sort_keys);
413
316
table_sort.sort_keys= 0;
317
if ((unsigned char*) buffpek)
318
free((unsigned char*) buffpek);
415
319
table_sort.buffpek= 0;
416
320
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
322
close_cached_file(&tempfile);
323
close_cached_file(&buffpek_pointers);
422
324
if (my_b_inited(outfile))
424
326
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
329
my_off_t save_pos=outfile->pos_in_file;
430
330
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
331
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
435
333
outfile->end_of_file=save_pos;
441
337
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
338
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;
340
statistic_add(session->status_var.filesort_rows,
341
(uint32_t) records, &LOCK_status);
342
*examined_rows= param.examined_rows;
343
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
451
344
DRIZZLE_FILESORT_DONE(error, records);
452
345
return (error ? HA_POS_ERROR : records);
349
void Table::filesort_free_buffers(bool full)
351
if (sort.record_pointers)
353
free((unsigned char*) sort.record_pointers);
354
sort.record_pointers=0;
360
if ((unsigned char*) sort.sort_keys)
361
free((unsigned char*) sort.sort_keys);
366
if ((unsigned char*) sort.buffpek)
367
free((unsigned char*) sort.buffpek);
374
free((char *) sort.addon_buf);
375
free((char *) sort.addon_field);
455
381
/** Make a array of string pointers. */
457
383
static char **make_char_array(char **old_pos, register uint32_t fields,
474
400
/** Read 'count' number of buffer pointers into memory. */
476
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
402
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
477
403
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
405
uint32_t length= sizeof(BUFFPEK)*count;
480
406
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
407
if (count > UINT_MAX/sizeof(BUFFPEK))
408
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
410
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
413
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
488
414
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
416
free((char*) tmp);
532
458
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)
461
static ha_rows find_all_keys(SORTPARAM *param,
462
optimizer::SqlSelect *select,
463
unsigned char **sort_keys,
464
IO_CACHE *buffpek_pointers,
465
IO_CACHE *tempfile, IO_CACHE *indexfile)
541
467
int error,flag,quick_select;
542
468
uint32_t idx,indexpos,ref_length;
543
469
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
internal::my_off_t record;
545
471
Table *sort_form;
546
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
472
Session *session= current_session;
473
volatile Session::killed_state *killed= &session->killed;
548
boost::dynamic_bitset<> *save_read_set= NULL;
549
boost::dynamic_bitset<> *save_write_set= NULL;
475
MyBitmap *save_read_set, *save_write_set;
552
478
error=quick_select=0;
564
490
if (! indexfile && ! quick_select)
566
492
next_pos=(unsigned char*) 0; /* Find records in sequence */
567
if (file->startTableScan(1))
568
return(HA_POS_ERROR);
569
file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
493
file->ha_rnd_init(1);
494
file->extra_opt(HA_EXTRA_CACHE,
495
current_session->variables.read_buff_size);
572
ReadRecord read_record_info;
498
READ_RECORD read_record_info;
573
499
if (quick_select)
575
501
if (select->quick->reset())
576
502
return(HA_POS_ERROR);
578
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
return(HA_POS_ERROR);
503
init_read_record(&read_record_info, current_session, select->quick->head,
582
507
/* Remember original bitmaps */
583
508
save_read_set= sort_form->read_set;
584
509
save_write_set= sort_form->write_set;
585
510
/* Set up temporary column read map for columns used by sort */
586
sort_form->tmp_set.reset();
511
sort_form->tmp_set.clearAll();
587
512
/* Temporary set for register_used_fields and register_field_in_read_map */
588
513
sort_form->read_set= &sort_form->tmp_set;
589
param->register_used_fields();
514
register_used_fields(param);
590
515
if (select && select->cond)
591
516
select->cond->walk(&Item::register_field_in_read_map, 1,
592
517
(unsigned char*) sort_form);
593
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
518
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
667
589
index_merge quick select uses table->sort when retrieving rows, so free
668
590
resoures it has allocated.
670
read_record_info.end_read_record();
592
end_read_record(&read_record_info);
674
596
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
676
file->endTableScan();
679
if (getSession().is_error())
601
if (session->is_error())
680
602
return(HA_POS_ERROR);
682
604
/* Signal we should use orignal column read and write maps */
683
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
605
sort_form->column_bitmaps_set(save_read_set, save_write_set);
685
607
if (error != HA_ERR_END_OF_FILE)
687
609
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
610
return(HA_POS_ERROR);
691
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
612
if (indexpos && idx &&
613
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
693
614
return(HA_POS_ERROR);
696
615
return(my_b_inited(tempfile) ?
697
616
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
724
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
725
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
644
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
645
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
647
size_t sort_length, rec_length;
729
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
651
sort_length= param->sort_length;
652
rec_length= param->rec_length;
653
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
654
if (!my_b_inited(tempfile) &&
731
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
655
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
735
658
/* 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)
659
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
741
661
buffpek.file_pos= my_b_tell(tempfile);
742
if ((ha_rows) count > max_rows)
743
count=(uint32_t) max_rows;
662
if ((ha_rows) count > param->max_rows)
663
count=(uint32_t) param->max_rows;
745
664
buffpek.count=(ha_rows) count;
747
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
665
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
666
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
755
668
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
761
674
} /* write_keys */
820
734
Item *item=sort_field->item;
821
735
maybe_null= item->maybe_null;
823
736
switch (sort_field->result_type) {
824
737
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;
739
const CHARSET_INFO * const cs=item->collation.collation;
740
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
742
uint32_t sort_field_length;
746
/* All item->str() to use some extra byte for end null.. */
747
String tmp((char*) to,sort_field->length+4,cs);
748
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);
752
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);
756
This should only happen during extreme conditions if we run out
757
of memory or have an item marked not null when it can be null.
758
This code is here mainly to avoid a hard crash in this case.
761
memset(to, 0, sort_field->length); // Avoid crash
765
length= res->length();
766
sort_field_length= sort_field->length - sort_field->suffix_length;
767
diff=(int) (sort_field_length - length);
771
length= sort_field_length;
773
if (sort_field->suffix_length)
775
/* Store length last in result_string */
776
store_length(to + sort_field_length, length,
777
sort_field->suffix_length);
779
if (sort_field->need_strxnfrm)
781
char *from=(char*) res->ptr();
783
if ((unsigned char*) from == to)
785
set_if_smaller(length,sort_field->length);
786
memcpy(param->tmp_buffer,from,length);
787
from=param->tmp_buffer;
789
tmp_length= my_strnxfrm(cs,to,sort_field->length,
790
(unsigned char*) from, length);
791
assert(tmp_length == sort_field->length);
795
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
796
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
889
802
int64_t value= item->val_int_result();
893
806
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);
817
to[7]= (unsigned char) value;
818
to[6]= (unsigned char) (value >> 8);
819
to[5]= (unsigned char) (value >> 16);
820
to[4]= (unsigned char) (value >> 24);
821
to[3]= (unsigned char) (value >> 32);
822
to[2]= (unsigned char) (value >> 40);
823
to[1]= (unsigned char) (value >> 48);
911
824
if (item->unsigned_flag) /* Fix sign */
912
825
to[0]= (unsigned char) (value >> 56);
914
827
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
830
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
832
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
835
if (item->null_value)
1062
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
973
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
974
filesort_info_st *table_sort)
976
uint32_t offset,res_length;
1065
977
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++)
979
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
980
res_length= param->res_length;
981
offset= param->rec_length-res_length;
982
if ((ha_rows) count > param->max_rows)
983
count=(uint32_t) param->max_rows;
984
if (!(to= table_sort->record_pointers=
985
(unsigned char*) malloc(res_length*count)))
987
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1078
989
memcpy(to, *sort_keys+offset, res_length);
1079
990
to+= res_length;
1086
996
/** 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)
998
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
999
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1091
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1001
register uint32_t i;
1002
IO_CACHE t_file2,*from_file,*to_file,*temp;
1094
1005
if (*maxbuffer < MERGEBUFF2)
1096
1007
if (flush_io_cache(t_file) ||
1097
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1008
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1102
1012
from_file= t_file ; to_file= &t_file2;
1103
1013
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;
1015
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1017
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1118
1020
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1120
1022
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1023
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1127
1026
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1027
buffpek+i,buffpek+ *maxbuffer,0))
1133
1029
if (flush_io_cache(to_file))
1138
1031
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;
1032
setup_io_cache(from_file);
1033
setup_io_cache(to_file);
1034
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1145
to_file->close_cached_file(); // This holds old result
1037
close_cached_file(to_file); // This holds old result
1146
1038
if (to_file == t_file)
1148
1040
*t_file=t_file2; // Copy result file
1149
t_file->setup_io_cache();
1041
setup_io_cache(t_file);
1152
1044
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1160
1052
(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)
1055
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1056
uint32_t rec_length)
1165
1058
register uint32_t count;
1166
1059
uint32_t length;
1168
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1061
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)
1063
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1171
1064
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;
1066
buffpek->key= buffpek->base;
1067
buffpek->file_pos+= length; /* New filepos */
1068
buffpek->count-= count;
1069
buffpek->mem_count= count;
1178
1071
return (count*rec_length);
1179
1072
} /* read_to_buffer */
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,
1109
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1110
IO_CACHE *to_file, unsigned char *sort_buffer,
1111
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1226
1115
uint32_t rec_length,res_length,offset;
1227
1116
size_t sort_length;
1228
1117
uint32_t maxcount;
1229
1118
ha_rows max_rows,org_max_rows;
1230
internal::my_off_t to_start_filepos;
1119
my_off_t to_start_filepos;
1231
1120
unsigned char *strpos;
1232
buffpek *buffpek_inst;
1233
1122
qsort2_cmp cmp;
1234
1123
void *first_cmp_arg;
1235
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1236
Session::killed_state_t not_killable;
1124
volatile Session::killed_state *killed= ¤t_session->killed;
1125
Session::killed_state not_killable;
1238
getSession().status_var.filesort_merge_passes++;
1127
status_var_increment(current_session->status_var.filesort_merge_passes);
1239
1128
if (param->not_killable)
1241
1130
killed= ¬_killable;
1265
cmp= internal::get_ptr_compare(sort_length);
1154
cmp= get_ptr_compare(sort_length);
1266
1155
first_cmp_arg= (void*) &sort_length;
1268
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1157
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1269
1158
queue(compare_functor(cmp, first_cmp_arg));
1270
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1159
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,
1161
buffpek->base= strpos;
1162
buffpek->max_keys= maxcount;
1163
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1276
1165
if (error == -1)
1279
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1280
queue.push(buffpek_inst);
1167
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1168
queue.push(buffpek);
1283
1171
if (param->unique_buff)
1306
1194
/* Top element has been used */
1308
queue.push(buffpek_inst);
1196
queue.push(buffpek);
1312
1199
cmp= 0; // Not unique
1315
1201
while (queue.size() > 1)
1323
buffpek_inst= queue.top();
1209
buffpek= queue.top();
1324
1210
if (cmp) // Remove duplicates
1326
1212
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
(unsigned char**) &buffpek_inst->key))
1213
(unsigned char**) &buffpek->key))
1328
1214
goto skip_duplicate;
1329
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1215
memcpy(param->unique_buff, buffpek->key, rec_length);
1333
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1219
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))
1226
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1345
1231
if (!--max_rows)
1351
1237
skip_duplicate:
1352
buffpek_inst->key+= rec_length;
1353
if (! --buffpek_inst->mem_count)
1238
buffpek->key+= rec_length;
1239
if (! --buffpek->mem_count)
1355
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1241
if (!(error= (int) read_to_buffer(from_file,buffpek,
1359
1245
break; /* One buffer have been removed */
1361
1247
else if (error == -1)
1366
1250
/* Top element has been replaced */
1368
queue.push(buffpek_inst);
1252
queue.push(buffpek);
1371
buffpek_inst= queue.top();
1372
buffpek_inst->base= sort_buffer;
1373
buffpek_inst->max_keys= param->keys;
1255
buffpek= queue.top();
1256
buffpek->base= sort_buffer;
1257
buffpek->max_keys= param->keys;
1376
1260
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))
1265
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;
1267
buffpek->key+= rec_length; // Remove duplicate
1268
--buffpek->mem_count;
1390
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1274
if ((ha_rows) buffpek->mem_count > max_rows)
1391
1275
{ /* Don't write too many records */
1392
buffpek_inst->mem_count= (uint32_t) max_rows;
1393
buffpek_inst->count= 0; /* Don't read more */
1276
buffpek->mem_count= (uint32_t) max_rows;
1277
buffpek->count= 0; /* Don't read more */
1395
max_rows-= buffpek_inst->mem_count;
1279
max_rows-= buffpek->mem_count;
1398
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
(rec_length*buffpek_inst->mem_count)))
1282
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1283
(rec_length*buffpek->mem_count)))
1406
1290
register unsigned char *end;
1407
strpos= buffpek_inst->key+offset;
1408
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1291
strpos= buffpek->key+offset;
1292
for (end= strpos+buffpek->mem_count*rec_length ;
1409
1293
strpos != end ;
1410
1294
strpos+= rec_length)
1412
1296
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1420
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1303
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1304
!= -1 && error != 0);
1424
1307
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1425
1308
lastbuff->file_pos= to_start_filepos;
1428
1311
} /* merge_buffers */
1431
1314
/* 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)
1316
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1317
BUFFPEK *buffpek, uint32_t maxbuffer,
1318
IO_CACHE *tempfile, IO_CACHE *outfile)
1437
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
buffpek_inst+maxbuffer,1))
1320
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1321
buffpek+maxbuffer,1))
1442
1324
} /* merge_index */
1502
1387
sortorder->result_type= sortorder->item->result_type();
1503
1388
if (sortorder->item->result_as_int64_t())
1504
1389
sortorder->result_type= INT_RESULT;
1506
1390
switch (sortorder->result_type) {
1507
1391
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1392
sortorder->length=sortorder->item->max_length;
1509
1393
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1394
session->variables.max_sort_length);
1395
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1397
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1398
sortorder->need_strxnfrm= 1;
1399
*multi_byte_charset= 1;
1517
1401
else if (cs == &my_charset_bin)
1519
1403
/* Store length last to be able to sort blob/varbinary */
1520
1404
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1405
sortorder->length+= sortorder->suffix_length;
1524
1408
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1409
sortorder->length=8; // Size of intern int64_t
1527
1411
case DECIMAL_RESULT:
1528
1412
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1413
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1414
(sortorder->item->decimals ? 1 : 0),
1531
1415
sortorder->item->decimals);
1533
1417
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1418
sortorder->length=sizeof(double);
1536
1420
case ROW_RESULT:
1537
// This case should never be choosen
1422
// This case should never be choosen
1541
1426
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1427
length++; // Place for NULL marker
1544
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1429
set_if_smaller(sortorder->length,
1430
(size_t)session->variables.max_sort_length);
1545
1431
length+=sortorder->length;
1547
1433
sortorder->field= (Field*) 0; // end marker