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,
950
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
991
951
filesort_info_st *table_sort)
993
953
uint32_t offset,res_length;
994
954
unsigned char *to;
996
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
956
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
997
957
res_length= param->res_length;
998
958
offset= param->rec_length-res_length;
999
959
if ((ha_rows) count > param->max_rows)
1000
960
count=(uint32_t) param->max_rows;
1001
if (!(to= table_sort->record_pointers=
1002
(unsigned char*) malloc(res_length*count)))
961
if (!(to= table_sort->record_pointers=
962
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
963
return(1); /* purecov: inspected */
1004
964
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1006
966
memcpy(to, *sort_keys+offset, res_length);
1013
973
/** Merge buffers to make < MERGEBUFF2 buffers. */
1015
975
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1016
BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
976
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1018
978
register uint32_t i;
1019
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
979
IO_CACHE t_file2,*from_file,*to_file,*temp;
1020
980
BUFFPEK *lastbuff;
1022
982
if (*maxbuffer < MERGEBUFF2)
983
return(0); /* purecov: inspected */
1024
984
if (flush_io_cache(t_file) ||
1025
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
985
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
987
return(1); /* purecov: inspected */
1029
989
from_file= t_file ; to_file= &t_file2;
1030
990
while (*maxbuffer >= MERGEBUFF2)
1032
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
992
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1034
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
994
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1036
996
lastbuff=buffpek;
1037
997
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1069
1029
(uint32_t)-1 if something goes wrong
1072
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1073
uint32_t rec_length)
1032
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1033
uint32_t rec_length)
1075
1035
register uint32_t count;
1076
1036
uint32_t length;
1078
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1038
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1080
1040
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;
1041
return((uint32_t) -1); /* purecov: inspected */
1042
buffpek->key=buffpek->base;
1084
1043
buffpek->file_pos+= length; /* New filepos */
1085
buffpek->count-= count;
1044
buffpek->count-= count;
1086
1045
buffpek->mem_count= count;
1088
1047
return (count*rec_length);
1089
1048
} /* read_to_buffer */
1092
class compare_functor
1052
Put all room used by freed buffer to use in adjacent buffer.
1054
Note, that we can't simply distribute memory evenly between all buffers,
1055
because new areas must not overlap with old ones.
1057
@param[in] queue list of non-empty buffers, without freed buffer
1058
@param[in] reuse empty buffer
1059
@param[in] key_length key length
1062
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
1064
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1065
for (uint32_t i= 0; i < queue->elements; ++i)
1101
int val= key_compare(key_compare_arg,
1067
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1068
if (bp->base + bp->max_keys * key_length == reuse->base)
1070
bp->max_keys+= reuse->max_keys;
1073
else if (bp->base == reuse_end)
1075
bp->base= reuse->base;
1076
bp->max_keys+= reuse->max_keys;
1171
cmp= internal::get_ptr_compare(sort_length);
1148
cmp= get_ptr_compare(sort_length);
1172
1149
first_cmp_arg= (void*) &sort_length;
1174
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1175
queue(compare_functor(cmp, first_cmp_arg));
1151
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1152
(queue_compare) cmp, first_cmp_arg))
1153
return(1); /* purecov: inspected */
1176
1154
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1178
1156
buffpek->base= strpos;
1195
1173
This is safe as we know that there is always more than one element
1196
1174
in each block to merge (This is guaranteed by the Unique:: algorithm
1198
buffpek= queue.top();
1176
buffpek= (BUFFPEK*) queue_top(&queue);
1199
1177
memcpy(param->unique_buff, buffpek->key, rec_length);
1200
1178
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1180
error=1; goto err; /* purecov: inspected */
1204
1182
buffpek->key+= rec_length;
1205
1183
buffpek->mem_count--;
1206
1184
if (!--max_rows)
1186
error= 0; /* purecov: inspected */
1187
goto end; /* purecov: inspected */
1211
/* Top element has been used */
1213
queue.push(buffpek);
1189
queue_replaced(&queue); // Top element has been used
1216
1192
cmp= 0; // Not unique
1218
while (queue.size() > 1)
1194
while (queue.elements > 1)
1198
error= 1; goto err; /* purecov: inspected */
1226
buffpek= queue.top();
1202
buffpek= (BUFFPEK*) queue_top(&queue);
1227
1203
if (cmp) // Remove duplicates
1229
1205
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1459
1433
The function first finds out what fields are used in the result set.
1460
1434
Then it calculates the length of the buffer to store the values of
1461
these fields together with the value of sort values.
1435
these fields together with the value of sort values.
1462
1436
If the calculated length is not greater than max_length_for_sort_data
1463
1437
the function allocates memory for an array of descriptors containing
1464
1438
layouts for the values of the non-sorted fields in the buffer and
1467
@param session Current thread
1441
@param thd Current thread
1468
1442
@param ptabfield Array of references to the table fields
1469
1443
@param sortlength Total length of sorted fields
1470
1444
@param[out] plength Total length of appended fields