27
27
#include <limits.h>
30
30
#include <algorithm>
33
#include <drizzled/drizzled.h>
34
#include <drizzled/sql_sort.h>
35
#include <drizzled/filesort.h>
36
#include <drizzled/error.h>
37
#include <drizzled/probes.h>
38
#include <drizzled/session.h>
39
#include <drizzled/table.h>
40
#include <drizzled/table_list.h>
41
#include <drizzled/optimizer/range.h>
42
#include <drizzled/records.h>
43
#include <drizzled/internal/iocache.h>
44
#include <drizzled/internal/my_sys.h>
45
#include <plugin/myisam/myisam.h>
46
#include <drizzled/plugin/transactional_storage_engine.h>
47
#include <drizzled/atomics.h>
48
#include <drizzled/global_buffer.h>
50
#include <drizzled/sort_field.h>
32
#include "drizzled/sql_sort.h"
33
#include "drizzled/error.h"
34
#include "drizzled/probes.h"
35
#include "drizzled/session.h"
36
#include "drizzled/table.h"
37
#include "drizzled/table_list.h"
38
#include "drizzled/optimizer/range.h"
39
#include "drizzled/records.h"
40
#include "drizzled/internal/iocache.h"
41
#include "drizzled/internal/my_sys.h"
42
#include "plugin/myisam/myisam.h"
43
#include "drizzled/plugin/transactional_storage_engine.h"
53
45
using namespace std;
58
/* Defines used by filesort and uniques */
62
class BufferCompareContext
65
qsort_cmp2 key_compare;
66
void *key_compare_arg;
68
BufferCompareContext() :
77
uint32_t rec_length; /* Length of sorted records */
78
uint32_t sort_length; /* Length of sorted columns */
79
uint32_t ref_length; /* Length of record ref. */
80
uint32_t addon_length; /* Length of added packed fields */
81
uint32_t res_length; /* Length of records in final sorted file/buffer */
82
uint32_t keys; /* Max keys / buffer */
83
ha_rows max_rows,examined_rows;
84
Table *sort_form; /* For quicker make_sortkey */
85
SortField *local_sortorder;
87
sort_addon_field *addon_field; /* Descriptors for companion fields */
88
unsigned char *unique_buff;
91
/* The fields below are used only by Unique class */
93
BufferCompareContext cmp_context;
121
int write_keys(unsigned char * *sort_keys,
123
internal::IO_CACHE *buffer_file,
124
internal::IO_CACHE *tempfile);
126
void make_sortkey(unsigned char *to,
127
unsigned char *ref_pos);
128
void register_used_fields();
129
bool save_index(unsigned char **sort_keys,
131
filesort_info *table_sort);
135
50
/* functions defined in this file */
137
static char **make_char_array(char **old_pos, uint32_t fields,
52
static char **make_char_array(char **old_pos, register uint32_t fields,
140
55
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
142
57
unsigned char *buf);
59
static ha_rows find_all_keys(Session *session,
61
optimizer::SqlSelect *select,
62
unsigned char * *sort_keys,
63
internal::IO_CACHE *buffer_file,
64
internal::IO_CACHE *tempfile,
65
internal::IO_CACHE *indexfile);
67
static int write_keys(SORTPARAM *param,
68
unsigned char * *sort_keys,
70
internal::IO_CACHE *buffer_file,
71
internal::IO_CACHE *tempfile);
73
static void make_sortkey(SORTPARAM *param,
75
unsigned char *ref_pos);
76
static void register_used_fields(SORTPARAM *param);
77
static int merge_index(SORTPARAM *param,
78
unsigned char *sort_buffer,
81
internal::IO_CACHE *tempfile,
82
internal::IO_CACHE *outfile);
83
static bool save_index(SORTPARAM *param,
84
unsigned char **sort_keys,
86
filesort_info_st *table_sort);
144
87
static uint32_t suffix_length(uint32_t string_length);
145
static void unpack_addon_fields(sort_addon_field *addon_field,
88
static uint32_t sortlength(Session *session,
89
SORT_FIELD *sortorder,
91
bool *multi_byte_charset);
92
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
96
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
146
97
unsigned char *buff);
148
FileSort::FileSort(Session &arg) :
155
100
Creates a set of pointers that can be used to read the rows
185
131
examined_rows will be set to number of examined rows
188
ha_rows FileSort::run(Table *table, SortField *sortorder, uint32_t s_length,
189
optimizer::SqlSelect *select, ha_rows max_rows,
190
bool sort_positions, ha_rows &examined_rows)
134
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
135
optimizer::SqlSelect *select, ha_rows max_rows,
136
bool sort_positions, ha_rows *examined_rows)
193
uint32_t memavl= 0, min_sort_memory;
139
uint32_t memavl, min_sort_memory;
194
140
uint32_t maxbuffer;
195
size_t allocated_sort_memory= 0;
196
buffpek *buffpek_inst= 0;
197
142
ha_rows records= HA_POS_ERROR;
198
143
unsigned char **sort_keys= 0;
199
internal::IO_CACHE tempfile;
200
internal::IO_CACHE buffpek_pointers;
201
internal::IO_CACHE *selected_records_file;
202
internal::IO_CACHE *outfile;
144
internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
204
146
bool multi_byte_charset;
207
Don't use table->sort in filesort as it is also used by
208
QuickIndexMergeSelect. Work with a copy and put it back at the end
209
when index_merge select has finished with it.
211
filesort_info table_sort(table->sort);
212
table->sort.io_cache= NULL;
148
filesort_info_st table_sort;
214
149
TableList *tab= table->pos_in_table_list;
215
150
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
220
155
Release InnoDB's adaptive hash index latch (if holding) before
223
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
158
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
161
Don't use table->sort in filesort as it is also used by
162
QuickIndexMergeSelect. Work with a copy and put it back at the end
163
when index_merge select has finished with it.
165
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
166
table->sort.io_cache= NULL;
226
168
outfile= table_sort.io_cache;
227
assert(tempfile.buffer == 0);
228
assert(buffpek_pointers.buffer == 0);
230
param.sort_length= sortlength(sortorder, s_length, &multi_byte_charset);
169
my_b_clear(&tempfile);
170
my_b_clear(&buffpek_pointers);
173
memset(¶m, 0, sizeof(param));
174
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
231
175
param.ref_length= table->cursor->ref_length;
176
param.addon_field= 0;
177
param.addon_length= 0;
233
178
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
236
181
Get the descriptors of all fields whose values are appended
237
182
to sorted fields and get its total length in param.spack_length.
239
param.addon_field= get_addon_fields(table->getFields(),
184
param.addon_field= get_addon_fields(session, table->getFields(),
240
185
param.sort_length,
241
186
¶m.addon_length);
293
236
selected_records_file= 0;
296
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
239
if (multi_byte_charset &&
240
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
301
memavl= getSession().variables.sortbuff_size;
243
memavl= session->variables.sortbuff_size;
302
244
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
245
while (memavl >= min_sort_memory)
305
247
uint32_t old_memavl;
306
248
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
307
249
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
309
allocated_sort_memory= param.keys * param.rec_length;
310
if (not global_sort_buffer.add(allocated_sort_memory))
312
my_error(ER_OUT_OF_GLOBAL_SORTMEMORY, MYF(ME_ERROR+ME_WAITTANG));
316
250
if ((table_sort.sort_keys=
317
251
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
252
param.keys, param.rec_length)))
321
global_sort_buffer.sub(allocated_sort_memory);
322
254
old_memavl= memavl;
323
255
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
256
memavl= min_sort_memory;
329
261
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
333
if (buffpek_pointers.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
264
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
265
DISK_BUFFER_SIZE, MYF(MY_WME)))
338
268
param.keys--; /* TODO: check why we do this */
339
269
param.sort_form= table;
340
270
param.end=(param.local_sortorder=sortorder)+s_length;
341
if ((records= find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
342
&tempfile, selected_records_file)) == HA_POS_ERROR)
271
if ((records=find_all_keys(session, ¶m,select,sort_keys, &buffpek_pointers,
272
&tempfile, selected_records_file)) ==
346
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
275
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
348
277
if (maxbuffer == 0) // The whole set is in memory
350
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
279
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
359
286
if (table_sort.buffpek)
360
287
free(table_sort.buffpek);
361
table_sort.buffpek = 0;
288
table_sort.buffpek= 0;
363
290
if (!(table_sort.buffpek=
364
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
291
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
292
table_sort.buffpek)))
368
buffpek_inst= (buffpek *) table_sort.buffpek;
294
buffpek= (BUFFPEK *) table_sort.buffpek;
369
295
table_sort.buffpek_len= maxbuffer;
370
buffpek_pointers.close_cached_file();
296
close_cached_file(&buffpek_pointers);
371
297
/* Open cached file if it isn't open */
372
if (! my_b_inited(outfile) && outfile->open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME)))
377
if (outfile->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
298
if (! my_b_inited(outfile) &&
299
open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
302
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
383
306
Use also the space previously used by string pointers in sort_buffer
384
307
for temporary key storage.
386
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
309
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
388
311
maxbuffer--; // Offset from 0
389
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
394
if (flush_io_cache(&tempfile) || tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
399
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek_inst,maxbuffer,&tempfile, outfile))
312
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
315
if (flush_io_cache(&tempfile) ||
316
reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
318
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
405
322
if (records > param.max_rows)
407
records= param.max_rows;
323
records=param.max_rows;
412
if (not subselect || not subselect->is_uncacheable())
327
if (param.tmp_buffer)
328
if (param.tmp_buffer)
329
free(param.tmp_buffer);
330
if (!subselect || !subselect->is_uncacheable())
415
333
table_sort.sort_keys= 0;
417
335
table_sort.buffpek= 0;
418
336
table_sort.buffpek_len= 0;
421
tempfile.close_cached_file();
422
buffpek_pointers.close_cached_file();
338
close_cached_file(&tempfile);
339
close_cached_file(&buffpek_pointers);
424
340
if (my_b_inited(outfile))
426
342
if (flush_io_cache(outfile))
431
internal::my_off_t save_pos= outfile->pos_in_file;
345
internal::my_off_t save_pos=outfile->pos_in_file;
432
346
/* For following reads */
433
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
347
if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
437
349
outfile->end_of_file=save_pos;
443
354
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
448
getSession().status_var.filesort_rows+= (uint32_t) records;
359
session->status_var.filesort_rows+= (uint32_t) records;
450
examined_rows= param.examined_rows;
451
global_sort_buffer.sub(allocated_sort_memory);
452
table->sort= table_sort;
361
*examined_rows= param.examined_rows;
362
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
453
363
DRIZZLE_FILESORT_DONE(error, records);
454
364
return (error ? HA_POS_ERROR : records);
368
void Table::filesort_free_buffers(bool full)
370
if (sort.record_pointers)
372
free((unsigned char*) sort.record_pointers);
373
sort.record_pointers=0;
379
if ((unsigned char*) sort.sort_keys)
380
free((unsigned char*) sort.sort_keys);
385
if ((unsigned char*) sort.buffpek)
386
free((unsigned char*) sort.buffpek);
393
free((char *) sort.addon_buf);
394
free((char *) sort.addon_field);
457
400
/** Make a array of string pointers. */
459
static char **make_char_array(char **old_pos, uint32_t fields,
402
static char **make_char_array(char **old_pos, register uint32_t fields,
478
421
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
479
422
unsigned char *buf)
481
uint32_t length= sizeof(buffpek)*count;
424
uint32_t length= sizeof(BUFFPEK)*count;
482
425
unsigned char *tmp= buf;
483
if (count > UINT_MAX/sizeof(buffpek))
484
return 0; /* sizeof(buffpek)*count will overflow */
426
if (count > UINT_MAX/sizeof(BUFFPEK))
427
return 0; /* sizeof(BUFFPEK)*count will overflow */
486
429
tmp= (unsigned char *)malloc(length);
489
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
432
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
490
433
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
492
435
free((char*) tmp);
534
477
HA_POS_ERROR on error.
537
ha_rows FileSort::find_all_keys(SortParam *param,
538
optimizer::SqlSelect *select,
539
unsigned char **sort_keys,
540
internal::IO_CACHE *buffpek_pointers,
541
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
480
static ha_rows find_all_keys(Session *session,
482
optimizer::SqlSelect *select,
483
unsigned char **sort_keys,
484
internal::IO_CACHE *buffpek_pointers,
485
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
543
487
int error,flag,quick_select;
544
488
uint32_t idx,indexpos,ref_length;
545
489
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
490
internal::my_off_t record;
547
491
Table *sort_form;
548
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
492
volatile Session::killed_state *killed= &session->killed;
550
boost::dynamic_bitset<> *save_read_set= NULL;
551
boost::dynamic_bitset<> *save_write_set= NULL;
494
MyBitmap *save_read_set, *save_write_set;
554
497
error=quick_select=0;
577
520
if (select->quick->reset())
578
521
return(HA_POS_ERROR);
580
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
return(HA_POS_ERROR);
523
read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
584
526
/* Remember original bitmaps */
585
527
save_read_set= sort_form->read_set;
586
528
save_write_set= sort_form->write_set;
587
529
/* Set up temporary column read map for columns used by sort */
588
sort_form->tmp_set.reset();
530
sort_form->tmp_set.clearAll();
589
531
/* Temporary set for register_used_fields and register_field_in_read_map */
590
532
sort_form->read_set= &sort_form->tmp_set;
591
param->register_used_fields();
533
register_used_fields(param);
592
534
if (select && select->cond)
593
535
select->cond->walk(&Item::register_field_in_read_map, 1,
594
536
(unsigned char*) sort_form);
595
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
537
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
706
642
Sort the buffer and write:
707
643
-# the sorted sequence to tempfile
708
-# a buffpek describing the sorted sequence position to buffpek_pointers
644
-# a BUFFPEK describing the sorted sequence position to buffpek_pointers
710
646
(was: Skriver en buffert med nycklar till filen)
712
648
@param param Sort parameters
713
649
@param sort_keys Array of pointers to keys to sort
714
650
@param count Number of elements in sort_keys array
715
@param buffpek_pointers One 'buffpek' struct will be written into this file.
716
The buffpek::{file_pos, count} will indicate where
651
@param buffpek_pointers One 'BUFFPEK' struct will be written into this file.
652
The BUFFPEK::{file_pos, count} will indicate where
717
653
the sorted data was stored.
718
654
@param tempfile The sorted sequence will be written into this file.
726
int SortParam::write_keys(unsigned char **sort_keys, uint32_t count,
727
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
663
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
664
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
666
size_t sort_length, rec_length;
670
sort_length= param->sort_length;
671
rec_length= param->rec_length;
731
672
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
732
673
if (!my_b_inited(tempfile) &&
733
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
674
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
737
677
/* check we won't have more buffpeks than we can possibly keep in memory */
738
if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
678
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
743
680
buffpek.file_pos= my_b_tell(tempfile);
744
if ((ha_rows) count > max_rows)
745
count=(uint32_t) max_rows;
681
if ((ha_rows) count > param->max_rows)
682
count=(uint32_t) param->max_rows;
747
683
buffpek.count=(ha_rows) count;
749
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
684
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
751
685
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
757
687
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
763
693
} /* write_keys */
822
753
Item *item=sort_field->item;
823
754
maybe_null= item->maybe_null;
825
755
switch (sort_field->result_type) {
826
756
case STRING_RESULT:
828
const CHARSET_INFO * const cs=item->collation.collation;
829
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
831
uint32_t sort_field_length;
758
const CHARSET_INFO * const cs=item->collation.collation;
759
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
761
uint32_t sort_field_length;
765
/* All item->str() to use some extra byte for end null.. */
766
String tmp((char*) to,sort_field->length+4,cs);
767
String *res= item->str_result(&tmp);
835
/* All item->str() to use some extra byte for end null.. */
836
String tmp((char*) to,sort_field->length+4,cs);
837
String *res= item->str_result(&tmp);
841
memset(to-1, 0, sort_field->length+1);
845
This should only happen during extreme conditions if we run out
846
of memory or have an item marked not null when it can be null.
847
This code is here mainly to avoid a hard crash in this case.
850
memset(to, 0, sort_field->length); // Avoid crash
854
length= res->length();
855
sort_field_length= sort_field->length - sort_field->suffix_length;
856
diff=(int) (sort_field_length - length);
860
length= sort_field_length;
862
if (sort_field->suffix_length)
864
/* Store length last in result_string */
865
store_length(to + sort_field_length, length,
866
sort_field->suffix_length);
868
if (sort_field->need_strxnfrm)
870
char *from=(char*) res->ptr();
872
if ((unsigned char*) from == to)
874
set_if_smaller(length,sort_field->length);
875
memcpy(tmp_buffer,from,length);
878
tmp_length= my_strnxfrm(cs,to,sort_field->length,
879
(unsigned char*) from, length);
880
assert(tmp_length == sort_field->length);
771
memset(to-1, 0, sort_field->length+1);
884
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
885
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
775
This should only happen during extreme conditions if we run out
776
of memory or have an item marked not null when it can be null.
777
This code is here mainly to avoid a hard crash in this case.
780
memset(to, 0, sort_field->length); // Avoid crash
784
length= res->length();
785
sort_field_length= sort_field->length - sort_field->suffix_length;
786
diff=(int) (sort_field_length - length);
790
length= sort_field_length;
792
if (sort_field->suffix_length)
794
/* Store length last in result_string */
795
store_length(to + sort_field_length, length,
796
sort_field->suffix_length);
798
if (sort_field->need_strxnfrm)
800
char *from=(char*) res->ptr();
802
if ((unsigned char*) from == to)
804
set_if_smaller(length,sort_field->length);
805
memcpy(param->tmp_buffer,from,length);
806
from=param->tmp_buffer;
808
tmp_length= my_strnxfrm(cs,to,sort_field->length,
809
(unsigned char*) from, length);
810
assert(tmp_length == sort_field->length);
814
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
815
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
891
821
int64_t value= item->val_int_result();
895
825
if (item->null_value)
906
to[7]= (unsigned char) value;
907
to[6]= (unsigned char) (value >> 8);
908
to[5]= (unsigned char) (value >> 16);
909
to[4]= (unsigned char) (value >> 24);
910
to[3]= (unsigned char) (value >> 32);
911
to[2]= (unsigned char) (value >> 40);
912
to[1]= (unsigned char) (value >> 48);
836
to[7]= (unsigned char) value;
837
to[6]= (unsigned char) (value >> 8);
838
to[5]= (unsigned char) (value >> 16);
839
to[4]= (unsigned char) (value >> 24);
840
to[3]= (unsigned char) (value >> 32);
841
to[2]= (unsigned char) (value >> 40);
842
to[1]= (unsigned char) (value >> 48);
913
843
if (item->unsigned_flag) /* Fix sign */
914
844
to[0]= (unsigned char) (value >> 56);
916
846
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
919
849
case DECIMAL_RESULT:
921
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
851
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
924
854
if (item->null_value)
1017
944
/* Save filepos last */
1018
memcpy(to, ref_pos, (size_t) ref_length);
945
memcpy(to, ref_pos, (size_t) param->ref_length);
1024
fields used by sorting in the sorted table's read set
952
Register fields used by sorting in the sorted table's read set
1027
void SortParam::register_used_fields()
955
static void register_used_fields(SORTPARAM *param)
1029
SortField *sort_field;
1030
Table *table= sort_form;
957
register SORT_FIELD *sort_field;
958
Table *table=param->sort_form;
1032
for (sort_field= local_sortorder ;
960
for (sort_field= param->local_sortorder ;
961
sort_field != param->end ;
1037
965
if ((field= sort_field->field))
1039
967
if (field->getTable() == table)
1040
table->setReadSet(field->position());
968
table->setReadSet(field->field_index);
1064
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
992
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
993
filesort_info_st *table_sort)
995
uint32_t offset,res_length;
1067
996
unsigned char *to;
1069
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1070
offset= rec_length - res_length;
1072
if ((ha_rows) count > max_rows)
1073
count=(uint32_t) max_rows;
1075
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1078
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
998
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
999
res_length= param->res_length;
1000
offset= param->rec_length-res_length;
1001
if ((ha_rows) count > param->max_rows)
1002
count=(uint32_t) param->max_rows;
1003
if (!(to= table_sort->record_pointers=
1004
(unsigned char*) malloc(res_length*count)))
1006
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1080
1008
memcpy(to, *sort_keys+offset, res_length);
1081
1009
to+= res_length;
1088
1015
/** Merge buffers to make < MERGEBUFF2 buffers. */
1090
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1091
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1017
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1018
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1020
register uint32_t i;
1093
1021
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1096
1024
if (*maxbuffer < MERGEBUFF2)
1098
1026
if (flush_io_cache(t_file) ||
1099
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1027
open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
1104
1031
from_file= t_file ; to_file= &t_file2;
1105
1032
while (*maxbuffer >= MERGEBUFF2)
1109
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1114
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1119
lastbuff=buffpek_inst;
1034
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1036
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1120
1039
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1122
1041
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1042
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1129
1045
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1046
buffpek+i,buffpek+ *maxbuffer,0))
1135
1048
if (flush_io_cache(to_file))
1140
1050
temp=from_file; from_file=to_file; to_file=temp;
1141
from_file->setup_io_cache();
1142
to_file->setup_io_cache();
1143
*maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
1051
setup_io_cache(from_file);
1052
setup_io_cache(to_file);
1053
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1147
to_file->close_cached_file(); // This holds old result
1056
close_cached_file(to_file); // This holds old result
1148
1057
if (to_file == t_file)
1150
1059
*t_file=t_file2; // Copy result file
1151
t_file->setup_io_cache();
1060
setup_io_cache(t_file);
1154
1063
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1162
1071
(uint32_t)-1 if something goes wrong
1165
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
1074
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1075
uint32_t rec_length)
1077
register uint32_t count;
1168
1078
uint32_t length;
1170
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1080
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1172
if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
1082
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1173
1083
return((uint32_t) -1);
1175
buffpek_inst->key= buffpek_inst->base;
1176
buffpek_inst->file_pos+= length; /* New filepos */
1177
buffpek_inst->count-= count;
1178
buffpek_inst->mem_count= count;
1085
buffpek->key= buffpek->base;
1086
buffpek->file_pos+= length; /* New filepos */
1087
buffpek->count-= count;
1088
buffpek->mem_count= count;
1180
1090
return (count*rec_length);
1181
1091
} /* read_to_buffer */
1267
1173
cmp= internal::get_ptr_compare(sort_length);
1268
1174
first_cmp_arg= (void*) &sort_length;
1270
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1176
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1271
1177
queue(compare_functor(cmp, first_cmp_arg));
1272
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1178
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1274
buffpek_inst->base= strpos;
1275
buffpek_inst->max_keys= maxcount;
1276
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
1180
buffpek->base= strpos;
1181
buffpek->max_keys= maxcount;
1182
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1278
1184
if (error == -1)
1281
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1282
queue.push(buffpek_inst);
1186
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1187
queue.push(buffpek);
1285
1190
if (param->unique_buff)
1308
1213
/* Top element has been used */
1310
queue.push(buffpek_inst);
1215
queue.push(buffpek);
1314
1218
cmp= 0; // Not unique
1317
1220
while (queue.size() > 1)
1325
buffpek_inst= queue.top();
1228
buffpek= queue.top();
1326
1229
if (cmp) // Remove duplicates
1328
1231
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
(unsigned char**) &buffpek_inst->key))
1232
(unsigned char**) &buffpek->key))
1330
1233
goto skip_duplicate;
1331
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1234
memcpy(param->unique_buff, buffpek->key, rec_length);
1335
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1238
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1342
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1245
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1347
1250
if (!--max_rows)
1353
1256
skip_duplicate:
1354
buffpek_inst->key+= rec_length;
1355
if (! --buffpek_inst->mem_count)
1257
buffpek->key+= rec_length;
1258
if (! --buffpek->mem_count)
1357
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1260
if (!(error= (int) read_to_buffer(from_file,buffpek,
1361
1264
break; /* One buffer have been removed */
1363
1266
else if (error == -1)
1368
1269
/* Top element has been replaced */
1370
queue.push(buffpek_inst);
1271
queue.push(buffpek);
1373
buffpek_inst= queue.top();
1374
buffpek_inst->base= sort_buffer;
1375
buffpek_inst->max_keys= param->keys;
1274
buffpek= queue.top();
1275
buffpek->base= sort_buffer;
1276
buffpek->max_keys= param->keys;
1378
1279
As we know all entries in the buffer are unique, we only have to
1383
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
1284
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1385
buffpek_inst->key+= rec_length; // Remove duplicate
1386
--buffpek_inst->mem_count;
1286
buffpek->key+= rec_length; // Remove duplicate
1287
--buffpek->mem_count;
1392
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1293
if ((ha_rows) buffpek->mem_count > max_rows)
1393
1294
{ /* Don't write too many records */
1394
buffpek_inst->mem_count= (uint32_t) max_rows;
1395
buffpek_inst->count= 0; /* Don't read more */
1295
buffpek->mem_count= (uint32_t) max_rows;
1296
buffpek->count= 0; /* Don't read more */
1397
max_rows-= buffpek_inst->mem_count;
1298
max_rows-= buffpek->mem_count;
1400
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
(rec_length*buffpek_inst->mem_count)))
1301
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1302
(rec_length*buffpek->mem_count)))
1409
strpos= buffpek_inst->key+offset;
1410
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1309
register unsigned char *end;
1310
strpos= buffpek->key+offset;
1311
for (end= strpos+buffpek->mem_count*rec_length ;
1411
1312
strpos != end ;
1412
1313
strpos+= rec_length)
1414
1315
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1422
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1322
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1323
!= -1 && error != 0);
1426
1326
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1427
1327
lastbuff->file_pos= to_start_filepos;
1430
1330
} /* merge_buffers */
1433
1333
/* Do a merge to output-file (save only positions) */
1435
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1436
buffpek *buffpek_inst, uint32_t maxbuffer,
1437
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1335
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1336
BUFFPEK *buffpek, uint32_t maxbuffer,
1337
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1439
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
buffpek_inst+maxbuffer,1))
1339
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1340
buffpek+maxbuffer,1))
1444
1343
} /* merge_index */
1504
1406
sortorder->result_type= sortorder->item->result_type();
1505
1407
if (sortorder->item->result_as_int64_t())
1506
1408
sortorder->result_type= INT_RESULT;
1508
1409
switch (sortorder->result_type) {
1509
1410
case STRING_RESULT:
1510
sortorder->length=sortorder->item->max_length;
1411
sortorder->length=sortorder->item->max_length;
1511
1412
set_if_smaller(sortorder->length,
1512
getSession().variables.max_sort_length);
1513
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1413
session->variables.max_sort_length);
1414
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1515
1416
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
sortorder->need_strxnfrm= 1;
1517
*multi_byte_charset= 1;
1417
sortorder->need_strxnfrm= 1;
1418
*multi_byte_charset= 1;
1519
1420
else if (cs == &my_charset_bin)
1521
1422
/* Store length last to be able to sort blob/varbinary */
1522
1423
sortorder->suffix_length= suffix_length(sortorder->length);
1523
1424
sortorder->length+= sortorder->suffix_length;
1526
1427
case INT_RESULT:
1527
sortorder->length=8; // Size of intern int64_t
1428
sortorder->length=8; // Size of intern int64_t
1529
1430
case DECIMAL_RESULT:
1530
1431
sortorder->length=
1531
class_decimal_get_binary_size(sortorder->item->max_length -
1432
my_decimal_get_binary_size(sortorder->item->max_length -
1532
1433
(sortorder->item->decimals ? 1 : 0),
1533
1434
sortorder->item->decimals);
1535
1436
case REAL_RESULT:
1536
sortorder->length=sizeof(double);
1437
sortorder->length=sizeof(double);
1538
1439
case ROW_RESULT:
1539
// This case should never be choosen
1441
// This case should never be choosen
1543
1445
if (sortorder->item->maybe_null)
1544
length++; // Place for NULL marker
1446
length++; // Place for NULL marker
1546
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1448
set_if_smaller(sortorder->length,
1449
(size_t)session->variables.max_sort_length);
1547
1450
length+=sortorder->length;
1549
1452
sortorder->field= (Field*) 0; // end marker