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