30
30
static char **make_char_array(char **old_pos, register uint32_t fields,
31
31
uint32_t length, myf my_flag);
32
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
32
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
34
34
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
35
uchar * *sort_keys, IO_CACHE *buffer_file,
35
unsigned char * *sort_keys, IO_CACHE *buffer_file,
36
36
IO_CACHE *tempfile,IO_CACHE *indexfile);
37
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
37
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
38
38
uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
39
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
39
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
40
40
static void register_used_fields(SORTPARAM *param);
41
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
41
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
43
43
uint32_t maxbuffer,IO_CACHE *tempfile,
44
44
IO_CACHE *outfile);
45
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint32_t count,
45
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
46
46
filesort_info_st *table_sort);
47
47
static uint32_t suffix_length(uint32_t string_length);
48
48
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
50
50
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
51
51
uint32_t sortlength, uint32_t *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
205
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
206
206
param.keys=(uint32_t) cmin(records+1, keys);
207
207
if ((table_sort.sort_keys=
208
(uchar **) make_char_array((char **) table_sort.sort_keys,
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
209
209
param.keys, param.rec_length, MYF(0))))
211
211
old_memavl=memavl;
245
245
table_sort.buffpek= 0;
247
247
if (!(table_sort.buffpek=
248
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
248
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
249
249
table_sort.buffpek)))
251
251
buffpek= (BUFFPEK *) table_sort.buffpek;
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,(uchar*) sort_keys,buffpek,&maxbuffer,
269
if (merge_many_buff(¶m,(unsigned char*) 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,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
275
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
286
286
free(param.tmp_buffer);
287
287
if (!subselect || !subselect->is_uncacheable())
289
if ((uchar*) sort_keys)
290
free((uchar*) sort_keys);
289
if ((unsigned char*) sort_keys)
290
free((unsigned char*) sort_keys);
291
291
table_sort.sort_keys= 0;
292
if ((uchar*) buffpek)
293
free((uchar*) buffpek);
292
if ((unsigned char*) buffpek)
293
free((unsigned char*) buffpek);
294
294
table_sort.buffpek= 0;
295
295
table_sort.buffpek_len= 0;
326
326
if (table->sort.record_pointers)
328
free((uchar*) table->sort.record_pointers);
328
free((unsigned char*) table->sort.record_pointers);
329
329
table->sort.record_pointers=0;
333
333
if (table->sort.sort_keys )
335
if ((uchar*) table->sort.sort_keys)
336
free((uchar*) table->sort.sort_keys);
335
if ((unsigned char*) table->sort.sort_keys)
336
free((unsigned char*) table->sort.sort_keys);
337
337
table->sort.sort_keys= 0;
339
339
if (table->sort.buffpek)
341
if ((uchar*) table->sort.buffpek)
342
free((uchar*) table->sort.buffpek);
341
if ((unsigned char*) table->sort.buffpek)
342
free((unsigned char*) table->sort.buffpek);
343
343
table->sort.buffpek= 0;
344
344
table->sort.buffpek_len= 0;
376
376
/** Read 'count' number of buffer pointers into memory. */
378
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
378
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t 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= (uchar *)my_malloc(length, MYF(MY_WME));
386
tmp= (unsigned char *)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, (uchar*) tmp, length))
390
my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
392
392
free((char*) tmp);
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
443
uint32_t idx,indexpos,ref_length;
444
uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
446
446
Table *sort_form;
447
447
THD *thd= current_thd;
464
464
next_pos=ref_pos;
465
465
if (! indexfile && ! quick_select)
467
next_pos=(uchar*) 0; /* Find records in sequence */
467
next_pos=(unsigned char*) 0; /* Find records in sequence */
468
468
file->ha_rnd_init(1);
469
469
file->extra_opt(HA_EXTRA_CACHE,
470
470
current_thd->variables.read_buff_size);
489
489
register_used_fields(param);
490
490
if (select && select->cond)
491
491
select->cond->walk(&Item::register_field_in_read_map, 1,
492
(unsigned char*) sort_form);
493
493
sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
510
if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */
510
if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) /* purecov: deadcode */
512
512
error= my_errno ? my_errno : -1; /* Abort */
618
write_keys(SORTPARAM *param, register uchar **sort_keys, uint32_t count,
618
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
619
619
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
621
621
size_t sort_length, rec_length;
625
625
sort_length= param->sort_length;
626
626
rec_length= param->rec_length;
627
my_string_ptr_sort((uchar*) sort_keys, (uint32_t) count, sort_length);
627
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
628
628
if (!my_b_inited(tempfile) &&
629
629
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
637
637
count=(uint32_t) param->max_rows; /* purecov: inspected */
638
638
buffpek.count=(ha_rows) count;
639
639
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
640
if (my_b_write(tempfile, (uchar*) *sort_keys, (uint32_t) rec_length))
640
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
642
if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
642
if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
652
652
Store length as suffix in high-byte-first order.
655
static inline void store_length(uchar *to, uint32_t length, uint32_t pack_length)
655
static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length)
657
657
switch (pack_length) {
659
*to= (unsigned char) length;
662
662
mi_int2store(to, length);
674
674
/** Make a sort-key from record. */
676
676
static void make_sortkey(register SORTPARAM *param,
677
register uchar *to, uchar *ref_pos)
677
register unsigned char *to, unsigned char *ref_pos)
679
679
register Field *field;
680
680
register SORT_FIELD *sort_field;
757
757
char *from=(char*) res->ptr();
758
758
uint32_t tmp_length;
759
if ((uchar*) from == to)
759
if ((unsigned char*) from == to)
761
761
set_if_smaller(length,sort_field->length);
762
762
memcpy(param->tmp_buffer,from,length);
763
763
from=param->tmp_buffer;
765
765
tmp_length= my_strnxfrm(cs,to,sort_field->length,
766
(uchar*) from, length);
766
(unsigned char*) from, length);
767
767
assert(tmp_length == sort_field->length);
771
my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
771
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
772
772
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
793
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);
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);
801
801
if (item->unsigned_flag) /* Fix sign */
802
to[0]= (uchar) (value >> 56);
802
to[0]= (unsigned char) (value >> 56);
804
to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
804
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
806
to[3]= (uchar) value;
807
to[2]= (uchar) (value >> 8);
808
to[1]= (uchar) (value >> 16);
806
to[3]= (unsigned char) value;
807
to[2]= (unsigned char) (value >> 8);
808
to[1]= (unsigned char) (value >> 16);
809
809
if (item->unsigned_flag) /* Fix sign */
810
to[0]= (uchar) (value >> 24);
810
to[0]= (unsigned char) (value >> 24);
812
to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
812
to[0]= (unsigned char) (value >> 24) ^ 128; /* Reverse signbit */
878
878
the same for all records.
880
880
SORT_ADDON_FIELD *addonf= param->addon_field;
881
unsigned char *nulls= to;
882
882
assert(addonf != 0);
883
883
memset(nulls, 0, addonf->offset);
884
884
to+= addonf->offset;
896
896
#ifdef HAVE_purify
897
uchar *end= field->pack(to, field->ptr);
897
unsigned char *end= field->pack(to, field->ptr);
898
898
uint32_t length= (uint32_t) ((to + addonf->length) - end);
899
899
assert((int) length >= 0);
960
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint32_t count,
960
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
961
961
filesort_info_st *table_sort)
963
963
uint32_t offset,res_length;
966
my_string_ptr_sort((uchar*) sort_keys, (uint32_t) count, param->sort_length);
966
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
967
967
res_length= param->res_length;
968
968
offset= param->rec_length-res_length;
969
969
if ((ha_rows) count > param->max_rows)
970
970
count=(uint32_t) param->max_rows;
971
971
if (!(to= table_sort->record_pointers=
972
(uchar*) my_malloc(res_length*count, MYF(MY_WME))))
972
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
973
973
return(1); /* purecov: inspected */
974
for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
974
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
976
976
memcpy(to, *sort_keys+offset, res_length);
983
983
/** Merge buffers to make < MERGEBUFF2 buffers. */
985
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
985
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
986
986
BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
988
988
register uint32_t i;
1048
1048
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1050
if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1050
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1051
1051
return((uint32_t) -1); /* purecov: inspected */
1052
1052
buffpek->key=buffpek->base;
1053
1053
buffpek->file_pos+= length; /* New filepos */
1072
1072
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1074
uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1074
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
1075
for (uint32_t i= 0; i < queue->elements; ++i)
1077
1077
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1112
1112
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1113
IO_CACHE *to_file, uchar *sort_buffer,
1113
IO_CACHE *to_file, unsigned char *sort_buffer,
1114
1114
BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1142
1142
offset= rec_length-res_length;
1143
1143
maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1144
1144
to_start_filepos= my_b_tell(to_file);
1145
strpos= (uchar*) sort_buffer;
1145
strpos= (unsigned char*) sort_buffer;
1146
1146
org_max_rows=max_rows= param->max_rows;
1148
1148
/* The following will fire if there is not enough space in sort_buffer */
1170
1170
if (error == -1)
1171
1171
goto err; /* purecov: inspected */
1172
1172
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1173
queue_insert(&queue, (uchar*) buffpek);
1173
queue_insert(&queue, (unsigned char*) buffpek);
1176
1176
if (param->unique_buff)
1186
1186
buffpek= (BUFFPEK*) queue_top(&queue);
1187
1187
memcpy(param->unique_buff, buffpek->key, rec_length);
1188
if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
1188
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1190
1190
error=1; goto err; /* purecov: inspected */
1213
1213
if (cmp) // Remove duplicates
1215
1215
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1216
(uchar**) &buffpek->key))
1216
(unsigned char**) &buffpek->key))
1217
1217
goto skip_duplicate;
1218
1218
memcpy(param->unique_buff, buffpek->key, rec_length);
1222
if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
1222
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1224
1224
error=1; goto err; /* purecov: inspected */
1229
if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
1229
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1231
1231
error=1; goto err; /* purecov: inspected */
1267
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
1267
if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1269
1269
buffpek->key+= rec_length; // Remove duplicate
1270
1270
--buffpek->mem_count;
1281
1281
max_rows-= buffpek->mem_count;
1284
if (my_b_write(to_file,(uchar*) buffpek->key,
1284
if (my_b_write(to_file,(unsigned char*) buffpek->key,
1285
1285
(rec_length*buffpek->mem_count)))
1287
1287
error= 1; goto err; /* purecov: inspected */
1292
register uchar *end;
1292
register unsigned char *end;
1293
1293
strpos= buffpek->key+offset;
1294
1294
for (end= strpos+buffpek->mem_count*rec_length ;
1295
1295
strpos != end ;
1296
1296
strpos+= rec_length)
1298
if (my_b_write(to_file, (uchar *) strpos, res_length))
1298
if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1300
1300
error=1; goto err;
1317
1317
/* Do a merge to output-file (save only positions) */
1319
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1319
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1320
1320
BUFFPEK *buffpek, uint32_t maxbuffer,
1321
1321
IO_CACHE *tempfile, IO_CACHE *outfile)
1580
1580
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1582
void change_double_for_sort(double nr,uchar *to)
1582
void change_double_for_sort(double nr,unsigned char *to)
1584
uchar *tmp=(uchar*) to;
1584
unsigned char *tmp=(unsigned char*) to;
1586
1586
{ /* Change to zero string */
1587
tmp[0]=(unsigned char) 128;
1588
1588
memset(tmp+1, 0, sizeof(nr)-1);
1593
1593
memcpy(tmp,&nr,sizeof(nr));
1596
uchar *ptr= (uchar*) &nr;
1596
unsigned char *ptr= (unsigned char*) &nr;
1597
1597
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
1598
1598
tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
1599
1599
tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
1607
1607
{ /* make complement */
1609
1609
for (i=0 ; i < sizeof(nr); i++)
1610
tmp[i]=tmp[i] ^ (uchar) 255;
1610
tmp[i]=tmp[i] ^ (unsigned char) 255;
1613
1613
{ /* Set high and move exponent one up */
1614
1614
uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1615
1615
(uint16_t) 32768);
1616
1616
exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
1617
tmp[0]= (uchar) (exp_part >> 8);
1618
tmp[1]= (uchar) exp_part;
1617
tmp[0]= (unsigned char) (exp_part >> 8);
1618
tmp[1]= (unsigned char) exp_part;