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);
36
using namespace drizzled;
135
38
/* functions defined in this file */
137
static char **make_char_array(char **old_pos, uint32_t fields,
40
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,
42
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
44
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
45
unsigned char * *sort_keys, IO_CACHE *buffer_file,
46
IO_CACHE *tempfile,IO_CACHE *indexfile);
47
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
48
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
49
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
50
static void register_used_fields(SORTPARAM *param);
51
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
53
uint32_t maxbuffer,IO_CACHE *tempfile,
55
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
56
filesort_info_st *table_sort);
144
57
static uint32_t suffix_length(uint32_t string_length);
145
static void unpack_addon_fields(sort_addon_field *addon_field,
58
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
59
bool *multi_byte_charset);
60
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
61
uint32_t sortlength, uint32_t *plength);
62
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
146
63
unsigned char *buff);
148
FileSort::FileSort(Session &arg) :
155
66
Creates a set of pointers that can be used to read the rows
185
97
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)
100
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
101
SQL_SELECT *select, ha_rows max_rows,
102
bool sort_positions, ha_rows *examined_rows)
193
uint32_t memavl= 0, min_sort_memory;
105
uint32_t memavl, min_sort_memory;
194
106
uint32_t maxbuffer;
195
size_t allocated_sort_memory= 0;
196
buffpek *buffpek_inst= 0;
197
108
ha_rows records= HA_POS_ERROR;
198
109
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;
110
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
204
112
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;
114
filesort_info_st table_sort;
214
115
TableList *tab= table->pos_in_table_list;
215
116
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
217
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
118
DRIZZLE_FILESORT_START(table->s->db.str, table->s->table_name.str);
220
121
Release InnoDB's adaptive hash index latch (if holding) before
223
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
124
plugin::StorageEngine::releaseTemporaryLatches(session);
127
Don't use table->sort in filesort as it is also used by
128
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
129
when index_merge select has finished with it.
131
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
132
table->sort.io_cache= NULL;
226
134
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)
135
my_b_clear(&tempfile);
136
my_b_clear(&buffpek_pointers);
139
memset(¶m, 0, sizeof(param));
140
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
141
param.ref_length= table->file->ref_length;
142
param.addon_field= 0;
143
param.addon_length= 0;
144
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
236
147
Get the descriptors of all fields whose values are appended
237
148
to sorted fields and get its total length in param.spack_length.
239
param.addon_field= get_addon_fields(table->getFields(),
150
param.addon_field= get_addon_fields(session, table->field,
240
151
param.sort_length,
241
152
¶m.addon_length);
293
202
selected_records_file= 0;
296
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
205
if (multi_byte_charset &&
206
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
301
memavl= getSession().variables.sortbuff_size;
209
memavl= session->variables.sortbuff_size;
302
210
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
211
while (memavl >= min_sort_memory)
305
213
uint32_t old_memavl;
306
214
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
307
215
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
216
if ((table_sort.sort_keys=
317
217
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
218
param.keys, param.rec_length)))
321
global_sort_buffer.sub(allocated_sort_memory);
322
220
old_memavl= memavl;
323
221
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
222
memavl= min_sort_memory;
329
227
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)))
230
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
231
DISK_BUFFER_SIZE, MYF(MY_WME)))
338
234
param.keys--; /* TODO: check why we do this */
339
235
param.sort_form= table;
340
236
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)
237
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
238
&tempfile, selected_records_file)) ==
346
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
241
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
348
243
if (maxbuffer == 0) // The whole set is in memory
350
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
245
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
359
252
if (table_sort.buffpek)
360
253
free(table_sort.buffpek);
361
table_sort.buffpek = 0;
254
table_sort.buffpek= 0;
363
256
if (!(table_sort.buffpek=
364
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
257
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
258
table_sort.buffpek)))
368
buffpek_inst= (buffpek *) table_sort.buffpek;
260
buffpek= (BUFFPEK *) table_sort.buffpek;
369
261
table_sort.buffpek_len= maxbuffer;
370
buffpek_pointers.close_cached_file();
262
close_cached_file(&buffpek_pointers);
371
263
/* 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))
264
if (! my_b_inited(outfile) &&
265
open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
268
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
383
272
Use also the space previously used by string pointers in sort_buffer
384
273
for temporary key storage.
386
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
275
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
388
277
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))
278
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
281
if (flush_io_cache(&tempfile) ||
282
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
284
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
405
288
if (records > param.max_rows)
407
records= param.max_rows;
289
records=param.max_rows;
412
if (not subselect || not subselect->is_uncacheable())
293
if (param.tmp_buffer)
294
if (param.tmp_buffer)
295
free(param.tmp_buffer);
296
if (!subselect || !subselect->is_uncacheable())
298
if ((unsigned char*) sort_keys)
299
free((unsigned char*) sort_keys);
415
300
table_sort.sort_keys= 0;
301
if ((unsigned char*) buffpek)
302
free((unsigned char*) buffpek);
417
303
table_sort.buffpek= 0;
418
304
table_sort.buffpek_len= 0;
421
tempfile.close_cached_file();
422
buffpek_pointers.close_cached_file();
306
close_cached_file(&tempfile);
307
close_cached_file(&buffpek_pointers);
424
308
if (my_b_inited(outfile))
426
310
if (flush_io_cache(outfile))
431
internal::my_off_t save_pos= outfile->pos_in_file;
313
my_off_t save_pos=outfile->pos_in_file;
432
314
/* For following reads */
433
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
315
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
437
317
outfile->end_of_file=save_pos;
443
321
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
444
322
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;
324
statistic_add(session->status_var.filesort_rows,
325
(uint32_t) records, &LOCK_status);
326
*examined_rows= param.examined_rows;
327
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
453
328
DRIZZLE_FILESORT_DONE(error, records);
454
329
return (error ? HA_POS_ERROR : records);
333
void Table::filesort_free_buffers(bool full)
335
if (sort.record_pointers)
337
free((unsigned char*) sort.record_pointers);
338
sort.record_pointers=0;
344
if ((unsigned char*) sort.sort_keys)
345
free((unsigned char*) sort.sort_keys);
350
if ((unsigned char*) sort.buffpek)
351
free((unsigned char*) sort.buffpek);
358
free((char *) sort.addon_buf);
359
free((char *) sort.addon_field);
457
365
/** Make a array of string pointers. */
459
static char **make_char_array(char **old_pos, uint32_t fields,
367
static char **make_char_array(char **old_pos, register uint32_t fields,
476
384
/** Read 'count' number of buffer pointers into memory. */
478
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
386
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
479
387
unsigned char *buf)
481
uint32_t length= sizeof(buffpek)*count;
389
uint32_t length= sizeof(BUFFPEK)*count;
482
390
unsigned char *tmp= buf;
483
if (count > UINT_MAX/sizeof(buffpek))
484
return 0; /* sizeof(buffpek)*count will overflow */
391
if (count > UINT_MAX/sizeof(BUFFPEK))
392
return 0; /* sizeof(BUFFPEK)*count will overflow */
486
394
tmp= (unsigned char *)malloc(length);
489
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
397
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
490
398
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
492
400
free((char*) tmp);
534
442
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)
445
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
446
unsigned char **sort_keys,
447
IO_CACHE *buffpek_pointers,
448
IO_CACHE *tempfile, IO_CACHE *indexfile)
543
450
int error,flag,quick_select;
544
451
uint32_t idx,indexpos,ref_length;
545
452
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
internal::my_off_t record;
547
454
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;
455
Session *session= current_session;
456
volatile Session::killed_state *killed= &session->killed;
458
MyBitmap *save_read_set, *save_write_set;
554
461
error=quick_select=0;
555
462
sort_form=param->sort_form;
556
file= sort_form->cursor;
463
file=sort_form->file;
557
464
ref_length=param->ref_length;
558
465
ref_pos= ref_buff;
559
466
quick_select=select && select->quick;
561
flag= ((!indexfile && ! file->isOrdered())
468
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
562
469
|| quick_select);
563
470
if (indexfile || flag)
564
471
ref_pos= &file->ref[0];
566
473
if (! indexfile && ! quick_select)
568
475
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);
476
file->ha_rnd_init(1);
477
file->extra_opt(HA_EXTRA_CACHE,
478
current_session->variables.read_buff_size);
574
ReadRecord read_record_info;
481
READ_RECORD read_record_info;
575
482
if (quick_select)
577
484
if (select->quick->reset())
578
485
return(HA_POS_ERROR);
580
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
return(HA_POS_ERROR);
486
init_read_record(&read_record_info, current_session, select->quick->head,
584
490
/* Remember original bitmaps */
585
491
save_read_set= sort_form->read_set;
586
492
save_write_set= sort_form->write_set;
587
493
/* Set up temporary column read map for columns used by sort */
588
sort_form->tmp_set.reset();
494
sort_form->tmp_set.clearAll();
589
495
/* Temporary set for register_used_fields and register_field_in_read_map */
590
496
sort_form->read_set= &sort_form->tmp_set;
591
param->register_used_fields();
497
register_used_fields(param);
592
498
if (select && select->cond)
593
499
select->cond->walk(&Item::register_field_in_read_map, 1,
594
500
(unsigned char*) sort_form);
595
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
501
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
612
518
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
614
error= errno ? errno : -1; /* Abort */
520
error= my_errno ? my_errno : -1; /* Abort */
617
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
523
error=file->rnd_pos(sort_form->record[0],next_pos);
621
error=file->rnd_next(sort_form->getInsertRecord());
527
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;
531
my_store_ptr(ref_pos,ref_length,record); // Position to row
532
record+= sort_form->s->db_record_offset;
629
file->position(sort_form->getInsertRecord());
535
file->position(sort_form->record[0]);
631
537
if (error && error != HA_ERR_RECORD_DELETED)
669
572
index_merge quick select uses table->sort when retrieving rows, so free
670
573
resoures it has allocated.
672
read_record_info.end_read_record();
575
end_read_record(&read_record_info);
676
579
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
678
file->endTableScan();
681
if (getSession().is_error())
584
if (session->is_error())
682
585
return(HA_POS_ERROR);
684
587
/* Signal we should use orignal column read and write maps */
685
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
588
sort_form->column_bitmaps_set(save_read_set, save_write_set);
687
590
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);
592
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
593
return(HA_POS_ERROR);
595
if (indexpos && idx &&
596
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
597
return(HA_POS_ERROR);
698
598
return(my_b_inited(tempfile) ?
699
599
(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)
627
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
628
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
630
size_t sort_length, rec_length;
731
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
634
sort_length= param->sort_length;
635
rec_length= param->rec_length;
636
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
732
637
if (!my_b_inited(tempfile) &&
733
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
638
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
737
641
/* 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)
642
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
743
644
buffpek.file_pos= my_b_tell(tempfile);
744
if ((ha_rows) count > max_rows)
745
count=(uint32_t) max_rows;
645
if ((ha_rows) count > param->max_rows)
646
count=(uint32_t) param->max_rows;
747
647
buffpek.count=(ha_rows) count;
749
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
648
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
751
649
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
757
651
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
763
657
} /* write_keys */
822
717
Item *item=sort_field->item;
823
718
maybe_null= item->maybe_null;
825
719
switch (sort_field->result_type) {
826
720
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;
722
const CHARSET_INFO * const cs=item->collation.collation;
723
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
725
uint32_t sort_field_length;
729
/* All item->str() to use some extra byte for end null.. */
730
String tmp((char*) to,sort_field->length+4,cs);
731
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);
735
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);
739
This should only happen during extreme conditions if we run out
740
of memory or have an item marked not null when it can be null.
741
This code is here mainly to avoid a hard crash in this case.
744
memset(to, 0, sort_field->length); // Avoid crash
748
length= res->length();
749
sort_field_length= sort_field->length - sort_field->suffix_length;
750
diff=(int) (sort_field_length - length);
754
length= sort_field_length;
756
if (sort_field->suffix_length)
758
/* Store length last in result_string */
759
store_length(to + sort_field_length, length,
760
sort_field->suffix_length);
762
if (sort_field->need_strxnfrm)
764
char *from=(char*) res->ptr();
766
if ((unsigned char*) from == to)
768
set_if_smaller(length,sort_field->length);
769
memcpy(param->tmp_buffer,from,length);
770
from=param->tmp_buffer;
772
tmp_length= my_strnxfrm(cs,to,sort_field->length,
773
(unsigned char*) from, length);
774
assert(tmp_length == sort_field->length);
778
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
779
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
891
785
int64_t value= item->val_int_result();
895
789
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);
800
to[7]= (unsigned char) value;
801
to[6]= (unsigned char) (value >> 8);
802
to[5]= (unsigned char) (value >> 16);
803
to[4]= (unsigned char) (value >> 24);
804
to[3]= (unsigned char) (value >> 32);
805
to[2]= (unsigned char) (value >> 40);
806
to[1]= (unsigned char) (value >> 48);
913
807
if (item->unsigned_flag) /* Fix sign */
914
808
to[0]= (unsigned char) (value >> 56);
916
810
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
919
813
case DECIMAL_RESULT:
921
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
815
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
924
818
if (item->null_value)
1017
908
/* Save filepos last */
1018
memcpy(to, ref_pos, (size_t) ref_length);
909
memcpy(to, ref_pos, (size_t) param->ref_length);
1024
fields used by sorting in the sorted table's read set
916
Register fields used by sorting in the sorted table's read set
1027
void SortParam::register_used_fields()
919
static void register_used_fields(SORTPARAM *param)
1029
SortField *sort_field;
1030
Table *table= sort_form;
921
register SORT_FIELD *sort_field;
922
Table *table=param->sort_form;
1032
for (sort_field= local_sortorder ;
924
for (sort_field= param->local_sortorder ;
925
sort_field != param->end ;
1037
929
if ((field= sort_field->field))
1039
if (field->getTable() == table)
1040
table->setReadSet(field->position());
931
if (field->table == table)
932
table->setReadSet(field->field_index);
1064
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
956
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
957
filesort_info_st *table_sort)
959
uint32_t offset,res_length;
1067
960
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++)
962
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
963
res_length= param->res_length;
964
offset= param->rec_length-res_length;
965
if ((ha_rows) count > param->max_rows)
966
count=(uint32_t) param->max_rows;
967
if (!(to= table_sort->record_pointers=
968
(unsigned char*) malloc(res_length*count)))
970
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1080
972
memcpy(to, *sort_keys+offset, res_length);
1081
973
to+= res_length;
1088
979
/** 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)
981
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
982
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1093
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
985
IO_CACHE t_file2,*from_file,*to_file,*temp;
1096
988
if (*maxbuffer < MERGEBUFF2)
1098
990
if (flush_io_cache(t_file) ||
1099
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
991
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1104
995
from_file= t_file ; to_file= &t_file2;
1105
996
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;
998
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1000
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1120
1003
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1122
1005
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1006
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1129
1009
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1010
buffpek+i,buffpek+ *maxbuffer,0))
1135
1012
if (flush_io_cache(to_file))
1140
1014
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;
1015
setup_io_cache(from_file);
1016
setup_io_cache(to_file);
1017
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1147
to_file->close_cached_file(); // This holds old result
1020
close_cached_file(to_file); // This holds old result
1148
1021
if (to_file == t_file)
1150
1023
*t_file=t_file2; // Copy result file
1151
t_file->setup_io_cache();
1024
setup_io_cache(t_file);
1154
1027
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1162
1035
(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)
1038
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1039
uint32_t rec_length)
1041
register uint32_t count;
1168
1042
uint32_t length;
1170
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1044
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)
1046
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1173
1047
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;
1049
buffpek->key= buffpek->base;
1050
buffpek->file_pos+= length; /* New filepos */
1051
buffpek->count-= count;
1052
buffpek->mem_count= count;
1180
1054
return (count*rec_length);
1181
1055
} /* 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,
1092
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1093
IO_CACHE *to_file, unsigned char *sort_buffer,
1094
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1228
1098
uint32_t rec_length,res_length,offset;
1229
1099
size_t sort_length;
1230
1100
uint32_t maxcount;
1231
1101
ha_rows max_rows,org_max_rows;
1232
internal::my_off_t to_start_filepos;
1102
my_off_t to_start_filepos;
1233
1103
unsigned char *strpos;
1234
buffpek *buffpek_inst;
1235
1105
qsort2_cmp cmp;
1236
1106
void *first_cmp_arg;
1237
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1238
Session::killed_state_t not_killable;
1107
volatile Session::killed_state *killed= ¤t_session->killed;
1108
Session::killed_state not_killable;
1240
getSession().status_var.filesort_merge_passes++;
1110
status_var_increment(current_session->status_var.filesort_merge_passes);
1241
1111
if (param->not_killable)
1243
1113
killed= ¬_killable;
1267
cmp= internal::get_ptr_compare(sort_length);
1137
cmp= get_ptr_compare(sort_length);
1268
1138
first_cmp_arg= (void*) &sort_length;
1270
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1140
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1271
1141
queue(compare_functor(cmp, first_cmp_arg));
1272
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1142
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,
1144
buffpek->base= strpos;
1145
buffpek->max_keys= maxcount;
1146
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1278
1148
if (error == -1)
1281
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1282
queue.push(buffpek_inst);
1150
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1151
queue.push(buffpek);
1285
1154
if (param->unique_buff)
1308
1177
/* Top element has been used */
1310
queue.push(buffpek_inst);
1179
queue.push(buffpek);
1314
1182
cmp= 0; // Not unique
1317
1184
while (queue.size() > 1)
1325
buffpek_inst= queue.top();
1192
buffpek= queue.top();
1326
1193
if (cmp) // Remove duplicates
1328
1195
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
(unsigned char**) &buffpek_inst->key))
1196
(unsigned char**) &buffpek->key))
1330
1197
goto skip_duplicate;
1331
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1198
memcpy(param->unique_buff, buffpek->key, rec_length);
1335
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1202
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))
1209
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1347
1214
if (!--max_rows)
1353
1220
skip_duplicate:
1354
buffpek_inst->key+= rec_length;
1355
if (! --buffpek_inst->mem_count)
1221
buffpek->key+= rec_length;
1222
if (! --buffpek->mem_count)
1357
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1224
if (!(error= (int) read_to_buffer(from_file,buffpek,
1361
1228
break; /* One buffer have been removed */
1363
1230
else if (error == -1)
1368
1233
/* Top element has been replaced */
1370
queue.push(buffpek_inst);
1235
queue.push(buffpek);
1373
buffpek_inst= queue.top();
1374
buffpek_inst->base= sort_buffer;
1375
buffpek_inst->max_keys= param->keys;
1238
buffpek= queue.top();
1239
buffpek->base= sort_buffer;
1240
buffpek->max_keys= param->keys;
1378
1243
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))
1248
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;
1250
buffpek->key+= rec_length; // Remove duplicate
1251
--buffpek->mem_count;
1392
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1257
if ((ha_rows) buffpek->mem_count > max_rows)
1393
1258
{ /* Don't write too many records */
1394
buffpek_inst->mem_count= (uint32_t) max_rows;
1395
buffpek_inst->count= 0; /* Don't read more */
1259
buffpek->mem_count= (uint32_t) max_rows;
1260
buffpek->count= 0; /* Don't read more */
1397
max_rows-= buffpek_inst->mem_count;
1262
max_rows-= buffpek->mem_count;
1400
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
(rec_length*buffpek_inst->mem_count)))
1265
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1266
(rec_length*buffpek->mem_count)))
1409
strpos= buffpek_inst->key+offset;
1410
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1273
register unsigned char *end;
1274
strpos= buffpek->key+offset;
1275
for (end= strpos+buffpek->mem_count*rec_length ;
1411
1276
strpos != end ;
1412
1277
strpos+= rec_length)
1414
1279
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1422
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1286
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1287
!= -1 && error != 0);
1426
1290
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1427
1291
lastbuff->file_pos= to_start_filepos;
1430
1294
} /* merge_buffers */
1433
1297
/* 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)
1299
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1300
BUFFPEK *buffpek, uint32_t maxbuffer,
1301
IO_CACHE *tempfile, IO_CACHE *outfile)
1439
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
buffpek_inst+maxbuffer,1))
1303
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1304
buffpek+maxbuffer,1))
1444
1307
} /* merge_index */
1504
1370
sortorder->result_type= sortorder->item->result_type();
1505
1371
if (sortorder->item->result_as_int64_t())
1506
1372
sortorder->result_type= INT_RESULT;
1508
1373
switch (sortorder->result_type) {
1509
1374
case STRING_RESULT:
1510
sortorder->length=sortorder->item->max_length;
1375
sortorder->length=sortorder->item->max_length;
1511
1376
set_if_smaller(sortorder->length,
1512
getSession().variables.max_sort_length);
1513
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1377
session->variables.max_sort_length);
1378
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1515
1380
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
sortorder->need_strxnfrm= 1;
1517
*multi_byte_charset= 1;
1381
sortorder->need_strxnfrm= 1;
1382
*multi_byte_charset= 1;
1519
1384
else if (cs == &my_charset_bin)
1521
1386
/* Store length last to be able to sort blob/varbinary */
1522
1387
sortorder->suffix_length= suffix_length(sortorder->length);
1523
1388
sortorder->length+= sortorder->suffix_length;
1526
1391
case INT_RESULT:
1527
sortorder->length=8; // Size of intern int64_t
1392
sortorder->length=8; // Size of intern int64_t
1529
1394
case DECIMAL_RESULT:
1530
1395
sortorder->length=
1531
class_decimal_get_binary_size(sortorder->item->max_length -
1396
my_decimal_get_binary_size(sortorder->item->max_length -
1532
1397
(sortorder->item->decimals ? 1 : 0),
1533
1398
sortorder->item->decimals);
1535
1400
case REAL_RESULT:
1536
sortorder->length=sizeof(double);
1401
sortorder->length=sizeof(double);
1538
1403
case ROW_RESULT:
1539
// This case should never be choosen
1405
// This case should never be choosen
1543
1409
if (sortorder->item->maybe_null)
1544
length++; // Place for NULL marker
1410
length++; // Place for NULL marker
1546
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1412
set_if_smaller(sortorder->length,
1413
(size_t)session->variables.max_sort_length);
1547
1414
length+=sortorder->length;
1549
1416
sortorder->field= (Field*) 0; // end marker