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,
144
static uint32_t suffix_length(uint32_t string_length);
145
static void unpack_addon_fields(sort_addon_field *addon_field,
146
unsigned char *buff);
148
FileSort::FileSort(Session &arg) :
24
#include "mysql_priv.h"
28
/// How to write record_ref.
29
#define WRITE_REF(file,from) \
30
if (my_b_write((file),(uchar*) (from),param->ref_length)) \
33
/* functions defined in this file */
35
static char **make_char_array(char **old_pos, register uint fields,
36
uint length, myf my_flag);
37
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
39
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
40
uchar * *sort_keys, IO_CACHE *buffer_file,
41
IO_CACHE *tempfile,IO_CACHE *indexfile);
42
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
43
uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
44
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
45
static void register_used_fields(SORTPARAM *param);
46
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
48
uint maxbuffer,IO_CACHE *tempfile,
50
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count,
51
FILESORT_INFO *table_sort);
52
static uint suffix_length(ulong string_length);
53
static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
54
bool *multi_byte_charset);
55
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
56
uint sortlength, uint *plength);
57
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
155
61
Creates a set of pointers that can be used to read the rows
185
92
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)
95
ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
96
SQL_SELECT *select, ha_rows max_rows,
97
bool sort_positions, ha_rows *examined_rows)
193
uint32_t memavl= 0, min_sort_memory;
195
size_t allocated_sort_memory= 0;
196
buffpek *buffpek_inst= 0;
100
ulong memavl, min_sort_memory;
197
103
ha_rows records= HA_POS_ERROR;
198
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;
104
uchar **sort_keys= 0;
105
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
204
107
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;
214
TableList *tab= table->pos_in_table_list;
109
FILESORT_INFO table_sort;
110
TABLE_LIST *tab= table->pos_in_table_list;
215
111
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
217
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
113
MYSQL_FILESORT_START();
220
116
Release InnoDB's adaptive hash index latch (if holding) before
223
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
119
ha_release_temporary_latches(thd);
122
Don't use table->sort in filesort as it is also used by
123
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
124
when index_merge select has finished with it.
126
memcpy(&table_sort, &table->sort, sizeof(FILESORT_INFO));
127
table->sort.io_cache= NULL;
226
129
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)
130
my_b_clear(&tempfile);
131
my_b_clear(&buffpek_pointers);
134
bzero((char*) ¶m,sizeof(param));
135
param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
136
param.ref_length= table->file->ref_length;
137
param.addon_field= 0;
138
param.addon_length= 0;
139
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
236
Get the descriptors of all fields whose values are appended
142
Get the descriptors of all fields whose values are appended
237
143
to sorted fields and get its total length in param.spack_length.
239
param.addon_field= get_addon_fields(table->getFields(),
145
param.addon_field= get_addon_fields(thd, table->field,
240
146
param.sort_length,
241
147
¶m.addon_length);
268
173
if (select && select->quick)
270
getSession().status_var.filesort_range_count++;
175
status_var_increment(thd->status_var.filesort_range_count);
274
getSession().status_var.filesort_scan_count++;
179
status_var_increment(thd->status_var.filesort_scan_count);
276
181
#ifdef CAN_TRUST_RANGE
277
182
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;
184
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
185
table->file->stats.records)+EXTRA_RECORDS;
281
186
selected_records_file=0;
286
records= table->cursor->estimate_rows_upper_bound();
191
records= table->file->estimate_rows_upper_bound();
288
If number of records is not known, use as much of sort buffer
193
If number of records is not known, use as much of sort buffer
291
196
if (records == HA_POS_ERROR)
292
197
records--; // we use 'records+1' below.
293
198
selected_records_file= 0;
296
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
201
if (multi_byte_charset &&
202
!(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);
205
memavl= thd->variables.sortbuff_size;
206
min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
207
while (memavl >= min_sort_memory)
306
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));
210
ulong keys= memavl/(param.rec_length+sizeof(char*));
211
param.keys=(uint) min(records+1, keys);
316
212
if ((table_sort.sort_keys=
317
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
param.keys, param.rec_length)))
213
(uchar **) make_char_array((char **) table_sort.sort_keys,
214
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)
217
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
218
memavl= min_sort_memory;
326
220
sort_keys= table_sort.sort_keys;
329
223
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)))
226
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
227
DISK_BUFFER_SIZE, MYF(MY_WME)))
338
230
param.keys--; /* TODO: check why we do this */
339
231
param.sort_form= table;
340
232
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)
233
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
234
&tempfile, selected_records_file)) ==
346
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
237
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
348
239
if (maxbuffer == 0) // The whole set is in memory
350
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
241
if (save_index(¶m,sort_keys,(uint) records, &table_sort))
357
246
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
359
if (table_sort.buffpek)
360
free(table_sort.buffpek);
361
table_sort.buffpek = 0;
248
x_free(table_sort.buffpek);
249
table_sort.buffpek= 0;
363
251
if (!(table_sort.buffpek=
364
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
252
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
253
table_sort.buffpek)))
368
buffpek_inst= (buffpek *) table_sort.buffpek;
255
buffpek= (BUFFPEK *) table_sort.buffpek;
369
256
table_sort.buffpek_len= maxbuffer;
370
buffpek_pointers.close_cached_file();
257
close_cached_file(&buffpek_pointers);
371
258
/* 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))
259
if (! my_b_inited(outfile) &&
260
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
263
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
383
267
Use also the space previously used by string pointers in sort_buffer
384
268
for temporary key storage.
386
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
270
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
388
272
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))
273
if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer,
276
if (flush_io_cache(&tempfile) ||
277
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
279
if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
405
283
if (records > param.max_rows)
407
records= param.max_rows;
284
records=param.max_rows;
412
if (not subselect || not subselect->is_uncacheable())
288
if (param.tmp_buffer)
289
x_free(param.tmp_buffer);
290
if (!subselect || !subselect->is_uncacheable())
292
x_free((uchar*) sort_keys);
415
293
table_sort.sort_keys= 0;
294
x_free((uchar*) buffpek);
417
295
table_sort.buffpek= 0;
418
296
table_sort.buffpek_len= 0;
421
tempfile.close_cached_file();
422
buffpek_pointers.close_cached_file();
298
close_cached_file(&tempfile);
299
close_cached_file(&buffpek_pointers);
424
300
if (my_b_inited(outfile))
426
302
if (flush_io_cache(outfile))
431
internal::my_off_t save_pos= outfile->pos_in_file;
305
my_off_t save_pos=outfile->pos_in_file;
432
306
/* For following reads */
433
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
307
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
437
309
outfile->end_of_file=save_pos;
443
313
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
444
314
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);
316
statistic_add(thd->status_var.filesort_rows,
317
(ulong) records, &LOCK_status);
318
*examined_rows= param.examined_rows;
319
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
320
MYSQL_FILESORT_END();
321
return(error ? HA_POS_ERROR : records);
325
void filesort_free_buffers(TABLE *table, bool full)
327
if (table->sort.record_pointers)
329
my_free((uchar*) table->sort.record_pointers,MYF(0));
330
table->sort.record_pointers=0;
334
if (table->sort.sort_keys )
336
x_free((uchar*) table->sort.sort_keys);
337
table->sort.sort_keys= 0;
339
if (table->sort.buffpek)
341
x_free((uchar*) table->sort.buffpek);
342
table->sort.buffpek= 0;
343
table->sort.buffpek_len= 0;
346
if (table->sort.addon_buf)
348
my_free((char *) table->sort.addon_buf, MYF(0));
349
my_free((char *) table->sort.addon_field, MYF(MY_ALLOW_ZERO_PTR));
350
table->sort.addon_buf=0;
351
table->sort.addon_field=0;
457
355
/** Make a array of string pointers. */
459
static char **make_char_array(char **old_pos, uint32_t fields,
357
static char **make_char_array(char **old_pos, register uint fields,
358
uint length, myf my_flag)
466
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
364
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
468
367
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
469
368
while (fields--) *(pos++) = (char_pos+= length);
534
433
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)
436
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
438
IO_CACHE *buffpek_pointers,
439
IO_CACHE *tempfile, IO_CACHE *indexfile)
543
441
int error,flag,quick_select;
544
uint32_t idx,indexpos,ref_length;
545
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
internal::my_off_t record;
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;
442
uint idx,indexpos,ref_length;
443
uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
446
THD *thd= current_thd;
447
volatile THD::killed_state *killed= &thd->killed;
449
MY_BITMAP *save_read_set, *save_write_set;
554
452
error=quick_select=0;
555
453
sort_form=param->sort_form;
556
file= sort_form->cursor;
454
file=sort_form->file;
557
455
ref_length=param->ref_length;
558
456
ref_pos= ref_buff;
559
457
quick_select=select && select->quick;
561
flag= ((!indexfile && ! file->isOrdered())
459
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
562
460
|| quick_select);
563
461
if (indexfile || flag)
564
462
ref_pos= &file->ref[0];
565
463
next_pos=ref_pos;
566
464
if (! indexfile && ! quick_select)
568
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);
466
next_pos=(uchar*) 0; /* Find records in sequence */
467
file->ha_rnd_init(1);
468
file->extra_opt(HA_EXTRA_CACHE,
469
current_thd->variables.read_buff_size);
574
ReadRecord read_record_info;
472
READ_RECORD read_record_info;
575
473
if (quick_select)
577
475
if (select->quick->reset())
578
476
return(HA_POS_ERROR);
580
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
return(HA_POS_ERROR);
477
init_read_record(&read_record_info, current_thd, select->quick->head,
584
481
/* Remember original bitmaps */
585
482
save_read_set= sort_form->read_set;
586
483
save_write_set= sort_form->write_set;
587
484
/* Set up temporary column read map for columns used by sort */
588
sort_form->tmp_set.reset();
485
bitmap_clear_all(&sort_form->tmp_set);
589
486
/* Temporary set for register_used_fields and register_field_in_read_map */
590
487
sort_form->read_set= &sort_form->tmp_set;
591
param->register_used_fields();
488
register_used_fields(param);
592
489
if (select && select->cond)
593
490
select->cond->walk(&Item::register_field_in_read_map, 1,
594
(unsigned char*) sort_form);
595
sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
492
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
726
int SortParam::write_keys(unsigned char **sort_keys, uint32_t count,
727
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
617
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
618
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
620
size_t sort_length, rec_length;
731
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
624
sort_length= param->sort_length;
625
rec_length= param->rec_length;
626
my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
732
627
if (!my_b_inited(tempfile) &&
733
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
628
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
630
goto err; /* purecov: inspected */
737
631
/* 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)
632
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
743
634
buffpek.file_pos= my_b_tell(tempfile);
744
if ((ha_rows) count > max_rows)
745
count=(uint32_t) max_rows;
635
if ((ha_rows) count > param->max_rows)
636
count=(uint) param->max_rows; /* purecov: inspected */
747
637
buffpek.count=(ha_rows) count;
749
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
751
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
757
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
638
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
639
if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
641
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
763
647
} /* write_keys */
822
707
Item *item=sort_field->item;
823
708
maybe_null= item->maybe_null;
825
709
switch (sort_field->result_type) {
826
710
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;
712
CHARSET_INFO *cs=item->collation.collation;
713
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
715
uint sort_field_length;
719
/* All item->str() to use some extra byte for end null.. */
720
String tmp((char*) to,sort_field->length+4,cs);
721
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);
725
bzero((char*) to-1,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);
728
/* purecov: begin deadcode */
730
This should only happen during extreme conditions if we run out
731
of memory or have an item marked not null when it can be null.
732
This code is here mainly to avoid a hard crash in this case.
735
bzero((char*) to,sort_field->length); // Avoid crash
740
length= res->length();
741
sort_field_length= sort_field->length - sort_field->suffix_length;
742
diff=(int) (sort_field_length - length);
746
length= sort_field_length;
748
if (sort_field->suffix_length)
750
/* Store length last in result_string */
751
store_length(to + sort_field_length, length,
752
sort_field->suffix_length);
754
if (sort_field->need_strxnfrm)
756
char *from=(char*) res->ptr();
758
if ((uchar*) from == to)
760
set_if_smaller(length,sort_field->length);
761
memcpy(param->tmp_buffer,from,length);
762
from=param->tmp_buffer;
764
tmp_length= my_strnxfrm(cs,to,sort_field->length,
765
(uchar*) from, length);
766
assert(tmp_length == sort_field->length);
770
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
771
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
891
777
int64_t value= item->val_int_result();
780
*to++=1; /* purecov: inspected */
895
781
if (item->null_value)
898
memset(to-1, 0, sort_field->length+1);
784
bzero((char*) to-1,sort_field->length+1);
901
memset(to, 0, sort_field->length);
787
bzero((char*) to,sort_field->length);
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);
913
if (item->unsigned_flag) /* Fix sign */
914
to[0]= (unsigned char) (value >> 56);
916
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
792
#if SIZEOF_LONG_LONG > 4
793
to[7]= (uchar) value;
794
to[6]= (uchar) (value >> 8);
795
to[5]= (uchar) (value >> 16);
796
to[4]= (uchar) (value >> 24);
797
to[3]= (uchar) (value >> 32);
798
to[2]= (uchar) (value >> 40);
799
to[1]= (uchar) (value >> 48);
800
if (item->unsigned_flag) /* Fix sign */
801
to[0]= (uchar) (value >> 56);
803
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
805
to[3]= (uchar) value;
806
to[2]= (uchar) (value >> 8);
807
to[1]= (uchar) (value >> 16);
808
if (item->unsigned_flag) /* Fix sign */
809
to[0]= (uchar) (value >> 24);
811
to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
919
815
case DECIMAL_RESULT:
921
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
817
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
924
820
if (item->null_value)
926
memset(to, 0, sort_field->length+1);
822
bzero((char*)to, sort_field->length+1);
932
dec_val->val_binary(E_DEC_FATAL_ERROR, to,
933
item->max_length - (item->decimals ? 1:0),
828
my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
829
item->max_length - (item->decimals ? 1:0),
937
833
case REAL_RESULT:
939
835
double value= item->val_result();
942
838
if (item->null_value)
944
memset(to, 0, sort_field->length+1);
840
bzero((char*) to,sort_field->length+1);
950
change_double_for_sort(value,(unsigned char*) to);
846
change_double_for_sort(value,(uchar*) to);
955
// This case should never be choosen
851
// This case should never be choosen
961
856
if (sort_field->reverse)
962
857
{ /* Revers key */
965
860
length=sort_field->length;
968
*to = (unsigned char) (~ *to);
863
*to = (uchar) (~ *to);
974
868
to+= sort_field->length;
871
if (param->addon_field)
981
874
Save field values appended to sorted fields.
982
875
First null bit indicators are appended then field values follow.
983
876
In this implementation we use fixed layout for field values -
984
877
the same for all records.
986
sort_addon_field *addonf= addon_field;
987
unsigned char *nulls= to;
879
SORT_ADDON_FIELD *addonf= param->addon_field;
988
881
assert(addonf != 0);
989
memset(nulls, 0, addonf->offset);
882
bzero((char *) nulls, addonf->offset);
990
883
to+= addonf->offset;
991
884
for ( ; (field= addonf->field) ; addonf++)
993
886
if (addonf->null_bit && field->is_null())
995
888
nulls[addonf->null_offset]|= addonf->null_bit;
997
memset(to, 0, addonf->length);
890
bzero(to, addonf->length);
1002
#ifdef HAVE_VALGRIND
1003
unsigned char *end= field->pack(to, field->ptr);
1004
uint32_t local_length= (uint32_t) ((to + addonf->length) - end);
1005
assert((int) local_length >= 0);
1007
memset(end, 0, local_length);
896
uchar *end= field->pack(to, field->ptr);
897
uint length= (uint) ((to + addonf->length) - end);
898
assert((int) length >= 0);
1009
902
(void) field->pack(to, field->ptr);
1017
910
/* Save filepos last */
1018
memcpy(to, ref_pos, (size_t) ref_length);
911
memcpy((uchar*) to, ref_pos, (size_t) param->ref_length);
1024
fields used by sorting in the sorted table's read set
918
Register fields used by sorting in the sorted table's read set
1027
void SortParam::register_used_fields()
921
static void register_used_fields(SORTPARAM *param)
1029
SortField *sort_field;
1030
Table *table= sort_form;
923
register SORT_FIELD *sort_field;
924
TABLE *table=param->sort_form;
925
MY_BITMAP *bitmap= table->read_set;
1032
for (sort_field= local_sortorder ;
927
for (sort_field= param->local_sortorder ;
928
sort_field != param->end ;
1037
932
if ((field= sort_field->field))
1039
if (field->getTable() == table)
1040
table->setReadSet(field->position());
934
if (field->table == table)
935
bitmap_set_bit(bitmap, field->field_index);
1044
939
sort_field->item->walk(&Item::register_field_in_read_map, 1,
1045
(unsigned char *) table);
944
if (param->addon_field)
1051
sort_addon_field *addonf= addon_field;
946
SORT_ADDON_FIELD *addonf= param->addon_field;
1053
948
for ( ; (field= addonf->field) ; addonf++)
1054
table->setReadSet(field->position());
949
bitmap_set_bit(bitmap, field->field_index);
1064
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
959
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
960
FILESORT_INFO *table_sort)
1069
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1070
offset= rec_length - res_length;
1072
if ((ha_rows) count > max_rows)
1073
count=(uint32_t) max_rows;
1075
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1078
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
962
uint offset,res_length;
965
my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
966
res_length= param->res_length;
967
offset= param->rec_length-res_length;
968
if ((ha_rows) count > param->max_rows)
969
count=(uint) param->max_rows;
970
if (!(to= table_sort->record_pointers=
971
(uchar*) my_malloc(res_length*count, MYF(MY_WME))))
972
return(1); /* purecov: inspected */
973
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1080
975
memcpy(to, *sort_keys+offset, res_length);
1081
976
to+= res_length;
1088
982
/** Merge buffers to make < MERGEBUFF2 buffers. */
1090
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1091
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
984
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
985
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
1093
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
988
IO_CACHE t_file2,*from_file,*to_file,*temp;
1096
991
if (*maxbuffer < MERGEBUFF2)
992
return(0); /* purecov: inspected */
1098
993
if (flush_io_cache(t_file) ||
1099
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
994
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
996
return(1); /* purecov: inspected */
1104
998
from_file= t_file ; to_file= &t_file2;
1105
999
while (*maxbuffer >= MERGEBUFF2)
1109
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1114
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1119
lastbuff=buffpek_inst;
1001
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1003
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1120
1006
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1122
1008
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1009
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1129
1012
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1013
buffpek+i,buffpek+ *maxbuffer,0))
1014
break; /* purecov: inspected */
1135
1015
if (flush_io_cache(to_file))
1016
break; /* purecov: inspected */
1140
1017
temp=from_file; from_file=to_file; to_file=temp;
1141
from_file->setup_io_cache();
1142
to_file->setup_io_cache();
1143
*maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
1018
setup_io_cache(from_file);
1019
setup_io_cache(to_file);
1020
*maxbuffer= (uint) (lastbuff-buffpek)-1;
1147
to_file->close_cached_file(); // This holds old result
1023
close_cached_file(to_file); // This holds old result
1148
1024
if (to_file == t_file)
1150
1026
*t_file=t_file2; // Copy result file
1151
t_file->setup_io_cache();
1027
setup_io_cache(t_file);
1154
1030
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1159
1035
Read data to buffer.
1162
(uint32_t)-1 if something goes wrong
1038
(uint)-1 if something goes wrong
1165
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
1041
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1044
register uint count;
1170
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1047
if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
1172
if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
1173
return((uint32_t) -1);
1175
buffpek_inst->key= buffpek_inst->base;
1176
buffpek_inst->file_pos+= length; /* New filepos */
1177
buffpek_inst->count-= count;
1178
buffpek_inst->mem_count= count;
1049
if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1050
return((uint) -1); /* purecov: inspected */
1051
buffpek->key=buffpek->base;
1052
buffpek->file_pos+= length; /* New filepos */
1053
buffpek->count-= count;
1054
buffpek->mem_count= count;
1180
1056
return (count*rec_length);
1181
1057
} /* read_to_buffer */
1184
class compare_functor
1061
Put all room used by freed buffer to use in adjacent buffer.
1063
Note, that we can't simply distribute memory evenly between all buffers,
1064
because new areas must not overlap with old ones.
1066
@param[in] queue list of non-empty buffers, without freed buffer
1067
@param[in] reuse empty buffer
1068
@param[in] key_length key length
1071
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint 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
1073
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1074
for (uint i= 0; i < queue->elements; ++i)
1197
int val= key_compare(key_compare_arg, &i->key, &j->key);
1076
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1077
if (bp->base + bp->max_keys * key_length == reuse->base)
1079
bp->max_keys+= reuse->max_keys;
1082
else if (bp->base == reuse_end)
1084
bp->base= reuse->base;
1085
bp->max_keys+= reuse->max_keys;
1205
1094
Merge buffers to one buffer.
1207
1096
@param param Sort parameter
1208
@param from_file File with source data (buffpeks point to this file)
1097
@param from_file File with source data (BUFFPEKs point to this file)
1209
1098
@param to_file File to write the sorted result data.
1210
1099
@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
1100
@param lastbuff OUT Store here BUFFPEK describing data written to to_file
1101
@param Fb First element in source BUFFPEKs array
1102
@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,
1111
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1112
IO_CACHE *to_file, uchar *sort_buffer,
1113
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1228
uint32_t rec_length,res_length,offset;
1117
uint rec_length,res_length,offset;
1229
1118
size_t sort_length;
1231
1120
ha_rows max_rows,org_max_rows;
1232
internal::my_off_t to_start_filepos;
1233
unsigned char *strpos;
1234
buffpek *buffpek_inst;
1121
my_off_t to_start_filepos;
1235
1125
qsort2_cmp cmp;
1236
1126
void *first_cmp_arg;
1237
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1238
Session::killed_state_t not_killable;
1127
volatile THD::killed_state *killed= ¤t_thd->killed;
1128
THD::killed_state not_killable;
1240
getSession().status_var.filesort_merge_passes++;
1130
status_var_increment(current_thd->status_var.filesort_merge_passes);
1241
1131
if (param->not_killable)
1243
1133
killed= ¬_killable;
1244
not_killable= Session::NOT_KILLED;
1134
not_killable= THD::NOT_KILLED;
1267
cmp= internal::get_ptr_compare(sort_length);
1157
cmp= get_ptr_compare(sort_length);
1268
1158
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++)
1160
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1161
(queue_compare) cmp, first_cmp_arg))
1162
return(1); /* purecov: inspected */
1163
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,
1165
buffpek->base= strpos;
1166
buffpek->max_keys= maxcount;
1167
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
1278
1169
if (error == -1)
1281
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1282
queue.push(buffpek_inst);
1170
goto err; /* purecov: inspected */
1171
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1172
queue_insert(&queue, (uchar*) buffpek);
1285
1175
if (param->unique_buff)
1288
1178
Called by Unique::get()
1289
1179
Copy the first argument to param->unique_buff for unique removal.
1290
1180
Store it also in 'to_file'.
1292
1182
This is safe as we know that there is always more than one element
1293
1183
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))
1185
buffpek= (BUFFPEK*) queue_top(&queue);
1186
memcpy(param->unique_buff, buffpek->key, rec_length);
1187
if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
1189
error=1; goto err; /* purecov: inspected */
1301
buffpek_inst->key+= rec_length;
1302
buffpek_inst->mem_count--;
1191
buffpek->key+= rec_length;
1192
buffpek->mem_count--;
1303
1193
if (!--max_rows)
1195
error= 0; /* purecov: inspected */
1196
goto end; /* purecov: inspected */
1308
/* Top element has been used */
1310
queue.push(buffpek_inst);
1198
queue_replaced(&queue); // Top element has been used
1314
1201
cmp= 0; // Not unique
1317
while (queue.size() > 1)
1203
while (queue.elements > 1)
1207
error= 1; goto err; /* purecov: inspected */
1325
buffpek_inst= queue.top();
1211
buffpek= (BUFFPEK*) queue_top(&queue);
1326
1212
if (cmp) // Remove duplicates
1328
1214
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
(unsigned char**) &buffpek_inst->key))
1215
(uchar**) &buffpek->key))
1330
1216
goto skip_duplicate;
1331
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1217
memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length);
1335
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1221
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1223
error=1; goto err; /* purecov: inspected */
1342
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1228
if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1230
error=1; goto err; /* purecov: inspected */
1347
1233
if (!--max_rows)
1235
error= 0; /* purecov: inspected */
1236
goto end; /* purecov: inspected */
1353
1239
skip_duplicate:
1354
buffpek_inst->key+= rec_length;
1355
if (! --buffpek_inst->mem_count)
1240
buffpek->key+= rec_length;
1241
if (! --buffpek->mem_count)
1357
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1243
if (!(error= (int) read_to_buffer(from_file,buffpek,
1246
VOID(queue_remove(&queue,0));
1247
reuse_freed_buff(&queue, buffpek, rec_length);
1361
1248
break; /* One buffer have been removed */
1363
1250
else if (error == -1)
1251
goto err; /* purecov: inspected */
1368
/* Top element has been replaced */
1370
queue.push(buffpek_inst);
1253
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;
1256
buffpek= (BUFFPEK*) queue_top(&queue);
1257
buffpek->base= sort_buffer;
1258
buffpek->max_keys= param->keys;
1378
1261
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))
1266
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
1385
buffpek_inst->key+= rec_length; // Remove duplicate
1386
--buffpek_inst->mem_count;
1268
buffpek->key+= rec_length; // Remove duplicate
1269
--buffpek->mem_count;
1392
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1275
if ((ha_rows) buffpek->mem_count > max_rows)
1393
1276
{ /* Don't write too many records */
1394
buffpek_inst->mem_count= (uint32_t) max_rows;
1395
buffpek_inst->count= 0; /* Don't read more */
1277
buffpek->mem_count= (uint) max_rows;
1278
buffpek->count= 0; /* Don't read more */
1397
max_rows-= buffpek_inst->mem_count;
1280
max_rows-= buffpek->mem_count;
1400
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
(rec_length*buffpek_inst->mem_count)))
1283
if (my_b_write(to_file,(uchar*) buffpek->key,
1284
(rec_length*buffpek->mem_count)))
1286
error= 1; goto err; /* purecov: inspected */
1409
strpos= buffpek_inst->key+offset;
1410
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1291
register uchar *end;
1292
strpos= buffpek->key+offset;
1293
for (end= strpos+buffpek->mem_count*rec_length ;
1411
1294
strpos != end ;
1412
1295
strpos+= rec_length)
1414
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1297
if (my_b_write(to_file, (uchar *) strpos, res_length))
1422
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1304
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1305
!= -1 && error != 0);
1426
1308
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1427
1309
lastbuff->file_pos= to_start_filepos;
1311
delete_queue(&queue);
1430
1313
} /* merge_buffers */
1433
1316
/* 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)
1318
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1319
BUFFPEK *buffpek, uint maxbuffer,
1320
IO_CACHE *tempfile, IO_CACHE *outfile)
1439
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
buffpek_inst+maxbuffer,1))
1322
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1323
buffpek+maxbuffer,1))
1324
return(1); /* purecov: inspected */
1444
1326
} /* merge_index */
1447
static uint32_t suffix_length(uint32_t string_length)
1329
static uint suffix_length(ulong string_length)
1449
1331
if (string_length < 256)
1504
1389
sortorder->result_type= sortorder->item->result_type();
1505
1390
if (sortorder->item->result_as_int64_t())
1506
1391
sortorder->result_type= INT_RESULT;
1508
1392
switch (sortorder->result_type) {
1509
1393
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)))
1394
sortorder->length=sortorder->item->max_length;
1395
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1396
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1515
1398
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
sortorder->need_strxnfrm= 1;
1517
*multi_byte_charset= 1;
1399
sortorder->need_strxnfrm= 1;
1400
*multi_byte_charset= 1;
1519
1402
else if (cs == &my_charset_bin)
1521
1404
/* Store length last to be able to sort blob/varbinary */
1522
1405
sortorder->suffix_length= suffix_length(sortorder->length);
1523
1406
sortorder->length+= sortorder->suffix_length;
1526
1409
case INT_RESULT:
1527
sortorder->length=8; // Size of intern int64_t
1410
#if SIZEOF_LONG_LONG > 4
1411
sortorder->length=8; // Size of intern int64_t
1413
sortorder->length=4;
1529
1416
case DECIMAL_RESULT:
1530
1417
sortorder->length=
1531
class_decimal_get_binary_size(sortorder->item->max_length -
1418
my_decimal_get_binary_size(sortorder->item->max_length -
1532
1419
(sortorder->item->decimals ? 1 : 0),
1533
1420
sortorder->item->decimals);
1535
1422
case REAL_RESULT:
1536
sortorder->length=sizeof(double);
1423
sortorder->length=sizeof(double);
1538
1425
case ROW_RESULT:
1539
// This case should never be choosen
1427
// This case should never be choosen
1543
1431
if (sortorder->item->maybe_null)
1544
length++; // Place for NULL marker
1432
length++; // Place for NULL marker
1546
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1434
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1547
1435
length+=sortorder->length;
1549
1437
sortorder->field= (Field*) 0; // end marker