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= max((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) min(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))
241
241
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
243
if (table_sort.buffpek)
244
free(table_sort.buffpek);
243
x_free(table_sort.buffpek);
245
244
table_sort.buffpek= 0;
247
246
if (!(table_sort.buffpek=
248
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
247
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
249
248
table_sort.buffpek)))
251
250
buffpek= (BUFFPEK *) table_sort.buffpek;
266
265
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
267
266
param.rec_length-1);
268
267
maxbuffer--; // Offset from 0
269
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek,&maxbuffer,
268
if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer,
272
271
if (flush_io_cache(&tempfile) ||
273
272
reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
275
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
274
if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
284
283
if (param.tmp_buffer)
285
if (param.tmp_buffer)
286
free(param.tmp_buffer);
284
x_free(param.tmp_buffer);
287
285
if (!subselect || !subselect->is_uncacheable())
289
if ((unsigned char*) sort_keys)
290
free((unsigned char*) sort_keys);
287
x_free((uchar*) sort_keys);
291
288
table_sort.sort_keys= 0;
292
if ((unsigned char*) buffpek)
293
free((unsigned char*) buffpek);
289
x_free((uchar*) buffpek);
294
290
table_sort.buffpek= 0;
295
291
table_sort.buffpek_len= 0;
326
322
if (table->sort.record_pointers)
328
free((unsigned char*) table->sort.record_pointers);
324
my_free((uchar*) table->sort.record_pointers,MYF(0));
329
325
table->sort.record_pointers=0;
333
329
if (table->sort.sort_keys )
335
if ((unsigned char*) table->sort.sort_keys)
336
free((unsigned char*) table->sort.sort_keys);
331
x_free((uchar*) table->sort.sort_keys);
337
332
table->sort.sort_keys= 0;
339
334
if (table->sort.buffpek)
341
if ((unsigned char*) table->sort.buffpek)
342
free((unsigned char*) table->sort.buffpek);
336
x_free((uchar*) table->sort.buffpek);
343
337
table->sort.buffpek= 0;
344
338
table->sort.buffpek_len= 0;
347
341
if (table->sort.addon_buf)
349
free((char *) table->sort.addon_buf);
350
free((char *) table->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));
351
345
table->sort.addon_buf=0;
352
346
table->sort.addon_field=0;
356
350
/** 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)
352
static char **make_char_array(char **old_pos, register uint fields,
353
uint length, myf my_flag)
361
355
register char **pos;
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
359
(old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
368
362
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
376
370
/** Read 'count' number of buffer pointers into memory. */
378
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
372
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
381
375
uint32_t length= sizeof(BUFFPEK)*count;
382
unsigned char *tmp= buf;
383
377
if (count > UINT_MAX/sizeof(BUFFPEK))
384
378
return 0; /* sizeof(BUFFPEK)*count will overflow */
386
tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
380
tmp= (uchar *)my_malloc(length, MYF(MY_WME));
389
383
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
390
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
384
my_b_read(buffpek_pointers, (uchar*) tmp, length))
386
my_free((char*) tmp, MYF(0));
437
431
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
438
unsigned char **sort_keys,
439
433
IO_CACHE *buffpek_pointers,
440
434
IO_CACHE *tempfile, IO_CACHE *indexfile)
442
436
int error,flag,quick_select;
443
uint32_t idx,indexpos,ref_length;
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
437
uint idx,indexpos,ref_length;
438
uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
446
440
Table *sort_form;
447
441
THD *thd= current_thd;
618
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
612
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
619
613
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
621
615
size_t sort_length, rec_length;
625
619
sort_length= param->sort_length;
626
620
rec_length= param->rec_length;
627
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);
628
622
if (!my_b_inited(tempfile) &&
629
623
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
635
629
buffpek.file_pos= my_b_tell(tempfile);
636
630
if ((ha_rows) count > param->max_rows)
637
count=(uint32_t) param->max_rows; /* purecov: inspected */
631
count=(uint) param->max_rows; /* purecov: inspected */
638
632
buffpek.count=(ha_rows) count;
639
633
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
640
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))
642
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
636
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
674
668
/** Make a sort-key from record. */
676
670
static void make_sortkey(register SORTPARAM *param,
677
register unsigned char *to, unsigned char *ref_pos)
671
register uchar *to, uchar *ref_pos)
679
673
register Field *field;
680
674
register SORT_FIELD *sort_field;
681
register uint32_t length;
675
register uint length;
683
677
for (sort_field=param->local_sortorder ;
684
678
sort_field != param->end ;
755
749
if (sort_field->need_strxnfrm)
757
751
char *from=(char*) res->ptr();
759
if ((unsigned char*) from == to)
753
if ((uchar*) from == to)
761
755
set_if_smaller(length,sort_field->length);
762
756
memcpy(param->tmp_buffer,from,length);
763
757
from=param->tmp_buffer;
765
759
tmp_length= my_strnxfrm(cs,to,sort_field->length,
766
(unsigned char*) from, length);
760
(uchar*) from, length);
767
761
assert(tmp_length == sort_field->length);
771
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);
772
766
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
793
787
#if SIZEOF_LONG_LONG > 4
794
to[7]= (unsigned char) value;
795
to[6]= (unsigned char) (value >> 8);
796
to[5]= (unsigned char) (value >> 16);
797
to[4]= (unsigned char) (value >> 24);
798
to[3]= (unsigned char) (value >> 32);
799
to[2]= (unsigned char) (value >> 40);
800
to[1]= (unsigned char) (value >> 48);
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);
801
795
if (item->unsigned_flag) /* Fix sign */
802
to[0]= (unsigned char) (value >> 56);
796
to[0]= (uchar) (value >> 56);
804
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
798
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
806
to[3]= (unsigned char) value;
807
to[2]= (unsigned char) (value >> 8);
808
to[1]= (unsigned char) (value >> 16);
800
to[3]= (uchar) value;
801
to[2]= (uchar) (value >> 8);
802
to[1]= (uchar) (value >> 16);
809
803
if (item->unsigned_flag) /* Fix sign */
810
to[0]= (unsigned char) (value >> 24);
804
to[0]= (uchar) (value >> 24);
812
to[0]= (unsigned char) (value >> 24) ^ 128; /* Reverse signbit */
806
to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
960
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,
961
955
filesort_info_st *table_sort)
963
uint32_t offset,res_length;
957
uint offset,res_length;
966
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);
967
961
res_length= param->res_length;
968
962
offset= param->rec_length-res_length;
969
963
if ((ha_rows) count > param->max_rows)
970
count=(uint32_t) param->max_rows;
964
count=(uint) param->max_rows;
971
965
if (!(to= table_sort->record_pointers=
972
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
966
(uchar*) my_malloc(res_length*count, MYF(MY_WME))))
973
967
return(1); /* purecov: inspected */
974
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
968
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
976
970
memcpy(to, *sort_keys+offset, res_length);
983
977
/** Merge buffers to make < MERGEBUFF2 buffers. */
985
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
986
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
979
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
980
BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
989
983
IO_CACHE t_file2,*from_file,*to_file,*temp;
990
984
BUFFPEK *lastbuff;
1036
1030
Read data to buffer.
1039
(uint32_t)-1 if something goes wrong
1033
(uint)-1 if something goes wrong
1042
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1043
uint32_t rec_length)
1036
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1045
register uint32_t count;
1039
register uint count;
1048
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1042
if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
1050
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1051
return((uint32_t) -1); /* purecov: inspected */
1044
if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1045
return((uint) -1); /* purecov: inspected */
1052
1046
buffpek->key=buffpek->base;
1053
1047
buffpek->file_pos+= length; /* New filepos */
1054
1048
buffpek->count-= count;
1069
1063
@param[in] key_length key length
1072
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1066
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
1074
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
for (uint32_t i= 0; i < queue->elements; ++i)
1068
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1069
for (uint i= 0; i < queue->elements; ++i)
1077
1071
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1078
1072
if (bp->base + bp->max_keys * key_length == reuse->base)
1112
1106
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1113
IO_CACHE *to_file, unsigned char *sort_buffer,
1107
IO_CACHE *to_file, uchar *sort_buffer,
1114
1108
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1118
uint32_t rec_length,res_length,offset;
1112
uint rec_length,res_length,offset;
1119
1113
size_t sort_length;
1120
1114
uint32_t maxcount;
1121
1115
ha_rows max_rows,org_max_rows;
1122
1116
my_off_t to_start_filepos;
1123
unsigned char *strpos;
1124
1118
BUFFPEK *buffpek;
1126
1120
qsort2_cmp cmp;
1140
1134
res_length= param->res_length;
1141
1135
sort_length= param->sort_length;
1142
1136
offset= rec_length-res_length;
1143
maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1137
maxcount= (uint32_t) (param->keys/((uint) (Tb-Fb) +1));
1144
1138
to_start_filepos= my_b_tell(to_file);
1145
strpos= (unsigned char*) sort_buffer;
1139
strpos= (uchar*) sort_buffer;
1146
1140
org_max_rows=max_rows= param->max_rows;
1148
1142
/* The following will fire if there is not enough space in sort_buffer */
1158
1152
cmp= get_ptr_compare(sort_length);
1159
1153
first_cmp_arg= (void*) &sort_length;
1161
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1155
if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1162
1156
(queue_compare) cmp, first_cmp_arg))
1163
1157
return(1); /* purecov: inspected */
1164
1158
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1166
1160
buffpek->base= strpos;
1167
1161
buffpek->max_keys= maxcount;
1168
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1162
strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
1170
1164
if (error == -1)
1171
1165
goto err; /* purecov: inspected */
1172
1166
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1173
queue_insert(&queue, (unsigned char*) buffpek);
1167
queue_insert(&queue, (uchar*) buffpek);
1176
1170
if (param->unique_buff)
1213
1207
if (cmp) // Remove duplicates
1215
1209
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1216
(unsigned char**) &buffpek->key))
1210
(uchar**) &buffpek->key))
1217
1211
goto skip_duplicate;
1218
1212
memcpy(param->unique_buff, buffpek->key, rec_length);
1222
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1216
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1224
1218
error=1; goto err; /* purecov: inspected */
1229
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))
1231
1225
error=1; goto err; /* purecov: inspected */
1276
1270
if ((ha_rows) buffpek->mem_count > max_rows)
1277
1271
{ /* Don't write too many records */
1278
buffpek->mem_count= (uint32_t) max_rows;
1272
buffpek->mem_count= (uint) max_rows;
1279
1273
buffpek->count= 0; /* Don't read more */
1281
1275
max_rows-= buffpek->mem_count;
1284
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1278
if (my_b_write(to_file,(uchar*) buffpek->key,
1285
1279
(rec_length*buffpek->mem_count)))
1287
1281
error= 1; goto err; /* purecov: inspected */
1317
1311
/* Do a merge to output-file (save only positions) */
1319
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1320
BUFFPEK *buffpek, uint32_t maxbuffer,
1313
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1314
BUFFPEK *buffpek, uint maxbuffer,
1321
1315
IO_CACHE *tempfile, IO_CACHE *outfile)
1323
1317
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1580
1574
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1582
void change_double_for_sort(double nr,unsigned char *to)
1576
void change_double_for_sort(double nr,uchar *to)
1584
unsigned char *tmp=(unsigned char*) to;
1578
uchar *tmp=(uchar*) to;
1586
1580
{ /* Change to zero string */
1587
tmp[0]=(unsigned char) 128;
1588
1582
memset(tmp+1, 0, sizeof(nr)-1);
1606
1600
if (tmp[0] & 128) /* Negative */
1607
1601
{ /* make complement */
1609
1603
for (i=0 ; i < sizeof(nr); i++)
1610
tmp[i]=tmp[i] ^ (unsigned char) 255;
1604
tmp[i]=tmp[i] ^ (uchar) 255;
1613
1607
{ /* Set high and move exponent one up */
1614
uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1616
exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
1617
tmp[0]= (unsigned char) (exp_part >> 8);
1618
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;