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);
36
using namespace drizzled;
133
38
/* functions defined in this file */
135
40
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,
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);
142
57
static uint32_t suffix_length(uint32_t string_length);
143
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,
144
63
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
66
Creates a set of pointers that can be used to read the rows
183
97
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)
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)
191
uint32_t memavl= 0, min_sort_memory;
105
uint32_t memavl, min_sort_memory;
192
106
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
195
108
ha_rows records= HA_POS_ERROR;
196
109
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;
110
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
112
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;
114
filesort_info_st table_sort;
212
115
TableList *tab= table->pos_in_table_list;
213
116
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
215
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
118
DRIZZLE_FILESORT_START(table->s->db.str, table->s->table_name.str);
218
121
Release InnoDB's adaptive hash index latch (if holding) before
221
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;
224
134
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)
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)
234
147
Get the descriptors of all fields whose values are appended
235
148
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
150
param.addon_field= get_addon_fields(session, table->field,
238
151
param.sort_length,
239
152
¶m.addon_length);
291
202
selected_records_file= 0;
294
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)))
299
memavl= getSession().variables.sortbuff_size;
209
memavl= session->variables.sortbuff_size;
300
210
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
211
while (memavl >= min_sort_memory)
303
213
uint32_t old_memavl;
304
214
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
215
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
216
if ((table_sort.sort_keys=
315
217
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
218
param.keys, param.rec_length)))
319
global_sort_buffer.sub(allocated_sort_memory);
320
220
old_memavl= memavl;
321
221
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
222
memavl= min_sort_memory;
327
227
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)))
230
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
231
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
234
param.keys--; /* TODO: check why we do this */
337
235
param.sort_form= table;
338
236
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)
237
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
238
&tempfile, selected_records_file)) ==
344
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
241
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
346
243
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
245
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
357
252
if (table_sort.buffpek)
358
253
free(table_sort.buffpek);
359
table_sort.buffpek = 0;
254
table_sort.buffpek= 0;
361
256
if (!(table_sort.buffpek=
362
(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)))
366
buffpek_inst= (buffpek *) table_sort.buffpek;
260
buffpek= (BUFFPEK *) table_sort.buffpek;
367
261
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
262
close_cached_file(&buffpek_pointers);
369
263
/* 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))
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))
381
272
Use also the space previously used by string pointers in sort_buffer
382
273
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
275
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
277
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))
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,
403
288
if (records > param.max_rows)
405
records= param.max_rows;
289
records=param.max_rows;
410
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);
413
300
table_sort.sort_keys= 0;
301
if ((unsigned char*) buffpek)
302
free((unsigned char*) buffpek);
415
303
table_sort.buffpek= 0;
416
304
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
306
close_cached_file(&tempfile);
307
close_cached_file(&buffpek_pointers);
422
308
if (my_b_inited(outfile))
424
310
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
313
my_off_t save_pos=outfile->pos_in_file;
430
314
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
315
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
435
317
outfile->end_of_file=save_pos;
441
321
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
322
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;
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));
451
328
DRIZZLE_FILESORT_DONE(error, records);
452
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);
455
365
/** Make a array of string pointers. */
457
367
static char **make_char_array(char **old_pos, register uint32_t fields,
474
384
/** Read 'count' number of buffer pointers into memory. */
476
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,
477
387
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
389
uint32_t length= sizeof(BUFFPEK)*count;
480
390
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
391
if (count > UINT_MAX/sizeof(BUFFPEK))
392
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
394
tmp= (unsigned char *)malloc(length);
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
397
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
488
398
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
400
free((char*) tmp);
532
442
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)
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)
541
450
int error,flag,quick_select;
542
451
uint32_t idx,indexpos,ref_length;
543
452
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
internal::my_off_t record;
545
454
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;
455
Session *session= current_session;
456
volatile Session::killed_state *killed= &session->killed;
458
MyBitmap *save_read_set, *save_write_set;
552
461
error=quick_select=0;
553
462
sort_form=param->sort_form;
554
file= sort_form->cursor;
463
file=sort_form->file;
555
464
ref_length=param->ref_length;
556
465
ref_pos= ref_buff;
557
466
quick_select=select && select->quick;
559
flag= ((!indexfile && ! file->isOrdered())
468
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
560
469
|| quick_select);
561
470
if (indexfile || flag)
562
471
ref_pos= &file->ref[0];
564
473
if (! indexfile && ! quick_select)
566
475
next_pos=(unsigned char*) 0; /* Find records in sequence */
567
file->startTableScan(1);
568
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);
571
ReadRecord read_record_info;
481
READ_RECORD read_record_info;
572
482
if (quick_select)
574
484
if (select->quick->reset())
575
485
return(HA_POS_ERROR);
577
read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1);
486
init_read_record(&read_record_info, current_session, select->quick->head,
580
490
/* Remember original bitmaps */
581
491
save_read_set= sort_form->read_set;
582
492
save_write_set= sort_form->write_set;
583
493
/* Set up temporary column read map for columns used by sort */
584
sort_form->tmp_set.reset();
494
sort_form->tmp_set.clearAll();
585
495
/* Temporary set for register_used_fields and register_field_in_read_map */
586
496
sort_form->read_set= &sort_form->tmp_set;
587
param->register_used_fields();
497
register_used_fields(param);
588
498
if (select && select->cond)
589
499
select->cond->walk(&Item::register_field_in_read_map, 1,
590
500
(unsigned char*) sort_form);
591
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);
608
518
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
610
error= errno ? errno : -1; /* Abort */
520
error= my_errno ? my_errno : -1; /* Abort */
613
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
523
error=file->rnd_pos(sort_form->record[0],next_pos);
617
error=file->rnd_next(sort_form->getInsertRecord());
527
error=file->rnd_next(sort_form->record[0]);
621
internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
622
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;
625
file->position(sort_form->getInsertRecord());
535
file->position(sort_form->record[0]);
627
537
if (error && error != HA_ERR_RECORD_DELETED)
665
572
index_merge quick select uses table->sort when retrieving rows, so free
666
573
resoures it has allocated.
668
read_record_info.end_read_record();
575
end_read_record(&read_record_info);
672
579
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
674
file->endTableScan();
677
if (getSession().is_error())
584
if (session->is_error())
678
585
return(HA_POS_ERROR);
680
587
/* Signal we should use orignal column read and write maps */
681
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
588
sort_form->column_bitmaps_set(save_read_set, save_write_set);
683
590
if (error != HA_ERR_END_OF_FILE)
685
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
686
return(HA_POS_ERROR);
689
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
691
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);
694
598
return(my_b_inited(tempfile) ?
695
599
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
722
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
723
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;
727
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);
728
637
if (!my_b_inited(tempfile) &&
729
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,
733
641
/* check we won't have more buffpeks than we can possibly keep in memory */
734
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)
739
644
buffpek.file_pos= my_b_tell(tempfile);
740
if ((ha_rows) count > max_rows)
741
count=(uint32_t) max_rows;
645
if ((ha_rows) count > param->max_rows)
646
count=(uint32_t) param->max_rows;
743
647
buffpek.count=(ha_rows) count;
745
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
648
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
747
649
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
753
651
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
759
657
} /* write_keys */
818
717
Item *item=sort_field->item;
819
718
maybe_null= item->maybe_null;
821
719
switch (sort_field->result_type) {
822
720
case STRING_RESULT:
824
const CHARSET_INFO * const cs=item->collation.collation;
825
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
827
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);
831
/* All item->str() to use some extra byte for end null.. */
832
String tmp((char*) to,sort_field->length+4,cs);
833
String *res= item->str_result(&tmp);
837
memset(to-1, 0, sort_field->length+1);
841
This should only happen during extreme conditions if we run out
842
of memory or have an item marked not null when it can be null.
843
This code is here mainly to avoid a hard crash in this case.
846
memset(to, 0, sort_field->length); // Avoid crash
850
length= res->length();
851
sort_field_length= sort_field->length - sort_field->suffix_length;
852
diff=(int) (sort_field_length - length);
856
length= sort_field_length;
858
if (sort_field->suffix_length)
860
/* Store length last in result_string */
861
store_length(to + sort_field_length, length,
862
sort_field->suffix_length);
864
if (sort_field->need_strxnfrm)
866
char *from=(char*) res->ptr();
868
if ((unsigned char*) from == to)
870
set_if_smaller(length,sort_field->length);
871
memcpy(tmp_buffer,from,length);
874
tmp_length= my_strnxfrm(cs,to,sort_field->length,
875
(unsigned char*) from, length);
876
assert(tmp_length == sort_field->length);
735
memset(to-1, 0, sort_field->length+1);
880
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
881
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);
887
785
int64_t value= item->val_int_result();
891
789
if (item->null_value)
902
to[7]= (unsigned char) value;
903
to[6]= (unsigned char) (value >> 8);
904
to[5]= (unsigned char) (value >> 16);
905
to[4]= (unsigned char) (value >> 24);
906
to[3]= (unsigned char) (value >> 32);
907
to[2]= (unsigned char) (value >> 40);
908
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);
909
807
if (item->unsigned_flag) /* Fix sign */
910
808
to[0]= (unsigned char) (value >> 56);
912
810
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
915
813
case DECIMAL_RESULT:
917
815
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
1060
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;
1063
960
unsigned char *to;
1065
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1066
offset= rec_length - res_length;
1068
if ((ha_rows) count > max_rows)
1069
count=(uint32_t) max_rows;
1071
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1074
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++)
1076
972
memcpy(to, *sort_keys+offset, res_length);
1077
973
to+= res_length;
1084
979
/** Merge buffers to make < MERGEBUFF2 buffers. */
1086
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1087
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)
1089
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
985
IO_CACHE t_file2,*from_file,*to_file,*temp;
1092
988
if (*maxbuffer < MERGEBUFF2)
1094
990
if (flush_io_cache(t_file) ||
1095
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,
1100
995
from_file= t_file ; to_file= &t_file2;
1101
996
while (*maxbuffer >= MERGEBUFF2)
1103
register uint32_t i;
1105
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1110
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1115
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))
1116
1003
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1118
1005
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1119
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1006
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1125
1009
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1126
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1010
buffpek+i,buffpek+ *maxbuffer,0))
1131
1012
if (flush_io_cache(to_file))
1136
1014
temp=from_file; from_file=to_file; to_file=temp;
1137
from_file->setup_io_cache();
1138
to_file->setup_io_cache();
1139
*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;
1143
to_file->close_cached_file(); // This holds old result
1020
close_cached_file(to_file); // This holds old result
1144
1021
if (to_file == t_file)
1146
1023
*t_file=t_file2; // Copy result file
1147
t_file->setup_io_cache();
1024
setup_io_cache(t_file);
1150
1027
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1158
1035
(uint32_t)-1 if something goes wrong
1161
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)
1163
1041
register uint32_t count;
1164
1042
uint32_t length;
1166
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)))
1168
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)
1169
1047
return((uint32_t) -1);
1171
buffpek_inst->key= buffpek_inst->base;
1172
buffpek_inst->file_pos+= length; /* New filepos */
1173
buffpek_inst->count-= count;
1174
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;
1176
1054
return (count*rec_length);
1177
1055
} /* read_to_buffer */
1218
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1219
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1220
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,
1224
1098
uint32_t rec_length,res_length,offset;
1225
1099
size_t sort_length;
1226
1100
uint32_t maxcount;
1227
1101
ha_rows max_rows,org_max_rows;
1228
internal::my_off_t to_start_filepos;
1102
my_off_t to_start_filepos;
1229
1103
unsigned char *strpos;
1230
buffpek *buffpek_inst;
1231
1105
qsort2_cmp cmp;
1232
1106
void *first_cmp_arg;
1233
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1234
Session::killed_state_t not_killable;
1107
volatile Session::killed_state *killed= ¤t_session->killed;
1108
Session::killed_state not_killable;
1236
getSession().status_var.filesort_merge_passes++;
1110
status_var_increment(current_session->status_var.filesort_merge_passes);
1237
1111
if (param->not_killable)
1239
1113
killed= ¬_killable;
1263
cmp= internal::get_ptr_compare(sort_length);
1137
cmp= get_ptr_compare(sort_length);
1264
1138
first_cmp_arg= (void*) &sort_length;
1266
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1140
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1267
1141
queue(compare_functor(cmp, first_cmp_arg));
1268
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1142
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1270
buffpek_inst->base= strpos;
1271
buffpek_inst->max_keys= maxcount;
1272
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,
1274
1148
if (error == -1)
1277
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1278
queue.push(buffpek_inst);
1150
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1151
queue.push(buffpek);
1281
1154
if (param->unique_buff)
1304
1177
/* Top element has been used */
1306
queue.push(buffpek_inst);
1179
queue.push(buffpek);
1310
1182
cmp= 0; // Not unique
1313
1184
while (queue.size() > 1)
1321
buffpek_inst= queue.top();
1192
buffpek= queue.top();
1322
1193
if (cmp) // Remove duplicates
1324
1195
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1325
(unsigned char**) &buffpek_inst->key))
1196
(unsigned char**) &buffpek->key))
1326
1197
goto skip_duplicate;
1327
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1198
memcpy(param->unique_buff, buffpek->key, rec_length);
1331
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))
1338
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))
1343
1214
if (!--max_rows)
1349
1220
skip_duplicate:
1350
buffpek_inst->key+= rec_length;
1351
if (! --buffpek_inst->mem_count)
1221
buffpek->key+= rec_length;
1222
if (! --buffpek->mem_count)
1353
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1224
if (!(error= (int) read_to_buffer(from_file,buffpek,
1357
1228
break; /* One buffer have been removed */
1359
1230
else if (error == -1)
1364
1233
/* Top element has been replaced */
1366
queue.push(buffpek_inst);
1235
queue.push(buffpek);
1369
buffpek_inst= queue.top();
1370
buffpek_inst->base= sort_buffer;
1371
buffpek_inst->max_keys= param->keys;
1238
buffpek= queue.top();
1239
buffpek->base= sort_buffer;
1240
buffpek->max_keys= param->keys;
1374
1243
As we know all entries in the buffer are unique, we only have to
1379
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))
1381
buffpek_inst->key+= rec_length; // Remove duplicate
1382
--buffpek_inst->mem_count;
1250
buffpek->key+= rec_length; // Remove duplicate
1251
--buffpek->mem_count;
1388
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1257
if ((ha_rows) buffpek->mem_count > max_rows)
1389
1258
{ /* Don't write too many records */
1390
buffpek_inst->mem_count= (uint32_t) max_rows;
1391
buffpek_inst->count= 0; /* Don't read more */
1259
buffpek->mem_count= (uint32_t) max_rows;
1260
buffpek->count= 0; /* Don't read more */
1393
max_rows-= buffpek_inst->mem_count;
1262
max_rows-= buffpek->mem_count;
1396
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1397
(rec_length*buffpek_inst->mem_count)))
1265
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1266
(rec_length*buffpek->mem_count)))
1404
1273
register unsigned char *end;
1405
strpos= buffpek_inst->key+offset;
1406
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1274
strpos= buffpek->key+offset;
1275
for (end= strpos+buffpek->mem_count*rec_length ;
1407
1276
strpos != end ;
1408
1277
strpos+= rec_length)
1410
1279
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1418
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1286
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1419
1287
!= -1 && error != 0);
1422
1290
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1423
1291
lastbuff->file_pos= to_start_filepos;
1426
1294
} /* merge_buffers */
1429
1297
/* Do a merge to output-file (save only positions) */
1431
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1432
buffpek *buffpek_inst, uint32_t maxbuffer,
1433
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)
1435
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1436
buffpek_inst+maxbuffer,1))
1303
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1304
buffpek+maxbuffer,1))
1440
1307
} /* merge_index */
1500
1370
sortorder->result_type= sortorder->item->result_type();
1501
1371
if (sortorder->item->result_as_int64_t())
1502
1372
sortorder->result_type= INT_RESULT;
1504
1373
switch (sortorder->result_type) {
1505
1374
case STRING_RESULT:
1506
sortorder->length=sortorder->item->max_length;
1375
sortorder->length=sortorder->item->max_length;
1507
1376
set_if_smaller(sortorder->length,
1508
getSession().variables.max_sort_length);
1509
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1377
session->variables.max_sort_length);
1378
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1511
1380
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1512
sortorder->need_strxnfrm= 1;
1513
*multi_byte_charset= 1;
1381
sortorder->need_strxnfrm= 1;
1382
*multi_byte_charset= 1;
1515
1384
else if (cs == &my_charset_bin)
1517
1386
/* Store length last to be able to sort blob/varbinary */
1518
1387
sortorder->suffix_length= suffix_length(sortorder->length);
1519
1388
sortorder->length+= sortorder->suffix_length;
1522
1391
case INT_RESULT:
1523
sortorder->length=8; // Size of intern int64_t
1392
sortorder->length=8; // Size of intern int64_t
1525
1394
case DECIMAL_RESULT:
1526
1395
sortorder->length=
1527
1396
my_decimal_get_binary_size(sortorder->item->max_length -