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"
24
#include <drizzled/server_includes.h>
25
#include <drizzled/sql_sort.h>
26
#include <drizzled/error.h>
27
#include <drizzled/probes.h>
28
#include <drizzled/session.h>
29
#include <drizzled/table.h>
30
#include <drizzled/table_list.h>
50
32
/* functions defined in this file */
52
34
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);
36
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
38
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
39
unsigned char * *sort_keys, IO_CACHE *buffer_file,
40
IO_CACHE *tempfile,IO_CACHE *indexfile);
41
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
42
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
43
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
75
44
static void register_used_fields(SORTPARAM *param);
76
static int merge_index(SORTPARAM *param,
77
unsigned char *sort_buffer,
45
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
80
internal::IO_CACHE *tempfile,
81
internal::IO_CACHE *outfile);
82
static bool save_index(SORTPARAM *param,
83
unsigned char **sort_keys,
47
uint32_t maxbuffer,IO_CACHE *tempfile,
49
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
85
50
filesort_info_st *table_sort);
86
51
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,
52
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
53
bool *multi_byte_charset);
54
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
55
uint32_t sortlength, uint32_t *plength);
95
56
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
96
57
unsigned char *buff);
148
109
TableList *tab= table->pos_in_table_list;
149
110
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
151
DRIZZLE_FILESORT_START(table->s->getSchemaName(), table->s->getTableName());
112
DRIZZLE_FILESORT_START();
154
115
Release InnoDB's adaptive hash index latch (if holding) before
157
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
118
ha_release_temporary_latches(session);
160
121
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
122
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
162
123
when index_merge select has finished with it.
164
125
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
242
203
memavl= session->variables.sortbuff_size;
243
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
204
min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
244
205
while (memavl >= min_sort_memory)
246
207
uint32_t old_memavl;
247
208
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
248
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
209
param.keys=(uint32_t) cmin(records+1, keys);
249
210
if ((table_sort.sort_keys=
250
211
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
251
212
param.keys, param.rec_length)))
254
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
215
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
255
216
memavl= min_sort_memory;
257
218
sort_keys= table_sort.sort_keys;
358
319
(uint32_t) records, &LOCK_status);
359
320
*examined_rows= param.examined_rows;
360
321
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
361
DRIZZLE_FILESORT_DONE(error, records);
362
return (error ? HA_POS_ERROR : records);
322
DRIZZLE_FILESORT_END();
323
return(error ? HA_POS_ERROR : records);
366
void Table::filesort_free_buffers(bool full)
327
void filesort_free_buffers(Table *table, bool full)
368
if (sort.record_pointers)
329
if (table->sort.record_pointers)
370
free((unsigned char*) sort.record_pointers);
371
sort.record_pointers=0;
331
free((unsigned char*) table->sort.record_pointers);
332
table->sort.record_pointers=0;
336
if (table->sort.sort_keys )
377
if ((unsigned char*) sort.sort_keys)
378
free((unsigned char*) sort.sort_keys);
338
if ((unsigned char*) table->sort.sort_keys)
339
free((unsigned char*) table->sort.sort_keys);
340
table->sort.sort_keys= 0;
342
if (table->sort.buffpek)
383
if ((unsigned char*) sort.buffpek)
384
free((unsigned char*) sort.buffpek);
344
if ((unsigned char*) table->sort.buffpek)
345
free((unsigned char*) table->sort.buffpek);
346
table->sort.buffpek= 0;
347
table->sort.buffpek_len= 0;
350
if (table->sort.addon_buf)
391
free((char *) sort.addon_buf);
392
free((char *) sort.addon_field);
352
free((char *) table->sort.addon_buf);
353
free((char *) table->sort.addon_field);
354
table->sort.addon_buf=0;
355
table->sort.addon_field=0;
475
436
HA_POS_ERROR on error.
478
static ha_rows find_all_keys(SORTPARAM *param,
479
optimizer::SqlSelect *select,
439
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
480
440
unsigned char **sort_keys,
481
internal::IO_CACHE *buffpek_pointers,
482
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
441
IO_CACHE *buffpek_pointers,
442
IO_CACHE *tempfile, IO_CACHE *indexfile)
484
444
int error,flag,quick_select;
485
445
uint32_t idx,indexpos,ref_length;
486
446
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
487
internal::my_off_t record;
488
448
Table *sort_form;
489
449
Session *session= current_session;
490
450
volatile Session::killed_state *killed= &session->killed;
492
MyBitmap *save_read_set, *save_write_set;
452
MY_BITMAP *save_read_set, *save_write_set;
495
455
error=quick_select=0;
496
456
sort_form=param->sort_form;
497
file= sort_form->cursor;
457
file=sort_form->file;
498
458
ref_length=param->ref_length;
499
459
ref_pos= ref_buff;
500
460
quick_select=select && select->quick;
502
flag= ((!indexfile && ! file->isOrdered())
462
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
503
463
|| quick_select);
504
464
if (indexfile || flag)
505
465
ref_pos= &file->ref[0];
668
630
sort_length= param->sort_length;
669
631
rec_length= param->rec_length;
670
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
632
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
671
633
if (!my_b_inited(tempfile) &&
672
634
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
636
goto err; /* purecov: inspected */
675
637
/* check we won't have more buffpeks than we can possibly keep in memory */
676
638
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
678
640
buffpek.file_pos= my_b_tell(tempfile);
679
641
if ((ha_rows) count > param->max_rows)
680
count=(uint32_t) param->max_rows;
642
count=(uint32_t) param->max_rows; /* purecov: inspected */
681
643
buffpek.count=(ha_rows) count;
682
644
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
683
645
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
993
958
uint32_t offset,res_length;
994
959
unsigned char *to;
996
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
961
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
997
962
res_length= param->res_length;
998
963
offset= param->rec_length-res_length;
999
964
if ((ha_rows) count > param->max_rows)
1000
965
count=(uint32_t) param->max_rows;
1001
966
if (!(to= table_sort->record_pointers=
1002
967
(unsigned char*) malloc(res_length*count)))
968
return(1); /* purecov: inspected */
1004
969
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1006
971
memcpy(to, *sort_keys+offset, res_length);
1013
978
/** Merge buffers to make < MERGEBUFF2 buffers. */
1015
980
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1016
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
981
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1018
983
register uint32_t i;
1019
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
984
IO_CACHE t_file2,*from_file,*to_file,*temp;
1020
985
BUFFPEK *lastbuff;
1022
987
if (*maxbuffer < MERGEBUFF2)
988
return(0); /* purecov: inspected */
1024
989
if (flush_io_cache(t_file) ||
1025
990
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
992
return(1); /* purecov: inspected */
1029
994
from_file= t_file ; to_file= &t_file2;
1030
995
while (*maxbuffer >= MERGEBUFF2)
1032
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
997
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1034
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
999
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1036
1001
lastbuff=buffpek;
1037
1002
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1069
1034
(uint32_t)-1 if something goes wrong
1072
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
uint32_t rec_length)
1037
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1038
uint32_t rec_length)
1075
1040
register uint32_t count;
1076
1041
uint32_t length;
1078
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1043
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1080
1045
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1081
return((uint32_t) -1);
1083
buffpek->key= buffpek->base;
1046
return((uint32_t) -1); /* purecov: inspected */
1047
buffpek->key=buffpek->base;
1084
1048
buffpek->file_pos+= length; /* New filepos */
1085
buffpek->count-= count;
1049
buffpek->count-= count;
1086
1050
buffpek->mem_count= count;
1088
1052
return (count*rec_length);
1089
1053
} /* read_to_buffer */
1092
class compare_functor
1057
Put all room used by freed buffer to use in adjacent buffer.
1059
Note, that we can't simply distribute memory evenly between all buffers,
1060
because new areas must not overlap with old ones.
1062
@param[in] queue list of non-empty buffers, without freed buffer
1063
@param[in] reuse empty buffer
1064
@param[in] key_length key length
1067
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1094
qsort2_cmp key_compare;
1095
void *key_compare_arg;
1097
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1098
: key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1099
inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1069
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1070
for (uint32_t i= 0; i < queue->elements; ++i)
1101
int val= key_compare(key_compare_arg,
1072
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1073
if (bp->base + bp->max_keys * key_length == reuse->base)
1075
bp->max_keys+= reuse->max_keys;
1078
else if (bp->base == reuse_end)
1080
bp->base= reuse->base;
1081
bp->max_keys+= reuse->max_keys;
1171
cmp= internal::get_ptr_compare(sort_length);
1153
cmp= get_ptr_compare(sort_length);
1172
1154
first_cmp_arg= (void*) &sort_length;
1174
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1175
queue(compare_functor(cmp, first_cmp_arg));
1156
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1157
(queue_compare) cmp, first_cmp_arg))
1158
return(1); /* purecov: inspected */
1176
1159
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1178
1161
buffpek->base= strpos;
1195
1178
This is safe as we know that there is always more than one element
1196
1179
in each block to merge (This is guaranteed by the Unique:: algorithm
1198
buffpek= queue.top();
1181
buffpek= (BUFFPEK*) queue_top(&queue);
1199
1182
memcpy(param->unique_buff, buffpek->key, rec_length);
1200
1183
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1185
error=1; goto err; /* purecov: inspected */
1204
1187
buffpek->key+= rec_length;
1205
1188
buffpek->mem_count--;
1206
1189
if (!--max_rows)
1191
error= 0; /* purecov: inspected */
1192
goto end; /* purecov: inspected */
1211
/* Top element has been used */
1213
queue.push(buffpek);
1194
queue_replaced(&queue); // Top element has been used
1216
1197
cmp= 0; // Not unique
1218
while (queue.size() > 1)
1199
while (queue.elements > 1)
1203
error= 1; goto err; /* purecov: inspected */
1226
buffpek= queue.top();
1207
buffpek= (BUFFPEK*) queue_top(&queue);
1227
1208
if (cmp) // Remove duplicates
1229
1210
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),