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(Session *session,
61
optimizer::SqlSelect *select,
62
unsigned char * *sort_keys,
63
internal::IO_CACHE *buffer_file,
64
internal::IO_CACHE *tempfile,
65
internal::IO_CACHE *indexfile);
67
static int write_keys(SORTPARAM *param,
68
unsigned char * *sort_keys,
70
internal::IO_CACHE *buffer_file,
71
internal::IO_CACHE *tempfile);
73
static void make_sortkey(SORTPARAM *param,
75
unsigned char *ref_pos);
24
#include <drizzled/server_includes.h>
26
#include <drizzled/drizzled_error_messages.h>
28
/* functions defined in this file */
30
static char **make_char_array(char **old_pos, register uint fields,
31
uint length, myf my_flag);
32
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
34
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
35
uchar * *sort_keys, IO_CACHE *buffer_file,
36
IO_CACHE *tempfile,IO_CACHE *indexfile);
37
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
38
uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
39
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
76
40
static void register_used_fields(SORTPARAM *param);
77
static int merge_index(SORTPARAM *param,
78
unsigned char *sort_buffer,
81
internal::IO_CACHE *tempfile,
82
internal::IO_CACHE *outfile);
83
static bool save_index(SORTPARAM *param,
84
unsigned char **sort_keys,
41
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
43
uint maxbuffer,IO_CACHE *tempfile,
45
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count,
86
46
filesort_info_st *table_sort);
87
static uint32_t suffix_length(uint32_t string_length);
88
static uint32_t sortlength(Session *session,
91
bool *multi_byte_charset);
92
static sort_addon_field_st *get_addon_fields(Session *session,
96
static void unpack_addon_fields(sort_addon_field_st *addon_field,
47
static uint suffix_length(uint32_t string_length);
48
static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
49
bool *multi_byte_charset);
50
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
51
uint sortlength, uint *plength);
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
100
56
Creates a set of pointers that can be used to read the rows
131
87
examined_rows will be set to number of examined rows
134
ha_rows filesort(Session *session, Table *table, SortField *sortorder, uint32_t s_length,
135
optimizer::SqlSelect *select, ha_rows max_rows,
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint s_length,
91
SQL_SELECT *select, ha_rows max_rows,
136
92
bool sort_positions, ha_rows *examined_rows)
139
95
uint32_t memavl, min_sort_memory;
142
98
ha_rows records= HA_POS_ERROR;
143
unsigned char **sort_keys= 0;
144
internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
100
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
146
102
bool multi_byte_charset;
149
105
TableList *tab= table->pos_in_table_list;
150
106
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
152
DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
108
DRIZZLE_FILESORT_START();
155
111
Release InnoDB's adaptive hash index latch (if holding) before
158
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
114
ha_release_temporary_latches(thd);
161
Don't use table->sort in filesort as it is also used by
162
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
163
119
when index_merge select has finished with it.
165
121
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
166
122
table->sort.io_cache= NULL;
168
124
outfile= table_sort.io_cache;
169
125
my_b_clear(&tempfile);
170
126
my_b_clear(&buffpek_pointers);
173
129
memset(¶m, 0, sizeof(param));
174
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
175
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;
176
132
param.addon_field= 0;
177
133
param.addon_length= 0;
178
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)
181
Get the descriptors of all fields whose values are appended
137
Get the descriptors of all fields whose values are appended
182
138
to sorted fields and get its total length in param.spack_length.
184
param.addon_field= get_addon_fields(session, table->getFields(),
140
param.addon_field= get_addon_fields(thd, table->field,
185
141
param.sort_length,
186
142
¶m.addon_length);
211
168
if (select && select->quick)
213
session->status_var.filesort_range_count++;
170
status_var_increment(thd->status_var.filesort_range_count);
217
session->status_var.filesort_scan_count++;
174
status_var_increment(thd->status_var.filesort_scan_count);
219
176
#ifdef CAN_TRUST_RANGE
220
177
if (select && select->quick && select->quick->records > 0L)
222
records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
223
table->cursor->stats.records)+EXTRA_RECORDS;
179
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
180
table->file->stats.records)+EXTRA_RECORDS;
224
181
selected_records_file=0;
229
records= table->cursor->estimate_rows_upper_bound();
186
records= table->file->estimate_rows_upper_bound();
231
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
234
191
if (records == HA_POS_ERROR)
235
192
records--; // we use 'records+1' below.
239
196
if (multi_byte_charset &&
240
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
197
!(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
243
memavl= session->variables.sortbuff_size;
244
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
200
memavl= thd->variables.sortbuff_size;
201
min_sort_memory= max((uint)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
245
202
while (memavl >= min_sort_memory)
247
204
uint32_t old_memavl;
248
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
249
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
206
param.keys=(uint) min(records+1, keys);
250
207
if ((table_sort.sort_keys=
251
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
252
param.keys, param.rec_length)))
208
(uchar **) make_char_array((char **) table_sort.sort_keys,
209
param.keys, param.rec_length, MYF(0))))
255
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)
256
213
memavl= min_sort_memory;
258
215
sort_keys= table_sort.sort_keys;
261
218
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
264
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
221
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
265
222
DISK_BUFFER_SIZE, MYF(MY_WME)))
268
225
param.keys--; /* TODO: check why we do this */
269
226
param.sort_form= table;
270
227
param.end=(param.local_sortorder=sortorder)+s_length;
271
if ((records=find_all_keys(session, ¶m,select,sort_keys, &buffpek_pointers,
228
if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
272
229
&tempfile, selected_records_file)) ==
275
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
232
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
277
234
if (maxbuffer == 0) // The whole set is in memory
279
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
236
if (save_index(¶m,sort_keys,(uint) records, &table_sort))
284
241
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
286
if (table_sort.buffpek)
287
free(table_sort.buffpek);
243
x_free(table_sort.buffpek);
288
244
table_sort.buffpek= 0;
290
246
if (!(table_sort.buffpek=
291
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
247
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
292
248
table_sort.buffpek)))
294
buffpek= (buffpek_st *) table_sort.buffpek;
250
buffpek= (BUFFPEK *) table_sort.buffpek;
295
251
table_sort.buffpek_len= maxbuffer;
296
252
close_cached_file(&buffpek_pointers);
297
253
/* Open cached file if it isn't open */
298
254
if (! my_b_inited(outfile) &&
299
open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
255
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
302
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
258
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
309
265
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
310
266
param.rec_length-1);
311
267
maxbuffer--; // Offset from 0
312
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
268
if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer,
315
271
if (flush_io_cache(&tempfile) ||
316
reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
272
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
318
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
274
if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
342
297
if (flush_io_cache(outfile))
345
internal::my_off_t save_pos=outfile->pos_in_file;
300
my_off_t save_pos=outfile->pos_in_file;
346
301
/* For following reads */
347
if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
302
if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
349
304
outfile->end_of_file=save_pos;
354
308
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
355
309
MYF(ME_ERROR+ME_WAITTANG));
359
session->status_var.filesort_rows+= (uint32_t) records;
311
statistic_add(thd->status_var.filesort_rows,
312
(uint32_t) records, &LOCK_status);
361
313
*examined_rows= param.examined_rows;
362
314
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
363
DRIZZLE_FILESORT_DONE(error, records);
364
return (error ? HA_POS_ERROR : records);
315
DRIZZLE_FILESORT_END();
316
return(error ? HA_POS_ERROR : records);
368
void Table::filesort_free_buffers(bool full)
320
void filesort_free_buffers(Table *table, bool full)
370
if (sort.record_pointers)
322
if (table->sort.record_pointers)
372
free((unsigned char*) sort.record_pointers);
373
sort.record_pointers=0;
324
my_free((uchar*) table->sort.record_pointers,MYF(0));
325
table->sort.record_pointers=0;
329
if (table->sort.sort_keys )
379
if ((unsigned char*) sort.sort_keys)
380
free((unsigned char*) sort.sort_keys);
331
x_free((uchar*) table->sort.sort_keys);
332
table->sort.sort_keys= 0;
334
if (table->sort.buffpek)
385
if ((unsigned char*) sort.buffpek)
386
free((unsigned char*) sort.buffpek);
336
x_free((uchar*) table->sort.buffpek);
337
table->sort.buffpek= 0;
338
table->sort.buffpek_len= 0;
341
if (table->sort.addon_buf)
393
free((char *) sort.addon_buf);
394
free((char *) sort.addon_field);
343
my_free((char *) table->sort.addon_buf, MYF(0));
344
my_free((char *) table->sort.addon_field, MYF(MY_ALLOW_ZERO_PTR));
345
table->sort.addon_buf=0;
346
table->sort.addon_field=0;
400
350
/** Make a array of string pointers. */
402
static char **make_char_array(char **old_pos, register uint32_t fields,
352
static char **make_char_array(char **old_pos, register uint fields,
353
uint length, myf my_flag)
405
355
register char **pos;
409
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
359
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
411
362
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
412
363
while (fields--) *(pos++) = (char_pos+= length);
419
370
/** Read 'count' number of buffer pointers into memory. */
421
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
372
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
424
uint32_t length= sizeof(buffpek_st)*count;
425
unsigned char *tmp= buf;
426
if (count > UINT_MAX/sizeof(buffpek_st))
427
return 0; /* sizeof(buffpek_st)*count will overflow */
375
uint32_t length= sizeof(BUFFPEK)*count;
377
if (count > UINT_MAX/sizeof(BUFFPEK))
378
return 0; /* sizeof(BUFFPEK)*count will overflow */
429
tmp= (unsigned char *)malloc(length);
380
tmp= (uchar *)my_malloc(length, MYF(MY_WME));
432
if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
433
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
383
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
384
my_b_read(buffpek_pointers, (uchar*) tmp, length))
386
my_free((char*) tmp, MYF(0));
477
428
HA_POS_ERROR on error.
480
static ha_rows find_all_keys(Session *session,
482
optimizer::SqlSelect *select,
483
unsigned char **sort_keys,
484
internal::IO_CACHE *buffpek_pointers,
485
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
431
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
433
IO_CACHE *buffpek_pointers,
434
IO_CACHE *tempfile, IO_CACHE *indexfile)
487
436
int error,flag,quick_select;
488
uint32_t idx,indexpos,ref_length;
489
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
490
internal::my_off_t record;
437
uint idx,indexpos,ref_length;
438
uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
491
440
Table *sort_form;
492
volatile Session::killed_state *killed= &session->killed;
494
MyBitmap *save_read_set, *save_write_set;
441
THD *thd= current_thd;
442
volatile THD::killed_state *killed= &thd->killed;
444
MY_BITMAP *save_read_set, *save_write_set;
497
447
error=quick_select=0;
498
448
sort_form=param->sort_form;
499
file= sort_form->cursor;
449
file=sort_form->file;
500
450
ref_length=param->ref_length;
501
451
ref_pos= ref_buff;
502
452
quick_select=select && select->quick;
504
flag= ((!indexfile && ! file->isOrdered())
454
flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
505
455
|| quick_select);
506
456
if (indexfile || flag)
507
457
ref_pos= &file->ref[0];
508
458
next_pos=ref_pos;
509
459
if (! indexfile && ! quick_select)
511
next_pos=(unsigned char*) 0; /* Find records in sequence */
512
file->startTableScan(1);
461
next_pos=(uchar*) 0; /* Find records in sequence */
462
file->ha_rnd_init(1);
513
463
file->extra_opt(HA_EXTRA_CACHE,
514
session->variables.read_buff_size);
464
current_thd->variables.read_buff_size);
517
ReadRecord read_record_info;
467
READ_RECORD read_record_info;
518
468
if (quick_select)
520
470
if (select->quick->reset())
521
471
return(HA_POS_ERROR);
523
read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
472
init_read_record(&read_record_info, current_thd, select->quick->head,
526
476
/* Remember original bitmaps */
527
477
save_read_set= sort_form->read_set;
528
478
save_write_set= sort_form->write_set;
529
479
/* Set up temporary column read map for columns used by sort */
530
sort_form->tmp_set.clearAll();
480
bitmap_clear_all(&sort_form->tmp_set);
531
481
/* Temporary set for register_used_fields and register_field_in_read_map */
532
482
sort_form->read_set= &sort_form->tmp_set;
533
483
register_used_fields(param);
534
484
if (select && select->cond)
535
485
select->cond->walk(&Item::register_field_in_read_map, 1,
536
(unsigned char*) sort_form);
537
487
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
545
495
error= HA_ERR_END_OF_FILE;
548
file->position(sort_form->getInsertRecord());
498
file->position(sort_form->record[0]);
550
500
else /* Not quick-select */
554
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
504
if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */
556
error= errno ? errno : -1; /* Abort */
506
error= my_errno ? my_errno : -1; /* Abort */
559
error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
509
error=file->rnd_pos(sort_form->record[0],next_pos);
563
error=file->rnd_next(sort_form->getInsertRecord());
513
error=file->rnd_next(sort_form->record[0]);
567
internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
568
record+= sort_form->getShare()->db_record_offset;
516
my_store_ptr(ref_pos,ref_length,record); // Position to row
517
record+= sort_form->s->db_record_offset;
571
file->position(sort_form->getInsertRecord());
520
file->position(sort_form->record[0]);
573
522
if (error && error != HA_ERR_RECORD_DELETED)
608
557
index_merge quick select uses table->sort when retrieving rows, so free
609
558
resoures it has allocated.
611
read_record_info.end_read_record();
560
end_read_record(&read_record_info);
615
564
(void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */
617
file->endTableScan();
620
if (session->is_error())
621
570
return(HA_POS_ERROR);
623
572
/* Signal we should use orignal column read and write maps */
624
573
sort_form->column_bitmaps_set(save_read_set, save_write_set);
626
575
if (error != HA_ERR_END_OF_FILE)
628
sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
629
return(HA_POS_ERROR);
577
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
578
return(HA_POS_ERROR); /* purecov: inspected */
631
580
if (indexpos && idx &&
632
581
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
633
return(HA_POS_ERROR);
582
return(HA_POS_ERROR); /* purecov: inspected */
634
583
return(my_b_inited(tempfile) ?
635
584
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
642
591
Sort the buffer and write:
643
592
-# the sorted sequence to tempfile
644
-# a buffpek_st describing the sorted sequence position to buffpek_pointers
593
-# a BUFFPEK describing the sorted sequence position to buffpek_pointers
646
595
(was: Skriver en buffert med nycklar till filen)
648
597
@param param Sort parameters
649
598
@param sort_keys Array of pointers to keys to sort
650
599
@param count Number of elements in sort_keys array
651
@param buffpek_pointers One 'buffpek_st' struct will be written into this file.
652
The buffpek_st::{file_pos, count} will indicate where
600
@param buffpek_pointers One 'BUFFPEK' struct will be written into this file.
601
The BUFFPEK::{file_pos, count} will indicate where
653
602
the sorted data was stored.
654
603
@param tempfile The sorted sequence will be written into this file.
663
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
664
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
612
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
613
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
666
615
size_t sort_length, rec_length;
670
619
sort_length= param->sort_length;
671
620
rec_length= param->rec_length;
672
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
621
my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
673
622
if (!my_b_inited(tempfile) &&
674
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
623
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
625
goto err; /* purecov: inspected */
677
626
/* check we won't have more buffpeks than we can possibly keep in memory */
678
if (my_b_tell(buffpek_pointers) + sizeof(buffpek_st) > (uint64_t)UINT_MAX)
627
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
680
629
buffpek.file_pos= my_b_tell(tempfile);
681
630
if ((ha_rows) count > param->max_rows)
682
count=(uint32_t) param->max_rows;
631
count=(uint) param->max_rows; /* purecov: inspected */
683
632
buffpek.count=(ha_rows) count;
684
633
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
685
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
634
if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
687
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
636
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
798
749
if (sort_field->need_strxnfrm)
800
751
char *from=(char*) res->ptr();
802
if ((unsigned char*) from == to)
753
if ((uchar*) from == to)
804
755
set_if_smaller(length,sort_field->length);
805
756
memcpy(param->tmp_buffer,from,length);
806
757
from=param->tmp_buffer;
808
759
tmp_length= my_strnxfrm(cs,to,sort_field->length,
809
(unsigned char*) from, length);
760
(uchar*) from, length);
810
761
assert(tmp_length == sort_field->length);
814
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
765
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
815
766
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
836
to[7]= (unsigned char) value;
837
to[6]= (unsigned char) (value >> 8);
838
to[5]= (unsigned char) (value >> 16);
839
to[4]= (unsigned char) (value >> 24);
840
to[3]= (unsigned char) (value >> 32);
841
to[2]= (unsigned char) (value >> 40);
842
to[1]= (unsigned char) (value >> 48);
843
if (item->unsigned_flag) /* Fix sign */
844
to[0]= (unsigned char) (value >> 56);
846
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
787
#if SIZEOF_LONG_LONG > 4
788
to[7]= (uchar) value;
789
to[6]= (uchar) (value >> 8);
790
to[5]= (uchar) (value >> 16);
791
to[4]= (uchar) (value >> 24);
792
to[3]= (uchar) (value >> 32);
793
to[2]= (uchar) (value >> 40);
794
to[1]= (uchar) (value >> 48);
795
if (item->unsigned_flag) /* Fix sign */
796
to[0]= (uchar) (value >> 56);
798
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
800
to[3]= (uchar) value;
801
to[2]= (uchar) (value >> 8);
802
to[1]= (uchar) (value >> 16);
803
if (item->unsigned_flag) /* Fix sign */
804
to[0]= (uchar) (value >> 24);
806
to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
849
810
case DECIMAL_RESULT:
965
927
if ((field= sort_field->field))
967
if (field->getTable() == table)
968
table->setReadSet(field->field_index);
929
if (field->table == table)
930
bitmap_set_bit(bitmap, field->field_index);
972
934
sort_field->item->walk(&Item::register_field_in_read_map, 1,
973
(unsigned char *) table);
977
939
if (param->addon_field)
979
sort_addon_field_st *addonf= param->addon_field;
941
SORT_ADDON_FIELD *addonf= param->addon_field;
981
943
for ( ; (field= addonf->field) ; addonf++)
982
table->setReadSet(field->field_index);
944
bitmap_set_bit(bitmap, field->field_index);
992
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
954
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
993
955
filesort_info_st *table_sort)
995
uint32_t offset,res_length;
957
uint offset,res_length;
998
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
960
my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
999
961
res_length= param->res_length;
1000
962
offset= param->rec_length-res_length;
1001
963
if ((ha_rows) count > param->max_rows)
1002
count=(uint32_t) param->max_rows;
1003
if (!(to= table_sort->record_pointers=
1004
(unsigned char*) malloc(res_length*count)))
1006
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
964
count=(uint) param->max_rows;
965
if (!(to= table_sort->record_pointers=
966
(uchar*) my_malloc(res_length*count, MYF(MY_WME))))
967
return(1); /* purecov: inspected */
968
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1008
970
memcpy(to, *sort_keys+offset, res_length);
1009
971
to+= res_length;
1015
977
/** Merge buffers to make < MERGEBUFF2 buffers. */
1017
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1018
buffpek_st *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
979
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
980
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
1020
register uint32_t i;
1021
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1022
buffpek_st *lastbuff;
983
IO_CACHE t_file2,*from_file,*to_file,*temp;
1024
986
if (*maxbuffer < MERGEBUFF2)
987
return(0); /* purecov: inspected */
1026
988
if (flush_io_cache(t_file) ||
1027
open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
989
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
991
return(1); /* purecov: inspected */
1031
993
from_file= t_file ; to_file= &t_file2;
1032
994
while (*maxbuffer >= MERGEBUFF2)
1034
if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
996
if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1036
if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
998
if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1038
1000
lastbuff=buffpek;
1039
1001
for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1068
1030
Read data to buffer.
1071
(uint32_t)-1 if something goes wrong
1033
(uint)-1 if something goes wrong
1074
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, buffpek_st *buffpek,
1075
uint32_t rec_length)
1036
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1077
register uint32_t count;
1039
register uint count;
1080
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1042
if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
1082
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1083
return((uint32_t) -1);
1085
buffpek->key= buffpek->base;
1044
if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1045
return((uint) -1); /* purecov: inspected */
1046
buffpek->key=buffpek->base;
1086
1047
buffpek->file_pos+= length; /* New filepos */
1087
buffpek->count-= count;
1048
buffpek->count-= count;
1088
1049
buffpek->mem_count= count;
1090
1051
return (count*rec_length);
1091
1052
} /* read_to_buffer */
1094
class compare_functor
1056
Put all room used by freed buffer to use in adjacent buffer.
1058
Note, that we can't simply distribute memory evenly between all buffers,
1059
because new areas must not overlap with old ones.
1061
@param[in] queue list of non-empty buffers, without freed buffer
1062
@param[in] reuse empty buffer
1063
@param[in] key_length key length
1066
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
1096
qsort2_cmp key_compare;
1097
void *key_compare_arg;
1099
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1100
: key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1101
inline bool operator()(const buffpek_st *i, const buffpek_st *j) const
1068
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1069
for (uint i= 0; i < queue->elements; ++i)
1103
int val= key_compare(key_compare_arg,
1071
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1072
if (bp->base + bp->max_keys * key_length == reuse->base)
1074
bp->max_keys+= reuse->max_keys;
1077
else if (bp->base == reuse_end)
1079
bp->base= reuse->base;
1080
bp->max_keys+= reuse->max_keys;
1111
1089
Merge buffers to one buffer.
1113
1091
@param param Sort parameter
1114
@param from_file File with source data (buffpek_sts point to this file)
1092
@param from_file File with source data (BUFFPEKs point to this file)
1115
1093
@param to_file File to write the sorted result data.
1116
1094
@param sort_buffer Buffer for data to store up to MERGEBUFF2 sort keys.
1117
@param lastbuff OUT Store here buffpek_st describing data written to to_file
1118
@param Fb First element in source buffpek_sts array
1119
@param Tb Last element in source buffpek_sts array
1095
@param lastbuff OUT Store here BUFFPEK describing data written to to_file
1096
@param Fb First element in source BUFFPEKs array
1097
@param Tb Last element in source BUFFPEKs array
1128
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1129
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1130
buffpek_st *lastbuff, buffpek_st *Fb, buffpek_st *Tb,
1106
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1107
IO_CACHE *to_file, uchar *sort_buffer,
1108
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1134
uint32_t rec_length,res_length,offset;
1112
uint rec_length,res_length,offset;
1135
1113
size_t sort_length;
1136
1114
uint32_t maxcount;
1137
1115
ha_rows max_rows,org_max_rows;
1138
internal::my_off_t to_start_filepos;
1139
unsigned char *strpos;
1140
buffpek_st *buffpek;
1116
my_off_t to_start_filepos;
1141
1120
qsort2_cmp cmp;
1142
1121
void *first_cmp_arg;
1143
volatile Session::killed_state *killed= ¤t_session->killed;
1144
Session::killed_state not_killable;
1122
volatile THD::killed_state *killed= ¤t_thd->killed;
1123
THD::killed_state not_killable;
1146
current_session->status_var.filesort_merge_passes++;
1125
status_var_increment(current_thd->status_var.filesort_merge_passes);
1147
1126
if (param->not_killable)
1149
1128
killed= ¬_killable;
1150
not_killable= Session::NOT_KILLED;
1129
not_killable= THD::NOT_KILLED;
1173
cmp= internal::get_ptr_compare(sort_length);
1152
cmp= get_ptr_compare(sort_length);
1174
1153
first_cmp_arg= (void*) &sort_length;
1176
priority_queue<buffpek_st *, vector<buffpek_st *>, compare_functor >
1177
queue(compare_functor(cmp, first_cmp_arg));
1155
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1156
(queue_compare) cmp, first_cmp_arg))
1157
return(1); /* purecov: inspected */
1178
1158
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1180
1160
buffpek->base= strpos;
1181
1161
buffpek->max_keys= maxcount;
1182
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1162
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
1184
1164
if (error == -1)
1165
goto err; /* purecov: inspected */
1186
1166
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1187
queue.push(buffpek);
1167
queue_insert(&queue, (uchar*) buffpek);
1190
1170
if (param->unique_buff)
1193
1173
Called by Unique::get()
1194
1174
Copy the first argument to param->unique_buff for unique removal.
1195
1175
Store it also in 'to_file'.
1197
1177
This is safe as we know that there is always more than one element
1198
1178
in each block to merge (This is guaranteed by the Unique:: algorithm
1200
buffpek= queue.top();
1180
buffpek= (BUFFPEK*) queue_top(&queue);
1201
1181
memcpy(param->unique_buff, buffpek->key, rec_length);
1202
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1182
if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
1184
error=1; goto err; /* purecov: inspected */
1206
1186
buffpek->key+= rec_length;
1207
1187
buffpek->mem_count--;
1208
1188
if (!--max_rows)
1190
error= 0; /* purecov: inspected */
1191
goto end; /* purecov: inspected */
1213
/* Top element has been used */
1215
queue.push(buffpek);
1193
queue_replaced(&queue); // Top element has been used
1218
1196
cmp= 0; // Not unique
1220
while (queue.size() > 1)
1198
while (queue.elements > 1)
1202
error= 1; goto err; /* purecov: inspected */
1228
buffpek= queue.top();
1206
buffpek= (BUFFPEK*) queue_top(&queue);
1229
1207
if (cmp) // Remove duplicates
1231
1209
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1232
(unsigned char**) &buffpek->key))
1210
(uchar**) &buffpek->key))
1233
1211
goto skip_duplicate;
1234
1212
memcpy(param->unique_buff, buffpek->key, rec_length);
1238
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1216
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1218
error=1; goto err; /* purecov: inspected */
1245
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1223
if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1225
error=1; goto err; /* purecov: inspected */
1250
1228
if (!--max_rows)
1230
error= 0; /* purecov: inspected */
1231
goto end; /* purecov: inspected */
1256
1234
skip_duplicate:
1293
1270
if ((ha_rows) buffpek->mem_count > max_rows)
1294
1271
{ /* Don't write too many records */
1295
buffpek->mem_count= (uint32_t) max_rows;
1272
buffpek->mem_count= (uint) max_rows;
1296
1273
buffpek->count= 0; /* Don't read more */
1298
1275
max_rows-= buffpek->mem_count;
1301
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1278
if (my_b_write(to_file,(uchar*) buffpek->key,
1302
1279
(rec_length*buffpek->mem_count)))
1281
error= 1; goto err; /* purecov: inspected */
1309
register unsigned char *end;
1286
register uchar *end;
1310
1287
strpos= buffpek->key+offset;
1311
1288
for (end= strpos+buffpek->mem_count*rec_length ;
1312
1289
strpos != end ;
1313
1290
strpos+= rec_length)
1315
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1292
if (my_b_write(to_file, (uchar *) strpos, res_length))
1326
1303
lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1327
1304
lastbuff->file_pos= to_start_filepos;
1306
delete_queue(&queue);
1330
1308
} /* merge_buffers */
1333
1311
/* Do a merge to output-file (save only positions) */
1335
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1336
buffpek_st *buffpek, uint32_t maxbuffer,
1337
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1313
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1314
BUFFPEK *buffpek, uint maxbuffer,
1315
IO_CACHE *tempfile, IO_CACHE *outfile)
1339
1317
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1340
1318
buffpek+maxbuffer,1))
1319
return(1); /* purecov: inspected */
1343
1321
} /* merge_index */
1346
static uint32_t suffix_length(uint32_t string_length)
1324
static uint suffix_length(uint32_t string_length)
1348
1326
if (string_length < 256)
1619
1600
if (tmp[0] & 128) /* Negative */
1620
1601
{ /* make complement */
1622
1603
for (i=0 ; i < sizeof(nr); i++)
1623
tmp[i]=tmp[i] ^ (unsigned char) 255;
1604
tmp[i]=tmp[i] ^ (uchar) 255;
1626
1607
{ /* Set high and move exponent one up */
1627
uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1629
exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
1630
tmp[0]= (unsigned char) (exp_part >> 8);
1631
tmp[1]= (unsigned char) exp_part;
1608
ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
1610
exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
1611
tmp[0]= (uchar) (exp_part >> 8);
1612
tmp[1]= (uchar) exp_part;
1636
} /* namespace drizzled */