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->db.str, table->s->table_name.str);
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
if (file->startTableScan(1))
568
return(HA_POS_ERROR);
569
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);
572
ReadRecord read_record_info;
515
READ_RECORD read_record_info;
573
516
if (quick_select)
575
518
if (select->quick->reset())
576
519
return(HA_POS_ERROR);
578
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
return(HA_POS_ERROR);
520
init_read_record(&read_record_info, current_session, select->quick->head,
582
524
/* Remember original bitmaps */
583
525
save_read_set= sort_form->read_set;
584
526
save_write_set= sort_form->write_set;
585
527
/* Set up temporary column read map for columns used by sort */
586
sort_form->tmp_set.reset();
528
sort_form->tmp_set.clearAll();
587
529
/* Temporary set for register_used_fields and register_field_in_read_map */
588
530
sort_form->read_set= &sort_form->tmp_set;
589
param->register_used_fields();
531
register_used_fields(param);
590
532
if (select && select->cond)
591
533
select->cond->walk(&Item::register_field_in_read_map, 1,
592
534
(unsigned char*) sort_form);
593
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);
667
606
index_merge quick select uses table->sort when retrieving rows, so free
668
607
resoures it has allocated.
670
read_record_info.end_read_record();
609
end_read_record(&read_record_info);
674
613
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
676
file->endTableScan();
679
if (getSession().is_error())
618
if (session->is_error())
680
619
return(HA_POS_ERROR);
682
621
/* Signal we should use orignal column read and write maps */
683
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
622
sort_form->column_bitmaps_set(save_read_set, save_write_set);
685
624
if (error != HA_ERR_END_OF_FILE)
687
626
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
627
return(HA_POS_ERROR);
691
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))
693
631
return(HA_POS_ERROR);
696
632
return(my_b_inited(tempfile) ?
697
633
(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)
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;
729
670
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
671
if (!my_b_inited(tempfile) &&
731
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,
735
675
/* 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)
676
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
741
678
buffpek.file_pos= my_b_tell(tempfile);
742
if ((ha_rows) count > max_rows)
743
count=(uint32_t) max_rows;
679
if ((ha_rows) count > param->max_rows)
680
count=(uint32_t) param->max_rows;
745
681
buffpek.count=(ha_rows) count;
747
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
682
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
683
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
755
685
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
761
691
} /* write_keys */
820
751
Item *item=sort_field->item;
821
752
maybe_null= item->maybe_null;
823
753
switch (sort_field->result_type) {
824
754
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;
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);
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);
769
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);
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);
889
819
int64_t value= item->val_int_result();
893
823
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);
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);
911
841
if (item->unsigned_flag) /* Fix sign */
912
842
to[0]= (unsigned char) (value >> 56);
914
844
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
847
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
849
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
852
if (item->null_value)
1062
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;
1065
994
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++)
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++)
1078
1006
memcpy(to, *sort_keys+offset, res_length);
1079
1007
to+= res_length;
1086
1013
/** 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)
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;
1091
1019
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1094
1022
if (*maxbuffer < MERGEBUFF2)
1096
1024
if (flush_io_cache(t_file) ||
1097
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,
1102
1029
from_file= t_file ; to_file= &t_file2;
1103
1030
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;
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))
1118
1037
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1120
1039
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1040
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1127
1043
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1044
buffpek+i,buffpek+ *maxbuffer,0))
1133
1046
if (flush_io_cache(to_file))
1138
1048
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;
1049
setup_io_cache(from_file);
1050
setup_io_cache(to_file);
1051
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1145
to_file->close_cached_file(); // This holds old result
1054
close_cached_file(to_file); // This holds old result
1146
1055
if (to_file == t_file)
1148
1057
*t_file=t_file2; // Copy result file
1149
t_file->setup_io_cache();
1058
setup_io_cache(t_file);
1152
1061
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1160
1069
(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)
1072
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
uint32_t rec_length)
1165
1075
register uint32_t count;
1166
1076
uint32_t length;
1168
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)))
1170
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)
1171
1081
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;
1083
buffpek->key= buffpek->base;
1084
buffpek->file_pos+= length; /* New filepos */
1085
buffpek->count-= count;
1086
buffpek->mem_count= count;
1178
1088
return (count*rec_length);
1179
1089
} /* read_to_buffer */
1265
1171
cmp= internal::get_ptr_compare(sort_length);
1266
1172
first_cmp_arg= (void*) &sort_length;
1268
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1174
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1269
1175
queue(compare_functor(cmp, first_cmp_arg));
1270
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1176
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,
1178
buffpek->base= strpos;
1179
buffpek->max_keys= maxcount;
1180
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1276
1182
if (error == -1)
1279
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1280
queue.push(buffpek_inst);
1184
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1185
queue.push(buffpek);
1283
1188
if (param->unique_buff)
1306
1211
/* Top element has been used */
1308
queue.push(buffpek_inst);
1213
queue.push(buffpek);
1312
1216
cmp= 0; // Not unique
1315
1218
while (queue.size() > 1)
1323
buffpek_inst= queue.top();
1226
buffpek= queue.top();
1324
1227
if (cmp) // Remove duplicates
1326
1229
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
(unsigned char**) &buffpek_inst->key))
1230
(unsigned char**) &buffpek->key))
1328
1231
goto skip_duplicate;
1329
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1232
memcpy(param->unique_buff, buffpek->key, rec_length);
1333
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))
1340
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))
1345
1248
if (!--max_rows)
1351
1254
skip_duplicate:
1352
buffpek_inst->key+= rec_length;
1353
if (! --buffpek_inst->mem_count)
1255
buffpek->key+= rec_length;
1256
if (! --buffpek->mem_count)
1355
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1258
if (!(error= (int) read_to_buffer(from_file,buffpek,
1359
1262
break; /* One buffer have been removed */
1361
1264
else if (error == -1)
1366
1267
/* Top element has been replaced */
1368
queue.push(buffpek_inst);
1269
queue.push(buffpek);
1371
buffpek_inst= queue.top();
1372
buffpek_inst->base= sort_buffer;
1373
buffpek_inst->max_keys= param->keys;
1272
buffpek= queue.top();
1273
buffpek->base= sort_buffer;
1274
buffpek->max_keys= param->keys;
1376
1277
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))
1282
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;
1284
buffpek->key+= rec_length; // Remove duplicate
1285
--buffpek->mem_count;
1390
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1291
if ((ha_rows) buffpek->mem_count > max_rows)
1391
1292
{ /* Don't write too many records */
1392
buffpek_inst->mem_count= (uint32_t) max_rows;
1393
buffpek_inst->count= 0; /* Don't read more */
1293
buffpek->mem_count= (uint32_t) max_rows;
1294
buffpek->count= 0; /* Don't read more */
1395
max_rows-= buffpek_inst->mem_count;
1296
max_rows-= buffpek->mem_count;
1398
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
(rec_length*buffpek_inst->mem_count)))
1299
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1300
(rec_length*buffpek->mem_count)))
1406
1307
register unsigned char *end;
1407
strpos= buffpek_inst->key+offset;
1408
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1308
strpos= buffpek->key+offset;
1309
for (end= strpos+buffpek->mem_count*rec_length ;
1409
1310
strpos != end ;
1410
1311
strpos+= rec_length)
1412
1313
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1420
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1320
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1321
!= -1 && error != 0);
1424
1324
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1425
1325
lastbuff->file_pos= to_start_filepos;
1428
1328
} /* merge_buffers */
1431
1331
/* 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)
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)
1437
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
buffpek_inst+maxbuffer,1))
1337
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1338
buffpek+maxbuffer,1))
1442
1341
} /* merge_index */
1502
1404
sortorder->result_type= sortorder->item->result_type();
1503
1405
if (sortorder->item->result_as_int64_t())
1504
1406
sortorder->result_type= INT_RESULT;
1506
1407
switch (sortorder->result_type) {
1507
1408
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1409
sortorder->length=sortorder->item->max_length;
1509
1410
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1411
session->variables.max_sort_length);
1412
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1414
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1415
sortorder->need_strxnfrm= 1;
1416
*multi_byte_charset= 1;
1517
1418
else if (cs == &my_charset_bin)
1519
1420
/* Store length last to be able to sort blob/varbinary */
1520
1421
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1422
sortorder->length+= sortorder->suffix_length;
1524
1425
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1426
sortorder->length=8; // Size of intern int64_t
1527
1428
case DECIMAL_RESULT:
1528
1429
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1430
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1431
(sortorder->item->decimals ? 1 : 0),
1531
1432
sortorder->item->decimals);
1533
1434
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1435
sortorder->length=sizeof(double);
1536
1437
case ROW_RESULT:
1537
// This case should never be choosen
1439
// This case should never be choosen
1541
1443
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1444
length++; // Place for NULL marker
1544
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1446
set_if_smaller(sortorder->length,
1447
(size_t)session->variables.max_sort_length);
1545
1448
length+=sortorder->length;
1547
1450
sortorder->field= (Field*) 0; // end marker