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"
56
/* Defines used by filesort and uniques */
60
class BufferCompareContext
63
qsort_cmp2 key_compare;
64
void *key_compare_arg;
66
BufferCompareContext() :
75
uint32_t rec_length; /* Length of sorted records */
76
uint32_t sort_length; /* Length of sorted columns */
77
uint32_t ref_length; /* Length of record ref. */
78
uint32_t addon_length; /* Length of added packed fields */
79
uint32_t res_length; /* Length of records in final sorted file/buffer */
80
uint32_t keys; /* Max keys / buffer */
81
ha_rows max_rows,examined_rows;
82
Table *sort_form; /* For quicker make_sortkey */
83
SortField *local_sortorder;
85
sort_addon_field *addon_field; /* Descriptors for companion fields */
86
unsigned char *unique_buff;
89
/* The fields below are used only by Unique class */
91
BufferCompareContext cmp_context;
119
int write_keys(unsigned char * *sort_keys,
121
internal::IO_CACHE *buffer_file,
122
internal::IO_CACHE *tempfile);
124
void make_sortkey(unsigned char *to,
125
unsigned char *ref_pos);
126
void register_used_fields();
127
bool save_index(unsigned char **sort_keys,
129
filesort_info *table_sort);
133
/* functions defined in this file */
24
#include <drizzled/server_includes.h>
26
#include <drizzled/drizzled_error_messages.h>
28
/* functions defined in this file */
135
30
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,
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);
142
47
static uint32_t suffix_length(uint32_t string_length);
143
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,
144
53
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
56
Creates a set of pointers that can be used to read the rows
183
87
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)
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)
191
uint32_t memavl= 0, min_sort_memory;
95
uint32_t memavl, min_sort_memory;
192
96
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
195
98
ha_rows records= HA_POS_ERROR;
196
99
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;
100
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
102
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;
104
filesort_info_st table_sort;
212
105
TableList *tab= table->pos_in_table_list;
213
106
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
215
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
108
DRIZZLE_FILESORT_START();
218
111
Release InnoDB's adaptive hash index latch (if holding) before
221
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;
224
124
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)
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)
234
Get the descriptors of all fields whose values are appended
137
Get the descriptors of all fields whose values are appended
235
138
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
140
param.addon_field= get_addon_fields(thd, table->field,
238
141
param.sort_length,
239
142
¶m.addon_length);
266
168
if (select && select->quick)
268
getSession().status_var.filesort_range_count++;
170
status_var_increment(thd->status_var.filesort_range_count);
272
getSession().status_var.filesort_scan_count++;
174
status_var_increment(thd->status_var.filesort_scan_count);
274
176
#ifdef CAN_TRUST_RANGE
275
177
if (select && select->quick && select->quick->records > 0L)
277
records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
278
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;
279
181
selected_records_file=0;
284
records= table->cursor->estimate_rows_upper_bound();
186
records= table->file->estimate_rows_upper_bound();
286
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
289
191
if (records == HA_POS_ERROR)
290
192
records--; // we use 'records+1' below.
291
193
selected_records_file= 0;
294
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))))
299
memavl= getSession().variables.sortbuff_size;
300
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);
301
202
while (memavl >= min_sort_memory)
303
204
uint32_t old_memavl;
304
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
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));
206
param.keys=(uint32_t) cmin(records+1, keys);
314
207
if ((table_sort.sort_keys=
315
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
param.keys, param.rec_length)))
209
param.keys, param.rec_length, MYF(0))))
319
global_sort_buffer.sub(allocated_sort_memory);
321
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)
322
213
memavl= min_sort_memory;
324
215
sort_keys= table_sort.sort_keys;
327
218
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)))
221
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
222
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
225
param.keys--; /* TODO: check why we do this */
337
226
param.sort_form= table;
338
227
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)
228
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
229
&tempfile, selected_records_file)) ==
344
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
232
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
346
234
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
236
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
357
243
if (table_sort.buffpek)
358
244
free(table_sort.buffpek);
359
table_sort.buffpek = 0;
245
table_sort.buffpek= 0;
361
247
if (!(table_sort.buffpek=
362
(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)))
366
buffpek_inst= (buffpek *) table_sort.buffpek;
251
buffpek= (BUFFPEK *) table_sort.buffpek;
367
252
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
253
close_cached_file(&buffpek_pointers);
369
254
/* 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))
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))
381
263
Use also the space previously used by string pointers in sort_buffer
382
264
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
266
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
268
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))
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,
403
279
if (records > param.max_rows)
405
records= param.max_rows;
280
records=param.max_rows;
410
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);
413
291
table_sort.sort_keys= 0;
292
if ((unsigned char*) buffpek)
293
free((unsigned char*) buffpek);
415
294
table_sort.buffpek= 0;
416
295
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
297
close_cached_file(&tempfile);
298
close_cached_file(&buffpek_pointers);
422
299
if (my_b_inited(outfile))
424
301
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
304
my_off_t save_pos=outfile->pos_in_file;
430
305
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
306
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
435
308
outfile->end_of_file=save_pos;
441
312
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
442
313
MYF(ME_ERROR+ME_WAITTANG));
446
getSession().status_var.filesort_rows+= (uint32_t) records;
448
examined_rows= param.examined_rows;
449
global_sort_buffer.sub(allocated_sort_memory);
450
table->sort= table_sort;
451
DRIZZLE_FILESORT_DONE(error, records);
452
return (error ? HA_POS_ERROR : records);
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;
455
356
/** Make a array of string pointers. */
457
358
static char **make_char_array(char **old_pos, register uint32_t fields,
359
uint32_t length, myf my_flag)
460
361
register char **pos;
464
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
466
368
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
467
369
while (fields--) *(pos++) = (char_pos+= length);
474
376
/** Read 'count' number of buffer pointers into memory. */
476
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,
477
379
unsigned char *buf)
479
uint32_t length= sizeof(buffpek)*count;
381
uint32_t length= sizeof(BUFFPEK)*count;
480
382
unsigned char *tmp= buf;
481
if (count > UINT_MAX/sizeof(buffpek))
482
return 0; /* sizeof(buffpek)*count will overflow */
383
if (count > UINT_MAX/sizeof(BUFFPEK))
384
return 0; /* sizeof(BUFFPEK)*count will overflow */
484
tmp= (unsigned char *)malloc(length);
386
tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
487
if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
389
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
488
390
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
490
392
free((char*) tmp);
532
434
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)
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)
541
442
int error,flag,quick_select;
542
443
uint32_t idx,indexpos,ref_length;
543
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
internal::my_off_t record;
545
446
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;
447
THD *thd= current_thd;
448
volatile THD::killed_state *killed= &thd->killed;
450
MY_BITMAP *save_read_set, *save_write_set;
552
453
error=quick_select=0;
553
454
sort_form=param->sort_form;
554
file= sort_form->cursor;
455
file=sort_form->file;
555
456
ref_length=param->ref_length;
556
457
ref_pos= ref_buff;
557
458
quick_select=select && select->quick;
559
flag= ((!indexfile && ! file->isOrdered())
460
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
560
461
|| quick_select);
561
462
if (indexfile || flag)
562
463
ref_pos= &file->ref[0];
564
465
if (! indexfile && ! quick_select)
566
467
next_pos=(unsigned char*) 0; /* Find records in sequence */
567
if (file->startTableScan(1))
568
return(HA_POS_ERROR);
569
file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
468
file->ha_rnd_init(1);
469
file->extra_opt(HA_EXTRA_CACHE,
470
current_thd->variables.read_buff_size);
572
ReadRecord read_record_info;
473
READ_RECORD read_record_info;
573
474
if (quick_select)
575
476
if (select->quick->reset())
576
477
return(HA_POS_ERROR);
578
if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
return(HA_POS_ERROR);
478
init_read_record(&read_record_info, current_thd, select->quick->head,
582
482
/* Remember original bitmaps */
583
483
save_read_set= sort_form->read_set;
584
484
save_write_set= sort_form->write_set;
585
485
/* Set up temporary column read map for columns used by sort */
586
sort_form->tmp_set.reset();
486
bitmap_clear_all(&sort_form->tmp_set);
587
487
/* Temporary set for register_used_fields and register_field_in_read_map */
588
488
sort_form->read_set= &sort_form->tmp_set;
589
param->register_used_fields();
489
register_used_fields(param);
590
490
if (select && select->cond)
591
491
select->cond->walk(&Item::register_field_in_read_map, 1,
592
492
(unsigned char*) sort_form);
593
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);
601
501
error= HA_ERR_END_OF_FILE;
604
file->position(sort_form->getInsertRecord());
504
file->position(sort_form->record[0]);
606
506
else /* Not quick-select */
610
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 */
612
error= errno ? errno : -1; /* Abort */
512
error= my_errno ? my_errno : -1; /* Abort */
615
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
515
error=file->rnd_pos(sort_form->record[0],next_pos);
619
error=file->rnd_next(sort_form->getInsertRecord());
519
error=file->rnd_next(sort_form->record[0]);
521
update_virtual_fields_marked_for_write(sort_form);
623
internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
624
record+= sort_form->getShare()->db_record_offset;
525
my_store_ptr(ref_pos,ref_length,record); // Position to row
526
record+= sort_form->s->db_record_offset;
627
file->position(sort_form->getInsertRecord());
529
file->position(sort_form->record[0]);
629
531
if (error && error != HA_ERR_RECORD_DELETED)
667
566
index_merge quick select uses table->sort when retrieving rows, so free
668
567
resoures it has allocated.
670
read_record_info.end_read_record();
569
end_read_record(&read_record_info);
674
573
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
676
file->endTableScan();
679
if (getSession().is_error())
680
579
return(HA_POS_ERROR);
682
581
/* Signal we should use orignal column read and write maps */
683
sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
582
sort_form->column_bitmaps_set(save_read_set, save_write_set);
685
584
if (error != HA_ERR_END_OF_FILE)
687
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
return(HA_POS_ERROR);
691
if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
693
return(HA_POS_ERROR);
586
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
587
return(HA_POS_ERROR); /* purecov: inspected */
589
if (indexpos && idx &&
590
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
591
return(HA_POS_ERROR); /* purecov: inspected */
696
592
return(my_b_inited(tempfile) ?
697
593
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
724
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
725
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
621
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
622
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
624
size_t sort_length, rec_length;
729
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
628
sort_length= param->sort_length;
629
rec_length= param->rec_length;
630
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
631
if (!my_b_inited(tempfile) &&
731
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
632
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
634
goto err; /* purecov: inspected */
735
635
/* check we won't have more buffpeks than we can possibly keep in memory */
736
if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
636
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
741
638
buffpek.file_pos= my_b_tell(tempfile);
742
if ((ha_rows) count > max_rows)
743
count=(uint32_t) max_rows;
639
if ((ha_rows) count > param->max_rows)
640
count=(uint32_t) param->max_rows; /* purecov: inspected */
745
641
buffpek.count=(ha_rows) count;
747
for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
642
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
749
643
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
755
645
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
761
651
} /* write_keys */
820
711
Item *item=sort_field->item;
821
712
maybe_null= item->maybe_null;
823
713
switch (sort_field->result_type) {
824
714
case STRING_RESULT:
826
const CHARSET_INFO * const cs=item->collation.collation;
827
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
829
uint32_t sort_field_length;
716
const CHARSET_INFO * const cs=item->collation.collation;
717
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
719
uint32_t sort_field_length;
723
/* All item->str() to use some extra byte for end null.. */
724
String tmp((char*) to,sort_field->length+4,cs);
725
String *res= item->str_result(&tmp);
833
/* All item->str() to use some extra byte for end null.. */
834
String tmp((char*) to,sort_field->length+4,cs);
835
String *res= item->str_result(&tmp);
839
memset(to-1, 0, sort_field->length+1);
843
This should only happen during extreme conditions if we run out
844
of memory or have an item marked not null when it can be null.
845
This code is here mainly to avoid a hard crash in this case.
848
memset(to, 0, sort_field->length); // Avoid crash
852
length= res->length();
853
sort_field_length= sort_field->length - sort_field->suffix_length;
854
diff=(int) (sort_field_length - length);
858
length= sort_field_length;
860
if (sort_field->suffix_length)
862
/* Store length last in result_string */
863
store_length(to + sort_field_length, length,
864
sort_field->suffix_length);
866
if (sort_field->need_strxnfrm)
868
char *from=(char*) res->ptr();
870
if ((unsigned char*) from == to)
872
set_if_smaller(length,sort_field->length);
873
memcpy(tmp_buffer,from,length);
876
tmp_length= my_strnxfrm(cs,to,sort_field->length,
877
(unsigned char*) from, length);
878
assert(tmp_length == sort_field->length);
729
memset(to-1, 0, sort_field->length+1);
882
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
883
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
732
/* purecov: begin deadcode */
734
This should only happen during extreme conditions if we run out
735
of memory or have an item marked not null when it can be null.
736
This code is here mainly to avoid a hard crash in this case.
739
memset(to, 0, sort_field->length); // Avoid crash
744
length= res->length();
745
sort_field_length= sort_field->length - sort_field->suffix_length;
746
diff=(int) (sort_field_length - length);
750
length= sort_field_length;
752
if (sort_field->suffix_length)
754
/* Store length last in result_string */
755
store_length(to + sort_field_length, length,
756
sort_field->suffix_length);
758
if (sort_field->need_strxnfrm)
760
char *from=(char*) res->ptr();
762
if ((unsigned char*) from == to)
764
set_if_smaller(length,sort_field->length);
765
memcpy(param->tmp_buffer,from,length);
766
from=param->tmp_buffer;
768
tmp_length= my_strnxfrm(cs,to,sort_field->length,
769
(unsigned char*) from, length);
770
assert(tmp_length == sort_field->length);
774
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
775
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
889
781
int64_t value= item->val_int_result();
784
*to++=1; /* purecov: inspected */
893
785
if (item->null_value)
904
to[7]= (unsigned char) value;
905
to[6]= (unsigned char) (value >> 8);
906
to[5]= (unsigned char) (value >> 16);
907
to[4]= (unsigned char) (value >> 24);
908
to[3]= (unsigned char) (value >> 32);
909
to[2]= (unsigned char) (value >> 40);
910
to[1]= (unsigned char) (value >> 48);
796
to[7]= (unsigned char) value;
797
to[6]= (unsigned char) (value >> 8);
798
to[5]= (unsigned char) (value >> 16);
799
to[4]= (unsigned char) (value >> 24);
800
to[3]= (unsigned char) (value >> 32);
801
to[2]= (unsigned char) (value >> 40);
802
to[1]= (unsigned char) (value >> 48);
911
803
if (item->unsigned_flag) /* Fix sign */
912
804
to[0]= (unsigned char) (value >> 56);
914
806
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
809
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
811
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
814
if (item->null_value)
924
816
memset(to, 0, sort_field->length+1);
930
dec_val->val_binary(E_DEC_FATAL_ERROR, to,
931
item->max_length - (item->decimals ? 1:0),
822
my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
823
item->max_length - (item->decimals ? 1:0),
935
827
case REAL_RESULT:
937
829
double value= item->val_result();
940
832
if (item->null_value)
1062
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
953
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
954
filesort_info_st *table_sort)
956
uint32_t offset,res_length;
1065
957
unsigned char *to;
1067
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1068
offset= rec_length - res_length;
1070
if ((ha_rows) count > max_rows)
1071
count=(uint32_t) max_rows;
1073
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1076
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
959
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
960
res_length= param->res_length;
961
offset= param->rec_length-res_length;
962
if ((ha_rows) count > param->max_rows)
963
count=(uint32_t) param->max_rows;
964
if (!(to= table_sort->record_pointers=
965
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
966
return(1); /* purecov: inspected */
967
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1078
969
memcpy(to, *sort_keys+offset, res_length);
1079
970
to+= res_length;
1086
976
/** Merge buffers to make < MERGEBUFF2 buffers. */
1088
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1089
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
978
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
979
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1091
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
982
IO_CACHE t_file2,*from_file,*to_file,*temp;
1094
985
if (*maxbuffer < MERGEBUFF2)
986
return(0); /* purecov: inspected */
1096
987
if (flush_io_cache(t_file) ||
1097
t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
988
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
990
return(1); /* purecov: inspected */
1102
992
from_file= t_file ; to_file= &t_file2;
1103
993
while (*maxbuffer >= MERGEBUFF2)
1105
register uint32_t i;
1107
if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1112
if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1117
lastbuff=buffpek_inst;
995
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
997
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1118
1000
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1120
1002
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1121
buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1003
buffpek+i,buffpek+i+MERGEBUFF-1,0))
1127
1006
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1128
buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1007
buffpek+i,buffpek+ *maxbuffer,0))
1008
break; /* purecov: inspected */
1133
1009
if (flush_io_cache(to_file))
1010
break; /* purecov: inspected */
1138
1011
temp=from_file; from_file=to_file; to_file=temp;
1139
from_file->setup_io_cache();
1140
to_file->setup_io_cache();
1141
*maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
1012
setup_io_cache(from_file);
1013
setup_io_cache(to_file);
1014
*maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1145
to_file->close_cached_file(); // This holds old result
1017
close_cached_file(to_file); // This holds old result
1146
1018
if (to_file == t_file)
1148
1020
*t_file=t_file2; // Copy result file
1149
t_file->setup_io_cache();
1021
setup_io_cache(t_file);
1152
1024
return(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
1160
1032
(uint32_t)-1 if something goes wrong
1163
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
1035
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1036
uint32_t rec_length)
1165
1038
register uint32_t count;
1166
1039
uint32_t length;
1168
if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
1041
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1170
if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
1171
return((uint32_t) -1);
1173
buffpek_inst->key= buffpek_inst->base;
1174
buffpek_inst->file_pos+= length; /* New filepos */
1175
buffpek_inst->count-= count;
1176
buffpek_inst->mem_count= count;
1043
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1044
return((uint32_t) -1); /* purecov: inspected */
1045
buffpek->key=buffpek->base;
1046
buffpek->file_pos+= length; /* New filepos */
1047
buffpek->count-= count;
1048
buffpek->mem_count= count;
1178
1050
return (count*rec_length);
1179
1051
} /* read_to_buffer */
1182
class compare_functor
1055
Put all room used by freed buffer to use in adjacent buffer.
1057
Note, that we can't simply distribute memory evenly between all buffers,
1058
because new areas must not overlap with old ones.
1060
@param[in] queue list of non-empty buffers, without freed buffer
1061
@param[in] reuse empty buffer
1062
@param[in] key_length key length
1065
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1184
qsort2_cmp key_compare;
1185
void *key_compare_arg;
1188
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1189
key_compare(in_key_compare),
1190
key_compare_arg(in_compare_arg)
1193
inline bool operator()(const buffpek *i, const buffpek *j) const
1067
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1068
for (uint32_t i= 0; i < queue->elements; ++i)
1195
int val= key_compare(key_compare_arg, &i->key, &j->key);
1070
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1071
if (bp->base + bp->max_keys * key_length == reuse->base)
1073
bp->max_keys+= reuse->max_keys;
1076
else if (bp->base == reuse_end)
1078
bp->base= reuse->base;
1079
bp->max_keys+= reuse->max_keys;
1203
1088
Merge buffers to one buffer.
1205
1090
@param param Sort parameter
1206
@param from_file File with source data (buffpeks point to this file)
1091
@param from_file File with source data (BUFFPEKs point to this file)
1207
1092
@param to_file File to write the sorted result data.
1208
1093
@param sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys.
1209
@param lastbuff OUT Store here buffpek describing data written to to_file
1210
@param Fb First element in source buffpeks array
1211
@param Tb Last element in source buffpeks array
1094
@param lastbuff OUT Store here BUFFPEK describing data written to to_file
1095
@param Fb First element in source BUFFPEKs array
1096
@param Tb Last element in source BUFFPEKs array
1220
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1221
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1222
buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1105
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1106
IO_CACHE *to_file, unsigned char *sort_buffer,
1107
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1226
1111
uint32_t rec_length,res_length,offset;
1227
1112
size_t sort_length;
1228
1113
uint32_t maxcount;
1229
1114
ha_rows max_rows,org_max_rows;
1230
internal::my_off_t to_start_filepos;
1115
my_off_t to_start_filepos;
1231
1116
unsigned char *strpos;
1232
buffpek *buffpek_inst;
1233
1119
qsort2_cmp cmp;
1234
1120
void *first_cmp_arg;
1235
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1236
Session::killed_state_t not_killable;
1121
volatile THD::killed_state *killed= ¤t_thd->killed;
1122
THD::killed_state not_killable;
1238
getSession().status_var.filesort_merge_passes++;
1124
status_var_increment(current_thd->status_var.filesort_merge_passes);
1239
1125
if (param->not_killable)
1241
1127
killed= ¬_killable;
1242
not_killable= Session::NOT_KILLED;
1128
not_killable= THD::NOT_KILLED;
1265
cmp= internal::get_ptr_compare(sort_length);
1151
cmp= get_ptr_compare(sort_length);
1266
1152
first_cmp_arg= (void*) &sort_length;
1268
priority_queue<buffpek *, vector<buffpek *>, compare_functor >
1269
queue(compare_functor(cmp, first_cmp_arg));
1270
for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
1154
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1155
(queue_compare) cmp, first_cmp_arg))
1156
return(1); /* purecov: inspected */
1157
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1272
buffpek_inst->base= strpos;
1273
buffpek_inst->max_keys= maxcount;
1274
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
1159
buffpek->base= strpos;
1160
buffpek->max_keys= maxcount;
1161
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1276
1163
if (error == -1)
1279
buffpek_inst->max_keys= buffpek_inst->mem_count; // If less data in buffers than expected
1280
queue.push(buffpek_inst);
1164
goto err; /* purecov: inspected */
1165
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1166
queue_insert(&queue, (unsigned char*) buffpek);
1283
1169
if (param->unique_buff)
1286
1172
Called by Unique::get()
1287
1173
Copy the first argument to param->unique_buff for unique removal.
1288
1174
Store it also in 'to_file'.
1290
1176
This is safe as we know that there is always more than one element
1291
1177
in each block to merge (This is guaranteed by the Unique:: algorithm
1293
buffpek_inst= queue.top();
1294
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1295
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key, rec_length))
1179
buffpek= (BUFFPEK*) queue_top(&queue);
1180
memcpy(param->unique_buff, buffpek->key, rec_length);
1181
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1183
error=1; goto err; /* purecov: inspected */
1299
buffpek_inst->key+= rec_length;
1300
buffpek_inst->mem_count--;
1185
buffpek->key+= rec_length;
1186
buffpek->mem_count--;
1301
1187
if (!--max_rows)
1189
error= 0; /* purecov: inspected */
1190
goto end; /* purecov: inspected */
1306
/* Top element has been used */
1308
queue.push(buffpek_inst);
1192
queue_replaced(&queue); // Top element has been used
1312
1195
cmp= 0; // Not unique
1315
while (queue.size() > 1)
1197
while (queue.elements > 1)
1201
error= 1; goto err; /* purecov: inspected */
1323
buffpek_inst= queue.top();
1205
buffpek= (BUFFPEK*) queue_top(&queue);
1324
1206
if (cmp) // Remove duplicates
1326
1208
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1327
(unsigned char**) &buffpek_inst->key))
1209
(unsigned char**) &buffpek->key))
1328
1210
goto skip_duplicate;
1329
memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1211
memcpy(param->unique_buff, buffpek->key, rec_length);
1333
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
1215
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1217
error=1; goto err; /* purecov: inspected */
1340
if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
1222
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1224
error=1; goto err; /* purecov: inspected */
1345
1227
if (!--max_rows)
1229
error= 0; /* purecov: inspected */
1230
goto end; /* purecov: inspected */
1351
1233
skip_duplicate:
1352
buffpek_inst->key+= rec_length;
1353
if (! --buffpek_inst->mem_count)
1234
buffpek->key+= rec_length;
1235
if (! --buffpek->mem_count)
1355
if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
1237
if (!(error= (int) read_to_buffer(from_file,buffpek,
1240
queue_remove(&queue,0);
1241
reuse_freed_buff(&queue, buffpek, rec_length);
1359
1242
break; /* One buffer have been removed */
1361
1244
else if (error == -1)
1245
goto err; /* purecov: inspected */
1366
/* Top element has been replaced */
1368
queue.push(buffpek_inst);
1247
queue_replaced(&queue); /* Top element has been replaced */
1371
buffpek_inst= queue.top();
1372
buffpek_inst->base= sort_buffer;
1373
buffpek_inst->max_keys= param->keys;
1250
buffpek= (BUFFPEK*) queue_top(&queue);
1251
buffpek->base= sort_buffer;
1252
buffpek->max_keys= param->keys;
1376
1255
As we know all entries in the buffer are unique, we only have to
1381
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
1260
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1383
buffpek_inst->key+= rec_length; // Remove duplicate
1384
--buffpek_inst->mem_count;
1262
buffpek->key+= rec_length; // Remove duplicate
1263
--buffpek->mem_count;
1390
if ((ha_rows) buffpek_inst->mem_count > max_rows)
1269
if ((ha_rows) buffpek->mem_count > max_rows)
1391
1270
{ /* Don't write too many records */
1392
buffpek_inst->mem_count= (uint32_t) max_rows;
1393
buffpek_inst->count= 0; /* Don't read more */
1271
buffpek->mem_count= (uint32_t) max_rows;
1272
buffpek->count= 0; /* Don't read more */
1395
max_rows-= buffpek_inst->mem_count;
1274
max_rows-= buffpek->mem_count;
1398
if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1399
(rec_length*buffpek_inst->mem_count)))
1277
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1278
(rec_length*buffpek->mem_count)))
1280
error= 1; goto err; /* purecov: inspected */
1406
1285
register unsigned char *end;
1407
strpos= buffpek_inst->key+offset;
1408
for (end= strpos+buffpek_inst->mem_count*rec_length ;
1286
strpos= buffpek->key+offset;
1287
for (end= strpos+buffpek->mem_count*rec_length ;
1409
1288
strpos != end ;
1410
1289
strpos+= rec_length)
1412
1291
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1420
while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
1298
while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1421
1299
!= -1 && error != 0);
1424
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1302
lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1425
1303
lastbuff->file_pos= to_start_filepos;
1305
delete_queue(&queue);
1428
1307
} /* merge_buffers */
1431
1310
/* Do a merge to output-file (save only positions) */
1433
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1434
buffpek *buffpek_inst, uint32_t maxbuffer,
1435
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1312
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1313
BUFFPEK *buffpek, uint32_t maxbuffer,
1314
IO_CACHE *tempfile, IO_CACHE *outfile)
1437
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
buffpek_inst+maxbuffer,1))
1316
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1317
buffpek+maxbuffer,1))
1318
return(1); /* purecov: inspected */
1442
1320
} /* merge_index */
1502
1383
sortorder->result_type= sortorder->item->result_type();
1503
1384
if (sortorder->item->result_as_int64_t())
1504
1385
sortorder->result_type= INT_RESULT;
1506
1386
switch (sortorder->result_type) {
1507
1387
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1509
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1388
sortorder->length=sortorder->item->max_length;
1389
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1390
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1392
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1393
sortorder->need_strxnfrm= 1;
1394
*multi_byte_charset= 1;
1517
1396
else if (cs == &my_charset_bin)
1519
1398
/* Store length last to be able to sort blob/varbinary */
1520
1399
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1400
sortorder->length+= sortorder->suffix_length;
1524
1403
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1404
sortorder->length=8; // Size of intern int64_t
1527
1406
case DECIMAL_RESULT:
1528
1407
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1408
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1409
(sortorder->item->decimals ? 1 : 0),
1531
1410
sortorder->item->decimals);
1533
1412
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1413
sortorder->length=sizeof(double);
1536
1415
case ROW_RESULT:
1537
// This case should never be choosen
1417
// This case should never be choosen
1541
1421
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1422
length++; // Place for NULL marker
1544
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1424
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1545
1425
length+=sortorder->length;
1547
1427
sortorder->field= (Field*) 0; // end marker