28
28
/* functions defined in this file */
30
static char **make_char_array(char **old_pos, register uint32_t fields,
31
uint32_t length, myf my_flag);
32
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
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
34
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
35
unsigned char * *sort_keys, IO_CACHE *buffer_file,
35
uchar * *sort_keys, IO_CACHE *buffer_file,
36
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);
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);
40
40
static void register_used_fields(SORTPARAM *param);
41
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
41
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
43
uint32_t maxbuffer,IO_CACHE *tempfile,
43
uint maxbuffer,IO_CACHE *tempfile,
44
44
IO_CACHE *outfile);
45
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
45
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count,
46
46
filesort_info_st *table_sort);
47
static uint32_t suffix_length(uint32_t string_length);
48
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
47
static uint suffix_length(uint32_t string_length);
48
static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
49
49
bool *multi_byte_charset);
50
50
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
51
uint32_t sortlength, uint32_t *plength);
51
uint sortlength, uint *plength);
52
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
56
56
Creates a set of pointers that can be used to read the rows
87
87
examined_rows will be set to number of examined rows
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint s_length,
91
91
SQL_SELECT *select, ha_rows max_rows,
92
92
bool sort_positions, ha_rows *examined_rows)
95
95
uint32_t memavl, min_sort_memory;
98
98
ha_rows records= HA_POS_ERROR;
99
unsigned char **sort_keys= 0;
100
100
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
102
102
bool multi_byte_charset;
200
200
memavl= thd->variables.sortbuff_size;
201
min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
201
min_sort_memory= cmax((uint)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
202
202
while (memavl >= min_sort_memory)
204
204
uint32_t old_memavl;
205
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
206
param.keys=(uint32_t) cmin(records+1, keys);
206
param.keys=(uint) cmin(records+1, keys);
207
207
if ((table_sort.sort_keys=
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
208
(uchar **) make_char_array((char **) table_sort.sort_keys,
209
209
param.keys, param.rec_length, MYF(0))))
211
211
old_memavl=memavl;
229
229
&tempfile, selected_records_file)) ==
232
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
232
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
234
234
if (maxbuffer == 0) // The whole set is in memory
236
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
236
if (save_index(¶m,sort_keys,(uint) records, &table_sort))
266
266
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
267
267
param.rec_length-1);
268
268
maxbuffer--; // Offset from 0
269
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
269
if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer,
272
272
if (flush_io_cache(&tempfile) ||
273
273
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
275
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
275
if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
326
326
if (table->sort.record_pointers)
328
free((unsigned char*) table->sort.record_pointers);
328
my_free((uchar*) table->sort.record_pointers,MYF(0));
329
329
table->sort.record_pointers=0;
333
333
if (table->sort.sort_keys )
335
if ((unsigned char*) table->sort.sort_keys)
336
free((unsigned char*) table->sort.sort_keys);
335
if ((uchar*) table->sort.sort_keys)
336
free((uchar*) table->sort.sort_keys);
337
337
table->sort.sort_keys= 0;
339
339
if (table->sort.buffpek)
341
if ((unsigned char*) table->sort.buffpek)
342
free((unsigned char*) table->sort.buffpek);
341
if ((uchar*) table->sort.buffpek)
342
free((uchar*) table->sort.buffpek);
343
343
table->sort.buffpek= 0;
344
344
table->sort.buffpek_len= 0;
347
347
if (table->sort.addon_buf)
349
free((char *) table->sort.addon_buf);
350
free((char *) table->sort.addon_field);
349
my_free((char *) table->sort.addon_buf, MYF(0));
350
my_free((char *) table->sort.addon_field, MYF(MY_ALLOW_ZERO_PTR));
351
351
table->sort.addon_buf=0;
352
352
table->sort.addon_field=0;
356
356
/** Make a array of string pointers. */
358
static char **make_char_array(char **old_pos, register uint32_t fields,
359
uint32_t length, myf my_flag)
358
static char **make_char_array(char **old_pos, register uint fields,
359
uint length, myf my_flag)
361
361
register char **pos;
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
365
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
368
368
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
376
376
/** Read 'count' number of buffer pointers into memory. */
378
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
378
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
381
381
uint32_t length= sizeof(BUFFPEK)*count;
382
unsigned char *tmp= buf;
383
383
if (count > UINT_MAX/sizeof(BUFFPEK))
384
384
return 0; /* sizeof(BUFFPEK)*count will overflow */
386
tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
386
tmp= (uchar *)my_malloc(length, MYF(MY_WME));
389
389
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
390
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
390
my_b_read(buffpek_pointers, (uchar*) tmp, length))
392
my_free((char*) tmp, MYF(0));
437
437
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
438
unsigned char **sort_keys,
439
439
IO_CACHE *buffpek_pointers,
440
440
IO_CACHE *tempfile, IO_CACHE *indexfile)
442
442
int error,flag,quick_select;
443
uint32_t idx,indexpos,ref_length;
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
443
uint idx,indexpos,ref_length;
444
uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
446
446
Table *sort_form;
447
447
THD *thd= current_thd;
621
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
618
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
622
619
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
624
621
size_t sort_length, rec_length;
628
625
sort_length= param->sort_length;
629
626
rec_length= param->rec_length;
630
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
627
my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
631
628
if (!my_b_inited(tempfile) &&
632
629
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
638
635
buffpek.file_pos= my_b_tell(tempfile);
639
636
if ((ha_rows) count > param->max_rows)
640
count=(uint32_t) param->max_rows; /* purecov: inspected */
637
count=(uint) param->max_rows; /* purecov: inspected */
641
638
buffpek.count=(ha_rows) count;
642
639
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
643
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
640
if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
645
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
642
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
677
674
/** Make a sort-key from record. */
679
676
static void make_sortkey(register SORTPARAM *param,
680
register unsigned char *to, unsigned char *ref_pos)
677
register uchar *to, uchar *ref_pos)
682
679
register Field *field;
683
680
register SORT_FIELD *sort_field;
684
register uint32_t length;
681
register uint length;
686
683
for (sort_field=param->local_sortorder ;
687
684
sort_field != param->end ;
758
755
if (sort_field->need_strxnfrm)
760
757
char *from=(char*) res->ptr();
762
if ((unsigned char*) from == to)
759
if ((uchar*) from == to)
764
761
set_if_smaller(length,sort_field->length);
765
762
memcpy(param->tmp_buffer,from,length);
766
763
from=param->tmp_buffer;
768
765
tmp_length= my_strnxfrm(cs,to,sort_field->length,
769
(unsigned char*) from, length);
766
(uchar*) from, length);
770
767
assert(tmp_length == sort_field->length);
774
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
771
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
775
772
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
796
to[7]= (unsigned char) value;
797
to[6]= (unsigned char) (value >> 8);
798
to[5]= (unsigned char) (value >> 16);
799
to[4]= (unsigned char) (value >> 24);
800
to[3]= (unsigned char) (value >> 32);
801
to[2]= (unsigned char) (value >> 40);
802
to[1]= (unsigned char) (value >> 48);
803
if (item->unsigned_flag) /* Fix sign */
804
to[0]= (unsigned char) (value >> 56);
806
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
793
#if SIZEOF_LONG_LONG > 4
794
to[7]= (uchar) value;
795
to[6]= (uchar) (value >> 8);
796
to[5]= (uchar) (value >> 16);
797
to[4]= (uchar) (value >> 24);
798
to[3]= (uchar) (value >> 32);
799
to[2]= (uchar) (value >> 40);
800
to[1]= (uchar) (value >> 48);
801
if (item->unsigned_flag) /* Fix sign */
802
to[0]= (uchar) (value >> 56);
804
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
806
to[3]= (uchar) value;
807
to[2]= (uchar) (value >> 8);
808
to[1]= (uchar) (value >> 16);
809
if (item->unsigned_flag) /* Fix sign */
810
to[0]= (uchar) (value >> 24);
812
to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
809
816
case DECIMAL_RESULT:
953
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
960
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count,
954
961
filesort_info_st *table_sort)
956
uint32_t offset,res_length;
963
uint offset,res_length;
959
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
966
my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
960
967
res_length= param->res_length;
961
968
offset= param->rec_length-res_length;
962
969
if ((ha_rows) count > param->max_rows)
963
count=(uint32_t) param->max_rows;
970
count=(uint) param->max_rows;
964
971
if (!(to= table_sort->record_pointers=
965
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
972
(uchar*) my_malloc(res_length*count, MYF(MY_WME))))
966
973
return(1); /* purecov: inspected */
967
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
974
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
969
976
memcpy(to, *sort_keys+offset, res_length);
976
983
/** Merge buffers to make < MERGEBUFF2 buffers. */
978
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
979
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
985
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
986
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
982
989
IO_CACHE t_file2,*from_file,*to_file,*temp;
983
990
BUFFPEK *lastbuff;
1029
1036
Read data to buffer.
1032
(uint32_t)-1 if something goes wrong
1039
(uint)-1 if something goes wrong
1035
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1036
uint32_t rec_length)
1042
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1038
register uint32_t count;
1045
register uint count;
1041
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1048
if ((count=(uint) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1043
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1044
return((uint32_t) -1); /* purecov: inspected */
1050
if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1051
return((uint) -1); /* purecov: inspected */
1045
1052
buffpek->key=buffpek->base;
1046
1053
buffpek->file_pos+= length; /* New filepos */
1047
1054
buffpek->count-= count;
1062
1069
@param[in] key_length key length
1065
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1072
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
1067
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1068
for (uint32_t i= 0; i < queue->elements; ++i)
1074
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
for (uint i= 0; i < queue->elements; ++i)
1070
1077
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1071
1078
if (bp->base + bp->max_keys * key_length == reuse->base)
1105
1112
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1106
IO_CACHE *to_file, unsigned char *sort_buffer,
1113
IO_CACHE *to_file, uchar *sort_buffer,
1107
1114
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1111
uint32_t rec_length,res_length,offset;
1118
uint rec_length,res_length,offset;
1112
1119
size_t sort_length;
1113
1120
uint32_t maxcount;
1114
1121
ha_rows max_rows,org_max_rows;
1115
1122
my_off_t to_start_filepos;
1116
unsigned char *strpos;
1117
1124
BUFFPEK *buffpek;
1119
1126
qsort2_cmp cmp;
1133
1140
res_length= param->res_length;
1134
1141
sort_length= param->sort_length;
1135
1142
offset= rec_length-res_length;
1136
maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1143
maxcount= (uint32_t) (param->keys/((uint) (Tb-Fb) +1));
1137
1144
to_start_filepos= my_b_tell(to_file);
1138
strpos= (unsigned char*) sort_buffer;
1145
strpos= (uchar*) sort_buffer;
1139
1146
org_max_rows=max_rows= param->max_rows;
1141
1148
/* The following will fire if there is not enough space in sort_buffer */
1151
1158
cmp= get_ptr_compare(sort_length);
1152
1159
first_cmp_arg= (void*) &sort_length;
1154
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1161
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1155
1162
(queue_compare) cmp, first_cmp_arg))
1156
1163
return(1); /* purecov: inspected */
1157
1164
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1159
1166
buffpek->base= strpos;
1160
1167
buffpek->max_keys= maxcount;
1161
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1168
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
1163
1170
if (error == -1)
1164
1171
goto err; /* purecov: inspected */
1165
1172
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1166
queue_insert(&queue, (unsigned char*) buffpek);
1173
queue_insert(&queue, (uchar*) buffpek);
1169
1176
if (param->unique_buff)
1206
1213
if (cmp) // Remove duplicates
1208
1215
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1209
(unsigned char**) &buffpek->key))
1216
(uchar**) &buffpek->key))
1210
1217
goto skip_duplicate;
1211
1218
memcpy(param->unique_buff, buffpek->key, rec_length);
1215
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1222
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1217
1224
error=1; goto err; /* purecov: inspected */
1222
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1229
if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1224
1231
error=1; goto err; /* purecov: inspected */
1269
1276
if ((ha_rows) buffpek->mem_count > max_rows)
1270
1277
{ /* Don't write too many records */
1271
buffpek->mem_count= (uint32_t) max_rows;
1278
buffpek->mem_count= (uint) max_rows;
1272
1279
buffpek->count= 0; /* Don't read more */
1274
1281
max_rows-= buffpek->mem_count;
1277
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1284
if (my_b_write(to_file,(uchar*) buffpek->key,
1278
1285
(rec_length*buffpek->mem_count)))
1280
1287
error= 1; goto err; /* purecov: inspected */
1310
1317
/* Do a merge to output-file (save only positions) */
1312
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1313
BUFFPEK *buffpek, uint32_t maxbuffer,
1319
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1320
BUFFPEK *buffpek, uint maxbuffer,
1314
1321
IO_CACHE *tempfile, IO_CACHE *outfile)
1316
1323
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1569
1580
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1571
void change_double_for_sort(double nr,unsigned char *to)
1582
void change_double_for_sort(double nr,uchar *to)
1573
unsigned char *tmp=(unsigned char*) to;
1584
uchar *tmp=(uchar*) to;
1575
1586
{ /* Change to zero string */
1576
tmp[0]=(unsigned char) 128;
1577
1588
memset(tmp+1, 0, sizeof(nr)-1);
1595
1606
if (tmp[0] & 128) /* Negative */
1596
1607
{ /* make complement */
1598
1609
for (i=0 ; i < sizeof(nr); i++)
1599
tmp[i]=tmp[i] ^ (unsigned char) 255;
1610
tmp[i]=tmp[i] ^ (uchar) 255;
1602
1613
{ /* Set high and move exponent one up */
1603
uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1605
exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
1606
tmp[0]= (unsigned char) (exp_part >> 8);
1607
tmp[1]= (unsigned char) exp_part;
1614
ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
1616
exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
1617
tmp[0]= (uchar) (exp_part >> 8);
1618
tmp[1]= (uchar) exp_part;