16
16
/* Describe, check and repair of MyISAM tables */
18
#include "myisamdef.h"
18
#include <my_global.h>
21
#include <mystrings/m_ctype.h>
22
#include <mysys/my_getopt.h>
23
#include <mysys/my_bit.h>
24
#include <mystrings/m_string.h>
26
21
#include <stdarg.h>
22
#include <my_getopt.h>
27
26
#ifdef HAVE_SYS_VADVICE_H
28
27
#include <sys/vadvise.h>
30
29
#ifdef HAVE_SYS_MMAN_H
31
30
#include <sys/mman.h>
33
#include <drizzled/util/test.h>
36
pthread_mutex_t THR_LOCK_myisam= PTHREAD_MUTEX_INITIALIZER;
38
static uint32_t decode_bits;
32
SET_STACK_SIZE(9000) /* Minimum stack size for program */
34
#define my_raid_create(A,B,C,D,E,F,G) my_create(A,B,C,G)
35
#define my_raid_delete(A,B,C) my_delete(A,B)
37
#include "myisamdef.h"
39
static uint decode_bits;
39
40
static char **default_argv;
40
41
static const char *load_default_groups[]= { "myisamchk", 0 };
41
42
static const char *set_collation_name, *opt_tmpdir;
42
static const CHARSET_INFO *set_collation;
43
static CHARSET_INFO *set_collation;
43
44
static long opt_myisam_block_size;
44
45
static long opt_key_cache_block_size;
45
46
static const char *my_progname_short;
47
static MY_TMPDIR myisamchk_tmpdir;
47
49
static const char *type_names[]=
48
50
{ "impossible","char","binary", "short", "long", "float",
49
51
"double","number","unsigned short",
50
"unsigned long","int64_t","uint64_t","int24",
52
"unsigned long","longlong","ulonglong","int24",
51
53
"uint24","int8","varchar", "varbin","?",
70
72
static int myisamchk(MI_CHECK *param, char *filename);
71
73
static void descript(MI_CHECK *param, register MI_INFO *info, char * name);
72
74
static int mi_sort_records(MI_CHECK *param, register MI_INFO *info,
73
char * name, uint32_t sort_key,
74
bool write_info, bool update_index);
75
char * name, uint sort_key,
76
my_bool write_info, my_bool update_index);
75
77
static int sort_record_index(MI_SORT_PARAM *sort_param, MI_INFO *info,
76
78
MI_KEYDEF *keyinfo,
77
my_off_t page,unsigned char *buff,uint32_t sortkey,
78
File new_file, bool update_index);
80
bool get_one_option(int optid, const struct my_option *, char *argument);
79
my_off_t page,uchar *buff,uint sortkey,
80
File new_file, my_bool update_index);
82
82
MI_CHECK check_param;
100
100
int new_error=myisamchk(&check_param, *(argv++));
101
101
if ((check_param.testflag & T_REP_ANY) != T_REP)
102
102
check_param.testflag&= ~T_REP;
103
VOID(fflush(stdout));
104
VOID(fflush(stderr));
105
105
if ((check_param.error_printed | check_param.warning_printed) &&
106
106
(check_param.testflag & T_FORCE_CREATE) &&
107
107
(!(check_param.testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
110
uint32_t old_testflag=check_param.testflag;
110
uint old_testflag=check_param.testflag;
111
111
if (!(check_param.testflag & T_REP))
112
112
check_param.testflag|= T_REP_BY_SORT;
113
113
check_param.testflag&= ~T_EXTEND; /* Don't needed */
114
114
error|=myisamchk(&check_param, argv[-1]);
115
115
check_param.testflag= old_testflag;
116
VOID(fflush(stdout));
117
VOID(fflush(stderr));
120
120
error|=new_error;
121
121
if (argc && (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO))
123
123
puts("\n---------\n");
124
VOID(fflush(stdout));
127
127
if (check_param.total_files > 1)
145
146
OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE,
146
147
OPT_KEY_CACHE_BLOCK_SIZE, OPT_MYISAM_BLOCK_SIZE,
147
148
OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
148
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS,
149
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
150
OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE,
149
151
OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD
155
157
"Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.",
156
158
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
160
{"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
161
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
163
{"block-search", 'b',
164
"No help available.",
165
0, 0, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
158
167
"Make a backup of the .MYD file as 'filename-time.BAK'.",
159
168
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
169
{"character-sets-dir", OPT_CHARSETS_DIR,
170
"Directory where character sets are.",
171
(char**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
161
173
"Check table for errors.",
162
174
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
166
178
{"correct-checksum", OPT_CORRECT_CHECKSUM,
167
179
"Correct checksum information for table.",
168
180
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
183
"Output debug log. Often this is 'd:t:o,filename'.",
184
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
169
186
{"description", 'd',
170
187
"Prints some information about table.",
171
188
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
201
218
"Skip rows bigger than this if myisamchk can't allocate memory to hold it",
202
219
(char**) &check_param.max_record_length,
203
220
(char**) &check_param.max_record_length,
204
0, GET_ULL, REQUIRED_ARG, INT64_MAX, 0, INT64_MAX, 0, 0, 0},
221
0, GET_ULL, REQUIRED_ARG, LONGLONG_MAX, 0, LONGLONG_MAX, 0, 0, 0},
205
222
{"medium-check", 'm',
206
223
"Faster than extend-check, but only finds 99.99% of all errors. Should be good enough for most cases.",
207
224
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
270
287
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
271
288
{ "key_buffer_size", OPT_KEY_BUFFER_SIZE, "",
272
289
(char**) &check_param.use_buffers, (char**) &check_param.use_buffers, 0,
273
GET_UINT64, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
274
INT32_MAX, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
290
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
291
(long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
275
292
{ "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "",
276
293
(char**) &opt_key_cache_block_size,
277
294
(char**) &opt_key_cache_block_size, 0,
283
300
MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
284
301
{ "read_buffer_size", OPT_READ_BUFFER_SIZE, "",
285
302
(char**) &check_param.read_buffer_length,
286
(char**) &check_param.read_buffer_length, 0, GET_SIZE, REQUIRED_ARG,
303
(char**) &check_param.read_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
287
304
(long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
288
SIZE_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
305
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
289
306
{ "write_buffer_size", OPT_WRITE_BUFFER_SIZE, "",
290
307
(char**) &check_param.write_buffer_length,
291
(char**) &check_param.write_buffer_length, 0, GET_SIZE, REQUIRED_ARG,
308
(char**) &check_param.write_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
292
309
(long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
293
SIZE_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
310
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
294
311
{ "sort_buffer_size", OPT_SORT_BUFFER_SIZE, "",
295
312
(char**) &check_param.sort_buffer_length,
296
(char**) &check_param.sort_buffer_length, 0, GET_SIZE, REQUIRED_ARG,
313
(char**) &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG,
297
314
(long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD),
298
SIZE_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0},
315
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
299
316
{ "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "",
300
317
(char**) &check_param.sort_key_blocks,
301
(char**) &check_param.sort_key_blocks, 0, GET_SIZE, REQUIRED_ARG,
318
(char**) &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG,
302
319
BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
303
320
{ "decode_bits", OPT_DECODE_BITS, "", (char**) &decode_bits,
304
321
(char**) &decode_bits, 0, GET_UINT, REQUIRED_ARG, 9L, 4L, 17L, 0L, 1L, 0},
424
448
-R, --sort-records=#\n\
425
449
Sort records according to an index. This makes your\n\
426
450
data much more localized and may speed up things\n\
427
(It may be VERY slow to do a sort the first time!).\n");
451
(It may be VERY slow to do a sort the first time!).\n\
452
-b, --block-search=#\n\
453
Find a record, a block at given offset belongs to.");
429
print_defaults("drizzle", load_default_groups);
455
print_defaults("my", load_default_groups);
430
456
my_print_variables(my_long_options);
459
#include <help_end.h>
433
461
const char *myisam_stats_method_names[] = {"nulls_unequal", "nulls_equal",
434
"nulls_ignored", NULL};
462
"nulls_ignored", NullS};
435
463
TYPELIB myisam_stats_method_typelib= {
436
464
array_elements(myisam_stats_method_names) - 1, "",
437
465
myisam_stats_method_names, NULL};
439
467
/* Read options */
441
bool get_one_option(int optid, const struct my_option *, char *argument)
470
get_one_option(int optid,
471
const struct my_option *opt __attribute__((unused)),
477
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
445
481
if (argument == disabled_my_option)
446
482
check_param.testflag&= ~T_STATISTICS;
716
760
(T_REP_ANY | T_STATISTICS | T_AUTO_INC |
717
761
T_SORT_RECORDS | T_SORT_INDEX | T_FORCE_CREATE)))
720
"%s: Can't use --readonly when repairing or sorting\n",
764
"%s: Can't use --readonly when repairing or sorting\n",
769
if (init_tmpdir(&myisamchk_tmpdir, opt_tmpdir))
772
check_param.tmpdir=&myisamchk_tmpdir;
725
773
check_param.key_cache_block_size= opt_key_cache_block_size;
727
775
if (set_collation_name)
728
if (!(set_collation= get_charset_by_name(set_collation_name)))
776
if (!(set_collation= get_charset_by_name(set_collation_name,
731
780
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
960
1010
if (!error && param->testflag & T_SORT_RECORDS)
964
1014
We can't update the index in mi_sort_records if we have a
965
1015
prefix compressed or fulltext index
1017
my_bool update_index=1;
968
1018
for (key=0 ; key < share->base.keys; key++)
969
if (share->keyinfo[key].flag & (HA_BINARY_PACK_KEY))
1019
if (share->keyinfo[key].flag & (HA_BINARY_PACK_KEY|HA_FULLTEXT))
972
1022
error=mi_sort_records(param,info,filename,param->opt_sort_key,
973
1023
/* what is the following parameter for ? */
974
(bool) !(param->testflag & T_REP),
1024
(my_bool) !(param->testflag & T_REP),
976
1026
datafile=info->dfile; /* This is now locked */
977
1027
if (!error && !update_index)
1017
1067
!(param->testflag & (T_FAST | T_FORCE_CREATE)))
1019
1069
if (param->testflag & (T_EXTEND | T_MEDIUM))
1020
init_key_cache(dflt_key_cache,opt_key_cache_block_size,
1021
(size_t)param->use_buffers, 0, 0);
1022
init_io_cache(¶m->read_cache,datafile,
1023
(uint) param->read_buffer_length,
1025
(param->start_check_pos ?
1026
param->start_check_pos :
1027
share->pack.header_length),
1070
VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size,
1071
param->use_buffers, 0, 0));
1072
VOID(init_io_cache(¶m->read_cache,datafile,
1073
(uint) param->read_buffer_length,
1075
(param->start_check_pos ?
1076
param->start_check_pos :
1077
share->pack.header_length),
1030
1080
lock_memory(param);
1031
1081
if ((info->s->options & (HA_OPTION_PACK_RECORD |
1032
1082
HA_OPTION_COMPRESS_RECORD)) ||
1033
1083
(param->testflag & (T_EXTEND | T_MEDIUM)))
1034
1084
error|=chk_data_link(param, info, param->testflag & T_EXTEND);
1035
1085
error|=flush_blocks(param, share->key_cache, share->kfile);
1036
end_io_cache(¶m->read_cache);
1086
VOID(end_io_cache(¶m->read_cache));
1086
1137
error|=change_to_newfile(filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
1089
fflush(stdout); fflush(stderr);
1140
VOID(fflush(stdout)); VOID(fflush(stderr));
1090
1141
if (param->error_printed)
1092
1143
if (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX))
1095
"MyISAM-table '%s' is not fixed because of errors\n",
1145
VOID(fprintf(stderr,
1146
"MyISAM-table '%s' is not fixed because of errors\n",
1097
1148
if (param->testflag & T_REP_ANY)
1099
"Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag\n");
1149
VOID(fprintf(stderr,
1150
"Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag\n"));
1101
1152
else if (!(param->error_printed & 2) &&
1102
1153
!(param->testflag & T_FORCE_CREATE))
1104
"MyISAM-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n",
1154
VOID(fprintf(stderr,
1155
"MyISAM-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n",
1107
1158
else if (param->warning_printed &&
1108
1159
! (param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
1109
1160
T_FORCE_CREATE)))
1110
fprintf(stderr, "MyISAM-table '%s' is usable but should be fixed\n",
1161
VOID(fprintf(stderr, "MyISAM-table '%s' is usable but should be fixed\n",
1163
VOID(fflush(stderr));
1114
1165
} /* myisamchk */
1157
1209
if (share->state.changed & STATE_CRASHED)
1158
strcpy(buff,"crashed");
1210
strmov(buff,"crashed");
1161
1213
if (share->state.open_count)
1162
pos= strcpy(pos,"open,")+5;
1214
pos=strmov(pos,"open,");
1163
1215
if (share->state.changed & STATE_CHANGED)
1164
pos= strcpy(pos,"changed,")+8;
1216
pos=strmov(pos,"changed,");
1166
pos= strcpy(pos,"checked,")+8;
1218
pos=strmov(pos,"checked,");
1167
1219
if (!(share->state.changed & STATE_NOT_ANALYZED))
1168
pos= strcpy(pos,"analyzed,")+9;
1220
pos=strmov(pos,"analyzed,");
1169
1221
if (!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))
1170
pos= strcpy(pos,"optimized keys,")+15;
1222
pos=strmov(pos,"optimized keys,");
1171
1223
if (!(share->state.changed & STATE_NOT_SORTED_PAGES))
1172
pos= strcpy(pos,"sorted index pages,")+19;
1224
pos=strmov(pos,"sorted index pages,");
1173
1225
pos[-1]=0; /* Remove extra ',' */
1175
1227
printf("Status: %s\n",buff);
1176
1228
if (share->base.auto_key)
1197
1256
printf("Init-relocation: %13s\n",llstr(share->base.reloc,llbuff));
1199
1258
printf("Datafile parts: %13s Deleted data: %13s\n",
1200
llstr(share->state.split,llbuff),
1201
llstr(info->state->empty,llbuff2));
1259
llstr(share->state.split,llbuff),
1260
llstr(info->state->empty,llbuff2));
1202
1261
printf("Datafile pointer (bytes):%9d Keyfile pointer (bytes):%9d\n",
1203
share->rec_reflength,share->base.key_reflength);
1262
share->rec_reflength,share->base.key_reflength);
1204
1263
printf("Datafile length: %13s Keyfile length: %13s\n",
1205
llstr(info->state->data_file_length,llbuff),
1206
llstr(info->state->key_file_length,llbuff2));
1264
llstr(info->state->data_file_length,llbuff),
1265
llstr(info->state->key_file_length,llbuff2));
1208
1267
if (info->s->base.reloc == 1L && info->s->base.records == 1L)
1209
1268
puts("This is a one-record table");
1212
1271
if (share->base.max_data_file_length != HA_OFFSET_ERROR ||
1213
share->base.max_key_file_length != HA_OFFSET_ERROR)
1214
printf("Max datafile length: %13s Max keyfile length: %13s\n",
1215
llstr(share->base.max_data_file_length-1,llbuff),
1216
llstr(share->base.max_key_file_length-1,llbuff2));
1272
share->base.max_key_file_length != HA_OFFSET_ERROR)
1273
printf("Max datafile length: %13s Max keyfile length: %13s\n",
1274
llstr(share->base.max_data_file_length-1,llbuff),
1275
llstr(share->base.max_key_file_length-1,llbuff2));
1220
1279
printf("Recordlength: %13d\n",(int) share->base.pack_reclength);
1221
1280
if (! mi_is_all_keys_active(share->state.key_map, share->base.keys))
1223
int64_t2str(share->state.key_map,buff,2);
1282
longlong2str(share->state.key_map,buff,2);
1224
1283
printf("Using only keys '%s' of %d possibly keys\n",
1225
buff, share->base.keys);
1284
buff, share->base.keys);
1227
1286
puts("\ntable description:");
1228
1287
printf("Key Start Len Index Type");
1229
1288
if (param->testflag & T_VERBOSE)
1230
1289
printf(" Rec/key Root Blocksize");
1290
VOID(putchar('\n'));
1233
1292
for (key=keyseg_nr=0, keyinfo= &share->keyinfo[0] ;
1234
1293
key < share->base.keys;
1237
1296
keyseg=keyinfo->seg;
1238
1297
if (keyinfo->flag & HA_NOSAME) text="unique ";
1298
else if (keyinfo->flag & HA_FULLTEXT) text="fulltext ";
1239
1299
else text="multip.";
1242
1302
if (keyseg->flag & HA_REVERSE_SORT)
1244
pos= strcpy(pos,type_names[keyseg->type]);
1245
pos+= strlen(type_names[keyseg->type]);
1304
pos=strmov(pos,type_names[keyseg->type]);
1248
1307
if (keyinfo->flag & HA_PACK_KEY)
1249
pos= strcpy(pos,prefix_packed_txt) + strlen(prefix_packed_txt);
1308
pos=strmov(pos,prefix_packed_txt);
1250
1309
if (keyinfo->flag & HA_BINARY_PACK_KEY)
1251
pos= strcpy(pos,bin_packed_txt) + strlen(bin_packed_txt);
1310
pos=strmov(pos,bin_packed_txt);
1252
1311
if (keyseg->flag & HA_SPACE_PACK)
1253
pos= strcpy(pos,diff_txt) + strlen(diff_txt);
1312
pos=strmov(pos,diff_txt);
1254
1313
if (keyseg->flag & HA_BLOB_PART)
1255
pos= strcpy(pos,blob_txt) + strlen(blob_txt);
1314
pos=strmov(pos,blob_txt);
1256
1315
if (keyseg->flag & HA_NULL_PART)
1257
pos= strcpy(pos,null_txt) + strlen(null_txt);
1316
pos=strmov(pos,null_txt);
1260
1319
printf("%-4d%-6ld%-3d %-8s%-21s",
1261
key+1,(long) keyseg->start+1,keyseg->length,text,buff);
1320
key+1,(long) keyseg->start+1,keyseg->length,text,buff);
1262
1321
if (share->state.key_root[key] != HA_OFFSET_ERROR)
1263
1322
llstr(share->state.key_root[key],buff);
1266
1325
if (param->testflag & T_VERBOSE)
1267
1326
printf("%11lu %12s %10d",
1268
share->state.rec_per_key_part[keyseg_nr++],
1269
buff,keyinfo->block_length);
1327
share->state.rec_per_key_part[keyseg_nr++],
1328
buff,keyinfo->block_length);
1329
VOID(putchar('\n'));
1271
1330
while ((++keyseg)->type != HA_KEYTYPE_END)
1274
1333
if (keyseg->flag & HA_REVERSE_SORT)
1276
pos= strcpy(pos,type_names[keyseg->type]);
1277
pos+= strlen(type_names[keyseg->type]);
1335
pos=strmov(pos,type_names[keyseg->type]);
1279
1337
if (keyseg->flag & HA_SPACE_PACK)
1280
pos= strcpy(pos,diff_txt) + strlen(diff_txt);
1338
pos=strmov(pos,diff_txt);
1281
1339
if (keyseg->flag & HA_BLOB_PART)
1282
pos= strcpy(pos,blob_txt) + strlen(blob_txt);
1340
pos=strmov(pos,blob_txt);
1283
1341
if (keyseg->flag & HA_NULL_PART)
1284
pos= strcpy(pos,null_txt) + strlen(null_txt);
1342
pos=strmov(pos,null_txt);
1286
1344
printf(" %-6ld%-3d %-21s",
1287
1345
(long) keyseg->start+1,keyseg->length,buff);
1288
1346
if (param->testflag & T_VERBOSE)
1289
printf("%11lu", share->state.rec_per_key_part[keyseg_nr++]);
1347
printf("%11lu", share->state.rec_per_key_part[keyseg_nr++]);
1348
VOID(putchar('\n'));
1296
1354
MI_UNIQUEDEF *uniqueinfo;
1297
1355
puts("\nUnique Key Start Len Nullpos Nullbit Type");
1298
1356
for (key=0,uniqueinfo= &share->uniqueinfo[0] ;
1299
key < share->state.header.uniques; key++, uniqueinfo++)
1357
key < share->state.header.uniques; key++, uniqueinfo++)
1302
1360
char null_bit[8],null_pos[8];
1303
1361
printf("%-8d%-5d",key+1,uniqueinfo->key+1);
1304
1362
for (keyseg=uniqueinfo->seg ; keyseg->type != HA_KEYTYPE_END ; keyseg++)
1308
null_bit[0]=null_pos[0]=0;
1309
if (keyseg->null_bit)
1311
sprintf(null_bit,"%d",keyseg->null_bit);
1312
sprintf(null_pos,"%ld",(long) keyseg->null_pos+1);
1314
printf("%-7ld%-5d%-9s%-10s%-30s\n",
1315
(long) keyseg->start+1,keyseg->length,
1317
type_names[keyseg->type]);
1366
null_bit[0]=null_pos[0]=0;
1367
if (keyseg->null_bit)
1369
sprintf(null_bit,"%d",keyseg->null_bit);
1370
sprintf(null_pos,"%ld",(long) keyseg->null_pos+1);
1372
printf("%-7ld%-5d%-9s%-10s%-30s\n",
1373
(long) keyseg->start+1,keyseg->length,
1375
type_names[keyseg->type]);
1325
1383
printf("\nField Start Length Nullpos Nullbit Type");
1326
1384
if (share->options & HA_OPTION_COMPRESS_RECORD)
1327
1385
printf(" Huff tree Bits");
1386
VOID(putchar('\n'));
1330
1388
for (field=0 ; field < share->base.fields ; field++)
1332
1390
if (share->options & HA_OPTION_COMPRESS_RECORD)
1333
type=share->rec[field].base_type;
1391
type=share->rec[field].base_type;
1335
type=(enum en_fieldtype) share->rec[field].type;
1336
end= strcpy(buff, field_pack[type]);
1337
end+= strlen(field_pack[type]);
1393
type=(enum en_fieldtype) share->rec[field].type;
1394
end=strmov(buff,field_pack[type]);
1338
1395
if (share->options & HA_OPTION_COMPRESS_RECORD)
1340
if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
1341
end= strcpy(end,", not_always")+12;
1342
if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
1343
end= strcpy(end,", no empty")+10;
1344
if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
1346
sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
1347
end= strchr(end, '\0');
1397
if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
1398
end=strmov(end,", not_always");
1399
if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
1400
end=strmov(end,", no empty");
1401
if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
1403
sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
1350
1407
if (buff[0] == ',')
1351
strcpy(buff,buff+2);
1408
strmov(buff,buff+2);
1352
1409
int10_to_str((long) share->rec[field].length,length,10);
1353
1410
null_bit[0]=null_pos[0]=0;
1354
1411
if (share->rec[field].null_bit)
1356
sprintf(null_bit,"%d",share->rec[field].null_bit);
1357
sprintf(null_pos,"%d",share->rec[field].null_pos+1);
1413
sprintf(null_bit,"%d",share->rec[field].null_bit);
1414
sprintf(null_pos,"%d",share->rec[field].null_pos+1);
1359
1416
printf("%-6d%-6d%-7s%-8s%-8s%-35s",field+1,start,length,
1360
1417
null_pos, null_bit, buff);
1378
1435
static int mi_sort_records(MI_CHECK *param,
1379
1436
register MI_INFO *info, char * name,
1439
my_bool update_index)
1386
1443
MI_KEYDEF *keyinfo;
1388
unsigned char *temp_buff;
1389
1446
ha_rows old_record_count;
1390
1447
MYISAM_SHARE *share=info->s;
1391
1448
char llbuff[22],llbuff2[22];
1392
1449
SORT_INFO sort_info;
1393
1450
MI_SORT_PARAM sort_param;
1451
DBUG_ENTER("sort_records");
1395
memset(&sort_info, 0, sizeof(sort_info));
1396
memset(&sort_param, 0, sizeof(sort_param));
1453
bzero((char*)&sort_info,sizeof(sort_info));
1454
bzero((char*)&sort_param,sizeof(sort_param));
1397
1455
sort_param.sort_info=&sort_info;
1398
1456
sort_info.param=param;
1399
1457
keyinfo= &share->keyinfo[sort_key];
1407
1465
"Can't sort table '%s' on key %d; No such key",
1408
1466
name,sort_key+1);
1409
1467
param->error_printed=0;
1410
return(0); /* Nothing to do */
1468
DBUG_RETURN(0); /* Nothing to do */
1470
if (keyinfo->flag & HA_FULLTEXT)
1472
mi_check_print_warning(param,"Can't sort table '%s' on FULLTEXT key %d",
1474
param->error_printed=0;
1475
DBUG_RETURN(0); /* Nothing to do */
1412
1477
if (share->data_file_type == COMPRESSED_RECORD)
1414
1479
mi_check_print_warning(param,"Can't sort read-only table '%s'", name);
1415
1480
param->error_printed=0;
1416
return(0); /* Nothing to do */
1481
DBUG_RETURN(0); /* Nothing to do */
1418
1483
if (!(param->testflag & T_SILENT))
1424
1489
llstr(info->state->del,llbuff2));
1426
1491
if (share->state.key_root[sort_key] == HA_OFFSET_ERROR)
1427
return(0); /* Nothing to do */
1492
DBUG_RETURN(0); /* Nothing to do */
1429
init_key_cache(dflt_key_cache, opt_key_cache_block_size,
1430
(size_t)param->use_buffers,
1494
init_key_cache(dflt_key_cache, opt_key_cache_block_size, param->use_buffers,
1432
1496
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
1433
1497
WRITE_CACHE,share->pack.header_length,1,
1436
1500
info->opt_flag|=WRITE_CACHE_USED;
1438
if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
1502
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1440
1504
mi_check_print_error(param,"Not enough memory for key block");
1444
if (!mi_alloc_rec_buff(info, (ulong)-1, &sort_param.record))
1508
if (!mi_alloc_rec_buff(info, -1, &sort_param.record))
1446
1510
mi_check_print_error(param,"Not enough memory for record");
1449
1513
fn_format(param->temp_filename,name,"", MI_NAME_DEXT,2+4+32);
1450
new_file=my_create(fn_format(param->temp_filename,
1451
param->temp_filename,"",
1453
0,param->tmpfile_createflag,
1514
new_file=my_raid_create(fn_format(param->temp_filename,
1515
param->temp_filename,"",
1517
0,param->tmpfile_createflag,
1518
share->base.raid_type,
1519
share->base.raid_chunks,
1520
share->base.raid_chunksize,
1455
1522
if (new_file < 0)
1457
1524
mi_check_print_error(param,"Can't create new tempfile: '%s'",
1518
1585
if (param->testflag & T_WRITE_LOOP)
1520
fputs(" \r",stdout); fflush(stdout);
1587
VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
1525
1592
if (got_error && new_file >= 0)
1527
end_io_cache(&info->rec_cache);
1594
VOID(end_io_cache(&info->rec_cache));
1528
1595
(void) my_close(new_file,MYF(MY_WME));
1529
(void) my_delete(param->temp_filename, MYF(MY_WME));
1596
(void) my_raid_delete(param->temp_filename, share->base.raid_chunks,
1533
free((unsigned char*) temp_buff);
1601
my_afree((uchar*) temp_buff);
1535
void * rec_buff_ptr= mi_get_rec_buff_ptr(info, sort_param.record);
1536
if (rec_buff_ptr != NULL)
1603
my_free(mi_get_rec_buff_ptr(info, sort_param.record),
1604
MYF(MY_ALLOW_ZERO_PTR));
1539
1605
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
1540
end_io_cache(&info->rec_cache);
1541
free(sort_info.buff);
1606
VOID(end_io_cache(&info->rec_cache));
1607
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
1542
1608
sort_info.buff=0;
1543
1609
share->state.sortkey=sort_key;
1544
return(flush_blocks(param, share->key_cache, share->kfile) |
1610
DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) |
1546
1612
} /* sort_records */
1551
1617
static int sort_record_index(MI_SORT_PARAM *sort_param,MI_INFO *info,
1552
1618
MI_KEYDEF *keyinfo,
1553
my_off_t page, unsigned char *buff, uint32_t sort_key,
1554
File new_file,bool update_index)
1619
my_off_t page, uchar *buff, uint sort_key,
1620
File new_file,my_bool update_index)
1556
1622
uint nod_flag,used_length,key_length;
1557
unsigned char *temp_buff,*keypos,*endpos;
1623
uchar *temp_buff,*keypos,*endpos;
1558
1624
my_off_t next_page,rec_pos;
1559
unsigned char lastkey[MI_MAX_KEY_BUFF];
1625
uchar lastkey[MI_MAX_KEY_BUFF];
1560
1626
char llbuff[22];
1561
1627
SORT_INFO *sort_info= sort_param->sort_info;
1562
1628
MI_CHECK *param=sort_info->param;
1629
DBUG_ENTER("sort_record_index");
1564
1631
nod_flag=mi_test_if_nod(buff);
1569
if (!(temp_buff=(unsigned char*) malloc(keyinfo->block_length)))
1636
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
1571
1638
mi_check_print_error(param,"Not Enough memory");
1575
1642
used_length=mi_getint(buff);
1620
1687
/* Clear end of block to get better compression if the table is backuped */
1621
memset(buff+used_length, 0, keyinfo->block_length-used_length);
1622
if (my_pwrite(info->s->kfile,(unsigned char*) buff,(uint) keyinfo->block_length,
1688
bzero((uchar*) buff+used_length,keyinfo->block_length-used_length);
1689
if (my_pwrite(info->s->kfile,(uchar*) buff,(uint) keyinfo->block_length,
1623
1690
page,param->myf_rw))
1625
1692
mi_check_print_error(param,"%d when updating keyblock",my_errno);
1629
free((unsigned char*) temp_buff);
1696
my_afree((uchar*) temp_buff);
1633
free((unsigned char*) temp_buff);
1700
my_afree((uchar*) temp_buff);
1635
1702
} /* sort_record_index */