24
#include <drizzled/server_includes.h>
26
#include <drizzled/drizzled_error_messages.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);
32
#include "drizzled/sql_sort.h"
33
#include "drizzled/error.h"
34
#include "drizzled/probes.h"
35
#include "drizzled/session.h"
36
#include "drizzled/table.h"
37
#include "drizzled/table_list.h"
38
#include "drizzled/optimizer/range.h"
39
#include "drizzled/records.h"
40
#include "drizzled/internal/iocache.h"
41
#include "drizzled/internal/my_sys.h"
42
#include "plugin/myisam/myisam.h"
43
#include "drizzled/plugin/transactional_storage_engine.h"
50
/* functions defined in this file */
52
static char **make_char_array(char **old_pos, register uint32_t fields,
55
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
59
static ha_rows find_all_keys(SORTPARAM *param,
60
optimizer::SqlSelect *select,
61
unsigned char * *sort_keys,
62
internal::IO_CACHE *buffer_file,
63
internal::IO_CACHE *tempfile,
64
internal::IO_CACHE *indexfile);
66
static int write_keys(SORTPARAM *param,
67
unsigned char * *sort_keys,
69
internal::IO_CACHE *buffer_file,
70
internal::IO_CACHE *tempfile);
72
static void make_sortkey(SORTPARAM *param,
74
unsigned char *ref_pos);
45
75
static void register_used_fields(SORTPARAM *param);
46
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
76
static int merge_index(SORTPARAM *param,
77
unsigned char *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(uint32_t 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);
80
internal::IO_CACHE *tempfile,
81
internal::IO_CACHE *outfile);
82
static bool save_index(SORTPARAM *param,
83
unsigned char **sort_keys,
85
filesort_info_st *table_sort);
86
static uint32_t suffix_length(uint32_t string_length);
87
static uint32_t sortlength(Session *session,
88
SORT_FIELD *sortorder,
90
bool *multi_byte_charset);
91
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
57
95
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
61
99
Creates a set of pointers that can be used to read the rows
92
130
examined_rows will be set to number of examined rows
95
ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
96
SQL_SELECT *select, ha_rows max_rows,
133
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
134
optimizer::SqlSelect *select, ha_rows max_rows,
97
135
bool sort_positions, ha_rows *examined_rows)
100
138
uint32_t memavl, min_sort_memory;
102
140
BUFFPEK *buffpek;
103
141
ha_rows records= HA_POS_ERROR;
104
uchar **sort_keys= 0;
105
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
142
unsigned char **sort_keys= 0;
143
internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
107
145
bool multi_byte_charset;
109
FILESORT_INFO table_sort;
110
TABLE_LIST *tab= table->pos_in_table_list;
147
filesort_info_st table_sort;
148
TableList *tab= table->pos_in_table_list;
111
149
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
113
DRIZZLE_FILESORT_START();
151
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
116
154
Release InnoDB's adaptive hash index latch (if holding) before
119
ha_release_temporary_latches(thd);
157
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
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
160
Don't use table->sort in filesort as it is also used by
161
QuickIndexMergeSelect. Work with a copy and put it back at the end
124
162
when index_merge select has finished with it.
126
memcpy(&table_sort, &table->sort, sizeof(FILESORT_INFO));
164
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
127
165
table->sort.io_cache= NULL;
129
167
outfile= table_sort.io_cache;
130
168
my_b_clear(&tempfile);
131
169
my_b_clear(&buffpek_pointers);
134
172
memset(¶m, 0, sizeof(param));
135
param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
136
param.ref_length= table->file->ref_length;
173
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
174
param.ref_length= table->cursor->ref_length;
137
175
param.addon_field= 0;
138
176
param.addon_length= 0;
139
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
177
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
142
Get the descriptors of all fields whose values are appended
180
Get the descriptors of all fields whose values are appended
143
181
to sorted fields and get its total length in param.spack_length.
145
param.addon_field= get_addon_fields(thd, table->field,
183
param.addon_field= get_addon_fields(session, table->field,
146
184
param.sort_length,
147
185
¶m.addon_length);
173
210
if (select && select->quick)
175
status_var_increment(thd->status_var.filesort_range_count);
212
status_var_increment(session->status_var.filesort_range_count);
179
status_var_increment(thd->status_var.filesort_scan_count);
216
status_var_increment(session->status_var.filesort_scan_count);
181
218
#ifdef CAN_TRUST_RANGE
182
219
if (select && select->quick && select->quick->records > 0L)
184
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
185
table->file->stats.records)+EXTRA_RECORDS;
221
records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
222
table->cursor->stats.records)+EXTRA_RECORDS;
186
223
selected_records_file=0;
191
records= table->file->estimate_rows_upper_bound();
228
records= table->cursor->estimate_rows_upper_bound();
193
If number of records is not known, use as much of sort buffer
230
If number of records is not known, use as much of sort buffer
196
233
if (records == HA_POS_ERROR)
197
234
records--; // we use 'records+1' below.
201
238
if (multi_byte_charset &&
202
!(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
239
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
205
memavl= thd->variables.sortbuff_size;
206
min_sort_memory= max((uint)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
242
memavl= session->variables.sortbuff_size;
243
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
207
244
while (memavl >= min_sort_memory)
209
246
uint32_t old_memavl;
210
247
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
211
param.keys=(uint) min(records+1, keys);
248
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
212
249
if ((table_sort.sort_keys=
213
(uchar **) make_char_array((char **) table_sort.sort_keys,
214
param.keys, param.rec_length, MYF(0))))
250
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
251
param.keys, param.rec_length)))
217
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
254
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
218
255
memavl= min_sort_memory;
220
257
sort_keys= table_sort.sort_keys;
234
271
&tempfile, selected_records_file)) ==
237
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
274
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
239
276
if (maxbuffer == 0) // The whole set is in memory
241
if (save_index(¶m,sort_keys,(uint) records, &table_sort))
278
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
246
283
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
248
x_free(table_sort.buffpek);
285
if (table_sort.buffpek)
286
free(table_sort.buffpek);
249
287
table_sort.buffpek= 0;
251
289
if (!(table_sort.buffpek=
252
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
290
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
253
291
table_sort.buffpek)))
255
293
buffpek= (BUFFPEK *) table_sort.buffpek;
257
295
close_cached_file(&buffpek_pointers);
258
296
/* Open cached file if it isn't open */
259
297
if (! my_b_inited(outfile) &&
260
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
298
open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
263
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
301
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
270
308
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
271
309
param.rec_length-1);
272
310
maxbuffer--; // Offset from 0
273
if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer,
311
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
276
314
if (flush_io_cache(&tempfile) ||
277
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
315
reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
279
if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
317
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
313
352
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
314
353
MYF(ME_ERROR+ME_WAITTANG));
316
statistic_add(thd->status_var.filesort_rows,
355
statistic_add(session->status_var.filesort_rows,
317
356
(uint32_t) records, &LOCK_status);
318
357
*examined_rows= param.examined_rows;
319
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
320
DRIZZLE_FILESORT_END();
321
return(error ? HA_POS_ERROR : records);
358
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
359
DRIZZLE_FILESORT_DONE(error, records);
360
return (error ? HA_POS_ERROR : records);
325
void filesort_free_buffers(TABLE *table, bool full)
364
void Table::filesort_free_buffers(bool full)
327
if (table->sort.record_pointers)
366
if (sort.record_pointers)
329
my_free((uchar*) table->sort.record_pointers,MYF(0));
330
table->sort.record_pointers=0;
368
free((unsigned char*) sort.record_pointers);
369
sort.record_pointers=0;
334
if (table->sort.sort_keys )
336
x_free((uchar*) table->sort.sort_keys);
337
table->sort.sort_keys= 0;
375
if ((unsigned char*) sort.sort_keys)
376
free((unsigned char*) sort.sort_keys);
339
if (table->sort.buffpek)
341
x_free((uchar*) table->sort.buffpek);
342
table->sort.buffpek= 0;
343
table->sort.buffpek_len= 0;
381
if ((unsigned char*) sort.buffpek)
382
free((unsigned char*) sort.buffpek);
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;
389
free((char *) sort.addon_buf);
390
free((char *) sort.addon_field);
355
396
/** Make a array of string pointers. */
357
static char **make_char_array(char **old_pos, register uint fields,
358
uint length, myf my_flag)
398
static char **make_char_array(char **old_pos, register uint32_t fields,
360
401
register char **pos;
364
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
405
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
367
407
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
368
408
while (fields--) *(pos++) = (char_pos+= length);
375
415
/** Read 'count' number of buffer pointers into memory. */
377
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
417
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
380
420
uint32_t length= sizeof(BUFFPEK)*count;
421
unsigned char *tmp= buf;
382
422
if (count > UINT_MAX/sizeof(BUFFPEK))
383
423
return 0; /* sizeof(BUFFPEK)*count will overflow */
385
tmp= (uchar *)my_malloc(length, MYF(MY_WME));
425
tmp= (unsigned char *)malloc(length);
388
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
389
my_b_read(buffpek_pointers, (uchar*) tmp, length))
428
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
429
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
391
my_free((char*) tmp, MYF(0));
433
473
HA_POS_ERROR on error.
436
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
438
IO_CACHE *buffpek_pointers,
439
IO_CACHE *tempfile, IO_CACHE *indexfile)
476
static ha_rows find_all_keys(SORTPARAM *param,
477
optimizer::SqlSelect *select,
478
unsigned char **sort_keys,
479
internal::IO_CACHE *buffpek_pointers,
480
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
441
482
int error,flag,quick_select;
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;
483
uint32_t idx,indexpos,ref_length;
484
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
485
internal::my_off_t record;
487
Session *session= current_session;
488
volatile Session::killed_state *killed= &session->killed;
490
MyBitmap *save_read_set, *save_write_set;
452
493
error=quick_select=0;
453
494
sort_form=param->sort_form;
454
file=sort_form->file;
495
file= sort_form->cursor;
455
496
ref_length=param->ref_length;
456
497
ref_pos= ref_buff;
457
498
quick_select=select && select->quick;
459
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
500
flag= ((!indexfile && ! file->isOrdered())
460
501
|| quick_select);
461
502
if (indexfile || flag)
462
503
ref_pos= &file->ref[0];
463
504
next_pos=ref_pos;
464
505
if (! indexfile && ! quick_select)
466
next_pos=(uchar*) 0; /* Find records in sequence */
467
file->ha_rnd_init(1);
507
next_pos=(unsigned char*) 0; /* Find records in sequence */
508
file->startTableScan(1);
468
509
file->extra_opt(HA_EXTRA_CACHE,
469
current_thd->variables.read_buff_size);
510
current_session->variables.read_buff_size);
472
READ_RECORD read_record_info;
513
ReadRecord read_record_info;
473
514
if (quick_select)
475
516
if (select->quick->reset())
476
517
return(HA_POS_ERROR);
477
init_read_record(&read_record_info, current_thd, select->quick->head,
519
read_record_info.init_read_record(current_session, select->quick->head, select, 1, 1);
481
522
/* Remember original bitmaps */
482
523
save_read_set= sort_form->read_set;
483
524
save_write_set= sort_form->write_set;
484
525
/* Set up temporary column read map for columns used by sort */
485
bitmap_clear_all(&sort_form->tmp_set);
526
sort_form->tmp_set.clearAll();
486
527
/* Temporary set for register_used_fields and register_field_in_read_map */
487
528
sort_form->read_set= &sort_form->tmp_set;
488
529
register_used_fields(param);
489
530
if (select && select->cond)
490
531
select->cond->walk(&Item::register_field_in_read_map, 1,
532
(unsigned char*) sort_form);
492
533
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
562
604
index_merge quick select uses table->sort when retrieving rows, so free
563
605
resoures it has allocated.
565
end_read_record(&read_record_info);
607
read_record_info.end_read_record();
569
611
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
613
file->endTableScan();
616
if (session->is_error())
575
617
return(HA_POS_ERROR);
577
619
/* Signal we should use orignal column read and write maps */
578
620
sort_form->column_bitmaps_set(save_read_set, save_write_set);
580
622
if (error != HA_ERR_END_OF_FILE)
582
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
583
return(HA_POS_ERROR); /* purecov: inspected */
624
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
625
return(HA_POS_ERROR);
585
627
if (indexpos && idx &&
586
628
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
587
return(HA_POS_ERROR); /* purecov: inspected */
629
return(HA_POS_ERROR);
588
630
return(my_b_inited(tempfile) ?
589
631
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
617
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
618
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
659
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
660
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
620
662
size_t sort_length, rec_length;
624
666
sort_length= param->sort_length;
625
667
rec_length= param->rec_length;
626
my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
668
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
627
669
if (!my_b_inited(tempfile) &&
628
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
670
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
630
goto err; /* purecov: inspected */
631
673
/* check we won't have more buffpeks than we can possibly keep in memory */
632
674
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
634
676
buffpek.file_pos= my_b_tell(tempfile);
635
677
if ((ha_rows) count > param->max_rows)
636
count=(uint) param->max_rows; /* purecov: inspected */
678
count=(uint32_t) param->max_rows;
637
679
buffpek.count=(ha_rows) count;
638
680
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
639
if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
681
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
641
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
683
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
754
794
if (sort_field->need_strxnfrm)
756
796
char *from=(char*) res->ptr();
758
if ((uchar*) from == to)
798
if ((unsigned char*) from == to)
760
800
set_if_smaller(length,sort_field->length);
761
801
memcpy(param->tmp_buffer,from,length);
762
802
from=param->tmp_buffer;
764
804
tmp_length= my_strnxfrm(cs,to,sort_field->length,
765
(uchar*) from, length);
805
(unsigned char*) from, length);
766
806
assert(tmp_length == sort_field->length);
770
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
810
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
771
811
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
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 */
832
to[7]= (unsigned char) value;
833
to[6]= (unsigned char) (value >> 8);
834
to[5]= (unsigned char) (value >> 16);
835
to[4]= (unsigned char) (value >> 24);
836
to[3]= (unsigned char) (value >> 32);
837
to[2]= (unsigned char) (value >> 40);
838
to[1]= (unsigned char) (value >> 48);
839
if (item->unsigned_flag) /* Fix sign */
840
to[0]= (unsigned char) (value >> 56);
842
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
815
845
case DECIMAL_RESULT:
959
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
960
FILESORT_INFO *table_sort)
988
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
989
filesort_info_st *table_sort)
962
uint offset,res_length;
991
uint32_t offset,res_length;
965
my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
994
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
966
995
res_length= param->res_length;
967
996
offset= param->rec_length-res_length;
968
997
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++)
998
count=(uint32_t) param->max_rows;
999
if (!(to= table_sort->record_pointers=
1000
(unsigned char*) malloc(res_length*count)))
1002
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
975
1004
memcpy(to, *sort_keys+offset, res_length);
976
1005
to+= res_length;
982
1011
/** Merge buffers to make < MERGEBUFF2 buffers. */
984
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
985
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
1013
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1014
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
988
IO_CACHE t_file2,*from_file,*to_file,*temp;
1016
register uint32_t i;
1017
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
989
1018
BUFFPEK *lastbuff;
991
1020
if (*maxbuffer < MERGEBUFF2)
992
return(0); /* purecov: inspected */
993
1022
if (flush_io_cache(t_file) ||
994
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1023
open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
996
return(1); /* purecov: inspected */
998
1027
from_file= t_file ; to_file= &t_file2;
999
1028
while (*maxbuffer >= MERGEBUFF2)
1001
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1030
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1003
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1032
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1005
1034
lastbuff=buffpek;
1006
1035
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1035
1064
Read data to buffer.
1038
(uint)-1 if something goes wrong
1067
(uint32_t)-1 if something goes wrong
1041
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1070
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1071
uint32_t rec_length)
1044
register uint count;
1073
register uint32_t count;
1047
if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
1076
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->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;
1078
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1079
return((uint32_t) -1);
1081
buffpek->key= buffpek->base;
1052
1082
buffpek->file_pos+= length; /* New filepos */
1053
buffpek->count-= count;
1083
buffpek->count-= count;
1054
1084
buffpek->mem_count= count;
1056
1086
return (count*rec_length);
1057
1087
} /* read_to_buffer */
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)
1090
class compare_functor
1073
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1074
for (uint i= 0; i < queue->elements; ++i)
1092
qsort2_cmp key_compare;
1093
void *key_compare_arg;
1095
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1096
: key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1097
inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
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;
1099
int val= key_compare(key_compare_arg,
1111
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1112
IO_CACHE *to_file, uchar *sort_buffer,
1124
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1125
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1113
1126
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1117
uint rec_length,res_length,offset;
1130
uint32_t rec_length,res_length,offset;
1118
1131
size_t sort_length;
1119
1132
uint32_t maxcount;
1120
1133
ha_rows max_rows,org_max_rows;
1121
my_off_t to_start_filepos;
1134
internal::my_off_t to_start_filepos;
1135
unsigned char *strpos;
1123
1136
BUFFPEK *buffpek;
1125
1137
qsort2_cmp cmp;
1126
1138
void *first_cmp_arg;
1127
volatile THD::killed_state *killed= ¤t_thd->killed;
1128
THD::killed_state not_killable;
1139
volatile Session::killed_state *killed= ¤t_session->killed;
1140
Session::killed_state not_killable;
1130
status_var_increment(current_thd->status_var.filesort_merge_passes);
1142
status_var_increment(current_session->status_var.filesort_merge_passes);
1131
1143
if (param->not_killable)
1133
1145
killed= ¬_killable;
1134
not_killable= THD::NOT_KILLED;
1146
not_killable= Session::NOT_KILLED;
1157
cmp= get_ptr_compare(sort_length);
1169
cmp= internal::get_ptr_compare(sort_length);
1158
1170
first_cmp_arg= (void*) &sort_length;
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 */
1172
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1173
queue(compare_functor(cmp, first_cmp_arg));
1163
1174
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1165
1176
buffpek->base= strpos;
1166
1177
buffpek->max_keys= maxcount;
1167
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
1178
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1169
1180
if (error == -1)
1170
goto err; /* purecov: inspected */
1171
1182
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1172
queue_insert(&queue, (uchar*) buffpek);
1183
queue.push(buffpek);
1175
1186
if (param->unique_buff)
1178
1189
Called by Unique::get()
1179
1190
Copy the first argument to param->unique_buff for unique removal.
1180
1191
Store it also in 'to_file'.
1182
1193
This is safe as we know that there is always more than one element
1183
1194
in each block to merge (This is guaranteed by the Unique:: algorithm
1185
buffpek= (BUFFPEK*) queue_top(&queue);
1196
buffpek= queue.top();
1186
1197
memcpy(param->unique_buff, buffpek->key, rec_length);
1187
if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
1198
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1189
error=1; goto err; /* purecov: inspected */
1191
1202
buffpek->key+= rec_length;
1192
1203
buffpek->mem_count--;
1193
1204
if (!--max_rows)
1195
error= 0; /* purecov: inspected */
1196
goto end; /* purecov: inspected */
1198
queue_replaced(&queue); // Top element has been used
1209
/* Top element has been used */
1211
queue.push(buffpek);
1201
1214
cmp= 0; // Not unique
1203
while (queue.elements > 1)
1216
while (queue.size() > 1)
1207
error= 1; goto err; /* purecov: inspected */
1211
buffpek= (BUFFPEK*) queue_top(&queue);
1224
buffpek= queue.top();
1212
1225
if (cmp) // Remove duplicates
1214
1227
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1215
(uchar**) &buffpek->key))
1228
(unsigned char**) &buffpek->key))
1216
1229
goto skip_duplicate;
1217
1230
memcpy(param->unique_buff, buffpek->key, rec_length);
1221
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1234
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1223
error=1; goto err; /* purecov: inspected */
1228
if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1241
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1230
error=1; goto err; /* purecov: inspected */
1233
1246
if (!--max_rows)
1235
error= 0; /* purecov: inspected */
1236
goto end; /* purecov: inspected */
1239
1252
skip_duplicate:
1275
1289
if ((ha_rows) buffpek->mem_count > max_rows)
1276
1290
{ /* Don't write too many records */
1277
buffpek->mem_count= (uint) max_rows;
1291
buffpek->mem_count= (uint32_t) max_rows;
1278
1292
buffpek->count= 0; /* Don't read more */
1280
1294
max_rows-= buffpek->mem_count;
1283
if (my_b_write(to_file,(uchar*) buffpek->key,
1297
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1284
1298
(rec_length*buffpek->mem_count)))
1286
error= 1; goto err; /* purecov: inspected */
1291
register uchar *end;
1305
register unsigned char *end;
1292
1306
strpos= buffpek->key+offset;
1293
1307
for (end= strpos+buffpek->mem_count*rec_length ;
1294
1308
strpos != end ;
1295
1309
strpos+= rec_length)
1297
if (my_b_write(to_file, (uchar *) strpos, res_length))
1311
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1308
1322
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1309
1323
lastbuff->file_pos= to_start_filepos;
1311
delete_queue(&queue);
1313
1326
} /* merge_buffers */
1316
1329
/* Do a merge to output-file (save only positions) */
1318
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1319
BUFFPEK *buffpek, uint maxbuffer,
1320
IO_CACHE *tempfile, IO_CACHE *outfile)
1331
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1332
BUFFPEK *buffpek, uint32_t maxbuffer,
1333
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1322
1335
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1323
1336
buffpek+maxbuffer,1))
1324
return(1); /* purecov: inspected */
1326
1339
} /* merge_index */
1329
static uint suffix_length(uint32_t string_length)
1342
static uint32_t suffix_length(uint32_t string_length)
1331
1344
if (string_length < 256)