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>
50
#include <drizzled/sort_field.h>
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
/* functions defined in this file */
137
static char **make_char_array(char **old_pos, uint32_t fields,
140
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
24
#include <drizzled/server_includes.h>
26
#include <drizzled/drizzled_error_messages.h>
28
/* functions defined in this file */
30
static char **make_char_array(char **old_pos, register uint32_t fields,
31
uint32_t length, myf my_flag);
32
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
34
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
35
unsigned char * *sort_keys, IO_CACHE *buffer_file,
36
IO_CACHE *tempfile,IO_CACHE *indexfile);
37
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
38
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
39
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
40
static void register_used_fields(SORTPARAM *param);
41
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
43
uint32_t maxbuffer,IO_CACHE *tempfile,
45
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
46
filesort_info_st *table_sort);
144
47
static uint32_t suffix_length(uint32_t string_length);
145
static void unpack_addon_fields(sort_addon_field *addon_field,
48
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
49
bool *multi_byte_charset);
50
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
51
uint32_t sortlength, uint32_t *plength);
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
146
53
unsigned char *buff);
148
FileSort::FileSort(Session &arg) :
155
56
Creates a set of pointers that can be used to read the rows
185
87
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)
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
91
SQL_SELECT *select, ha_rows max_rows,
92
bool sort_positions, ha_rows *examined_rows)
193
uint32_t memavl= 0, min_sort_memory;
95
uint32_t memavl, min_sort_memory;
194
96
uint32_t maxbuffer;
195
size_t allocated_sort_memory= 0;
196
buffpek *buffpek_inst= 0;
197
98
ha_rows records= HA_POS_ERROR;
198
99
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;
100
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
204
102
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;
104
filesort_info_st table_sort;
214
105
TableList *tab= table->pos_in_table_list;
215
106
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
217
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
108
DRIZZLE_FILESORT_START();
220
111
Release InnoDB's adaptive hash index latch (if holding) before
223
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
114
ha_release_temporary_latches(thd);
117
Don't use table->sort in filesort as it is also used by
118
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
119
when index_merge select has finished with it.
121
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
122
table->sort.io_cache= NULL;
226
124
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)
125
my_b_clear(&tempfile);
126
my_b_clear(&buffpek_pointers);
129
memset(¶m, 0, sizeof(param));
130
param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
131
param.ref_length= table->file->ref_length;
132
param.addon_field= 0;
133
param.addon_length= 0;
134
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
236
Get the descriptors of all fields whose values are appended
137
Get the descriptors of all fields whose values are appended
237
138
to sorted fields and get its total length in param.spack_length.
239
param.addon_field= get_addon_fields(table->getFields(),
140
param.addon_field= get_addon_fields(thd, table->field,
240
141
param.sort_length,
241
142
¶m.addon_length);
268
168
if (select && select->quick)
270
getSession().status_var.filesort_range_count++;
170
status_var_increment(thd->status_var.filesort_range_count);
274
getSession().status_var.filesort_scan_count++;
174
status_var_increment(thd->status_var.filesort_scan_count);
276
176
#ifdef CAN_TRUST_RANGE
277
177
if (select && select->quick && select->quick->records > 0L)
279
records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
280
table->cursor->stats.records)+EXTRA_RECORDS;
179
records=cmin((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
180
table->file->stats.records)+EXTRA_RECORDS;
281
181
selected_records_file=0;
286
records= table->cursor->estimate_rows_upper_bound();
186
records= table->file->estimate_rows_upper_bound();
288
If number of records is not known, use as much of sort buffer
188
If number of records is not known, use as much of sort buffer
291
191
if (records == HA_POS_ERROR)
292
192
records--; // we use 'records+1' below.
293
193
selected_records_file= 0;
296
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
196
if (multi_byte_charset &&
197
!(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
301
memavl= getSession().variables.sortbuff_size;
302
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
200
memavl= thd->variables.sortbuff_size;
201
min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
202
while (memavl >= min_sort_memory)
305
204
uint32_t old_memavl;
306
205
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));
206
param.keys=(uint32_t) cmin(records+1, keys);
316
207
if ((table_sort.sort_keys=
317
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
param.keys, param.rec_length)))
209
param.keys, param.rec_length, MYF(0))))
321
global_sort_buffer.sub(allocated_sort_memory);
323
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
212
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
213
memavl= min_sort_memory;
326
215
sort_keys= table_sort.sort_keys;
329
218
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)))
221
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
222
DISK_BUFFER_SIZE, MYF(MY_WME)))
338
225
param.keys--; /* TODO: check why we do this */
339
226
param.sort_form= table;
340
227
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)
228
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
229
&tempfile, selected_records_file)) ==
346
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
232
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
348
234
if (maxbuffer == 0) // The whole set is in memory
350
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
236
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
359
243
if (table_sort.buffpek)
360
244
free(table_sort.buffpek);
361
table_sort.buffpek = 0;
245
table_sort.buffpek= 0;
363
247
if (!(table_sort.buffpek=
364
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
248
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
249
table_sort.buffpek)))
368
buffpek_inst= (buffpek *) table_sort.buffpek;
251
buffpek= (BUFFPEK *) table_sort.buffpek;
369
252
table_sort.buffpek_len= maxbuffer;
370
buffpek_pointers.close_cached_file();
253
close_cached_file(&buffpek_pointers);
371
254
/* 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))
255
if (! my_b_inited(outfile) &&
256
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
259
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
383
263
Use also the space previously used by string pointers in sort_buffer
384
264
for temporary key storage.
386
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
266
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
388
268
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))
269
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
272
if (flush_io_cache(&tempfile) ||
273
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
275
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
405
279
if (records > param.max_rows)
407
records= param.max_rows;
280
records=param.max_rows;
412
if (not subselect || not subselect->is_uncacheable())
284
if (param.tmp_buffer)
285
if (param.tmp_buffer)
286
free(param.tmp_buffer);
287
if (!subselect || !subselect->is_uncacheable())
289
if ((unsigned char*) sort_keys)
290
free((unsigned char*) sort_keys);
415
291
table_sort.sort_keys= 0;
292
if ((unsigned char*) buffpek)
293
free((unsigned char*) buffpek);
417
294
table_sort.buffpek= 0;
418
295
table_sort.buffpek_len= 0;
421
tempfile.close_cached_file();
422
buffpek_pointers.close_cached_file();
297
close_cached_file(&tempfile);
298
close_cached_file(&buffpek_pointers);
424
299
if (my_b_inited(outfile))
426
301
if (flush_io_cache(outfile))
431
internal::my_off_t save_pos= outfile->pos_in_file;
304
my_off_t save_pos=outfile->pos_in_file;
432
305
/* For following reads */
433
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
306
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
437
308
outfile->end_of_file=save_pos;
443
312
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
444
313
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);
315
statistic_add(thd->status_var.filesort_rows,
316
(uint32_t) records, &LOCK_status);
317
*examined_rows= param.examined_rows;
318
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
319
DRIZZLE_FILESORT_END();
320
return(error ? HA_POS_ERROR : records);
324
void filesort_free_buffers(Table *table, bool full)
326
if (table->sort.record_pointers)
328
free((unsigned char*) table->sort.record_pointers);
329
table->sort.record_pointers=0;
333
if (table->sort.sort_keys )
335
if ((unsigned char*) table->sort.sort_keys)
336
free((unsigned char*) table->sort.sort_keys);
337
table->sort.sort_keys= 0;
339
if (table->sort.buffpek)
341
if ((unsigned char*) table->sort.buffpek)
342
free((unsigned char*) table->sort.buffpek);
343
table->sort.buffpek= 0;
344
table->sort.buffpek_len= 0;
347
if (table->sort.addon_buf)
349
free((char *) table->sort.addon_buf);
350
free((char *) table->sort.addon_field);
351
table->sort.addon_buf=0;
352
table->sort.addon_field=0;
457
356
/** Make a array of string pointers. */
459
static char **make_char_array(char **old_pos, uint32_t fields,
358
static char **make_char_array(char **old_pos, register uint32_t fields,
359
uint32_t length, myf my_flag)
466
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
468
368
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
469
369
while (fields--) *(pos++) = (char_pos+= length);
476
376
/** Read 'count' number of buffer pointers into memory. */
478
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
378
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
479
379
unsigned char *buf)
481
uint32_t length= sizeof(buffpek)*count;
381
uint32_t length= sizeof(BUFFPEK)*count;
482
382
unsigned char *tmp= buf;
483
if (count > UINT_MAX/sizeof(buffpek))
484
return 0; /* sizeof(buffpek)*count will overflow */
383
if (count > UINT_MAX/sizeof(BUFFPEK))
384
return 0; /* sizeof(BUFFPEK)*count will overflow */
486
tmp= (unsigned char *)malloc(length);
386
tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
489
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
389
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
490
390
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
492
392
free((char*) tmp);
534
434
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)
437
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
438
unsigned char **sort_keys,
439
IO_CACHE *buffpek_pointers,
440
IO_CACHE *tempfile, IO_CACHE *indexfile)
543
442
int error,flag,quick_select;
544
443
uint32_t idx,indexpos,ref_length;
545
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
internal::my_off_t record;
547
446
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;
447
THD *thd= current_thd;
448
volatile THD::killed_state *killed= &thd->killed;
450
MY_BITMAP *save_read_set, *save_write_set;
554
453
error=quick_select=0;
555
454
sort_form=param->sort_form;
556
file= sort_form->cursor;
455
file=sort_form->file;
557
456
ref_length=param->ref_length;
558
457
ref_pos= ref_buff;
559
458
quick_select=select && select->quick;
561
flag= ((!indexfile && ! file->isOrdered())
460
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
562
461
|| quick_select);
563
462
if (indexfile || flag)
564
463
ref_pos= &file->ref[0];
566
465
if (! indexfile && ! quick_select)
568
467
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);
468
file->ha_rnd_init(1);
469
file->extra_opt(HA_EXTRA_CACHE,
470
current_thd->variables.read_buff_size);
574
ReadRecord read_record_info;
473
READ_RECORD read_record_info;
575
474
if (quick_select)
577
476
if (select->quick->reset())
578
477
return(HA_POS_ERROR);
580
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
return(HA_POS_ERROR);
478
init_read_record(&read_record_info, current_thd, select->quick->head,
584
482
/* Remember original bitmaps */
585
483
save_read_set= sort_form->read_set;
586
484
save_write_set= sort_form->write_set;
587
485
/* Set up temporary column read map for columns used by sort */
588
sort_form->tmp_set.reset();
486
bitmap_clear_all(&sort_form->tmp_set);
589
487
/* Temporary set for register_used_fields and register_field_in_read_map */
590
488
sort_form->read_set= &sort_form->tmp_set;
591
param->register_used_fields();
489
register_used_fields(param);
592
490
if (select && select->cond)
593
491
select->cond->walk(&Item::register_field_in_read_map, 1,
594
492
(unsigned char*) sort_form);
595
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
493
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
603
501
error= HA_ERR_END_OF_FILE;
606
file->position(sort_form->getInsertRecord());
504
file->position(sort_form->record[0]);
608
506
else /* Not quick-select */
612
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
510
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) /* purecov: deadcode */
614
error= errno ? errno : -1; /* Abort */
512
error= my_errno ? my_errno : -1; /* Abort */
617
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
515
error=file->rnd_pos(sort_form->record[0],next_pos);
621
error=file->rnd_next(sort_form->getInsertRecord());
519
error=file->rnd_next(sort_form->record[0]);
625
internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
626
record+= sort_form->getShare()->db_record_offset;
522
my_store_ptr(ref_pos,ref_length,record); // Position to row
523
record+= sort_form->s->db_record_offset;
629
file->position(sort_form->getInsertRecord());
526
file->position(sort_form->record[0]);
631
528
if (error && error != HA_ERR_RECORD_DELETED)
669
563
index_merge quick select uses table->sort when retrieving rows, so free
670
564
resoures it has allocated.
672
read_record_info.end_read_record();
566
end_read_record(&read_record_info);
676
570
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
678
file->endTableScan();
681
if (getSession().is_error())
682
576
return(HA_POS_ERROR);
684
578
/* Signal we should use orignal column read and write maps */
685
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
579
sort_form->column_bitmaps_set(save_read_set, save_write_set);
687
581
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);
583
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
584
return(HA_POS_ERROR); /* purecov: inspected */
586
if (indexpos && idx &&
587
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
588
return(HA_POS_ERROR); /* purecov: inspected */
698
589
return(my_b_inited(tempfile) ?
699
590
(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)
618
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
619
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
621
size_t sort_length, rec_length;
731
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
625
sort_length= param->sort_length;
626
rec_length= param->rec_length;
627
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
732
628
if (!my_b_inited(tempfile) &&
733
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
629
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
631
goto err; /* purecov: inspected */
737
632
/* 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)
633
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
743
635
buffpek.file_pos= my_b_tell(tempfile);
744
if ((ha_rows) count > max_rows)
745
count=(uint32_t) max_rows;
636
if ((ha_rows) count > param->max_rows)
637
count=(uint32_t) param->max_rows; /* purecov: inspected */
747
638
buffpek.count=(ha_rows) count;
749
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
639
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
751
640
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
757
642
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
763
648
} /* write_keys */
822
708
Item *item=sort_field->item;
823
709
maybe_null= item->maybe_null;
825
710
switch (sort_field->result_type) {
826
711
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;
713
const CHARSET_INFO * const cs=item->collation.collation;
714
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
716
uint32_t sort_field_length;
720
/* All item->str() to use some extra byte for end null.. */
721
String tmp((char*) to,sort_field->length+4,cs);
722
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);
726
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);
729
/* purecov: begin deadcode */
731
This should only happen during extreme conditions if we run out
732
of memory or have an item marked not null when it can be null.
733
This code is here mainly to avoid a hard crash in this case.
736
memset(to, 0, sort_field->length); // Avoid crash
741
length= res->length();
742
sort_field_length= sort_field->length - sort_field->suffix_length;
743
diff=(int) (sort_field_length - length);
747
length= sort_field_length;
749
if (sort_field->suffix_length)
751
/* Store length last in result_string */
752
store_length(to + sort_field_length, length,
753
sort_field->suffix_length);
755
if (sort_field->need_strxnfrm)
757
char *from=(char*) res->ptr();
759
if ((unsigned char*) from == to)
761
set_if_smaller(length,sort_field->length);
762
memcpy(param->tmp_buffer,from,length);
763
from=param->tmp_buffer;
765
tmp_length= my_strnxfrm(cs,to,sort_field->length,
766
(unsigned char*) from, length);
767
assert(tmp_length == sort_field->length);
771
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
772
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
891
778
int64_t value= item->val_int_result();
781
*to++=1; /* purecov: inspected */
895
782
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);
793
to[7]= (unsigned char) value;
794
to[6]= (unsigned char) (value >> 8);
795
to[5]= (unsigned char) (value >> 16);
796
to[4]= (unsigned char) (value >> 24);
797
to[3]= (unsigned char) (value >> 32);
798
to[2]= (unsigned char) (value >> 40);
799
to[1]= (unsigned char) (value >> 48);
913
800
if (item->unsigned_flag) /* Fix sign */
914
801
to[0]= (unsigned char) (value >> 56);
916
803
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
919
806
case DECIMAL_RESULT:
921
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
808
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
924
811
if (item->null_value)
926
813
memset(to, 0, sort_field->length+1);
932
dec_val->val_binary(E_DEC_FATAL_ERROR, to,
933
item->max_length - (item->decimals ? 1:0),
819
my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
820
item->max_length - (item->decimals ? 1:0),
937
824
case REAL_RESULT:
939
826
double value= item->val_result();
942
829
if (item->null_value)
1017
901
/* Save filepos last */
1018
memcpy(to, ref_pos, (size_t) ref_length);
902
memcpy(to, ref_pos, (size_t) param->ref_length);
1024
fields used by sorting in the sorted table's read set
909
Register fields used by sorting in the sorted table's read set
1027
void SortParam::register_used_fields()
912
static void register_used_fields(SORTPARAM *param)
1029
SortField *sort_field;
1030
Table *table= sort_form;
914
register SORT_FIELD *sort_field;
915
Table *table=param->sort_form;
916
MY_BITMAP *bitmap= table->read_set;
1032
for (sort_field= local_sortorder ;
918
for (sort_field= param->local_sortorder ;
919
sort_field != param->end ;
1037
923
if ((field= sort_field->field))
1039
if (field->getTable() == table)
1040
table->setReadSet(field->position());
925
if (field->table == table)
926
bitmap_set_bit(bitmap, field->field_index);
1064
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
950
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
951
filesort_info_st *table_sort)
953
uint32_t offset,res_length;
1067
954
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++)
956
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
957
res_length= param->res_length;
958
offset= param->rec_length-res_length;
959
if ((ha_rows) count > param->max_rows)
960
count=(uint32_t) param->max_rows;
961
if (!(to= table_sort->record_pointers=
962
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
963
return(1); /* purecov: inspected */
964
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1080
966
memcpy(to, *sort_keys+offset, res_length);
1081
967
to+= res_length;
1088
973
/** 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)
975
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
976
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1093
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
979
IO_CACHE t_file2,*from_file,*to_file,*temp;
1096
982
if (*maxbuffer < MERGEBUFF2)
983
return(0); /* purecov: inspected */
1098
984
if (flush_io_cache(t_file) ||
1099
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
985
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
987
return(1); /* purecov: inspected */
1104
989
from_file= t_file ; to_file= &t_file2;
1105
990
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;
992
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
994
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1120
997
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1122
999
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1000
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1129
1003
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1004
buffpek+i,buffpek+ *maxbuffer,0))
1005
break; /* purecov: inspected */
1135
1006
if (flush_io_cache(to_file))
1007
break; /* purecov: inspected */
1140
1008
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;
1009
setup_io_cache(from_file);
1010
setup_io_cache(to_file);
1011
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1147
to_file->close_cached_file(); // This holds old result
1014
close_cached_file(to_file); // This holds old result
1148
1015
if (to_file == t_file)
1150
1017
*t_file=t_file2; // Copy result file
1151
t_file->setup_io_cache();
1018
setup_io_cache(t_file);
1154
1021
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1162
1029
(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)
1032
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1033
uint32_t rec_length)
1035
register uint32_t count;
1168
1036
uint32_t length;
1170
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1038
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;
1040
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1041
return((uint32_t) -1); /* purecov: inspected */
1042
buffpek->key=buffpek->base;
1043
buffpek->file_pos+= length; /* New filepos */
1044
buffpek->count-= count;
1045
buffpek->mem_count= count;
1180
1047
return (count*rec_length);
1181
1048
} /* read_to_buffer */
1184
class compare_functor
1052
Put all room used by freed buffer to use in adjacent buffer.
1054
Note, that we can't simply distribute memory evenly between all buffers,
1055
because new areas must not overlap with old ones.
1057
@param[in] queue list of non-empty buffers, without freed buffer
1058
@param[in] reuse empty buffer
1059
@param[in] key_length key length
1062
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1186
qsort2_cmp key_compare;
1187
void *key_compare_arg;
1190
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1191
key_compare(in_key_compare),
1192
key_compare_arg(in_compare_arg)
1195
inline bool operator()(const buffpek *i, const buffpek *j) const
1064
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1065
for (uint32_t i= 0; i < queue->elements; ++i)
1197
int val= key_compare(key_compare_arg, &i->key, &j->key);
1067
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1068
if (bp->base + bp->max_keys * key_length == reuse->base)
1070
bp->max_keys+= reuse->max_keys;
1073
else if (bp->base == reuse_end)
1075
bp->base= reuse->base;
1076
bp->max_keys+= reuse->max_keys;
1205
1085
Merge buffers to one buffer.
1207
1087
@param param Sort parameter
1208
@param from_file File with source data (buffpeks point to this file)
1088
@param from_file File with source data (BUFFPEKs point to this file)
1209
1089
@param to_file File to write the sorted result data.
1210
1090
@param sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys.
1211
@param lastbuff OUT Store here buffpek describing data written to to_file
1212
@param Fb First element in source buffpeks array
1213
@param Tb Last element in source buffpeks array
1091
@param lastbuff OUT Store here BUFFPEK describing data written to to_file
1092
@param Fb First element in source BUFFPEKs array
1093
@param Tb Last element in source BUFFPEKs array
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,
1102
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1103
IO_CACHE *to_file, unsigned char *sort_buffer,
1104
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1228
1108
uint32_t rec_length,res_length,offset;
1229
1109
size_t sort_length;
1230
1110
uint32_t maxcount;
1231
1111
ha_rows max_rows,org_max_rows;
1232
internal::my_off_t to_start_filepos;
1112
my_off_t to_start_filepos;
1233
1113
unsigned char *strpos;
1234
buffpek *buffpek_inst;
1235
1116
qsort2_cmp cmp;
1236
1117
void *first_cmp_arg;
1237
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1238
Session::killed_state_t not_killable;
1118
volatile THD::killed_state *killed= ¤t_thd->killed;
1119
THD::killed_state not_killable;
1240
getSession().status_var.filesort_merge_passes++;
1121
status_var_increment(current_thd->status_var.filesort_merge_passes);
1241
1122
if (param->not_killable)
1243
1124
killed= ¬_killable;
1244
not_killable= Session::NOT_KILLED;
1125
not_killable= THD::NOT_KILLED;
1267
cmp= internal::get_ptr_compare(sort_length);
1148
cmp= get_ptr_compare(sort_length);
1268
1149
first_cmp_arg= (void*) &sort_length;
1270
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1271
queue(compare_functor(cmp, first_cmp_arg));
1272
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1151
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1152
(queue_compare) cmp, first_cmp_arg))
1153
return(1); /* purecov: inspected */
1154
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,
1156
buffpek->base= strpos;
1157
buffpek->max_keys= maxcount;
1158
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1278
1160
if (error == -1)
1281
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1282
queue.push(buffpek_inst);
1161
goto err; /* purecov: inspected */
1162
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1163
queue_insert(&queue, (unsigned char*) buffpek);
1285
1166
if (param->unique_buff)
1288
1169
Called by Unique::get()
1289
1170
Copy the first argument to param->unique_buff for unique removal.
1290
1171
Store it also in 'to_file'.
1292
1173
This is safe as we know that there is always more than one element
1293
1174
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))
1176
buffpek= (BUFFPEK*) queue_top(&queue);
1177
memcpy(param->unique_buff, buffpek->key, rec_length);
1178
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1180
error=1; goto err; /* purecov: inspected */
1301
buffpek_inst->key+= rec_length;
1302
buffpek_inst->mem_count--;
1182
buffpek->key+= rec_length;
1183
buffpek->mem_count--;
1303
1184
if (!--max_rows)
1186
error= 0; /* purecov: inspected */
1187
goto end; /* purecov: inspected */
1308
/* Top element has been used */
1310
queue.push(buffpek_inst);
1189
queue_replaced(&queue); // Top element has been used
1314
1192
cmp= 0; // Not unique
1317
while (queue.size() > 1)
1194
while (queue.elements > 1)
1198
error= 1; goto err; /* purecov: inspected */
1325
buffpek_inst= queue.top();
1202
buffpek= (BUFFPEK*) queue_top(&queue);
1326
1203
if (cmp) // Remove duplicates
1328
1205
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
(unsigned char**) &buffpek_inst->key))
1206
(unsigned char**) &buffpek->key))
1330
1207
goto skip_duplicate;
1331
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1208
memcpy(param->unique_buff, buffpek->key, rec_length);
1335
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1212
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1214
error=1; goto err; /* purecov: inspected */
1342
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1219
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1221
error=1; goto err; /* purecov: inspected */
1347
1224
if (!--max_rows)
1226
error= 0; /* purecov: inspected */
1227
goto end; /* purecov: inspected */
1353
1230
skip_duplicate:
1354
buffpek_inst->key+= rec_length;
1355
if (! --buffpek_inst->mem_count)
1231
buffpek->key+= rec_length;
1232
if (! --buffpek->mem_count)
1357
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1234
if (!(error= (int) read_to_buffer(from_file,buffpek,
1237
queue_remove(&queue,0);
1238
reuse_freed_buff(&queue, buffpek, rec_length);
1361
1239
break; /* One buffer have been removed */
1363
1241
else if (error == -1)
1242
goto err; /* purecov: inspected */
1368
/* Top element has been replaced */
1370
queue.push(buffpek_inst);
1244
queue_replaced(&queue); /* Top element has been replaced */
1373
buffpek_inst= queue.top();
1374
buffpek_inst->base= sort_buffer;
1375
buffpek_inst->max_keys= param->keys;
1247
buffpek= (BUFFPEK*) queue_top(&queue);
1248
buffpek->base= sort_buffer;
1249
buffpek->max_keys= param->keys;
1378
1252
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))
1257
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;
1259
buffpek->key+= rec_length; // Remove duplicate
1260
--buffpek->mem_count;
1392
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1266
if ((ha_rows) buffpek->mem_count > max_rows)
1393
1267
{ /* Don't write too many records */
1394
buffpek_inst->mem_count= (uint32_t) max_rows;
1395
buffpek_inst->count= 0; /* Don't read more */
1268
buffpek->mem_count= (uint32_t) max_rows;
1269
buffpek->count= 0; /* Don't read more */
1397
max_rows-= buffpek_inst->mem_count;
1271
max_rows-= buffpek->mem_count;
1400
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
(rec_length*buffpek_inst->mem_count)))
1274
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1275
(rec_length*buffpek->mem_count)))
1277
error= 1; goto err; /* purecov: inspected */
1409
strpos= buffpek_inst->key+offset;
1410
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1282
register unsigned char *end;
1283
strpos= buffpek->key+offset;
1284
for (end= strpos+buffpek->mem_count*rec_length ;
1411
1285
strpos != end ;
1412
1286
strpos+= rec_length)
1414
1288
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1422
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1295
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1296
!= -1 && error != 0);
1426
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1299
lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1427
1300
lastbuff->file_pos= to_start_filepos;
1302
delete_queue(&queue);
1430
1304
} /* merge_buffers */
1433
1307
/* 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)
1309
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1310
BUFFPEK *buffpek, uint32_t maxbuffer,
1311
IO_CACHE *tempfile, IO_CACHE *outfile)
1439
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
buffpek_inst+maxbuffer,1))
1313
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1314
buffpek+maxbuffer,1))
1315
return(1); /* purecov: inspected */
1444
1317
} /* merge_index */
1504
1380
sortorder->result_type= sortorder->item->result_type();
1505
1381
if (sortorder->item->result_as_int64_t())
1506
1382
sortorder->result_type= INT_RESULT;
1508
1383
switch (sortorder->result_type) {
1509
1384
case STRING_RESULT:
1510
sortorder->length=sortorder->item->max_length;
1511
set_if_smaller(sortorder->length,
1512
getSession().variables.max_sort_length);
1513
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1385
sortorder->length=sortorder->item->max_length;
1386
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1387
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1515
1389
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
sortorder->need_strxnfrm= 1;
1517
*multi_byte_charset= 1;
1390
sortorder->need_strxnfrm= 1;
1391
*multi_byte_charset= 1;
1519
1393
else if (cs == &my_charset_bin)
1521
1395
/* Store length last to be able to sort blob/varbinary */
1522
1396
sortorder->suffix_length= suffix_length(sortorder->length);
1523
1397
sortorder->length+= sortorder->suffix_length;
1526
1400
case INT_RESULT:
1527
sortorder->length=8; // Size of intern int64_t
1401
sortorder->length=8; // Size of intern int64_t
1529
1403
case DECIMAL_RESULT:
1530
1404
sortorder->length=
1531
class_decimal_get_binary_size(sortorder->item->max_length -
1405
my_decimal_get_binary_size(sortorder->item->max_length -
1532
1406
(sortorder->item->decimals ? 1 : 0),
1533
1407
sortorder->item->decimals);
1535
1409
case REAL_RESULT:
1536
sortorder->length=sizeof(double);
1410
sortorder->length=sizeof(double);
1538
1412
case ROW_RESULT:
1539
// This case should never be choosen
1414
// This case should never be choosen
1543
1418
if (sortorder->item->maybe_null)
1544
length++; // Place for NULL marker
1419
length++; // Place for NULL marker
1546
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1421
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1547
1422
length+=sortorder->length;
1549
1424
sortorder->field= (Field*) 0; // end marker