24
#include <drizzled/server_includes.h>
25
#include <drizzled/sql_sort.h>
26
#include <drizzled/error.h>
27
#include <drizzled/probes.h>
28
#include <drizzled/session.h>
29
#include <drizzled/table.h>
30
#include <drizzled/table_list.h>
30
33
#include <algorithm>
33
#include "drizzled/drizzled.h"
34
#include "drizzled/sql_sort.h"
35
#include "drizzled/filesort.h"
36
#include "drizzled/error.h"
37
#include "drizzled/probes.h"
38
#include "drizzled/session.h"
39
#include "drizzled/table.h"
40
#include "drizzled/table_list.h"
41
#include "drizzled/optimizer/range.h"
42
#include "drizzled/records.h"
43
#include "drizzled/internal/iocache.h"
44
#include "drizzled/internal/my_sys.h"
45
#include "plugin/myisam/myisam.h"
46
#include "drizzled/plugin/transactional_storage_engine.h"
47
#include "drizzled/atomics.h"
48
#include "drizzled/global_buffer.h"
51
35
using namespace std;
56
/* Defines used by filesort and uniques */
60
class BufferCompareContext
63
qsort_cmp2 key_compare;
64
void *key_compare_arg;
66
BufferCompareContext() :
75
uint32_t rec_length; /* Length of sorted records */
76
uint32_t sort_length; /* Length of sorted columns */
77
uint32_t ref_length; /* Length of record ref. */
78
uint32_t addon_length; /* Length of added packed fields */
79
uint32_t res_length; /* Length of records in final sorted file/buffer */
80
uint32_t keys; /* Max keys / buffer */
81
ha_rows max_rows,examined_rows;
82
Table *sort_form; /* For quicker make_sortkey */
83
SortField *local_sortorder;
85
sort_addon_field *addon_field; /* Descriptors for companion fields */
86
unsigned char *unique_buff;
89
/* The fields below are used only by Unique class */
91
BufferCompareContext cmp_context;
119
int write_keys(unsigned char * *sort_keys,
121
internal::IO_CACHE *buffer_file,
122
internal::IO_CACHE *tempfile);
124
void make_sortkey(unsigned char *to,
125
unsigned char *ref_pos);
126
void register_used_fields();
127
bool save_index(unsigned char **sort_keys,
129
filesort_info *table_sort);
133
37
/* functions defined in this file */
135
39
static char **make_char_array(char **old_pos, register uint32_t fields,
138
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);
142
56
static uint32_t suffix_length(uint32_t string_length);
143
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,
144
62
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
65
Creates a set of pointers that can be used to read the rows
183
96
examined_rows will be set to number of examined rows
186
ha_rows FileSort::run(Table *table, SortField *sortorder, uint32_t s_length,
187
optimizer::SqlSelect *select, ha_rows max_rows,
188
bool sort_positions, ha_rows &examined_rows)
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)
191
uint32_t memavl= 0, min_sort_memory;
104
uint32_t memavl, min_sort_memory;
192
105
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
195
107
ha_rows records= HA_POS_ERROR;
196
108
unsigned char **sort_keys= 0;
197
internal::IO_CACHE tempfile;
198
internal::IO_CACHE buffpek_pointers;
199
internal::IO_CACHE *selected_records_file;
200
internal::IO_CACHE *outfile;
109
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
111
bool multi_byte_charset;
205
Don't use table->sort in filesort as it is also used by
206
QuickIndexMergeSelect. Work with a copy and put it back at the end
207
when index_merge select has finished with it.
209
filesort_info table_sort(table->sort);
210
table->sort.io_cache= NULL;
113
filesort_info_st table_sort;
212
114
TableList *tab= table->pos_in_table_list;
213
115
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
215
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
117
DRIZZLE_FILESORT_START();
218
120
Release InnoDB's adaptive hash index latch (if holding) before
221
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;
224
133
outfile= table_sort.io_cache;
225
assert(tempfile.buffer == 0);
226
assert(buffpek_pointers.buffer == 0);
228
param.sort_length= sortlength(sortorder, s_length, &multi_byte_charset);
229
param.ref_length= table->cursor->ref_length;
231
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)
234
146
Get the descriptors of all fields whose values are appended
235
147
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
149
param.addon_field= get_addon_fields(session, table->field,
238
150
param.sort_length,
239
151
¶m.addon_length);
291
201
selected_records_file= 0;
294
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)))
299
memavl= getSession().variables.sortbuff_size;
208
memavl= session->variables.sortbuff_size;
300
209
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
210
while (memavl >= min_sort_memory)
303
212
uint32_t old_memavl;
304
213
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
214
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
307
allocated_sort_memory= param.keys * param.rec_length;
308
if (not global_sort_buffer.add(allocated_sort_memory))
310
my_error(ER_OUT_OF_GLOBAL_SORTMEMORY, MYF(ME_ERROR+ME_WAITTANG));
314
215
if ((table_sort.sort_keys=
315
216
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
217
param.keys, param.rec_length)))
319
global_sort_buffer.sub(allocated_sort_memory);
320
219
old_memavl= memavl;
321
220
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
221
memavl= min_sort_memory;
327
226
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
331
if (buffpek_pointers.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
229
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
230
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
233
param.keys--; /* TODO: check why we do this */
337
234
param.sort_form= table;
338
235
param.end=(param.local_sortorder=sortorder)+s_length;
339
if ((records= find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
340
&tempfile, selected_records_file)) == HA_POS_ERROR)
236
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
237
&tempfile, selected_records_file)) ==
344
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
240
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
346
242
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
244
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
357
251
if (table_sort.buffpek)
358
252
free(table_sort.buffpek);
359
table_sort.buffpek = 0;
253
table_sort.buffpek= 0;
361
255
if (!(table_sort.buffpek=
362
(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)))
366
buffpek_inst= (buffpek *) table_sort.buffpek;
259
buffpek= (BUFFPEK *) table_sort.buffpek;
367
260
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
261
close_cached_file(&buffpek_pointers);
369
262
/* Open cached file if it isn't open */
370
if (! my_b_inited(outfile) && outfile->open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME)))
375
if (outfile->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
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))
381
271
Use also the space previously used by string pointers in sort_buffer
382
272
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
274
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
276
maxbuffer--; // Offset from 0
387
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
392
if (flush_io_cache(&tempfile) || tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
397
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek_inst,maxbuffer,&tempfile, outfile))
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,
403
287
if (records > param.max_rows)
405
records= param.max_rows;
288
records=param.max_rows;
410
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);
413
299
table_sort.sort_keys= 0;
300
if ((unsigned char*) buffpek)
301
free((unsigned char*) buffpek);
415
302
table_sort.buffpek= 0;
416
303
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
305
close_cached_file(&tempfile);
306
close_cached_file(&buffpek_pointers);
422
307
if (my_b_inited(outfile))
424
309
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
312
my_off_t save_pos=outfile->pos_in_file;
430
313
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
314
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
435
316
outfile->end_of_file=save_pos;
441
320
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
321
MYF(ME_ERROR+ME_WAITTANG));
446
getSession().status_var.filesort_rows+= (uint32_t) records;
448
examined_rows= param.examined_rows;
449
global_sort_buffer.sub(allocated_sort_memory);
450
table->sort= table_sort;
451
DRIZZLE_FILESORT_DONE(error, records);
452
return (error ? HA_POS_ERROR : records);
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));
327
DRIZZLE_FILESORT_END();
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);
455
364
/** Make a array of string pointers. */
457
366
static char **make_char_array(char **old_pos, register uint32_t fields,
474
383
/** Read 'count' number of buffer pointers into memory. */
476
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,
477
386
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
388
uint32_t length= sizeof(BUFFPEK)*count;
480
389
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
390
if (count > UINT_MAX/sizeof(BUFFPEK))
391
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
393
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
396
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
488
397
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
399
free((char*) tmp);
532
441
HA_POS_ERROR on error.
535
ha_rows FileSort::find_all_keys(SortParam *param,
536
optimizer::SqlSelect *select,
537
unsigned char **sort_keys,
538
internal::IO_CACHE *buffpek_pointers,
539
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
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)
541
449
int error,flag,quick_select;
542
450
uint32_t idx,indexpos,ref_length;
543
451
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
internal::my_off_t record;
545
453
Table *sort_form;
546
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
548
boost::dynamic_bitset<> *save_read_set= NULL;
549
boost::dynamic_bitset<> *save_write_set= NULL;
454
Session *session= current_session;
455
volatile Session::killed_state *killed= &session->killed;
457
MY_BITMAP *save_read_set, *save_write_set;
552
460
error=quick_select=0;
553
461
sort_form=param->sort_form;
554
file= sort_form->cursor;
462
file=sort_form->file;
555
463
ref_length=param->ref_length;
556
464
ref_pos= ref_buff;
557
465
quick_select=select && select->quick;
559
flag= ((!indexfile && ! file->isOrdered())
467
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
560
468
|| quick_select);
561
469
if (indexfile || flag)
562
470
ref_pos= &file->ref[0];
564
472
if (! indexfile && ! quick_select)
566
474
next_pos=(unsigned char*) 0; /* Find records in sequence */
567
if (file->startTableScan(1))
568
return(HA_POS_ERROR);
569
file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
475
file->ha_rnd_init(1);
476
file->extra_opt(HA_EXTRA_CACHE,
477
current_session->variables.read_buff_size);
572
ReadRecord read_record_info;
480
READ_RECORD read_record_info;
573
481
if (quick_select)
575
483
if (select->quick->reset())
576
484
return(HA_POS_ERROR);
578
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
return(HA_POS_ERROR);
485
init_read_record(&read_record_info, current_session, select->quick->head,
582
489
/* Remember original bitmaps */
583
490
save_read_set= sort_form->read_set;
584
491
save_write_set= sort_form->write_set;
585
492
/* Set up temporary column read map for columns used by sort */
586
sort_form->tmp_set.reset();
493
bitmap_clear_all(&sort_form->tmp_set);
587
494
/* Temporary set for register_used_fields and register_field_in_read_map */
588
495
sort_form->read_set= &sort_form->tmp_set;
589
param->register_used_fields();
496
register_used_fields(param);
590
497
if (select && select->cond)
591
498
select->cond->walk(&Item::register_field_in_read_map, 1,
592
499
(unsigned char*) sort_form);
593
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);
601
508
error= HA_ERR_END_OF_FILE;
604
file->position(sort_form->getInsertRecord());
511
file->position(sort_form->record[0]);
606
513
else /* Not quick-select */
610
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
517
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) /* purecov: deadcode */
612
error= errno ? errno : -1; /* Abort */
519
error= my_errno ? my_errno : -1; /* Abort */
615
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
522
error=file->rnd_pos(sort_form->record[0],next_pos);
619
error=file->rnd_next(sort_form->getInsertRecord());
526
error=file->rnd_next(sort_form->record[0]);
623
internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
624
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;
627
file->position(sort_form->getInsertRecord());
534
file->position(sort_form->record[0]);
629
536
if (error && error != HA_ERR_RECORD_DELETED)
667
571
index_merge quick select uses table->sort when retrieving rows, so free
668
572
resoures it has allocated.
670
read_record_info.end_read_record();
574
end_read_record(&read_record_info);
674
578
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
676
file->endTableScan();
679
if (getSession().is_error())
583
if (session->is_error())
680
584
return(HA_POS_ERROR);
682
586
/* Signal we should use orignal column read and write maps */
683
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
587
sort_form->column_bitmaps_set(save_read_set, save_write_set);
685
589
if (error != HA_ERR_END_OF_FILE)
687
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
return(HA_POS_ERROR);
691
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
693
return(HA_POS_ERROR);
591
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
592
return(HA_POS_ERROR); /* purecov: inspected */
594
if (indexpos && idx &&
595
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
596
return(HA_POS_ERROR); /* purecov: inspected */
696
597
return(my_b_inited(tempfile) ?
697
598
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
724
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
725
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
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;
729
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);
730
636
if (!my_b_inited(tempfile) &&
731
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,
639
goto err; /* purecov: inspected */
735
640
/* check we won't have more buffpeks than we can possibly keep in memory */
736
if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
641
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
741
643
buffpek.file_pos= my_b_tell(tempfile);
742
if ((ha_rows) count > max_rows)
743
count=(uint32_t) max_rows;
644
if ((ha_rows) count > param->max_rows)
645
count=(uint32_t) param->max_rows; /* purecov: inspected */
745
646
buffpek.count=(ha_rows) count;
747
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
647
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
648
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
755
650
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
761
656
} /* write_keys */
820
716
Item *item=sort_field->item;
821
717
maybe_null= item->maybe_null;
823
718
switch (sort_field->result_type) {
824
719
case STRING_RESULT:
826
const CHARSET_INFO * const cs=item->collation.collation;
827
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
829
uint32_t sort_field_length;
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);
833
/* All item->str() to use some extra byte for end null.. */
834
String tmp((char*) to,sort_field->length+4,cs);
835
String *res= item->str_result(&tmp);
839
memset(to-1, 0, sort_field->length+1);
843
This should only happen during extreme conditions if we run out
844
of memory or have an item marked not null when it can be null.
845
This code is here mainly to avoid a hard crash in this case.
848
memset(to, 0, sort_field->length); // Avoid crash
852
length= res->length();
853
sort_field_length= sort_field->length - sort_field->suffix_length;
854
diff=(int) (sort_field_length - length);
858
length= sort_field_length;
860
if (sort_field->suffix_length)
862
/* Store length last in result_string */
863
store_length(to + sort_field_length, length,
864
sort_field->suffix_length);
866
if (sort_field->need_strxnfrm)
868
char *from=(char*) res->ptr();
870
if ((unsigned char*) from == to)
872
set_if_smaller(length,sort_field->length);
873
memcpy(tmp_buffer,from,length);
876
tmp_length= my_strnxfrm(cs,to,sort_field->length,
877
(unsigned char*) from, length);
878
assert(tmp_length == sort_field->length);
734
memset(to-1, 0, sort_field->length+1);
882
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
883
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
737
/* purecov: begin deadcode */
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
749
length= res->length();
750
sort_field_length= sort_field->length - sort_field->suffix_length;
751
diff=(int) (sort_field_length - length);
755
length= sort_field_length;
757
if (sort_field->suffix_length)
759
/* Store length last in result_string */
760
store_length(to + sort_field_length, length,
761
sort_field->suffix_length);
763
if (sort_field->need_strxnfrm)
765
char *from=(char*) res->ptr();
767
if ((unsigned char*) from == to)
769
set_if_smaller(length,sort_field->length);
770
memcpy(param->tmp_buffer,from,length);
771
from=param->tmp_buffer;
773
tmp_length= my_strnxfrm(cs,to,sort_field->length,
774
(unsigned char*) from, length);
775
assert(tmp_length == sort_field->length);
779
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
780
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
889
786
int64_t value= item->val_int_result();
789
*to++=1; /* purecov: inspected */
893
790
if (item->null_value)
904
to[7]= (unsigned char) value;
905
to[6]= (unsigned char) (value >> 8);
906
to[5]= (unsigned char) (value >> 16);
907
to[4]= (unsigned char) (value >> 24);
908
to[3]= (unsigned char) (value >> 32);
909
to[2]= (unsigned char) (value >> 40);
910
to[1]= (unsigned char) (value >> 48);
801
to[7]= (unsigned char) value;
802
to[6]= (unsigned char) (value >> 8);
803
to[5]= (unsigned char) (value >> 16);
804
to[4]= (unsigned char) (value >> 24);
805
to[3]= (unsigned char) (value >> 32);
806
to[2]= (unsigned char) (value >> 40);
807
to[1]= (unsigned char) (value >> 48);
911
808
if (item->unsigned_flag) /* Fix sign */
912
809
to[0]= (unsigned char) (value >> 56);
914
811
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
814
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
816
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
819
if (item->null_value)
1062
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
957
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
958
filesort_info_st *table_sort)
960
uint32_t offset,res_length;
1065
961
unsigned char *to;
1067
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1068
offset= rec_length - res_length;
1070
if ((ha_rows) count > max_rows)
1071
count=(uint32_t) max_rows;
1073
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1076
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
963
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
964
res_length= param->res_length;
965
offset= param->rec_length-res_length;
966
if ((ha_rows) count > param->max_rows)
967
count=(uint32_t) param->max_rows;
968
if (!(to= table_sort->record_pointers=
969
(unsigned char*) malloc(res_length*count)))
970
return(1); /* purecov: inspected */
971
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1078
973
memcpy(to, *sort_keys+offset, res_length);
1079
974
to+= res_length;
1086
980
/** Merge buffers to make < MERGEBUFF2 buffers. */
1088
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1089
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
982
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
983
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1091
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
986
IO_CACHE t_file2,*from_file,*to_file,*temp;
1094
989
if (*maxbuffer < MERGEBUFF2)
990
return(0); /* purecov: inspected */
1096
991
if (flush_io_cache(t_file) ||
1097
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
992
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
994
return(1); /* purecov: inspected */
1102
996
from_file= t_file ; to_file= &t_file2;
1103
997
while (*maxbuffer >= MERGEBUFF2)
1105
register uint32_t i;
1107
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1112
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1117
lastbuff=buffpek_inst;
999
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1001
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1118
1004
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1120
1006
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1007
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1127
1010
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1011
buffpek+i,buffpek+ *maxbuffer,0))
1012
break; /* purecov: inspected */
1133
1013
if (flush_io_cache(to_file))
1014
break; /* purecov: inspected */
1138
1015
temp=from_file; from_file=to_file; to_file=temp;
1139
from_file->setup_io_cache();
1140
to_file->setup_io_cache();
1141
*maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
1016
setup_io_cache(from_file);
1017
setup_io_cache(to_file);
1018
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1145
to_file->close_cached_file(); // This holds old result
1021
close_cached_file(to_file); // This holds old result
1146
1022
if (to_file == t_file)
1148
1024
*t_file=t_file2; // Copy result file
1149
t_file->setup_io_cache();
1025
setup_io_cache(t_file);
1152
1028
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1160
1036
(uint32_t)-1 if something goes wrong
1163
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
1039
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1040
uint32_t rec_length)
1165
1042
register uint32_t count;
1166
1043
uint32_t length;
1168
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1045
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1170
if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
1171
return((uint32_t) -1);
1047
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1048
return((uint32_t) -1); /* purecov: inspected */
1173
buffpek_inst->key= buffpek_inst->base;
1174
buffpek_inst->file_pos+= length; /* New filepos */
1175
buffpek_inst->count-= count;
1176
buffpek_inst->mem_count= count;
1050
buffpek->key= buffpek->base;
1051
buffpek->file_pos+= length; /* New filepos */
1052
buffpek->count-= count;
1053
buffpek->mem_count= count;
1178
1055
return (count*rec_length);
1179
1056
} /* read_to_buffer */
1220
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1221
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1222
buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1093
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1094
IO_CACHE *to_file, unsigned char *sort_buffer,
1095
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1226
1099
uint32_t rec_length,res_length,offset;
1227
1100
size_t sort_length;
1228
1101
uint32_t maxcount;
1229
1102
ha_rows max_rows,org_max_rows;
1230
internal::my_off_t to_start_filepos;
1103
my_off_t to_start_filepos;
1231
1104
unsigned char *strpos;
1232
buffpek *buffpek_inst;
1233
1106
qsort2_cmp cmp;
1234
1107
void *first_cmp_arg;
1235
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1236
Session::killed_state_t not_killable;
1108
volatile Session::killed_state *killed= ¤t_session->killed;
1109
Session::killed_state not_killable;
1238
getSession().status_var.filesort_merge_passes++;
1111
status_var_increment(current_session->status_var.filesort_merge_passes);
1239
1112
if (param->not_killable)
1241
1114
killed= ¬_killable;
1265
cmp= internal::get_ptr_compare(sort_length);
1138
cmp= get_ptr_compare(sort_length);
1266
1139
first_cmp_arg= (void*) &sort_length;
1268
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1141
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1269
1142
queue(compare_functor(cmp, first_cmp_arg));
1270
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1143
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1272
buffpek_inst->base= strpos;
1273
buffpek_inst->max_keys= maxcount;
1274
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
1145
buffpek->base= strpos;
1146
buffpek->max_keys= maxcount;
1147
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1276
1149
if (error == -1)
1279
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1280
queue.push(buffpek_inst);
1150
goto err; /* purecov: inspected */
1151
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1152
queue.push(buffpek);
1283
1155
if (param->unique_buff)
1290
1162
This is safe as we know that there is always more than one element
1291
1163
in each block to merge (This is guaranteed by the Unique:: algorithm
1293
buffpek_inst= queue.top();
1294
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1295
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key, rec_length))
1165
buffpek= queue.top();
1166
memcpy(param->unique_buff, buffpek->key, rec_length);
1167
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1169
error=1; goto err; /* purecov: inspected */
1299
buffpek_inst->key+= rec_length;
1300
buffpek_inst->mem_count--;
1171
buffpek->key+= rec_length;
1172
buffpek->mem_count--;
1301
1173
if (!--max_rows)
1175
error= 0; /* purecov: inspected */
1176
goto end; /* purecov: inspected */
1306
1178
/* Top element has been used */
1308
queue.push(buffpek_inst);
1180
queue.push(buffpek);
1312
1183
cmp= 0; // Not unique
1315
1185
while (queue.size() > 1)
1189
error= 1; goto err; /* purecov: inspected */
1323
buffpek_inst= queue.top();
1193
buffpek= queue.top();
1324
1194
if (cmp) // Remove duplicates
1326
1196
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
(unsigned char**) &buffpek_inst->key))
1197
(unsigned char**) &buffpek->key))
1328
1198
goto skip_duplicate;
1329
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1199
memcpy(param->unique_buff, buffpek->key, rec_length);
1333
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1203
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1205
error=1; goto err; /* purecov: inspected */
1340
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1210
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1212
error=1; goto err; /* purecov: inspected */
1345
1215
if (!--max_rows)
1217
error= 0; /* purecov: inspected */
1218
goto end; /* purecov: inspected */
1351
1221
skip_duplicate:
1352
buffpek_inst->key+= rec_length;
1353
if (! --buffpek_inst->mem_count)
1222
buffpek->key+= rec_length;
1223
if (! --buffpek->mem_count)
1355
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1225
if (!(error= (int) read_to_buffer(from_file,buffpek,
1359
1229
break; /* One buffer have been removed */
1361
1231
else if (error == -1)
1232
goto err; /* purecov: inspected */
1366
1234
/* Top element has been replaced */
1368
queue.push(buffpek_inst);
1236
queue.push(buffpek);
1371
buffpek_inst= queue.top();
1372
buffpek_inst->base= sort_buffer;
1373
buffpek_inst->max_keys= param->keys;
1239
buffpek= queue.top();
1240
buffpek->base= sort_buffer;
1241
buffpek->max_keys= param->keys;
1376
1244
As we know all entries in the buffer are unique, we only have to
1381
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
1249
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1383
buffpek_inst->key+= rec_length; // Remove duplicate
1384
--buffpek_inst->mem_count;
1251
buffpek->key+= rec_length; // Remove duplicate
1252
--buffpek->mem_count;
1390
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1258
if ((ha_rows) buffpek->mem_count > max_rows)
1391
1259
{ /* Don't write too many records */
1392
buffpek_inst->mem_count= (uint32_t) max_rows;
1393
buffpek_inst->count= 0; /* Don't read more */
1260
buffpek->mem_count= (uint32_t) max_rows;
1261
buffpek->count= 0; /* Don't read more */
1395
max_rows-= buffpek_inst->mem_count;
1263
max_rows-= buffpek->mem_count;
1398
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
(rec_length*buffpek_inst->mem_count)))
1266
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1267
(rec_length*buffpek->mem_count)))
1269
error= 1; goto err; /* purecov: inspected */
1406
1274
register unsigned char *end;
1407
strpos= buffpek_inst->key+offset;
1408
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1275
strpos= buffpek->key+offset;
1276
for (end= strpos+buffpek->mem_count*rec_length ;
1409
1277
strpos != end ;
1410
1278
strpos+= rec_length)
1412
1280
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1420
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1287
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1288
!= -1 && error != 0);
1424
1291
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1425
1292
lastbuff->file_pos= to_start_filepos;
1428
1295
} /* merge_buffers */
1431
1298
/* Do a merge to output-file (save only positions) */
1433
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1434
buffpek *buffpek_inst, uint32_t maxbuffer,
1435
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1300
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1301
BUFFPEK *buffpek, uint32_t maxbuffer,
1302
IO_CACHE *tempfile, IO_CACHE *outfile)
1437
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
buffpek_inst+maxbuffer,1))
1304
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1305
buffpek+maxbuffer,1))
1306
return(1); /* purecov: inspected */
1442
1308
} /* merge_index */
1502
1371
sortorder->result_type= sortorder->item->result_type();
1503
1372
if (sortorder->item->result_as_int64_t())
1504
1373
sortorder->result_type= INT_RESULT;
1506
1374
switch (sortorder->result_type) {
1507
1375
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1376
sortorder->length=sortorder->item->max_length;
1509
1377
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1378
session->variables.max_sort_length);
1379
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1381
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1382
sortorder->need_strxnfrm= 1;
1383
*multi_byte_charset= 1;
1517
1385
else if (cs == &my_charset_bin)
1519
1387
/* Store length last to be able to sort blob/varbinary */
1520
1388
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1389
sortorder->length+= sortorder->suffix_length;
1524
1392
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1393
sortorder->length=8; // Size of intern int64_t
1527
1395
case DECIMAL_RESULT:
1528
1396
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1397
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1398
(sortorder->item->decimals ? 1 : 0),
1531
1399
sortorder->item->decimals);
1533
1401
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1402
sortorder->length=sizeof(double);
1536
1404
case ROW_RESULT:
1537
// This case should never be choosen
1406
// This case should never be choosen
1541
1410
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1411
length++; // Place for NULL marker
1544
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1413
set_if_smaller(sortorder->length,
1414
(size_t)session->variables.max_sort_length);
1545
1415
length+=sortorder->length;
1547
1417
sortorder->field= (Field*) 0; // end marker