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 */
24
#include <drizzled/server_includes.h>
26
#include <drizzled/drizzled_error_messages.h>
28
/* functions defined in this file */
52
30
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);
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);
75
40
static void register_used_fields(SORTPARAM *param);
76
static int merge_index(SORTPARAM *param,
77
unsigned char *sort_buffer,
41
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,
43
uint32_t maxbuffer,IO_CACHE *tempfile,
45
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
85
46
filesort_info_st *table_sort);
86
47
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,
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);
95
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
96
53
unsigned char *buff);
148
105
TableList *tab= table->pos_in_table_list;
149
106
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
151
DRIZZLE_FILESORT_START(table->s->getSchemaName(), table->s->getTableName());
108
DRIZZLE_FILESORT_START();
154
111
Release InnoDB's adaptive hash index latch (if holding) before
157
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
114
ha_release_temporary_latches(thd);
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
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
162
119
when index_merge select has finished with it.
164
121
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
165
122
table->sort.io_cache= NULL;
167
124
outfile= table_sort.io_cache;
168
125
my_b_clear(&tempfile);
169
126
my_b_clear(&buffpek_pointers);
172
129
memset(¶m, 0, sizeof(param));
173
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
174
param.ref_length= table->cursor->ref_length;
130
param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
131
param.ref_length= table->file->ref_length;
175
132
param.addon_field= 0;
176
133
param.addon_length= 0;
177
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
134
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
180
Get the descriptors of all fields whose values are appended
137
Get the descriptors of all fields whose values are appended
181
138
to sorted fields and get its total length in param.spack_length.
183
param.addon_field= get_addon_fields(session, table->field,
140
param.addon_field= get_addon_fields(thd, table->field,
184
141
param.sort_length,
185
142
¶m.addon_length);
210
168
if (select && select->quick)
212
status_var_increment(session->status_var.filesort_range_count);
170
status_var_increment(thd->status_var.filesort_range_count);
216
status_var_increment(session->status_var.filesort_scan_count);
174
status_var_increment(thd->status_var.filesort_scan_count);
218
176
#ifdef CAN_TRUST_RANGE
219
177
if (select && select->quick && select->quick->records > 0L)
221
records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
222
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;
223
181
selected_records_file=0;
228
records= table->cursor->estimate_rows_upper_bound();
186
records= table->file->estimate_rows_upper_bound();
230
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
233
191
if (records == HA_POS_ERROR)
234
192
records--; // we use 'records+1' below.
238
196
if (multi_byte_charset &&
239
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
197
!(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
242
memavl= session->variables.sortbuff_size;
243
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);
244
202
while (memavl >= min_sort_memory)
246
204
uint32_t old_memavl;
247
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
248
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
206
param.keys=(uint32_t) cmin(records+1, keys);
249
207
if ((table_sort.sort_keys=
250
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
251
param.keys, param.rec_length)))
209
param.keys, param.rec_length, MYF(0))))
254
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)
255
213
memavl= min_sort_memory;
257
215
sort_keys= table_sort.sort_keys;
295
253
close_cached_file(&buffpek_pointers);
296
254
/* Open cached file if it isn't open */
297
255
if (! my_b_inited(outfile) &&
298
open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
256
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
301
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
259
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
354
312
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
355
313
MYF(ME_ERROR+ME_WAITTANG));
357
statistic_add(session->status_var.filesort_rows,
315
statistic_add(thd->status_var.filesort_rows,
358
316
(uint32_t) records, &LOCK_status);
359
317
*examined_rows= param.examined_rows;
360
318
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
361
DRIZZLE_FILESORT_DONE(error, records);
362
return (error ? HA_POS_ERROR : records);
319
DRIZZLE_FILESORT_END();
320
return(error ? HA_POS_ERROR : records);
366
void Table::filesort_free_buffers(bool full)
324
void filesort_free_buffers(Table *table, bool full)
368
if (sort.record_pointers)
326
if (table->sort.record_pointers)
370
free((unsigned char*) sort.record_pointers);
371
sort.record_pointers=0;
328
free((unsigned char*) table->sort.record_pointers);
329
table->sort.record_pointers=0;
333
if (table->sort.sort_keys )
377
if ((unsigned char*) sort.sort_keys)
378
free((unsigned char*) 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)
383
if ((unsigned char*) sort.buffpek)
384
free((unsigned char*) 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)
391
free((char *) sort.addon_buf);
392
free((char *) sort.addon_field);
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;
398
356
/** Make a array of string pointers. */
400
358
static char **make_char_array(char **old_pos, register uint32_t fields,
359
uint32_t length, myf my_flag)
403
361
register char **pos;
407
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
409
368
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
410
369
while (fields--) *(pos++) = (char_pos+= length);
475
434
HA_POS_ERROR on error.
478
static ha_rows find_all_keys(SORTPARAM *param,
479
optimizer::SqlSelect *select,
437
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
480
438
unsigned char **sort_keys,
481
internal::IO_CACHE *buffpek_pointers,
482
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
439
IO_CACHE *buffpek_pointers,
440
IO_CACHE *tempfile, IO_CACHE *indexfile)
484
442
int error,flag,quick_select;
485
443
uint32_t idx,indexpos,ref_length;
486
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
487
internal::my_off_t record;
488
446
Table *sort_form;
489
Session *session= current_session;
490
volatile Session::killed_state *killed= &session->killed;
492
MyBitmap *save_read_set, *save_write_set;
447
THD *thd= current_thd;
448
volatile THD::killed_state *killed= &thd->killed;
450
MY_BITMAP *save_read_set, *save_write_set;
495
453
error=quick_select=0;
496
454
sort_form=param->sort_form;
497
file= sort_form->cursor;
455
file=sort_form->file;
498
456
ref_length=param->ref_length;
499
457
ref_pos= ref_buff;
500
458
quick_select=select && select->quick;
502
flag= ((!indexfile && ! file->isOrdered())
460
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
503
461
|| quick_select);
504
462
if (indexfile || flag)
505
463
ref_pos= &file->ref[0];
615
572
file->ha_rnd_end();
618
if (session->is_error())
619
576
return(HA_POS_ERROR);
621
578
/* Signal we should use orignal column read and write maps */
622
579
sort_form->column_bitmaps_set(save_read_set, save_write_set);
624
581
if (error != HA_ERR_END_OF_FILE)
626
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
627
return(HA_POS_ERROR);
583
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
584
return(HA_POS_ERROR); /* purecov: inspected */
629
586
if (indexpos && idx &&
630
587
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
631
return(HA_POS_ERROR);
588
return(HA_POS_ERROR); /* purecov: inspected */
632
589
return(my_b_inited(tempfile) ?
633
590
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
668
625
sort_length= param->sort_length;
669
626
rec_length= param->rec_length;
670
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
627
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
671
628
if (!my_b_inited(tempfile) &&
672
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
629
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
631
goto err; /* purecov: inspected */
675
632
/* check we won't have more buffpeks than we can possibly keep in memory */
676
633
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
678
635
buffpek.file_pos= my_b_tell(tempfile);
679
636
if ((ha_rows) count > param->max_rows)
680
count=(uint32_t) param->max_rows;
637
count=(uint32_t) param->max_rows; /* purecov: inspected */
681
638
buffpek.count=(ha_rows) count;
682
639
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
683
640
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
990
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
960
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
991
961
filesort_info_st *table_sort)
993
963
uint32_t offset,res_length;
994
964
unsigned char *to;
996
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
966
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
997
967
res_length= param->res_length;
998
968
offset= param->rec_length-res_length;
999
969
if ((ha_rows) count > param->max_rows)
1000
970
count=(uint32_t) param->max_rows;
1001
if (!(to= table_sort->record_pointers=
1002
(unsigned char*) malloc(res_length*count)))
971
if (!(to= table_sort->record_pointers=
972
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
973
return(1); /* purecov: inspected */
1004
974
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1006
976
memcpy(to, *sort_keys+offset, res_length);
1013
983
/** Merge buffers to make < MERGEBUFF2 buffers. */
1015
985
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1016
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
986
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1018
988
register uint32_t i;
1019
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
989
IO_CACHE t_file2,*from_file,*to_file,*temp;
1020
990
BUFFPEK *lastbuff;
1022
992
if (*maxbuffer < MERGEBUFF2)
993
return(0); /* purecov: inspected */
1024
994
if (flush_io_cache(t_file) ||
1025
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
995
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
997
return(1); /* purecov: inspected */
1029
999
from_file= t_file ; to_file= &t_file2;
1030
1000
while (*maxbuffer >= MERGEBUFF2)
1032
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1002
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1034
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1004
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1036
1006
lastbuff=buffpek;
1037
1007
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1069
1039
(uint32_t)-1 if something goes wrong
1072
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
uint32_t rec_length)
1042
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1043
uint32_t rec_length)
1075
1045
register uint32_t count;
1076
1046
uint32_t length;
1078
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1048
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1080
1050
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;
1051
return((uint32_t) -1); /* purecov: inspected */
1052
buffpek->key=buffpek->base;
1084
1053
buffpek->file_pos+= length; /* New filepos */
1085
buffpek->count-= count;
1054
buffpek->count-= count;
1086
1055
buffpek->mem_count= count;
1088
1057
return (count*rec_length);
1089
1058
} /* read_to_buffer */
1092
class compare_functor
1062
Put all room used by freed buffer to use in adjacent buffer.
1064
Note, that we can't simply distribute memory evenly between all buffers,
1065
because new areas must not overlap with old ones.
1067
@param[in] queue list of non-empty buffers, without freed buffer
1068
@param[in] reuse empty buffer
1069
@param[in] key_length key length
1072
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
1074
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
for (uint32_t i= 0; i < queue->elements; ++i)
1101
int val= key_compare(key_compare_arg,
1077
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1078
if (bp->base + bp->max_keys * key_length == reuse->base)
1080
bp->max_keys+= reuse->max_keys;
1083
else if (bp->base == reuse_end)
1085
bp->base= reuse->base;
1086
bp->max_keys+= reuse->max_keys;
1171
cmp= internal::get_ptr_compare(sort_length);
1158
cmp= get_ptr_compare(sort_length);
1172
1159
first_cmp_arg= (void*) &sort_length;
1174
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1175
queue(compare_functor(cmp, first_cmp_arg));
1161
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1162
(queue_compare) cmp, first_cmp_arg))
1163
return(1); /* purecov: inspected */
1176
1164
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1178
1166
buffpek->base= strpos;
1195
1183
This is safe as we know that there is always more than one element
1196
1184
in each block to merge (This is guaranteed by the Unique:: algorithm
1198
buffpek= queue.top();
1186
buffpek= (BUFFPEK*) queue_top(&queue);
1199
1187
memcpy(param->unique_buff, buffpek->key, rec_length);
1200
1188
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1190
error=1; goto err; /* purecov: inspected */
1204
1192
buffpek->key+= rec_length;
1205
1193
buffpek->mem_count--;
1206
1194
if (!--max_rows)
1196
error= 0; /* purecov: inspected */
1197
goto end; /* purecov: inspected */
1211
/* Top element has been used */
1213
queue.push(buffpek);
1199
queue_replaced(&queue); // Top element has been used
1216
1202
cmp= 0; // Not unique
1218
while (queue.size() > 1)
1204
while (queue.elements > 1)
1208
error= 1; goto err; /* purecov: inspected */
1226
buffpek= queue.top();
1212
buffpek= (BUFFPEK*) queue_top(&queue);
1227
1213
if (cmp) // Remove duplicates
1229
1215
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1459
1447
The function first finds out what fields are used in the result set.
1460
1448
Then it calculates the length of the buffer to store the values of
1461
these fields together with the value of sort values.
1449
these fields together with the value of sort values.
1462
1450
If the calculated length is not greater than max_length_for_sort_data
1463
1451
the function allocates memory for an array of descriptors containing
1464
1452
layouts for the values of the non-sorted fields in the buffer and
1467
@param session Current thread
1455
@param thd Current thread
1468
1456
@param ptabfield Array of references to the table fields
1469
1457
@param sortlength Total length of sorted fields
1470
1458
@param[out] plength Total length of appended fields