43
43
#include "myisamdef.h"
44
#include <mystrings/m_string.h>
44
45
#include <stdarg.h>
45
46
#include <mysys/my_getopt.h>
46
47
#ifdef HAVE_SYS_VADVISE_H
47
48
#include <sys/vadvise.h>
51
#include <sys/types.h>
49
53
#ifdef HAVE_SYS_MMAN_H
50
54
#include <sys/mman.h>
54
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
55
#define my_raid_delete(A,B,C) my_delete(A,B)
58
/* Functions defined in this file */
60
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint nr);
56
#include <drizzled/util/test.h>
63
/* Functions defined in this file */
65
static int check_k_link(MI_CHECK *param, MI_INFO *info,uint32_t nr);
61
66
static int chk_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
62
my_off_t page, uchar *buff, ha_rows *keys,
63
ha_checksum *key_checksum, uint level);
64
static uint isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
67
my_off_t page, unsigned char *buff, ha_rows *keys,
68
ha_checksum *key_checksum, uint32_t level);
69
static uint32_t isam_key_length(MI_INFO *info,MI_KEYDEF *keyinfo);
65
70
static ha_checksum calc_checksum(ha_rows count);
66
71
static int writekeys(MI_SORT_PARAM *sort_param);
67
72
static int sort_one_index(MI_CHECK *param, MI_INFO *info,MI_KEYDEF *keyinfo,
68
73
my_off_t pagepos, File new_file);
69
static int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
70
static int sort_get_next_record(MI_SORT_PARAM *sort_param);
71
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
72
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
73
static my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
75
static int sort_insert_key(MI_SORT_PARAM *sort_param,
76
register SORT_KEY_BLOCKS *key_block,
77
uchar *key, my_off_t prev_block);
78
static int sort_delete_record(MI_SORT_PARAM *sort_param);
76
int sort_key_read(MI_SORT_PARAM *sort_param,void *key);
77
int sort_get_next_record(MI_SORT_PARAM *sort_param);
78
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,const void *b);
79
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a);
80
my_off_t get_record_for_key(MI_INFO *info,MI_KEYDEF *keyinfo,
82
int sort_insert_key(MI_SORT_PARAM *sort_param,
83
register SORT_KEY_BLOCKS *key_block,
84
unsigned char *key, my_off_t prev_block);
85
int sort_delete_record(MI_SORT_PARAM *sort_param);
79
87
/*static int flush_pending_blocks(MI_CHECK *param);*/
80
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint blocks,
82
static ha_checksum mi_byte_checksum(const uchar *buf, uint length);
88
static SORT_KEY_BLOCKS *alloc_key_blocks(MI_CHECK *param, uint32_t blocks,
89
uint32_t buffer_length);
90
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length);
83
91
static void set_data_file_type(SORT_INFO *sort_info, MYISAM_SHARE *share);
85
93
void myisamchk_init(MI_CHECK *param)
117
125
if (share->state.open_count != (uint) (info->s->global_changed ? 1 : 0))
119
127
/* Don't count this as a real warning, as check can correct this ! */
120
uint save=param->warning_printed;
128
uint32_t save=param->warning_printed;
121
129
mi_check_print_warning(param,
122
share->state.open_count==1 ?
123
"%d client is using or hasn't closed the table properly" :
130
share->state.open_count==1 ?
131
"%d client is using or hasn't closed the table properly" :
124
132
"%d clients are using or haven't closed the table properly",
125
133
share->state.open_count);
126
134
/* If this will be fixed by the check, forget the warning */
240
248
/* Check delete links in index file */
242
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint nr)
250
static int check_k_link(MI_CHECK *param, register MI_INFO *info, uint32_t nr)
244
252
my_off_t next_link;
245
uint block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
253
uint32_t block_size=(nr+1)*MI_MIN_KEY_BLOCK_LENGTH;
247
255
char llbuff[21], llbuff2[21];
250
258
if (param->testflag & T_VERBOSE)
251
printf("block_size %4u:", block_size); /* purecov: tested */
259
printf("block_size %4u:", block_size);
253
261
next_link=info->s->state.key_del[nr];
254
262
records= (ha_rows) (info->state->key_file_length / block_size);
262
270
/* Key blocks must lay within the key file length entirely. */
263
271
if (next_link + block_size > info->state->key_file_length)
265
/* purecov: begin tested */
266
273
mi_check_print_error(param, "Invalid key block position: %s "
267
274
"key block size: %u file_length: %s",
268
275
llstr(next_link, llbuff), block_size,
269
276
llstr(info->state->key_file_length, llbuff2));
274
280
/* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
275
281
if (next_link & (MI_MIN_KEY_BLOCK_LENGTH - 1))
277
/* purecov: begin tested */
278
283
mi_check_print_error(param, "Mis-aligned key block: %s "
279
284
"minimum key block length: %u",
280
285
llstr(next_link, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
290
294
if (!(buff=key_cache_read(info->s->key_cache,
291
295
info->s->kfile, next_link, DFLT_INIT_HITS,
292
(uchar*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
296
(unsigned char*) info->buff, MI_MIN_KEY_BLOCK_LENGTH,
293
297
MI_MIN_KEY_BLOCK_LENGTH, 1)))
295
/* purecov: begin tested */
296
299
mi_check_print_error(param, "key cache read error for block: %s",
297
300
llstr(next_link,llbuff));
301
303
next_link=mi_sizekorr(buff);
520
522
/* Check that there isn't a row with auto_increment = 0 in the table */
521
523
mi_extra(info,HA_EXTRA_KEYREAD,0);
522
524
memset(info->lastkey, 0, keyinfo->seg->length);
523
if (!mi_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
525
if (!mi_rkey(info, info->rec_buff, key, (const unsigned char*) info->lastkey,
524
526
(key_part_map)1, HA_READ_KEY_EXACT))
526
528
/* Don't count this as a real warning, as myisamchk can't correct it */
527
uint save=param->warning_printed;
529
uint32_t save=param->warning_printed;
528
530
mi_check_print_warning(param, "Found row where the auto_increment "
529
531
"column has the value 0");
530
532
param->warning_printed=save;
575
577
static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
576
my_off_t page, uchar *buff, ha_rows *keys,
577
ha_checksum *key_checksum, uint level)
578
my_off_t page, unsigned char *buff, ha_rows *keys,
579
ha_checksum *key_checksum, uint32_t level)
579
581
char llbuff[22],llbuff2[22];
581
583
/* Key blocks must lay within the key file length entirely. */
582
584
if (page + keyinfo->block_length > info->state->key_file_length)
584
/* purecov: begin tested */
585
586
/* Give it a chance to fit in the real file size. */
586
my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
587
my_off_t max_length= lseek(info->s->kfile, 0, SEEK_END);
588
588
mi_check_print_error(param, "Invalid key block position: %s "
589
589
"key block size: %u file_length: %s",
590
590
llstr(page, llbuff), keyinfo->block_length,
594
594
/* Fix the remebered key file length. */
595
595
info->state->key_file_length= (max_length &
596
596
~ (my_off_t) (keyinfo->block_length - 1));
600
599
/* Key blocks must be aligned at MI_MIN_KEY_BLOCK_LENGTH. */
601
600
if (page & (MI_MIN_KEY_BLOCK_LENGTH - 1))
603
/* purecov: begin tested */
604
602
mi_check_print_error(param, "Mis-aligned key block: %s "
605
603
"minimum key block length: %u",
606
604
llstr(page, llbuff), MI_MIN_KEY_BLOCK_LENGTH);
611
608
if (!_mi_fetch_keypage(info,keyinfo,page, DFLT_INIT_HITS,buff,0))
673
668
1. Find out which prefix tuples of last_key don't contain NULLs, and
674
669
update the array of notnull counters accordingly.
675
670
2. Find the first keypart number where the prev_key and last_key tuples
676
are different(A), or last_key has NULL value(B), and return it, so the
677
caller can count number of unique tuples for each key prefix. We don't
678
need (B) to be counted, and that is compensated back in
671
are different(A), or last_key has NULL value(B), and return it, so the
672
caller can count number of unique tuples for each key prefix. We don't
673
need (B) to be counted, and that is compensated back in
679
674
update_key_parts().
719
714
/* Check if index is ok */
721
716
static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
722
my_off_t page, uchar *buff, ha_rows *keys,
723
ha_checksum *key_checksum, uint level)
717
my_off_t page, unsigned char *buff, ha_rows *keys,
718
ha_checksum *key_checksum, uint32_t level)
726
uint used_length,comp_flag,nod_flag,key_length=0;
727
uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
721
uint32_t used_length,comp_flag,nod_flag,key_length=0;
722
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
728
723
my_off_t next_page,record;
725
uint32_t diff_pos[2];
732
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
727
if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
734
729
mi_check_print_error(param,"Not enough memory for keyblock");
799
794
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
801
diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
796
diff_pos[0]= mi_collect_stats_nonulls_next(keyinfo->seg,
802
797
param->notnull_count,
803
798
info->lastkey, key);
805
800
param->unique_count[diff_pos[0]-1]++;
809
804
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
810
805
mi_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
814
(*key_checksum)+= mi_byte_checksum((uchar*) key,
809
(*key_checksum)+= mi_byte_checksum((unsigned char*) key,
815
810
key_length- info->s->rec_reflength);
816
811
record= _mi_dpos(info,0,key+key_length);
817
812
if (record >= info->state->data_file_length)
881
876
ha_rows records, del_blocks;
882
877
my_off_t used, empty, pos, splits, start_recpos= 0,
883
878
del_length, link_used, start_block;
884
uchar *record= NULL, *to= NULL;
879
unsigned char *record= NULL, *to= NULL;
885
880
char llbuff[22],llbuff2[22],llbuff3[22];
886
881
ha_checksum intern_record_checksum;
887
882
ha_checksum key_checksum[HA_MAX_POSSIBLE_KEY];
1265
1260
printf("Lost space: %12s Linkdata: %10s\n",
1266
1261
llstr(empty,llbuff),llstr(link_used,llbuff2));
1268
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1263
free(mi_get_rec_buff_ptr(info, record));
1269
1264
return (error);
1271
1266
mi_check_print_error(param,"got error: %d when reading datafile at record: %s",my_errno, llstr(records,llbuff));
1273
my_free(mi_get_rec_buff_ptr(info, record), MYF(0));
1268
free(mi_get_rec_buff_ptr(info, record));
1274
1269
param->testflag|=T_RETRY_WITHOUT_QUICK;
1276
1271
} /* chk_data_link */
1432
1427
param->testflag|=T_REP; /* for easy checking */
1434
if (info->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
1429
if (info->s->options & (HA_OPTION_COMPRESS_RECORD))
1435
1430
param->testflag|=T_CALC_CHECKSUM;
1437
1432
if (!param->using_global_keycache)
1438
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
1439
param->use_buffers, 0, 0));
1433
init_key_cache(dflt_key_cache, param->key_cache_block_size,
1434
(size_t)param->use_buffers, 0, 0);
1441
1436
if (init_io_cache(¶m->read_cache,info->dfile,
1442
1437
(uint) param->read_buffer_length,
1461
1456
if (!rep_quick)
1463
1458
/* Get real path for data file */
1464
if ((new_file=my_raid_create(fn_format(param->temp_filename,
1465
share->data_file_name, "",
1467
0,param->tmpfile_createflag,
1468
share->base.raid_type,
1469
share->base.raid_chunks,
1470
share->base.raid_chunksize,
1459
if ((new_file=my_create(fn_format(param->temp_filename,
1460
share->data_file_name, "",
1462
0,param->tmpfile_createflag,
1473
1465
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1474
param->temp_filename);
1466
param->temp_filename);
1477
1469
if (new_header_length &&
1478
1470
filecopy(param,new_file,info->dfile,0L,new_header_length,
1481
1473
info->s->state.dellink= HA_OFFSET_ERROR;
1482
1474
info->rec_cache.file=new_file;
1631
1623
llstr(sort_param.start_recpos,llbuff));
1632
1624
if (new_file >= 0)
1634
VOID(my_close(new_file,MYF(0)));
1635
VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
1626
my_close(new_file,MYF(0));
1627
my_delete(param->temp_filename, MYF(MY_WME));
1637
1628
info->rec_cache.file=-1; /* don't flush data to new_file, it's closed */
1639
1630
mi_mark_crashed_on_repair(info);
1641
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
1642
MYF(MY_ALLOW_ZERO_PTR));
1643
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1644
MYF(MY_ALLOW_ZERO_PTR));
1645
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1646
VOID(end_io_cache(¶m->read_cache));
1633
void * rec_buff_ptr= NULL;
1634
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
1635
if (rec_buff_ptr != NULL)
1637
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1638
if (rec_buff_ptr != NULL)
1642
free(sort_info.buff);
1643
end_io_cache(¶m->read_cache);
1647
1644
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1648
VOID(end_io_cache(&info->rec_cache));
1645
end_io_cache(&info->rec_cache);
1649
1646
got_error|=flush_blocks(param, share->key_cache, share->kfile);
1650
1647
if (!got_error && param->testflag & T_UNPACK)
1652
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
1649
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
1653
1650
share->pack.header_length=0;
1654
1651
share->data_file_type=sort_info.new_data_file_type;
1846
1845
/* Put same locks as old file */
1847
1846
share->r_locks= share->w_locks= share->tot_locks= 0;
1848
1847
(void) _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
1849
VOID(my_close(share->kfile,MYF(MY_WME)));
1848
my_close(share->kfile,MYF(MY_WME));
1850
1849
share->kfile = -1;
1851
VOID(my_close(new_file,MYF(MY_WME)));
1850
my_close(new_file,MYF(MY_WME));
1852
1851
if (change_to_newfile(share->index_file_name,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1854
1853
mi_open_keyfile(share))
1884
1883
static int sort_one_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
1885
1884
my_off_t pagepos, File new_file)
1887
uint length,nod_flag,used_length, key_length;
1888
uchar *buff,*keypos,*endpos;
1889
uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
1886
uint32_t length,nod_flag,used_length, key_length;
1887
unsigned char *buff,*keypos,*endpos;
1888
unsigned char key[HA_MAX_POSSIBLE_KEY_BUFF];
1890
1889
my_off_t new_page_pos,next_page;
1891
1890
char llbuff[22];
1893
1892
new_page_pos=param->new_file_pos;
1894
1893
param->new_file_pos+=keyinfo->block_length;
1896
if (!(buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1895
if (!(buff=(unsigned char*) malloc(keyinfo->block_length)))
1898
1897
mi_check_print_error(param,"Not enough memory for key block");
1930
1929
/* Fill block with zero and write it to the new index file */
1931
1930
length=mi_getint(buff);
1932
1931
memset(buff+length, 0, keyinfo->block_length-length);
1933
if (my_pwrite(new_file,(uchar*) buff,(uint) keyinfo->block_length,
1932
if (my_pwrite(new_file,(unsigned char*) buff,(uint) keyinfo->block_length,
1934
1933
new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
1936
1935
mi_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
1939
my_afree((uchar*) buff);
1942
my_afree((uchar*) buff);
1944
1943
} /* sort_one_index */
1976
1976
char tmp_buff[IO_SIZE],*buff;
1977
1977
ulong buff_length;
1979
buff_length=(ulong) min(param->write_buffer_length,length);
1980
if (!(buff=my_malloc(buff_length,MYF(0))))
1979
buff_length=(ulong) min(param->write_buffer_length, (size_t)length);
1980
if (!(buff=(char *)malloc(buff_length)))
1982
1982
buff=tmp_buff; buff_length=IO_SIZE;
1985
VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
1985
lseek(from,start,SEEK_SET);
1986
1986
while (length > buff_length)
1988
if (my_read(from,(uchar*) buff,buff_length,MYF(MY_NABP)) ||
1989
my_write(to,(uchar*) buff,buff_length,param->myf_rw))
1988
if (my_read(from,(unsigned char*) buff,buff_length,MYF(MY_NABP)) ||
1989
my_write(to,(unsigned char*) buff,buff_length,param->myf_rw))
1991
1991
length-= buff_length;
1993
if (my_read(from,(uchar*) buff,(uint) length,MYF(MY_NABP)) ||
1994
my_write(to,(uchar*) buff,(uint) length,param->myf_rw))
1993
if (my_read(from,(unsigned char*) buff,(uint) length,MYF(MY_NABP)) ||
1994
my_write(to,(unsigned char*) buff,(uint) length,param->myf_rw))
1996
1996
if (buff != tmp_buff)
1997
my_free(buff,MYF(0));
2000
2000
if (buff != tmp_buff)
2001
my_free(buff,MYF(0));
2002
2002
mi_check_print_error(param,"Can't copy %s to tempfile, error %d",
2003
2003
type,my_errno);
2080
2080
if (!rep_quick)
2082
2082
/* Get real path for data file */
2083
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2084
share->data_file_name, "",
2086
0,param->tmpfile_createflag,
2087
share->base.raid_type,
2088
share->base.raid_chunks,
2089
share->base.raid_chunksize,
2083
if ((new_file=my_create(fn_format(param->temp_filename,
2084
share->data_file_name, "",
2086
0,param->tmpfile_createflag,
2092
2089
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2093
param->temp_filename);
2090
param->temp_filename);
2096
2093
if (new_header_length &&
2339
2334
share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS;
2340
2335
share->state.changed|=STATE_NOT_SORTED_PAGES;
2342
my_free(mi_get_rec_buff_ptr(info, sort_param.rec_buff),
2343
MYF(MY_ALLOW_ZERO_PTR));
2344
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
2345
MYF(MY_ALLOW_ZERO_PTR));
2346
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2347
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2348
VOID(end_io_cache(¶m->read_cache));
2337
void * rec_buff_ptr= NULL;
2338
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.rec_buff);
2339
if (rec_buff_ptr != NULL)
2341
rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
2342
if (rec_buff_ptr != NULL)
2346
free((unsigned char*) sort_info.key_block);
2347
free(sort_info.buff);
2348
end_io_cache(¶m->read_cache);
2349
2349
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2350
2350
if (!got_error && (param->testflag & T_UNPACK))
2352
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2352
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2353
2353
share->pack.header_length=0;
2355
2355
return(got_error);
2489
2489
if (!rep_quick)
2491
2491
/* Get real path for data file */
2492
if ((new_file=my_raid_create(fn_format(param->temp_filename,
2493
share->data_file_name, "",
2496
0,param->tmpfile_createflag,
2497
share->base.raid_type,
2498
share->base.raid_chunks,
2499
share->base.raid_chunksize,
2492
if ((new_file=my_create(fn_format(param->temp_filename,
2493
share->data_file_name, "",
2496
0,param->tmpfile_createflag,
2502
2499
mi_check_print_error(param,"Can't create new tempfile: '%s'",
2503
2500
param->temp_filename);
2565
2562
if (share->options & HA_OPTION_COMPRESS_RECORD)
2566
2563
set_if_bigger(max_pack_reclength, share->max_pack_length);
2567
2564
if (!(sort_param=(MI_SORT_PARAM *)
2568
my_malloc((uint) share->base.keys *
2569
(sizeof(MI_SORT_PARAM) + max_pack_reclength),
2565
malloc(share->base.keys *
2566
(sizeof(MI_SORT_PARAM) + max_pack_reclength))))
2572
2568
mi_check_print_error(param,"Not enough memory for key!");
2571
memset(sort_param, 0, share->base.keys *
2572
(sizeof(MI_SORT_PARAM) + max_pack_reclength));
2575
2573
total_key_length=0;
2576
2574
rec_per_key_part= param->rec_per_key_part;
2577
2575
info->state->records=info->state->del=share->state.split=0;
2851
2847
pthread_cond_destroy (&sort_info.cond);
2852
2848
pthread_mutex_destroy(&sort_info.mutex);
2854
my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR));
2855
my_free((uchar*) sort_param,MYF(MY_ALLOW_ZERO_PTR));
2856
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
2857
VOID(end_io_cache(¶m->read_cache));
2850
free((unsigned char*) sort_info.key_block);
2851
free((unsigned char*) sort_param);
2852
free(sort_info.buff);
2853
end_io_cache(¶m->read_cache);
2858
2854
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
2859
2855
if (!got_error && (param->testflag & T_UNPACK))
2861
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
2857
share->state.header.options[0]&= (unsigned char) ~HA_OPTION_COMPRESS_RECORD;
2862
2858
share->pack.header_length=0;
2864
2860
return(got_error);
2884
2880
sort_param->real_key_length=
2885
2881
(info->s->rec_reflength+
2886
_mi_make_key(info, sort_param->key, (uchar*) key,
2882
_mi_make_key(info, sort_param->key, (unsigned char*) key,
2887
2883
sort_param->record, sort_param->filepos));
2888
2884
#ifdef HAVE_purify
2889
memset(key+sort_param->real_key_length, 0,
2885
memset((unsigned char *)key+sort_param->real_key_length, 0,
2890
2886
(sort_param->key_length-sort_param->real_key_length));
2892
2888
return(sort_write_record(sort_param));
3006
3002
llstr(param->search_after_block,llbuff),
3007
3003
llstr(sort_param->start_recpos,llbuff2));
3008
3004
if (_mi_read_cache(&sort_param->read_cache,
3009
(uchar*) block_info.header,pos,
3005
(unsigned char*) block_info.header,pos,
3010
3006
MI_BLOCK_INFO_HEADER_LENGTH,
3011
3007
(! found_record ? READING_NEXT : 0) |
3012
3008
parallel_flag | READING_HEADER))
3326
3322
MI_DYN_DELETE_BLOCK_HEADER;
3327
3323
if (sort_info->buff_length < reclength)
3329
if (!(sort_info->buff=my_realloc(sort_info->buff, (uint) reclength,
3330
MYF(MY_FREE_ON_ERROR |
3331
MY_ALLOW_ZERO_PTR))))
3333
sort_info->buff_length=reclength;
3326
tmpptr= realloc(sort_info->buff, reclength);
3329
sort_info->buff_length=reclength;
3330
sort_info->buff= (unsigned char *)tmpptr;
3334
mi_check_print_error(param,"Could not realloc() sort_info->buff "
3335
" to %ul bytes", reclength);
3335
3339
from= sort_info->buff+ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER);
3384
3388
/* Compare two keys from _create_index_by_sort */
3386
static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
3390
int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a, const void *b)
3390
return (ha_key_cmp(sort_param->seg, *((uchar* const *) a), *((uchar* const *) b),
3392
uint32_t not_used[2];
3393
return (ha_key_cmp(sort_param->seg, *((unsigned char* const *) a), *((unsigned char* const *) b),
3391
3394
USE_WHOLE_KEY, SEARCH_SAME, not_used));
3392
3395
} /* sort_key_cmp */
3395
static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3398
int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
3400
uint32_t diff_pos[2];
3398
3401
char llbuff[22],llbuff2[22];
3399
3402
SORT_INFO *sort_info=sort_param->sort_info;
3400
3403
MI_CHECK *param= sort_info->param;
3403
3406
if (sort_info->key_block->inited)
3405
3408
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3406
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3409
(unsigned char*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
3408
3411
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
3409
3412
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
3410
(uchar*) a, USE_WHOLE_KEY,
3413
(unsigned char*) a, USE_WHOLE_KEY,
3411
3414
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, diff_pos);
3412
3415
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
3414
3417
diff_pos[0]= mi_collect_stats_nonulls_next(sort_param->seg,
3415
3418
sort_param->notnull,
3416
3419
sort_info->key_block->lastkey,
3419
3422
sort_param->unique[diff_pos[0]-1]++;
3443
3446
return (sort_delete_record(sort_param));
3445
3448
return (sort_insert_key(sort_param,sort_info->key_block,
3446
(uchar*) a, HA_OFFSET_ERROR));
3449
(unsigned char*) a, HA_OFFSET_ERROR));
3447
3450
} /* sort_key_write */
3450
3453
/* get pointer to record from a key */
3452
static my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3455
my_off_t get_record_for_key(MI_INFO *info, MI_KEYDEF *keyinfo,
3456
unsigned char *key) {
3455
3457
return _mi_dpos(info,0,key+_mi_keylength(keyinfo,key));
3456
3458
} /* get_record_for_key */
3459
3461
/* Insert a key in sort-key-blocks */
3461
static int sort_insert_key(MI_SORT_PARAM *sort_param,
3462
register SORT_KEY_BLOCKS *key_block, uchar *key,
3463
my_off_t prev_block)
3463
int sort_insert_key(MI_SORT_PARAM *sort_param,
3464
register SORT_KEY_BLOCKS *key_block, unsigned char *key,
3465
my_off_t prev_block)
3465
uint a_length,t_length,nod_flag;
3467
uint32_t a_length,t_length,nod_flag;
3466
3468
my_off_t filepos,key_file_length;
3467
uchar *anc_buff,*lastkey;
3469
unsigned char *anc_buff,*lastkey;
3468
3470
MI_KEY_PARAM s_temp;
3470
3472
MI_KEYDEF *keyinfo=sort_param->keyinfo;
3666
3667
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
3668
return my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)) / 10 * 9 >
3669
return (my_off_t)(lseek(info->s->kfile, 0L, SEEK_END) / 10 * 9) >
3669
3670
(my_off_t) info->s->base.max_key_file_length ||
3670
my_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
3671
(my_off_t)(lseek(info->dfile, 0L, SEEK_END) / 10 * 9) >
3671
3672
(my_off_t) info->s->base.max_data_file_length;
3695
3696
share= *(*org_info)->s;
3696
3697
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
3697
3698
(param->testflag & T_UNPACK);
3698
if (!(keyinfo=(MI_KEYDEF*) my_alloca(sizeof(MI_KEYDEF)*share.base.keys)))
3699
if (!(keyinfo=(MI_KEYDEF*) malloc(sizeof(MI_KEYDEF)*share.base.keys)))
3700
3701
memcpy(keyinfo,share.keyinfo,sizeof(MI_KEYDEF)*share.base.keys);
3702
3703
key_parts= share.base.all_key_parts;
3703
if (!(keysegs=(HA_KEYSEG*) my_alloca(sizeof(HA_KEYSEG)*
3704
(key_parts+share.base.keys))))
3704
if (!(keysegs=(HA_KEYSEG*) malloc(sizeof(HA_KEYSEG)*
3705
(key_parts+share.base.keys))))
3706
my_afree((uchar*) keyinfo);
3709
3710
if (!(recdef=(MI_COLUMNDEF*)
3710
my_alloca(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3711
malloc(sizeof(MI_COLUMNDEF)*(share.base.fields+1))))
3712
my_afree((uchar*) keyinfo);
3713
my_afree((uchar*) keysegs);
3716
3717
if (!(uniquedef=(MI_UNIQUEDEF*)
3717
my_alloca(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3718
malloc(sizeof(MI_UNIQUEDEF)*(share.state.header.uniques+1))))
3719
my_afree((uchar*) recdef);
3720
my_afree((uchar*) keyinfo);
3721
my_afree((uchar*) keysegs);
3770
3771
(param->testflag & T_UNPACK);
3771
3772
share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
3773
file_length=(uint64_t) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0));
3774
file_length=(uint64_t) lseek(info.dfile,0L,SEEK_END);
3774
3775
tmp_length= file_length+file_length/10;
3775
3776
set_if_bigger(file_length,param->max_data_file_length);
3776
3777
set_if_bigger(file_length,tmp_length);
3777
3778
set_if_bigger(file_length,(uint64_t) share.base.max_data_file_length);
3779
VOID(mi_close(*org_info));
3780
mi_close(*org_info);
3780
3781
memset(&create_info, 0, sizeof(create_info));
3781
3782
create_info.max_rows=max(max_records,share.base.records);
3782
3783
create_info.reloc_rows=share.base.reloc;
4017
4018
For MI_STATS_METHOD_IGNORE_NULLS method, notnull_tuples is an array too:
4018
4019
notnull_tuples[0]= (#of {keypart1} tuples such that keypart1 is not NULL)
4019
notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4020
notnull_tuples[1]= (#of {keypart1,keypart2} tuples such that all
4020
4021
keypart{i} are not NULL)
4022
4023
For all other statistics collection methods notnull_tuples==NULL.
4024
4025
Output is an array:
4025
rec_per_key_part[k] =
4026
= E(#records in the table such that keypart_1=c_1 AND ... AND
4027
keypart_k=c_k for arbitrary constants c_1 ... c_k)
4026
rec_per_key_part[k] =
4027
= E(#records in the table such that keypart_1=c_1 AND ... AND
4028
keypart_k=c_k for arbitrary constants c_1 ... c_k)
4029
4030
= {assuming that values have uniform distribution and index contains all
4030
4031
tuples from the domain (or that {c_1, ..., c_k} tuple is choosen from
4033
4034
= #tuples-in-the-index / #distinct-tuples-in-the-index.
4035
The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4036
The #tuples-in-the-index and #distinct-tuples-in-the-index have different
4036
4037
meaning depending on which statistics collection method is used:
4038
4039
MI_STATS_METHOD_* how are nulls compared? which tuples are counted?
4039
4040
NULLS_EQUAL NULL == NULL all tuples in table
4040
4041
NULLS_NOT_EQUAL NULL != NULL all tuples in table
4087
static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
4089
static ha_checksum mi_byte_checksum(const unsigned char *buf, uint32_t length)
4089
4091
ha_checksum crc;
4090
const uchar *end=buf+length;
4092
const unsigned char *end=buf+length;
4091
4093
for (crc=0; buf != end; buf++)
4092
crc=((crc << 1) + *((uchar*) buf)) +
4094
crc=((crc << 1) + *((unsigned char*) buf)) +
4093
4095
test(crc & (((ha_checksum) 1) << (8*sizeof(ha_checksum)-1)));
4097
4099
static bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
4099
uint key_maxlength=key->maxlength;
4101
uint32_t key_maxlength=key->maxlength;
4100
4102
return (key->flag & (HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY) &&
4101
4103
((uint64_t) rows * key_maxlength >
4102
(uint64_t) myisam_max_temp_length));
4104
(uint64_t) MAX_FILE_SIZE));