33
#include <drizzled/drizzled.h>
24
#include <drizzled/server_includes.h>
34
25
#include <drizzled/sql_sort.h>
35
#include <drizzled/filesort.h>
36
26
#include <drizzled/error.h>
37
27
#include <drizzled/probes.h>
38
28
#include <drizzled/session.h>
39
29
#include <drizzled/table.h>
40
30
#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>
53
35
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
37
/* functions defined in this file */
137
static char **make_char_array(char **old_pos, uint32_t fields,
39
static char **make_char_array(char **old_pos, register uint32_t fields,
140
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
41
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
43
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
44
unsigned char * *sort_keys, IO_CACHE *buffer_file,
45
IO_CACHE *tempfile,IO_CACHE *indexfile);
46
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
47
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
48
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
49
static void register_used_fields(SORTPARAM *param);
50
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
52
uint32_t maxbuffer,IO_CACHE *tempfile,
54
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
55
filesort_info_st *table_sort);
144
56
static uint32_t suffix_length(uint32_t string_length);
145
static void unpack_addon_fields(sort_addon_field *addon_field,
57
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
58
bool *multi_byte_charset);
59
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
60
uint32_t sortlength, uint32_t *plength);
61
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
146
62
unsigned char *buff);
148
FileSort::FileSort(Session &arg) :
155
65
Creates a set of pointers that can be used to read the rows
185
96
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)
99
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
100
SQL_SELECT *select, ha_rows max_rows,
101
bool sort_positions, ha_rows *examined_rows)
193
uint32_t memavl= 0, min_sort_memory;
104
uint32_t memavl, min_sort_memory;
194
105
uint32_t maxbuffer;
195
size_t allocated_sort_memory= 0;
196
buffpek *buffpek_inst= 0;
197
107
ha_rows records= HA_POS_ERROR;
198
108
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;
109
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
204
111
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;
113
filesort_info_st table_sort;
214
114
TableList *tab= table->pos_in_table_list;
215
115
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
217
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
117
DRIZZLE_FILESORT_START(table->s->db.str, table->s->table_name.str);
220
120
Release InnoDB's adaptive hash index latch (if holding) before
223
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
123
ha_release_temporary_latches(session);
126
Don't use table->sort in filesort as it is also used by
127
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
128
when index_merge select has finished with it.
130
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
131
table->sort.io_cache= NULL;
226
133
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);
231
param.ref_length= table->cursor->ref_length;
233
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
134
my_b_clear(&tempfile);
135
my_b_clear(&buffpek_pointers);
138
memset(¶m, 0, sizeof(param));
139
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
140
param.ref_length= table->file->ref_length;
141
param.addon_field= 0;
142
param.addon_length= 0;
143
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
236
146
Get the descriptors of all fields whose values are appended
237
147
to sorted fields and get its total length in param.spack_length.
239
param.addon_field= get_addon_fields(table->getFields(),
149
param.addon_field= get_addon_fields(session, table->field,
240
150
param.sort_length,
241
151
¶m.addon_length);
293
201
selected_records_file= 0;
296
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
204
if (multi_byte_charset &&
205
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
301
memavl= getSession().variables.sortbuff_size;
208
memavl= session->variables.sortbuff_size;
302
209
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
210
while (memavl >= min_sort_memory)
305
212
uint32_t old_memavl;
306
213
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
307
214
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
215
if ((table_sort.sort_keys=
317
216
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
217
param.keys, param.rec_length)))
321
global_sort_buffer.sub(allocated_sort_memory);
322
219
old_memavl= memavl;
323
220
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
221
memavl= min_sort_memory;
329
226
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)))
229
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
230
DISK_BUFFER_SIZE, MYF(MY_WME)))
338
233
param.keys--; /* TODO: check why we do this */
339
234
param.sort_form= table;
340
235
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)
236
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
237
&tempfile, selected_records_file)) ==
346
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
240
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
348
242
if (maxbuffer == 0) // The whole set is in memory
350
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
244
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
359
251
if (table_sort.buffpek)
360
252
free(table_sort.buffpek);
361
table_sort.buffpek = 0;
253
table_sort.buffpek= 0;
363
255
if (!(table_sort.buffpek=
364
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
256
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
257
table_sort.buffpek)))
368
buffpek_inst= (buffpek *) table_sort.buffpek;
259
buffpek= (BUFFPEK *) table_sort.buffpek;
369
260
table_sort.buffpek_len= maxbuffer;
370
buffpek_pointers.close_cached_file();
261
close_cached_file(&buffpek_pointers);
371
262
/* 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))
263
if (! my_b_inited(outfile) &&
264
open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
267
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
383
271
Use also the space previously used by string pointers in sort_buffer
384
272
for temporary key storage.
386
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
274
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
388
276
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))
277
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
280
if (flush_io_cache(&tempfile) ||
281
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
283
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
405
287
if (records > param.max_rows)
407
records= param.max_rows;
288
records=param.max_rows;
412
if (not subselect || not subselect->is_uncacheable())
292
if (param.tmp_buffer)
293
if (param.tmp_buffer)
294
free(param.tmp_buffer);
295
if (!subselect || !subselect->is_uncacheable())
297
if ((unsigned char*) sort_keys)
298
free((unsigned char*) sort_keys);
415
299
table_sort.sort_keys= 0;
300
if ((unsigned char*) buffpek)
301
free((unsigned char*) buffpek);
417
302
table_sort.buffpek= 0;
418
303
table_sort.buffpek_len= 0;
421
tempfile.close_cached_file();
422
buffpek_pointers.close_cached_file();
305
close_cached_file(&tempfile);
306
close_cached_file(&buffpek_pointers);
424
307
if (my_b_inited(outfile))
426
309
if (flush_io_cache(outfile))
431
internal::my_off_t save_pos= outfile->pos_in_file;
312
my_off_t save_pos=outfile->pos_in_file;
432
313
/* For following reads */
433
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
314
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
437
316
outfile->end_of_file=save_pos;
443
320
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
444
321
MYF(ME_ERROR+ME_WAITTANG));
448
getSession().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;
323
statistic_add(session->status_var.filesort_rows,
324
(uint32_t) records, &LOCK_status);
325
*examined_rows= param.examined_rows;
326
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
453
327
DRIZZLE_FILESORT_DONE(error, records);
454
328
return (error ? HA_POS_ERROR : records);
332
void Table::filesort_free_buffers(bool full)
334
if (sort.record_pointers)
336
free((unsigned char*) sort.record_pointers);
337
sort.record_pointers=0;
343
if ((unsigned char*) sort.sort_keys)
344
free((unsigned char*) sort.sort_keys);
349
if ((unsigned char*) sort.buffpek)
350
free((unsigned char*) sort.buffpek);
357
free((char *) sort.addon_buf);
358
free((char *) sort.addon_field);
457
364
/** Make a array of string pointers. */
459
static char **make_char_array(char **old_pos, uint32_t fields,
366
static char **make_char_array(char **old_pos, register uint32_t fields,
476
383
/** Read 'count' number of buffer pointers into memory. */
478
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
385
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
479
386
unsigned char *buf)
481
uint32_t length= sizeof(buffpek)*count;
388
uint32_t length= sizeof(BUFFPEK)*count;
482
389
unsigned char *tmp= buf;
483
if (count > UINT_MAX/sizeof(buffpek))
484
return 0; /* sizeof(buffpek)*count will overflow */
390
if (count > UINT_MAX/sizeof(BUFFPEK))
391
return 0; /* sizeof(BUFFPEK)*count will overflow */
486
393
tmp= (unsigned char *)malloc(length);
489
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
396
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
490
397
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
492
399
free((char*) tmp);
534
441
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)
444
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
445
unsigned char **sort_keys,
446
IO_CACHE *buffpek_pointers,
447
IO_CACHE *tempfile, IO_CACHE *indexfile)
543
449
int error,flag,quick_select;
544
450
uint32_t idx,indexpos,ref_length;
545
451
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
internal::my_off_t record;
547
453
Table *sort_form;
548
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
550
boost::dynamic_bitset<> *save_read_set= NULL;
551
boost::dynamic_bitset<> *save_write_set= NULL;
454
Session *session= current_session;
455
volatile Session::killed_state *killed= &session->killed;
457
MyBitmap *save_read_set, *save_write_set;
554
460
error=quick_select=0;
555
461
sort_form=param->sort_form;
556
file= sort_form->cursor;
462
file=sort_form->file;
557
463
ref_length=param->ref_length;
558
464
ref_pos= ref_buff;
559
465
quick_select=select && select->quick;
561
flag= ((!indexfile && ! file->isOrdered())
467
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
562
468
|| quick_select);
563
469
if (indexfile || flag)
564
470
ref_pos= &file->ref[0];
566
472
if (! indexfile && ! quick_select)
568
474
next_pos=(unsigned char*) 0; /* Find records in sequence */
569
if (file->startTableScan(1))
570
return(HA_POS_ERROR);
571
file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
475
file->ha_rnd_init(1);
476
file->extra_opt(HA_EXTRA_CACHE,
477
current_session->variables.read_buff_size);
574
ReadRecord read_record_info;
480
READ_RECORD read_record_info;
575
481
if (quick_select)
577
483
if (select->quick->reset())
578
484
return(HA_POS_ERROR);
580
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
return(HA_POS_ERROR);
485
init_read_record(&read_record_info, current_session, select->quick->head,
584
489
/* Remember original bitmaps */
585
490
save_read_set= sort_form->read_set;
586
491
save_write_set= sort_form->write_set;
587
492
/* Set up temporary column read map for columns used by sort */
588
sort_form->tmp_set.reset();
493
sort_form->tmp_set.clearAll();
589
494
/* Temporary set for register_used_fields and register_field_in_read_map */
590
495
sort_form->read_set= &sort_form->tmp_set;
591
param->register_used_fields();
496
register_used_fields(param);
592
497
if (select && select->cond)
593
498
select->cond->walk(&Item::register_field_in_read_map, 1,
594
499
(unsigned char*) sort_form);
595
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
500
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
612
517
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
614
error= errno ? errno : -1; /* Abort */
519
error= my_errno ? my_errno : -1; /* Abort */
617
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
522
error=file->rnd_pos(sort_form->record[0],next_pos);
621
error=file->rnd_next(sort_form->getInsertRecord());
526
error=file->rnd_next(sort_form->record[0]);
625
internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
626
record+= sort_form->getShare()->db_record_offset;
530
my_store_ptr(ref_pos,ref_length,record); // Position to row
531
record+= sort_form->s->db_record_offset;
629
file->position(sort_form->getInsertRecord());
534
file->position(sort_form->record[0]);
631
536
if (error && error != HA_ERR_RECORD_DELETED)
669
571
index_merge quick select uses table->sort when retrieving rows, so free
670
572
resoures it has allocated.
672
read_record_info.end_read_record();
574
end_read_record(&read_record_info);
676
578
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
678
file->endTableScan();
681
if (getSession().is_error())
583
if (session->is_error())
682
584
return(HA_POS_ERROR);
684
586
/* Signal we should use orignal column read and write maps */
685
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
587
sort_form->column_bitmaps_set(save_read_set, save_write_set);
687
589
if (error != HA_ERR_END_OF_FILE)
689
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
690
return(HA_POS_ERROR);
693
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
695
return(HA_POS_ERROR);
591
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
592
return(HA_POS_ERROR);
594
if (indexpos && idx &&
595
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
596
return(HA_POS_ERROR);
698
597
return(my_b_inited(tempfile) ?
699
598
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
726
int SortParam::write_keys(unsigned char **sort_keys, uint32_t count,
727
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
626
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
627
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
629
size_t sort_length, rec_length;
731
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
633
sort_length= param->sort_length;
634
rec_length= param->rec_length;
635
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
732
636
if (!my_b_inited(tempfile) &&
733
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
637
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
737
640
/* 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)
641
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
743
643
buffpek.file_pos= my_b_tell(tempfile);
744
if ((ha_rows) count > max_rows)
745
count=(uint32_t) max_rows;
644
if ((ha_rows) count > param->max_rows)
645
count=(uint32_t) param->max_rows;
747
646
buffpek.count=(ha_rows) count;
749
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
647
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
751
648
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
757
650
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
763
656
} /* write_keys */
822
716
Item *item=sort_field->item;
823
717
maybe_null= item->maybe_null;
825
718
switch (sort_field->result_type) {
826
719
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;
721
const CHARSET_INFO * const cs=item->collation.collation;
722
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
724
uint32_t sort_field_length;
728
/* All item->str() to use some extra byte for end null.. */
729
String tmp((char*) to,sort_field->length+4,cs);
730
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);
734
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);
738
This should only happen during extreme conditions if we run out
739
of memory or have an item marked not null when it can be null.
740
This code is here mainly to avoid a hard crash in this case.
743
memset(to, 0, sort_field->length); // Avoid crash
747
length= res->length();
748
sort_field_length= sort_field->length - sort_field->suffix_length;
749
diff=(int) (sort_field_length - length);
753
length= sort_field_length;
755
if (sort_field->suffix_length)
757
/* Store length last in result_string */
758
store_length(to + sort_field_length, length,
759
sort_field->suffix_length);
761
if (sort_field->need_strxnfrm)
763
char *from=(char*) res->ptr();
765
if ((unsigned char*) from == to)
767
set_if_smaller(length,sort_field->length);
768
memcpy(param->tmp_buffer,from,length);
769
from=param->tmp_buffer;
771
tmp_length= my_strnxfrm(cs,to,sort_field->length,
772
(unsigned char*) from, length);
773
assert(tmp_length == sort_field->length);
777
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
778
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
891
784
int64_t value= item->val_int_result();
895
788
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);
799
to[7]= (unsigned char) value;
800
to[6]= (unsigned char) (value >> 8);
801
to[5]= (unsigned char) (value >> 16);
802
to[4]= (unsigned char) (value >> 24);
803
to[3]= (unsigned char) (value >> 32);
804
to[2]= (unsigned char) (value >> 40);
805
to[1]= (unsigned char) (value >> 48);
913
806
if (item->unsigned_flag) /* Fix sign */
914
807
to[0]= (unsigned char) (value >> 56);
916
809
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
919
812
case DECIMAL_RESULT:
921
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
814
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
924
817
if (item->null_value)
1017
907
/* Save filepos last */
1018
memcpy(to, ref_pos, (size_t) ref_length);
908
memcpy(to, ref_pos, (size_t) param->ref_length);
1024
fields used by sorting in the sorted table's read set
915
Register fields used by sorting in the sorted table's read set
1027
void SortParam::register_used_fields()
918
static void register_used_fields(SORTPARAM *param)
1029
SortField *sort_field;
1030
Table *table= sort_form;
920
register SORT_FIELD *sort_field;
921
Table *table=param->sort_form;
1032
for (sort_field= local_sortorder ;
923
for (sort_field= param->local_sortorder ;
924
sort_field != param->end ;
1037
928
if ((field= sort_field->field))
1039
if (field->getTable() == table)
1040
table->setReadSet(field->position());
930
if (field->table == table)
931
table->setReadSet(field->field_index);
1064
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
955
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
956
filesort_info_st *table_sort)
958
uint32_t offset,res_length;
1067
959
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++)
961
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
962
res_length= param->res_length;
963
offset= param->rec_length-res_length;
964
if ((ha_rows) count > param->max_rows)
965
count=(uint32_t) param->max_rows;
966
if (!(to= table_sort->record_pointers=
967
(unsigned char*) malloc(res_length*count)))
969
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1080
971
memcpy(to, *sort_keys+offset, res_length);
1081
972
to+= res_length;
1088
978
/** 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)
980
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
981
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1093
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
984
IO_CACHE t_file2,*from_file,*to_file,*temp;
1096
987
if (*maxbuffer < MERGEBUFF2)
1098
989
if (flush_io_cache(t_file) ||
1099
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
990
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1104
994
from_file= t_file ; to_file= &t_file2;
1105
995
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;
997
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
999
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1120
1002
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1122
1004
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1005
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1129
1008
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1009
buffpek+i,buffpek+ *maxbuffer,0))
1135
1011
if (flush_io_cache(to_file))
1140
1013
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;
1014
setup_io_cache(from_file);
1015
setup_io_cache(to_file);
1016
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1147
to_file->close_cached_file(); // This holds old result
1019
close_cached_file(to_file); // This holds old result
1148
1020
if (to_file == t_file)
1150
1022
*t_file=t_file2; // Copy result file
1151
t_file->setup_io_cache();
1023
setup_io_cache(t_file);
1154
1026
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1162
1034
(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)
1037
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1038
uint32_t rec_length)
1040
register uint32_t count;
1168
1041
uint32_t length;
1170
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1043
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)
1045
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1173
1046
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;
1048
buffpek->key= buffpek->base;
1049
buffpek->file_pos+= length; /* New filepos */
1050
buffpek->count-= count;
1051
buffpek->mem_count= count;
1180
1053
return (count*rec_length);
1181
1054
} /* read_to_buffer */
1222
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1223
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1224
buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1091
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1092
IO_CACHE *to_file, unsigned char *sort_buffer,
1093
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1228
1097
uint32_t rec_length,res_length,offset;
1229
1098
size_t sort_length;
1230
1099
uint32_t maxcount;
1231
1100
ha_rows max_rows,org_max_rows;
1232
internal::my_off_t to_start_filepos;
1101
my_off_t to_start_filepos;
1233
1102
unsigned char *strpos;
1234
buffpek *buffpek_inst;
1235
1104
qsort2_cmp cmp;
1236
1105
void *first_cmp_arg;
1237
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1238
Session::killed_state_t not_killable;
1106
volatile Session::killed_state *killed= ¤t_session->killed;
1107
Session::killed_state not_killable;
1240
getSession().status_var.filesort_merge_passes++;
1109
status_var_increment(current_session->status_var.filesort_merge_passes);
1241
1110
if (param->not_killable)
1243
1112
killed= ¬_killable;
1267
cmp= internal::get_ptr_compare(sort_length);
1136
cmp= get_ptr_compare(sort_length);
1268
1137
first_cmp_arg= (void*) &sort_length;
1270
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1139
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1271
1140
queue(compare_functor(cmp, first_cmp_arg));
1272
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1141
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,
1143
buffpek->base= strpos;
1144
buffpek->max_keys= maxcount;
1145
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1278
1147
if (error == -1)
1281
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1282
queue.push(buffpek_inst);
1149
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1150
queue.push(buffpek);
1285
1153
if (param->unique_buff)
1308
1176
/* Top element has been used */
1310
queue.push(buffpek_inst);
1178
queue.push(buffpek);
1314
1181
cmp= 0; // Not unique
1317
1183
while (queue.size() > 1)
1325
buffpek_inst= queue.top();
1191
buffpek= queue.top();
1326
1192
if (cmp) // Remove duplicates
1328
1194
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
(unsigned char**) &buffpek_inst->key))
1195
(unsigned char**) &buffpek->key))
1330
1196
goto skip_duplicate;
1331
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1197
memcpy(param->unique_buff, buffpek->key, rec_length);
1335
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1201
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))
1208
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1347
1213
if (!--max_rows)
1353
1219
skip_duplicate:
1354
buffpek_inst->key+= rec_length;
1355
if (! --buffpek_inst->mem_count)
1220
buffpek->key+= rec_length;
1221
if (! --buffpek->mem_count)
1357
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1223
if (!(error= (int) read_to_buffer(from_file,buffpek,
1361
1227
break; /* One buffer have been removed */
1363
1229
else if (error == -1)
1368
1232
/* Top element has been replaced */
1370
queue.push(buffpek_inst);
1234
queue.push(buffpek);
1373
buffpek_inst= queue.top();
1374
buffpek_inst->base= sort_buffer;
1375
buffpek_inst->max_keys= param->keys;
1237
buffpek= queue.top();
1238
buffpek->base= sort_buffer;
1239
buffpek->max_keys= param->keys;
1378
1242
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))
1247
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;
1249
buffpek->key+= rec_length; // Remove duplicate
1250
--buffpek->mem_count;
1392
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1256
if ((ha_rows) buffpek->mem_count > max_rows)
1393
1257
{ /* Don't write too many records */
1394
buffpek_inst->mem_count= (uint32_t) max_rows;
1395
buffpek_inst->count= 0; /* Don't read more */
1258
buffpek->mem_count= (uint32_t) max_rows;
1259
buffpek->count= 0; /* Don't read more */
1397
max_rows-= buffpek_inst->mem_count;
1261
max_rows-= buffpek->mem_count;
1400
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
(rec_length*buffpek_inst->mem_count)))
1264
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1265
(rec_length*buffpek->mem_count)))
1409
strpos= buffpek_inst->key+offset;
1410
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1272
register unsigned char *end;
1273
strpos= buffpek->key+offset;
1274
for (end= strpos+buffpek->mem_count*rec_length ;
1411
1275
strpos != end ;
1412
1276
strpos+= rec_length)
1414
1278
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1422
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1285
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1286
!= -1 && error != 0);
1426
1289
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1427
1290
lastbuff->file_pos= to_start_filepos;
1430
1293
} /* merge_buffers */
1433
1296
/* 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)
1298
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1299
BUFFPEK *buffpek, uint32_t maxbuffer,
1300
IO_CACHE *tempfile, IO_CACHE *outfile)
1439
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
buffpek_inst+maxbuffer,1))
1302
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1303
buffpek+maxbuffer,1))
1444
1306
} /* merge_index */
1504
1369
sortorder->result_type= sortorder->item->result_type();
1505
1370
if (sortorder->item->result_as_int64_t())
1506
1371
sortorder->result_type= INT_RESULT;
1508
1372
switch (sortorder->result_type) {
1509
1373
case STRING_RESULT:
1510
sortorder->length=sortorder->item->max_length;
1374
sortorder->length=sortorder->item->max_length;
1511
1375
set_if_smaller(sortorder->length,
1512
getSession().variables.max_sort_length);
1513
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1376
session->variables.max_sort_length);
1377
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1515
1379
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
sortorder->need_strxnfrm= 1;
1517
*multi_byte_charset= 1;
1380
sortorder->need_strxnfrm= 1;
1381
*multi_byte_charset= 1;
1519
1383
else if (cs == &my_charset_bin)
1521
1385
/* Store length last to be able to sort blob/varbinary */
1522
1386
sortorder->suffix_length= suffix_length(sortorder->length);
1523
1387
sortorder->length+= sortorder->suffix_length;
1526
1390
case INT_RESULT:
1527
sortorder->length=8; // Size of intern int64_t
1391
sortorder->length=8; // Size of intern int64_t
1529
1393
case DECIMAL_RESULT:
1530
1394
sortorder->length=
1531
class_decimal_get_binary_size(sortorder->item->max_length -
1395
my_decimal_get_binary_size(sortorder->item->max_length -
1532
1396
(sortorder->item->decimals ? 1 : 0),
1533
1397
sortorder->item->decimals);
1535
1399
case REAL_RESULT:
1536
sortorder->length=sizeof(double);
1400
sortorder->length=sizeof(double);
1538
1402
case ROW_RESULT:
1539
// This case should never be choosen
1404
// This case should never be choosen
1543
1408
if (sortorder->item->maybe_null)
1544
length++; // Place for NULL marker
1409
length++; // Place for NULL marker
1546
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1411
set_if_smaller(sortorder->length,
1412
(size_t)session->variables.max_sort_length);
1547
1413
length+=sortorder->length;
1549
1415
sortorder->field= (Field*) 0; // end marker