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
34
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
36
/* functions defined in this file */
137
static char **make_char_array(char **old_pos, uint32_t fields,
38
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,
40
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
42
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
43
unsigned char * *sort_keys, IO_CACHE *buffer_file,
44
IO_CACHE *tempfile,IO_CACHE *indexfile);
45
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
46
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
47
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
48
static void register_used_fields(SORTPARAM *param);
49
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
51
uint32_t maxbuffer,IO_CACHE *tempfile,
53
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
54
filesort_info_st *table_sort);
144
55
static uint32_t suffix_length(uint32_t string_length);
145
static void unpack_addon_fields(sort_addon_field *addon_field,
56
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
57
bool *multi_byte_charset);
58
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
59
uint32_t sortlength, uint32_t *plength);
60
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
146
61
unsigned char *buff);
148
FileSort::FileSort(Session &arg) :
155
64
Creates a set of pointers that can be used to read the rows
185
95
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)
98
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
99
SQL_SELECT *select, ha_rows max_rows,
100
bool sort_positions, ha_rows *examined_rows)
193
uint32_t memavl= 0, min_sort_memory;
103
uint32_t memavl, min_sort_memory;
194
104
uint32_t maxbuffer;
195
size_t allocated_sort_memory= 0;
196
buffpek *buffpek_inst= 0;
197
106
ha_rows records= HA_POS_ERROR;
198
107
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;
108
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
204
110
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;
112
filesort_info_st table_sort;
214
113
TableList *tab= table->pos_in_table_list;
215
114
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
217
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
116
DRIZZLE_FILESORT_START();
220
119
Release InnoDB's adaptive hash index latch (if holding) before
223
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
122
ha_release_temporary_latches(session);
125
Don't use table->sort in filesort as it is also used by
126
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
127
when index_merge select has finished with it.
129
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
130
table->sort.io_cache= NULL;
226
132
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)
133
my_b_clear(&tempfile);
134
my_b_clear(&buffpek_pointers);
137
memset(¶m, 0, sizeof(param));
138
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
139
param.ref_length= table->file->ref_length;
140
param.addon_field= 0;
141
param.addon_length= 0;
142
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
236
145
Get the descriptors of all fields whose values are appended
237
146
to sorted fields and get its total length in param.spack_length.
239
param.addon_field= get_addon_fields(table->getFields(),
148
param.addon_field= get_addon_fields(session, table->field,
240
149
param.sort_length,
241
150
¶m.addon_length);
293
200
selected_records_file= 0;
296
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
203
if (multi_byte_charset &&
204
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
301
memavl= getSession().variables.sortbuff_size;
302
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
207
memavl= session->variables.sortbuff_size;
208
min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
209
while (memavl >= min_sort_memory)
305
211
uint32_t old_memavl;
306
212
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
307
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));
213
param.keys=(uint32_t) cmin(records+1, keys);
316
214
if ((table_sort.sort_keys=
317
215
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
216
param.keys, param.rec_length)))
321
global_sort_buffer.sub(allocated_sort_memory);
323
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
219
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
220
memavl= min_sort_memory;
326
222
sort_keys= table_sort.sort_keys;
329
225
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)))
228
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
229
DISK_BUFFER_SIZE, MYF(MY_WME)))
338
232
param.keys--; /* TODO: check why we do this */
339
233
param.sort_form= table;
340
234
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)
235
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
236
&tempfile, selected_records_file)) ==
346
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
239
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
348
241
if (maxbuffer == 0) // The whole set is in memory
350
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
243
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
359
250
if (table_sort.buffpek)
360
251
free(table_sort.buffpek);
361
table_sort.buffpek = 0;
252
table_sort.buffpek= 0;
363
254
if (!(table_sort.buffpek=
364
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
255
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
256
table_sort.buffpek)))
368
buffpek_inst= (buffpek *) table_sort.buffpek;
258
buffpek= (BUFFPEK *) table_sort.buffpek;
369
259
table_sort.buffpek_len= maxbuffer;
370
buffpek_pointers.close_cached_file();
260
close_cached_file(&buffpek_pointers);
371
261
/* 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))
262
if (! my_b_inited(outfile) &&
263
open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
266
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
383
270
Use also the space previously used by string pointers in sort_buffer
384
271
for temporary key storage.
386
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
273
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
388
275
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))
276
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
279
if (flush_io_cache(&tempfile) ||
280
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
282
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
405
286
if (records > param.max_rows)
407
records= param.max_rows;
287
records=param.max_rows;
412
if (not subselect || not subselect->is_uncacheable())
291
if (param.tmp_buffer)
292
if (param.tmp_buffer)
293
free(param.tmp_buffer);
294
if (!subselect || !subselect->is_uncacheable())
296
if ((unsigned char*) sort_keys)
297
free((unsigned char*) sort_keys);
415
298
table_sort.sort_keys= 0;
299
if ((unsigned char*) buffpek)
300
free((unsigned char*) buffpek);
417
301
table_sort.buffpek= 0;
418
302
table_sort.buffpek_len= 0;
421
tempfile.close_cached_file();
422
buffpek_pointers.close_cached_file();
304
close_cached_file(&tempfile);
305
close_cached_file(&buffpek_pointers);
424
306
if (my_b_inited(outfile))
426
308
if (flush_io_cache(outfile))
431
internal::my_off_t save_pos= outfile->pos_in_file;
311
my_off_t save_pos=outfile->pos_in_file;
432
312
/* For following reads */
433
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
313
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
437
315
outfile->end_of_file=save_pos;
443
319
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
444
320
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;
453
DRIZZLE_FILESORT_DONE(error, records);
454
return (error ? HA_POS_ERROR : records);
322
statistic_add(session->status_var.filesort_rows,
323
(uint32_t) records, &LOCK_status);
324
*examined_rows= param.examined_rows;
325
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
326
DRIZZLE_FILESORT_END();
327
return(error ? HA_POS_ERROR : records);
331
void filesort_free_buffers(Table *table, bool full)
333
if (table->sort.record_pointers)
335
free((unsigned char*) table->sort.record_pointers);
336
table->sort.record_pointers=0;
340
if (table->sort.sort_keys )
342
if ((unsigned char*) table->sort.sort_keys)
343
free((unsigned char*) table->sort.sort_keys);
344
table->sort.sort_keys= 0;
346
if (table->sort.buffpek)
348
if ((unsigned char*) table->sort.buffpek)
349
free((unsigned char*) table->sort.buffpek);
350
table->sort.buffpek= 0;
351
table->sort.buffpek_len= 0;
354
if (table->sort.addon_buf)
356
free((char *) table->sort.addon_buf);
357
free((char *) table->sort.addon_field);
358
table->sort.addon_buf=0;
359
table->sort.addon_field=0;
457
363
/** Make a array of string pointers. */
459
static char **make_char_array(char **old_pos, uint32_t fields,
365
static char **make_char_array(char **old_pos, register uint32_t fields,
476
382
/** Read 'count' number of buffer pointers into memory. */
478
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
384
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
479
385
unsigned char *buf)
481
uint32_t length= sizeof(buffpek)*count;
387
uint32_t length= sizeof(BUFFPEK)*count;
482
388
unsigned char *tmp= buf;
483
if (count > UINT_MAX/sizeof(buffpek))
484
return 0; /* sizeof(buffpek)*count will overflow */
389
if (count > UINT_MAX/sizeof(BUFFPEK))
390
return 0; /* sizeof(BUFFPEK)*count will overflow */
486
392
tmp= (unsigned char *)malloc(length);
489
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
395
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
490
396
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
492
398
free((char*) tmp);
534
440
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)
443
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
444
unsigned char **sort_keys,
445
IO_CACHE *buffpek_pointers,
446
IO_CACHE *tempfile, IO_CACHE *indexfile)
543
448
int error,flag,quick_select;
544
449
uint32_t idx,indexpos,ref_length;
545
450
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
internal::my_off_t record;
547
452
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;
453
Session *session= current_session;
454
volatile Session::killed_state *killed= &session->killed;
456
MY_BITMAP *save_read_set, *save_write_set;
554
459
error=quick_select=0;
555
460
sort_form=param->sort_form;
556
file= sort_form->cursor;
461
file=sort_form->file;
557
462
ref_length=param->ref_length;
558
463
ref_pos= ref_buff;
559
464
quick_select=select && select->quick;
561
flag= ((!indexfile && ! file->isOrdered())
466
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
562
467
|| quick_select);
563
468
if (indexfile || flag)
564
469
ref_pos= &file->ref[0];
566
471
if (! indexfile && ! quick_select)
568
473
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);
474
file->ha_rnd_init(1);
475
file->extra_opt(HA_EXTRA_CACHE,
476
current_session->variables.read_buff_size);
574
ReadRecord read_record_info;
479
READ_RECORD read_record_info;
575
480
if (quick_select)
577
482
if (select->quick->reset())
578
483
return(HA_POS_ERROR);
580
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
return(HA_POS_ERROR);
484
init_read_record(&read_record_info, current_session, select->quick->head,
584
488
/* Remember original bitmaps */
585
489
save_read_set= sort_form->read_set;
586
490
save_write_set= sort_form->write_set;
587
491
/* Set up temporary column read map for columns used by sort */
588
sort_form->tmp_set.reset();
492
bitmap_clear_all(&sort_form->tmp_set);
589
493
/* Temporary set for register_used_fields and register_field_in_read_map */
590
494
sort_form->read_set= &sort_form->tmp_set;
591
param->register_used_fields();
495
register_used_fields(param);
592
496
if (select && select->cond)
593
497
select->cond->walk(&Item::register_field_in_read_map, 1,
594
498
(unsigned char*) sort_form);
595
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
499
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
603
507
error= HA_ERR_END_OF_FILE;
606
file->position(sort_form->getInsertRecord());
510
file->position(sort_form->record[0]);
608
512
else /* Not quick-select */
612
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
516
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) /* purecov: deadcode */
614
error= errno ? errno : -1; /* Abort */
518
error= my_errno ? my_errno : -1; /* Abort */
617
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
521
error=file->rnd_pos(sort_form->record[0],next_pos);
621
error=file->rnd_next(sort_form->getInsertRecord());
525
error=file->rnd_next(sort_form->record[0]);
527
update_virtual_fields_marked_for_write(sort_form);
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)); /* purecov: inspected */
593
return(HA_POS_ERROR); /* purecov: inspected */
595
if (indexpos && idx &&
596
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
597
return(HA_POS_ERROR); /* purecov: inspected */
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,
640
goto err; /* purecov: inspected */
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; /* purecov: inspected */
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);
738
/* purecov: begin deadcode */
740
This should only happen during extreme conditions if we run out
741
of memory or have an item marked not null when it can be null.
742
This code is here mainly to avoid a hard crash in this case.
745
memset(to, 0, sort_field->length); // Avoid crash
750
length= res->length();
751
sort_field_length= sort_field->length - sort_field->suffix_length;
752
diff=(int) (sort_field_length - length);
756
length= sort_field_length;
758
if (sort_field->suffix_length)
760
/* Store length last in result_string */
761
store_length(to + sort_field_length, length,
762
sort_field->suffix_length);
764
if (sort_field->need_strxnfrm)
766
char *from=(char*) res->ptr();
768
if ((unsigned char*) from == to)
770
set_if_smaller(length,sort_field->length);
771
memcpy(param->tmp_buffer,from,length);
772
from=param->tmp_buffer;
774
tmp_length= my_strnxfrm(cs,to,sort_field->length,
775
(unsigned char*) from, length);
776
assert(tmp_length == sort_field->length);
780
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
781
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
891
787
int64_t value= item->val_int_result();
790
*to++=1; /* purecov: inspected */
895
791
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);
802
to[7]= (unsigned char) value;
803
to[6]= (unsigned char) (value >> 8);
804
to[5]= (unsigned char) (value >> 16);
805
to[4]= (unsigned char) (value >> 24);
806
to[3]= (unsigned char) (value >> 32);
807
to[2]= (unsigned char) (value >> 40);
808
to[1]= (unsigned char) (value >> 48);
913
809
if (item->unsigned_flag) /* Fix sign */
914
810
to[0]= (unsigned char) (value >> 56);
916
812
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
919
815
case DECIMAL_RESULT:
921
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
817
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
924
820
if (item->null_value)
1017
910
/* Save filepos last */
1018
memcpy(to, ref_pos, (size_t) ref_length);
911
memcpy(to, ref_pos, (size_t) param->ref_length);
1024
fields used by sorting in the sorted table's read set
918
Register fields used by sorting in the sorted table's read set
1027
void SortParam::register_used_fields()
921
static void register_used_fields(SORTPARAM *param)
1029
SortField *sort_field;
1030
Table *table= sort_form;
923
register SORT_FIELD *sort_field;
924
Table *table=param->sort_form;
925
MY_BITMAP *bitmap= table->read_set;
1032
for (sort_field= local_sortorder ;
927
for (sort_field= param->local_sortorder ;
928
sort_field != param->end ;
1037
932
if ((field= sort_field->field))
1039
if (field->getTable() == table)
1040
table->setReadSet(field->position());
934
if (field->table == table)
935
bitmap_set_bit(bitmap, field->field_index);
1064
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
959
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
960
filesort_info_st *table_sort)
962
uint32_t offset,res_length;
1067
963
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++)
965
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
966
res_length= param->res_length;
967
offset= param->rec_length-res_length;
968
if ((ha_rows) count > param->max_rows)
969
count=(uint32_t) param->max_rows;
970
if (!(to= table_sort->record_pointers=
971
(unsigned char*) malloc(res_length*count)))
972
return(1); /* purecov: inspected */
973
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1080
975
memcpy(to, *sort_keys+offset, res_length);
1081
976
to+= res_length;
1088
982
/** 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)
984
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
985
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1093
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
988
IO_CACHE t_file2,*from_file,*to_file,*temp;
1096
991
if (*maxbuffer < MERGEBUFF2)
992
return(0); /* purecov: inspected */
1098
993
if (flush_io_cache(t_file) ||
1099
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
994
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
996
return(1); /* purecov: inspected */
1104
998
from_file= t_file ; to_file= &t_file2;
1105
999
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;
1001
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1003
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1120
1006
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1122
1008
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1009
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1129
1012
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1013
buffpek+i,buffpek+ *maxbuffer,0))
1014
break; /* purecov: inspected */
1135
1015
if (flush_io_cache(to_file))
1016
break; /* purecov: inspected */
1140
1017
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;
1018
setup_io_cache(from_file);
1019
setup_io_cache(to_file);
1020
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1147
to_file->close_cached_file(); // This holds old result
1023
close_cached_file(to_file); // This holds old result
1148
1024
if (to_file == t_file)
1150
1026
*t_file=t_file2; // Copy result file
1151
t_file->setup_io_cache();
1027
setup_io_cache(t_file);
1154
1030
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1162
1038
(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)
1041
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1042
uint32_t rec_length)
1044
register uint32_t count;
1168
1045
uint32_t length;
1170
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1047
if ((count=(uint32_t) cmin((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)
1173
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
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1050
return((uint32_t) -1); /* purecov: inspected */
1051
buffpek->key=buffpek->base;
1052
buffpek->file_pos+= length; /* New filepos */
1053
buffpek->count-= count;
1054
buffpek->mem_count= count;
1180
1056
return (count*rec_length);
1181
1057
} /* 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,
1094
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1095
IO_CACHE *to_file, unsigned char *sort_buffer,
1096
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1228
1100
uint32_t rec_length,res_length,offset;
1229
1101
size_t sort_length;
1230
1102
uint32_t maxcount;
1231
1103
ha_rows max_rows,org_max_rows;
1232
internal::my_off_t to_start_filepos;
1104
my_off_t to_start_filepos;
1233
1105
unsigned char *strpos;
1234
buffpek *buffpek_inst;
1235
1107
qsort2_cmp cmp;
1236
1108
void *first_cmp_arg;
1237
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1238
Session::killed_state_t not_killable;
1109
volatile Session::killed_state *killed= ¤t_session->killed;
1110
Session::killed_state not_killable;
1240
getSession().status_var.filesort_merge_passes++;
1112
status_var_increment(current_session->status_var.filesort_merge_passes);
1241
1113
if (param->not_killable)
1243
1115
killed= ¬_killable;
1267
cmp= internal::get_ptr_compare(sort_length);
1139
cmp= get_ptr_compare(sort_length);
1268
1140
first_cmp_arg= (void*) &sort_length;
1270
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1142
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1271
1143
queue(compare_functor(cmp, first_cmp_arg));
1272
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1144
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,
1146
buffpek->base= strpos;
1147
buffpek->max_keys= maxcount;
1148
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1278
1150
if (error == -1)
1281
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1282
queue.push(buffpek_inst);
1151
goto err; /* purecov: inspected */
1152
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1153
queue.push(buffpek);
1285
1156
if (param->unique_buff)
1292
1163
This is safe as we know that there is always more than one element
1293
1164
in each block to merge (This is guaranteed by the Unique:: algorithm
1295
buffpek_inst= queue.top();
1296
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1297
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key, rec_length))
1166
buffpek= queue.top();
1167
memcpy(param->unique_buff, buffpek->key, rec_length);
1168
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1170
error=1; goto err; /* purecov: inspected */
1301
buffpek_inst->key+= rec_length;
1302
buffpek_inst->mem_count--;
1172
buffpek->key+= rec_length;
1173
buffpek->mem_count--;
1303
1174
if (!--max_rows)
1176
error= 0; /* purecov: inspected */
1177
goto end; /* purecov: inspected */
1308
1179
/* Top element has been used */
1310
queue.push(buffpek_inst);
1181
queue.push(buffpek);
1314
1184
cmp= 0; // Not unique
1317
1186
while (queue.size() > 1)
1190
error= 1; goto err; /* purecov: inspected */
1325
buffpek_inst= queue.top();
1194
buffpek= queue.top();
1326
1195
if (cmp) // Remove duplicates
1328
1197
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
(unsigned char**) &buffpek_inst->key))
1198
(unsigned char**) &buffpek->key))
1330
1199
goto skip_duplicate;
1331
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1200
memcpy(param->unique_buff, buffpek->key, rec_length);
1335
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1204
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1206
error=1; goto err; /* purecov: inspected */
1342
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1211
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1213
error=1; goto err; /* purecov: inspected */
1347
1216
if (!--max_rows)
1218
error= 0; /* purecov: inspected */
1219
goto end; /* purecov: inspected */
1353
1222
skip_duplicate:
1354
buffpek_inst->key+= rec_length;
1355
if (! --buffpek_inst->mem_count)
1223
buffpek->key+= rec_length;
1224
if (! --buffpek->mem_count)
1357
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1226
if (!(error= (int) read_to_buffer(from_file,buffpek,
1361
1230
break; /* One buffer have been removed */
1363
1232
else if (error == -1)
1233
goto err; /* purecov: inspected */
1368
1235
/* Top element has been replaced */
1370
queue.push(buffpek_inst);
1237
queue.push(buffpek);
1373
buffpek_inst= queue.top();
1374
buffpek_inst->base= sort_buffer;
1375
buffpek_inst->max_keys= param->keys;
1240
buffpek= queue.top();
1241
buffpek->base= sort_buffer;
1242
buffpek->max_keys= param->keys;
1378
1245
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))
1250
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;
1252
buffpek->key+= rec_length; // Remove duplicate
1253
--buffpek->mem_count;
1392
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1259
if ((ha_rows) buffpek->mem_count > max_rows)
1393
1260
{ /* Don't write too many records */
1394
buffpek_inst->mem_count= (uint32_t) max_rows;
1395
buffpek_inst->count= 0; /* Don't read more */
1261
buffpek->mem_count= (uint32_t) max_rows;
1262
buffpek->count= 0; /* Don't read more */
1397
max_rows-= buffpek_inst->mem_count;
1264
max_rows-= buffpek->mem_count;
1400
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
(rec_length*buffpek_inst->mem_count)))
1267
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1268
(rec_length*buffpek->mem_count)))
1270
error= 1; goto err; /* purecov: inspected */
1409
strpos= buffpek_inst->key+offset;
1410
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1275
register unsigned char *end;
1276
strpos= buffpek->key+offset;
1277
for (end= strpos+buffpek->mem_count*rec_length ;
1411
1278
strpos != end ;
1412
1279
strpos+= rec_length)
1414
1281
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1422
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1288
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1289
!= -1 && error != 0);
1426
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1292
lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1427
1293
lastbuff->file_pos= to_start_filepos;
1430
1296
} /* merge_buffers */
1433
1299
/* 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)
1301
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1302
BUFFPEK *buffpek, uint32_t maxbuffer,
1303
IO_CACHE *tempfile, IO_CACHE *outfile)
1439
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
buffpek_inst+maxbuffer,1))
1305
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1306
buffpek+maxbuffer,1))
1307
return(1); /* purecov: inspected */
1444
1309
} /* merge_index */
1504
1372
sortorder->result_type= sortorder->item->result_type();
1505
1373
if (sortorder->item->result_as_int64_t())
1506
1374
sortorder->result_type= INT_RESULT;
1508
1375
switch (sortorder->result_type) {
1509
1376
case STRING_RESULT:
1510
sortorder->length=sortorder->item->max_length;
1377
sortorder->length=sortorder->item->max_length;
1511
1378
set_if_smaller(sortorder->length,
1512
getSession().variables.max_sort_length);
1513
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1379
session->variables.max_sort_length);
1380
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1515
1382
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
sortorder->need_strxnfrm= 1;
1517
*multi_byte_charset= 1;
1383
sortorder->need_strxnfrm= 1;
1384
*multi_byte_charset= 1;
1519
1386
else if (cs == &my_charset_bin)
1521
1388
/* Store length last to be able to sort blob/varbinary */
1522
1389
sortorder->suffix_length= suffix_length(sortorder->length);
1523
1390
sortorder->length+= sortorder->suffix_length;
1526
1393
case INT_RESULT:
1527
sortorder->length=8; // Size of intern int64_t
1394
sortorder->length=8; // Size of intern int64_t
1529
1396
case DECIMAL_RESULT:
1530
1397
sortorder->length=
1531
class_decimal_get_binary_size(sortorder->item->max_length -
1398
my_decimal_get_binary_size(sortorder->item->max_length -
1532
1399
(sortorder->item->decimals ? 1 : 0),
1533
1400
sortorder->item->decimals);
1535
1402
case REAL_RESULT:
1536
sortorder->length=sizeof(double);
1403
sortorder->length=sizeof(double);
1538
1405
case ROW_RESULT:
1539
// This case should never be choosen
1407
// This case should never be choosen
1543
1411
if (sortorder->item->maybe_null)
1544
length++; // Place for NULL marker
1412
length++; // Place for NULL marker
1546
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1414
set_if_smaller(sortorder->length,
1415
(size_t)session->variables.max_sort_length);
1547
1416
length+=sortorder->length;
1549
1418
sortorder->field= (Field*) 0; // end marker