1 /*
2    Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
23 
24 /* Testing of the basic functions of a MyISAM table */
25 
26 #include <m_string.h>
27 #include <my_getopt.h>
28 #include "my_byteorder.h"
29 #include "myisam.h"
30 #include "sql/field.h"
31 
32 #define MAX_REC_LENGTH 1024
33 
34 static void usage();
35 
36 static int rec_pointer_size = 0, flags[50];
37 static int key_field = FIELD_SKIP_PRESPACE, extra_field = FIELD_SKIP_ENDSPACE;
38 static int key_type = HA_KEYTYPE_NUM;
39 static int create_flag = 0;
40 
41 static uint insert_count, update_count, remove_count;
42 static uint pack_keys = 0, pack_seg = 0, key_length;
43 static uint unique_key = HA_NOSAME;
44 static bool key_cacheing, null_fields, silent, skip_update, opt_unique, verbose;
45 static MI_COLUMNDEF recinfo[4];
46 static MI_KEYDEF keyinfo[10];
47 static HA_KEYSEG keyseg[10];
48 static HA_KEYSEG uniqueseg[10];
49 
50 static int run_test(const char *filename);
51 static void get_options(int argc, char *argv[]);
52 static void create_key(uchar *key, uint rownr);
53 static void create_record(uchar *record, uint rownr);
54 static void update_record(uchar *record);
55 
56 /*
57   strappend(dest, len, fill) appends fill-characters to a string so that
58   the result length == len. If the string is longer than len it's
59   trunked. The des+len character is allways set to NULL.
60 */
strappend(char * s,size_t len,char fill)61 static inline void strappend(char *s, size_t len, char fill) {
62   char *endpos;
63 
64   endpos = s + len;
65   while (*s++)
66     ;
67   s--;
68   while (s < endpos) *(s++) = fill;
69   *(endpos) = '\0';
70 }
71 
main(int argc,char * argv[])72 int main(int argc, char *argv[]) {
73   MY_INIT(argv[0]);
74   my_init();
75   if (key_cacheing)
76     init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, IO_SIZE * 16, 0, 0);
77   get_options(argc, argv);
78 
79   exit(run_test("test1"));
80 }
81 
run_test(const char * filename)82 static int run_test(const char *filename) {
83   MI_INFO *file;
84   int i, j, error, deleted, rec_length, uniques = 0;
85   ha_rows found, row_count;
86   my_off_t pos;
87   uchar record[MAX_REC_LENGTH], key[MAX_REC_LENGTH],
88       read_record[MAX_REC_LENGTH];
89   MI_UNIQUEDEF uniquedef;
90   MI_CREATE_INFO create_info;
91 
92   memset(recinfo, 0, sizeof(recinfo));
93 
94   /* First define 2 columns */
95   recinfo[0].type = FIELD_NORMAL;
96   recinfo[0].length = 1; /* For NULL bits */
97   recinfo[1].type = key_field;
98   recinfo[1].length =
99       (key_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : key_length);
100   if (key_field == FIELD_VARCHAR)
101     recinfo[1].length += HA_VARCHAR_PACKLENGTH(key_length);
102   ;
103   recinfo[2].type = extra_field;
104   recinfo[2].length =
105       (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24);
106   if (extra_field == FIELD_VARCHAR)
107     recinfo[2].length += HA_VARCHAR_PACKLENGTH(recinfo[2].length);
108   if (opt_unique) {
109     recinfo[3].type = FIELD_CHECK;
110     recinfo[3].length = MI_UNIQUE_HASH_LENGTH;
111   }
112   rec_length = recinfo[0].length + recinfo[1].length + recinfo[2].length +
113                recinfo[3].length;
114 
115   if (key_type == HA_KEYTYPE_VARTEXT1 && key_length > 255)
116     key_type = HA_KEYTYPE_VARTEXT2;
117 
118   /* Define a key over the first column */
119   keyinfo[0].seg = keyseg;
120   keyinfo[0].keysegs = 1;
121   keyinfo[0].block_length = 0; /* Default block length */
122   keyinfo[0].key_alg = HA_KEY_ALG_BTREE;
123   keyinfo[0].seg[0].type = key_type;
124   keyinfo[0].seg[0].flag = pack_seg;
125   keyinfo[0].seg[0].start = 1;
126   keyinfo[0].seg[0].length = key_length;
127   keyinfo[0].seg[0].null_bit = null_fields ? 2 : 0;
128   keyinfo[0].seg[0].null_pos = 0;
129   keyinfo[0].seg[0].language = default_charset_info->number;
130   if (pack_seg & HA_BLOB_PART) {
131     keyinfo[0].seg[0].bit_start = 4; /* Length of blob length */
132   }
133   keyinfo[0].flag = (uint8)(pack_keys | unique_key);
134 
135   memset(flags, 0, sizeof(flags));
136   if (opt_unique) {
137     uint start;
138     uniques = 1;
139     memset(&uniquedef, 0, sizeof(uniquedef));
140     memset(uniqueseg, 0, sizeof(uniqueseg));
141     uniquedef.seg = uniqueseg;
142     uniquedef.keysegs = 2;
143 
144     /* Make a unique over all columns (except first NULL fields) */
145     for (i = 0, start = 1; i < 2; i++) {
146       uniqueseg[i].start = start;
147       start += recinfo[i + 1].length;
148       uniqueseg[i].length = recinfo[i + 1].length;
149       uniqueseg[i].language = default_charset_info->number;
150     }
151     uniqueseg[0].type = key_type;
152     uniqueseg[0].null_bit = null_fields ? 2 : 0;
153     uniqueseg[1].type = HA_KEYTYPE_TEXT;
154     if (extra_field == FIELD_BLOB) {
155       uniqueseg[1].length = 0;    /* The whole blob */
156       uniqueseg[1].bit_start = 4; /* long blob */
157       uniqueseg[1].flag |= HA_BLOB_PART;
158     } else if (extra_field == FIELD_VARCHAR)
159       uniqueseg[1].flag |= HA_VAR_LENGTH_PART;
160   } else
161     uniques = 0;
162 
163   if (!silent) printf("- Creating isam-file\n");
164   memset(&create_info, 0, sizeof(create_info));
165   create_info.max_rows =
166       (ulong)(rec_pointer_size ? (1L << (rec_pointer_size * 8)) / 40 : 0);
167   if (mi_create(filename, 1, keyinfo, 3 + opt_unique, recinfo, uniques,
168                 &uniquedef, &create_info, create_flag))
169     goto err;
170   if (!(file = mi_open(filename, 2, HA_OPEN_ABORT_IF_LOCKED))) goto err;
171   if (!silent) printf("- Writing key:s\n");
172 
173   my_errno = 0;
174   row_count = deleted = 0;
175   for (i = 49; i >= 1; i -= 2) {
176     if (insert_count-- == 0) {
177       (void)mi_close(file);
178       exit(0);
179     }
180     j = i % 25 + 1;
181     create_record(record, j);
182     error = mi_write(file, record);
183     if (!error) row_count++;
184     flags[j] = 1;
185     if (verbose || error)
186       printf("J= %2d  mi_write: %d  errno: %d\n", j, error, my_errno);
187   }
188 
189   /* Insert 2 rows with null values */
190   if (null_fields) {
191     create_record(record, 0);
192     error = mi_write(file, record);
193     if (!error) row_count++;
194     if (verbose || error)
195       printf("J= NULL  mi_write: %d  errno: %d\n", error, my_errno);
196     error = mi_write(file, record);
197     if (!error) row_count++;
198     if (verbose || error)
199       printf("J= NULL  mi_write: %d  errno: %d\n", error, my_errno);
200     flags[0] = 2;
201   }
202 
203   if (!skip_update) {
204     if (opt_unique) {
205       if (!silent) printf("- Checking unique constraint\n");
206       create_record(record, j);
207       if (!mi_write(file, record) || my_errno != HA_ERR_FOUND_DUPP_UNIQUE) {
208         printf("unique check failed\n");
209       }
210     }
211     if (!silent) printf("- Updating rows\n");
212 
213     /* Update first last row to force extend of file */
214     if (mi_rsame(file, read_record, -1)) {
215       printf("Can't find last row with mi_rsame\n");
216     } else {
217       memcpy(record, read_record, rec_length);
218       update_record(record);
219       if (mi_update(file, read_record, record)) {
220         printf("Can't update last row: %.*s\n", keyinfo[0].seg[0].length,
221                read_record + 1);
222       }
223     }
224 
225     /* Read through all rows and update them */
226     pos = (my_off_t)0;
227     found = 0;
228     while ((error = mi_rrnd(file, read_record, pos)) == 0) {
229       if (update_count-- == 0) {
230         (void)mi_close(file);
231         exit(0);
232       }
233       memcpy(record, read_record, rec_length);
234       update_record(record);
235       if (mi_update(file, read_record, record)) {
236         printf("Can't update row: %.*s, error: %d\n", keyinfo[0].seg[0].length,
237                record + 1, my_errno);
238       }
239       found++;
240       pos = HA_OFFSET_ERROR;
241     }
242     if (found != row_count)
243       printf("Found %ld of %ld rows\n", (ulong)found, (ulong)row_count);
244   }
245 
246   if (!silent) printf("- Reopening file\n");
247   if (mi_close(file)) goto err;
248   if (!(file = mi_open(filename, 2, HA_OPEN_ABORT_IF_LOCKED))) goto err;
249   if (!skip_update) {
250     if (!silent) printf("- Removing keys\n");
251 
252     for (i = 0; i <= 10; i++) {
253       /* testing */
254       if (remove_count-- == 0) {
255         (void)mi_close(file);
256         exit(0);
257       }
258       j = i * 2;
259       if (!flags[j]) continue;
260       create_key(key, j);
261       my_errno = 0;
262       if ((error = mi_rkey(file, read_record, 0, key, HA_WHOLE_KEY,
263                            HA_READ_KEY_EXACT))) {
264         if (verbose ||
265             (flags[j] >= 1 || (error && my_errno != HA_ERR_KEY_NOT_FOUND)))
266           printf("key: '%.*s'  mi_rkey:  %3d  errno: %3d\n", (int)key_length,
267                  key + null_fields, error, my_errno);
268       } else {
269         error = mi_delete(file, read_record);
270         if (verbose || error)
271           printf("key: '%.*s'  mi_delete: %3d  errno: %3d\n", (int)key_length,
272                  key + null_fields, error, my_errno);
273         if (!error) {
274           deleted++;
275           flags[j]--;
276         }
277       }
278     }
279   }
280   if (!silent) printf("- Reading rows with key\n");
281   for (i = 0; i <= 25; i++) {
282     create_key(key, i);
283     my_errno = 0;
284     error = mi_rkey(file, read_record, 0, key, HA_WHOLE_KEY, HA_READ_KEY_EXACT);
285     if (verbose || (error == 0 && flags[i] == 0 && unique_key) ||
286         (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND))) {
287       printf("key: '%.*s'  mi_rkey: %3d  errno: %3d  record: %s\n",
288              (int)key_length, key + null_fields, error, my_errno, record + 1);
289     }
290   }
291 
292   if (!silent) printf("- Reading rows with position\n");
293   for (i = 1, found = 0; i <= 30; i++) {
294     my_errno = 0;
295     if ((error = mi_rrnd(file, read_record, i == 1 ? 0L : HA_OFFSET_ERROR)) ==
296         -1) {
297       if (found != row_count - deleted)
298         printf("Found only %ld of %ld rows\n", (ulong)found,
299                (ulong)(row_count - deleted));
300       break;
301     }
302     if (!error) found++;
303     if (verbose || (error != 0 && error != HA_ERR_RECORD_DELETED &&
304                     error != HA_ERR_END_OF_FILE)) {
305       printf("pos: %2d  mi_rrnd: %3d  errno: %3d  record: %s\n", i - 1, error,
306              my_errno, read_record + 1);
307     }
308   }
309   if (mi_close(file)) goto err;
310   my_end(MY_CHECK_ERROR);
311 
312   return (0);
313 err:
314   printf("got error: %3d when using myisam-database\n", my_errno);
315   return 1; /* skip warning */
316 }
317 
create_key_part(uchar * key,uint rownr)318 static void create_key_part(uchar *key, uint rownr) {
319   if (!unique_key) rownr &= 7; /* Some identical keys */
320   if (keyinfo[0].seg[0].type == HA_KEYTYPE_NUM) {
321     sprintf((char *)key, "%*d", keyinfo[0].seg[0].length, rownr);
322   } else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT1 ||
323              keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT2) { /* Alpha record */
324     /* Create a key that may be easily packed */
325     memset(key, rownr < 10 ? 'A' : 'B', keyinfo[0].seg[0].length);
326     sprintf((char *)key + keyinfo[0].seg[0].length - 2, "%-2d", rownr);
327     if ((rownr & 7) == 0) {
328       /* Change the key to force a unpack of the next key */
329       memset(key + 3, rownr < 10 ? 'a' : 'b', keyinfo[0].seg[0].length - 4);
330     }
331   } else { /* Alpha record */
332     if (keyinfo[0].seg[0].flag & HA_SPACE_PACK)
333       sprintf((char *)key, "%-*d", keyinfo[0].seg[0].length, rownr);
334     else {
335       /* Create a key that may be easily packed */
336       memset(key, rownr < 10 ? 'A' : 'B', keyinfo[0].seg[0].length);
337       sprintf((char *)key + keyinfo[0].seg[0].length - 2, "%-2d", rownr);
338       if ((rownr & 7) == 0) {
339         /* Change the key to force a unpack of the next key */
340         key[1] = (rownr < 10 ? 'a' : 'b');
341       }
342     }
343   }
344 }
345 
create_key(uchar * key,uint rownr)346 static void create_key(uchar *key, uint rownr) {
347   if (keyinfo[0].seg[0].null_bit) {
348     if (rownr == 0) {
349       key[0] = 1; /* null key */
350       key[1] = 0; /* Fore easy print of key */
351       return;
352     }
353     *key++ = 0;
354   }
355   if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART)) {
356     uint tmp;
357     create_key_part(key + 2, rownr);
358     tmp = strlen((char *)key + 2);
359     int2store(key, tmp);
360   } else
361     create_key_part(key, rownr);
362 }
363 
364 static uchar blob_key[MAX_REC_LENGTH];
365 static uchar blob_record[MAX_REC_LENGTH + 20 * 20];
366 
create_record(uchar * record,uint rownr)367 static void create_record(uchar *record, uint rownr) {
368   uchar *pos;
369   memset(record, 0, MAX_REC_LENGTH);
370   record[0] = 1; /* delete marker */
371   if (rownr == 0 && keyinfo[0].seg[0].null_bit)
372     record[0] |= keyinfo[0].seg[0].null_bit; /* Null key */
373 
374   pos = record + 1;
375   if (recinfo[1].type == FIELD_BLOB) {
376     uint tmp;
377     uchar *ptr;
378     create_key_part(blob_key, rownr);
379     tmp = strlen((char *)blob_key);
380     int4store(pos, tmp);
381     ptr = blob_key;
382     memcpy(pos + 4, &ptr, sizeof(char *));
383     pos += recinfo[1].length;
384   } else if (recinfo[1].type == FIELD_VARCHAR) {
385     uint tmp, pack_length = HA_VARCHAR_PACKLENGTH(recinfo[1].length - 1);
386     create_key_part(pos + pack_length, rownr);
387     tmp = strlen((char *)pos + pack_length);
388     if (pack_length == 1)
389       *(uchar *)pos = (uchar)tmp;
390     else
391       int2store(pos, tmp);
392     pos += recinfo[1].length;
393   } else {
394     create_key_part(pos, rownr);
395     pos += recinfo[1].length;
396   }
397   if (recinfo[2].type == FIELD_BLOB) {
398     uint tmp;
399     uchar *ptr;
400     ;
401     sprintf((char *)blob_record, "... row: %d", rownr);
402     strappend((char *)blob_record, max(MAX_REC_LENGTH - rownr, 10), ' ');
403     tmp = strlen((char *)blob_record);
404     int4store(pos, tmp);
405     ptr = blob_record;
406     memcpy(pos + 4, &ptr, sizeof(char *));
407   } else if (recinfo[2].type == FIELD_VARCHAR) {
408     uint tmp, pack_length = HA_VARCHAR_PACKLENGTH(recinfo[1].length - 1);
409     sprintf((char *)pos + pack_length, "... row: %d", rownr);
410     tmp = strlen((char *)pos + pack_length);
411     if (pack_length == 1)
412       *pos = (uchar)tmp;
413     else
414       int2store(pos, tmp);
415   } else {
416     sprintf((char *)pos, "... row: %d", rownr);
417     strappend((char *)pos, recinfo[2].length, ' ');
418   }
419 }
420 
421 /* change row to test re-packing of rows and reallocation of keys */
422 
update_record(uchar * record)423 static void update_record(uchar *record) {
424   uchar *pos = record + 1;
425   if (recinfo[1].type == FIELD_BLOB) {
426     uchar *column, *ptr;
427     int length;
428     length = uint4korr(pos); /* Long blob */
429     memcpy(&column, pos + 4, sizeof(char *));
430     memcpy(blob_key, column, length); /* Move old key */
431     ptr = blob_key;
432     memcpy(pos + 4, &ptr, sizeof(char *)); /* Store pointer to new key */
433     if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
434       default_charset_info->cset->casedn(default_charset_info, (char *)blob_key,
435                                          length, (char *)blob_key, length);
436     pos += recinfo[1].length;
437   } else if (recinfo[1].type == FIELD_VARCHAR) {
438     uint pack_length = HA_VARCHAR_PACKLENGTH(recinfo[1].length - 1);
439     uint length = pack_length == 1 ? (uint) * (uchar *)pos : uint2korr(pos);
440     default_charset_info->cset->casedn(default_charset_info,
441                                        (char *)pos + pack_length, length,
442                                        (char *)pos + pack_length, length);
443     pos += recinfo[1].length;
444   } else {
445     if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
446       default_charset_info->cset->casedn(default_charset_info, (char *)pos,
447                                          keyinfo[0].seg[0].length, (char *)pos,
448                                          keyinfo[0].seg[0].length);
449     pos += recinfo[1].length;
450   }
451 
452   if (recinfo[2].type == FIELD_BLOB) {
453     uchar *column;
454     int length;
455     length = uint4korr(pos);
456     memcpy(&column, pos + 4, sizeof(char *));
457     memcpy(blob_record, column, length);
458     memset(blob_record + length, '.', 20); /* Make it larger */
459     length += 20;
460     int4store(pos, length);
461     column = blob_record;
462     memcpy(pos + 4, &column, sizeof(char *));
463   } else if (recinfo[2].type == FIELD_VARCHAR) {
464     /* Second field is longer than 10 characters */
465     uint pack_length = HA_VARCHAR_PACKLENGTH(recinfo[1].length - 1);
466     uint length = pack_length == 1 ? (uint) * (uchar *)pos : uint2korr(pos);
467     memset(pos + pack_length + length, '.',
468            recinfo[2].length - length - pack_length);
469     length = recinfo[2].length - pack_length;
470     if (pack_length == 1)
471       *(uchar *)pos = (uchar)length;
472     else
473       int2store(pos, length);
474   } else {
475     memset(pos + recinfo[2].length - 10, '.', 10);
476   }
477 }
478 
479 static struct my_option my_long_options[] = {
480     {"checksum", 'c', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
481      0, 0},
482 #ifndef DBUG_OFF
483     {"debug", '#', "Undocumented", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
484      0, 0},
485 #endif
486     {"delete_rows", 'd', "Undocumented", &remove_count, &remove_count, 0,
487      GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0},
488     {"help", '?', "Display help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0,
489      0, 0, 0},
490     {"insert_rows", 'i', "Undocumented", &insert_count, &insert_count, 0,
491      GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0},
492     {"key_alpha", 'a', "Use a key of type HA_KEYTYPE_TEXT", 0, 0, 0, GET_NO_ARG,
493      NO_ARG, 0, 0, 0, 0, 0, 0},
494     {"key_binary_pack", 'B', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
495      0, 0, 0, 0},
496     {"key_blob", 'b', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
497      0, 0},
498     {"key_cache", 'K', "Undocumented", &key_cacheing, &key_cacheing, 0,
499      GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
500     {"key_length", 'k', "Undocumented", &key_length, &key_length, 0, GET_UINT,
501      REQUIRED_ARG, 6, 0, 0, 0, 0, 0},
502     {"key_multiple", 'm', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0,
503      0, 0, 0},
504     {"key_prefix_pack", 'P', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
505      0, 0, 0, 0},
506     {"key_space_pack", 'p', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
507      0, 0, 0, 0},
508     {"key_varchar", 'w', "Test VARCHAR keys", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
509      0, 0, 0, 0},
510     {"null_fields", 'N', "Define fields with NULL", &null_fields, &null_fields,
511      0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
512     {"row_fixed_size", 'S', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
513      0, 0, 0, 0},
514     {"row_pointer_size", 'R', "Undocumented", &rec_pointer_size,
515      &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
516     {"silent", 's', "Undocumented", &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0,
517      0, 0, 0, 0},
518     {"skip_update", 'U', "Undocumented", &skip_update, &skip_update, 0,
519      GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
520     {"unique", 'C', "Undocumented", &opt_unique, &opt_unique, 0, GET_BOOL,
521      NO_ARG, 0, 0, 0, 0, 0, 0},
522     {"update_rows", 'u', "Undocumented", &update_count, &update_count, 0,
523      GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0},
524     {"verbose", 'v', "Be more verbose", &verbose, &verbose, 0, GET_BOOL, NO_ARG,
525      0, 0, 0, 0, 0, 0},
526     {"version", 'V', "Print version number and exit", 0, 0, 0, GET_NO_ARG,
527      NO_ARG, 0, 0, 0, 0, 0, 0},
528     {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}};
529 
get_one_option(int optid,const struct my_option * opt MY_ATTRIBUTE ((unused)),char * argument MY_ATTRIBUTE ((unused)))530 static bool get_one_option(int optid,
531                            const struct my_option *opt MY_ATTRIBUTE((unused)),
532                            char *argument MY_ATTRIBUTE((unused))) {
533   switch (optid) {
534     case 'a':
535       key_type = HA_KEYTYPE_TEXT;
536       break;
537     case 'c':
538       create_flag |= HA_CREATE_CHECKSUM;
539       break;
540     case 'R': /* Length of record pointer */
541       if (rec_pointer_size > 3) rec_pointer_size = 0;
542       break;
543     case 'P':
544       pack_keys = HA_PACK_KEY; /* Use prefix compression */
545       break;
546     case 'B':
547       pack_keys = HA_BINARY_PACK_KEY; /* Use binary compression */
548       break;
549     case 'S':
550       if (key_field == FIELD_VARCHAR) {
551         create_flag = 0; /* Static sized varchar */
552       } else if (key_field != FIELD_BLOB) {
553         key_field = FIELD_NORMAL; /* static-size record */
554         extra_field = FIELD_NORMAL;
555       }
556       break;
557     case 'p':
558       pack_keys = HA_PACK_KEY; /* Use prefix + space packing */
559       pack_seg = HA_SPACE_PACK;
560       key_type = HA_KEYTYPE_TEXT;
561       break;
562     case 'm':
563       unique_key = 0;
564       break;
565     case 'b':
566       key_field = FIELD_BLOB; /* blob key */
567       extra_field = FIELD_BLOB;
568       pack_seg |= HA_BLOB_PART;
569       key_type = HA_KEYTYPE_VARTEXT1;
570       break;
571     case 'k':
572       if (key_length < 4 || key_length > MI_MAX_KEY_LENGTH) {
573         fprintf(stderr, "Wrong key length\n");
574         exit(1);
575       }
576       break;
577     case 'w':
578       key_field = FIELD_VARCHAR; /* varchar keys */
579       extra_field = FIELD_VARCHAR;
580       key_type = HA_KEYTYPE_VARTEXT1;
581       pack_seg |= HA_VAR_LENGTH_PART;
582       create_flag |= HA_PACK_RECORD;
583       break;
584     case 'K': /* Use key cacheing */
585       key_cacheing = 1;
586       break;
587     case 'V':
588       printf("test1 Ver 1.2 \n");
589       exit(0);
590     case '#':
591       DBUG_PUSH(argument);
592       break;
593     case '?':
594       usage();
595       exit(1);
596   }
597   return 0;
598 }
599 
600 /* Read options */
601 
get_options(int argc,char * argv[])602 static void get_options(int argc, char *argv[]) {
603   int ho_error;
604 
605   if ((ho_error =
606            handle_options(&argc, &argv, my_long_options, get_one_option)))
607     exit(ho_error);
608 
609   return;
610 } /* get options */
611 
usage()612 static void usage() {
613   printf("Usage: %s [options]\n\n", my_progname);
614   my_print_help(my_long_options);
615   my_print_variables(my_long_options);
616 }
617 
618 #include "mi_extrafunc.h"
619