1 /*
2    Copyright (c) 2000, 2021, Oracle and/or its affiliates.
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 /* This file should be included when using myisam_funktions */
25 
26 #ifndef _myisam_h
27 #define _myisam_h
28 
29 #include "my_base.h"
30 #include "m_ctype.h"
31 #include "keycache.h"
32 #include "my_compare.h"
33 #include "my_check_opt.h"
34 #include "m_string.h"
35 
36 #ifdef	__cplusplus
37 extern "C" {
38 #endif
39 
40 /*
41   Limit max keys according to HA_MAX_POSSIBLE_KEY
42 */
43 
44 #if MAX_INDEXES > HA_MAX_POSSIBLE_KEY
45 #define MI_MAX_KEY                  HA_MAX_POSSIBLE_KEY /* Max allowed keys */
46 #else
47 #define MI_MAX_KEY                  MAX_INDEXES         /* Max allowed keys */
48 #endif
49 
50 #define MI_MAX_POSSIBLE_KEY_BUFF    HA_MAX_POSSIBLE_KEY_BUFF
51 /*
52   The following defines can be increased if necessary.
53   But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH.
54 */
55 #define MI_MAX_KEY_LENGTH           4000            /* Max length in bytes */
56 #define MI_MAX_KEY_SEG              16              /* Max segments for key */
57 
58 #define MI_MAX_KEY_BUFF  (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8)
59 #define MI_MAX_MSG_BUF      1024 /* used in CHECK TABLE, REPAIR TABLE */
60 #define MI_NAME_IEXT	".MYI"
61 #define MI_NAME_DEXT	".MYD"
62 
63 /* Possible values for myisam_block_size (must be power of 2) */
64 #define MI_KEY_BLOCK_LENGTH	1024	/* default key block length */
65 #define MI_MIN_KEY_BLOCK_LENGTH	1024	/* Min key block length */
66 #define MI_MAX_KEY_BLOCK_LENGTH	16384
67 
68 /*
69   In the following macros '_keyno_' is 0 .. keys-1.
70   If there can be more keys than bits in the key_map, the highest bit
71   is for all upper keys. They cannot be switched individually.
72   This means that clearing of high keys is ignored, setting one high key
73   sets all high keys.
74 */
75 #define MI_KEYMAP_BITS      (8 * SIZEOF_LONG_LONG)
76 #define MI_KEYMAP_HIGH_MASK (1ULL << (MI_KEYMAP_BITS - 1))
77 #define mi_get_mask_all_keys_active(_keys_) \
78                             (((_keys_) < MI_KEYMAP_BITS) ? \
79                              ((1ULL << (_keys_)) - 1ULL) : \
80                              (~ 0ULL))
81 
82 #if MI_MAX_KEY > MI_KEYMAP_BITS
83 
84 #define mi_is_key_active(_keymap_,_keyno_) \
85                             (((_keyno_) < MI_KEYMAP_BITS) ? \
86                              MY_TEST((_keymap_) & (1ULL << (_keyno_))) : \
87                              MY_TEST((_keymap_) & MI_KEYMAP_HIGH_MASK))
88 #define mi_set_key_active(_keymap_,_keyno_) \
89                             (_keymap_)|= (((_keyno_) < MI_KEYMAP_BITS) ? \
90                                           (1ULL << (_keyno_)) : \
91                                           MI_KEYMAP_HIGH_MASK)
92 #define mi_clear_key_active(_keymap_,_keyno_) \
93                             (_keymap_)&= (((_keyno_) < MI_KEYMAP_BITS) ? \
94                                           (~ (1ULL << (_keyno_))) : \
95                                           (~ (0ULL)) /*ignore*/ )
96 
97 #else
98 
99 #define mi_is_key_active(_keymap_,_keyno_) \
100                             MY_TEST((_keymap_) & (1ULL << (_keyno_)))
101 #define mi_set_key_active(_keymap_,_keyno_) \
102                             (_keymap_)|= (1ULL << (_keyno_))
103 #define mi_clear_key_active(_keymap_,_keyno_) \
104                             (_keymap_)&= (~ (1ULL << (_keyno_)))
105 
106 #endif
107 
108 #define mi_is_any_key_active(_keymap_) \
109                             MY_TEST((_keymap_))
110 #define mi_is_all_keys_active(_keymap_,_keys_) \
111                             ((_keymap_) == mi_get_mask_all_keys_active(_keys_))
112 #define mi_set_all_keys_active(_keymap_,_keys_) \
113                             (_keymap_)= mi_get_mask_all_keys_active(_keys_)
114 #define mi_clear_all_keys_active(_keymap_) \
115                             (_keymap_)= 0
116 #define mi_intersect_keys_active(_to_,_from_) \
117                             (_to_)&= (_from_)
118 #define mi_is_any_intersect_keys_active(_keymap1_,_keys_,_keymap2_) \
119                             ((_keymap1_) & (_keymap2_) & \
120                              mi_get_mask_all_keys_active(_keys_))
121 #define mi_copy_keys_active(_to_,_maxkeys_,_from_) \
122                             (_to_)= (mi_get_mask_all_keys_active(_maxkeys_) & \
123                                      (_from_))
124 
125 	/* Param to/from mi_status */
126 
127 typedef struct st_mi_isaminfo		/* Struct from h_info */
128 {
129   ha_rows records;			/* Records in database */
130   ha_rows deleted;			/* Deleted records in database */
131   my_off_t recpos;			/* Pos for last used record */
132   my_off_t newrecpos;			/* Pos if we write new record */
133   my_off_t dupp_key_pos;		/* Position to record with dupp key */
134   my_off_t data_file_length,		/* Length of data file */
135            max_data_file_length,
136            index_file_length,
137            max_index_file_length,
138            delete_length;
139   ulong reclength;			/* Recordlength */
140   ulong mean_reclength;			/* Mean recordlength (if packed) */
141   ulonglong auto_increment;
142   ulonglong key_map;			/* Which keys are used */
143   char  *data_file_name, *index_file_name;
144   uint  keys;				/* Number of keys in use */
145   uint	options;			/* HA_OPTION_... used */
146   int	errkey,				/* With key was dupplicated on err */
147 	sortkey;			/* clustered by this key */
148   File	filenr;				/* (uniq) filenr for datafile */
149   time_t create_time;			/* When table was created */
150   time_t check_time;
151   time_t update_time;
152   uint  reflength;
153   ulong record_offset;
154   ulong *rec_per_key;			/* for sql optimizing */
155 } MI_ISAMINFO;
156 
157 
158 typedef struct st_mi_create_info
159 {
160   const char *index_file_name, *data_file_name;	/* If using symlinks */
161   ha_rows max_rows;
162   ha_rows reloc_rows;
163   ulonglong auto_increment;
164   ulonglong data_file_length;
165   ulonglong key_file_length;
166   uint old_options;
167   uint16 language;
168   my_bool with_auto_increment;
169 } MI_CREATE_INFO;
170 
171 struct st_myisam_info;			/* For referense */
172 struct st_mi_isam_share;
173 typedef struct st_myisam_info MI_INFO;
174 struct st_mi_s_param;
175 
176 typedef struct st_mi_keydef		/* Key definition with open & info */
177 {
178   struct st_mi_isam_share *share;       /* Pointer to base (set in mi_open) */
179   uint16 keysegs;			/* Number of key-segment */
180   uint16 flag;				/* NOSAME, PACK_USED */
181 
182   uint8  key_alg;			/* BTREE, RTREE */
183   uint16 block_length;			/* Length of keyblock (auto) */
184   uint16 underflow_block_length;	/* When to execute underflow */
185   uint16 keylength;			/* Tot length of keyparts (auto) */
186   uint16 minlength;			/* min length of (packed) key (auto) */
187   uint16 maxlength;			/* max length of (packed) key (auto) */
188   uint16 block_size_index;		/* block_size (auto) */
189   uint32 version;			/* For concurrent read/write */
190   uint32 ftkey_nr;                      /* full-text index number */
191 
192   HA_KEYSEG *seg,*end;
193   struct st_mysql_ftparser *parser;     /* Fulltext [pre]parser */
194   int (*bin_search)(struct st_myisam_info *info,struct st_mi_keydef *keyinfo,
195 		    uchar *page,uchar *key,
196 		    uint key_len,uint comp_flag,uchar * *ret_pos,
197 		    uchar *buff, my_bool *was_last_key);
198   uint (*get_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar * *page,
199 		  uchar *key);
200   int (*pack_key)(struct st_mi_keydef *keyinfo,uint nod_flag,uchar *next_key,
201 		  uchar *org_key, uchar *prev_key, uchar *key,
202 		  struct st_mi_s_param *s_temp);
203   void (*store_key)(struct st_mi_keydef *keyinfo, uchar *key_pos,
204 		    struct st_mi_s_param *s_temp);
205   int (*ck_insert)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
206   int (*ck_delete)(struct st_myisam_info *inf, uint k_nr, uchar *k, uint klen);
207 } MI_KEYDEF;
208 
209 
210 #define MI_UNIQUE_HASH_LENGTH	4
211 
212 typedef struct st_unique_def		/* Segment definition of unique */
213 {
214   uint16 keysegs;			/* Number of key-segment */
215   uchar key;				/* Mapped to which key */
216   uint8 null_are_equal;
217   HA_KEYSEG *seg,*end;
218 } MI_UNIQUEDEF;
219 
220 typedef struct st_mi_decode_tree	/* Decode huff-table */
221 {
222   uint16 *table;
223   uint	 quick_table_bits;
224   uchar	 *intervalls;
225 } MI_DECODE_TREE;
226 
227 
228 struct st_mi_bit_buff;
229 
230 /*
231   Note that null markers should always be first in a row !
232   When creating a column, one should only specify:
233   type, length, null_bit and null_pos
234 */
235 
236 typedef struct st_columndef		/* column information */
237 {
238   int16  type;				/* en_fieldtype */
239   uint16 length;			/* length of field */
240   uint32 offset;			/* Offset to position in row */
241   uint8  null_bit;			/* If column may be 0 */
242   uint16 null_pos;			/* position for null marker */
243 
244   void (*unpack)(struct st_columndef *rec,struct st_mi_bit_buff *buff,
245 		 uchar *start,uchar *end);
246   enum en_fieldtype base_type;
247   uint space_length_bits,pack_type;
248   MI_DECODE_TREE *huff_tree;
249 } MI_COLUMNDEF;
250 
251 
252 extern char * myisam_log_filename;		/* Name of logfile */
253 extern ulong myisam_block_size;
254 extern ulong myisam_concurrent_insert;
255 extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user;
256 extern my_off_t myisam_max_temp_length;
257 extern ulong myisam_data_pointer_size;
258 
259 /* usually used to check if a symlink points into the mysql data home */
260 /* which is normally forbidden                                        */
261 extern int (*myisam_test_invalid_symlink)(const char *filename);
262 extern ulonglong myisam_mmap_size, myisam_mmap_used;
263 extern mysql_mutex_t THR_LOCK_myisam_mmap;
264 
265 	/* Prototypes for myisam-functions */
266 
267 extern int mi_close_share(struct st_myisam_info *file, my_bool *closed_share);
268 #define mi_close(file) mi_close_share(file, NULL)
269 extern int mi_delete(struct st_myisam_info *file,const uchar *buff);
270 extern struct st_myisam_info *mi_open_share(const char *name,
271                                             struct st_mi_isam_share *old_share,
272                                             int mode,
273                                             uint wait_if_locked);
274 #define mi_open(name, mode, wait_if_locked) \
275   mi_open_share(name, NULL, mode, wait_if_locked)
276 extern int mi_panic(enum ha_panic_function function);
277 extern int mi_rfirst(struct st_myisam_info *file,uchar *buf,int inx);
278 extern int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key,
279                    key_part_map keypart_map, enum ha_rkey_function search_flag);
280 extern int mi_rlast(struct st_myisam_info *file,uchar *buf,int inx);
281 extern int mi_rnext(struct st_myisam_info *file,uchar *buf,int inx);
282 extern int mi_rnext_same(struct st_myisam_info *info, uchar *buf);
283 extern int mi_rprev(struct st_myisam_info *file,uchar *buf,int inx);
284 extern int mi_rrnd(struct st_myisam_info *file,uchar *buf, my_off_t pos);
285 extern int mi_scan_init(struct st_myisam_info *file);
286 extern int mi_scan(struct st_myisam_info *file,uchar *buf);
287 extern int mi_rsame(struct st_myisam_info *file,uchar *record,int inx);
288 extern int mi_rsame_with_pos(struct st_myisam_info *file,uchar *record,
289 			     int inx, my_off_t pos);
290 extern int mi_update(struct st_myisam_info *file,const uchar *old,
291 		     uchar *new_record);
292 extern int mi_write(struct st_myisam_info *file,uchar *buff);
293 extern my_off_t mi_position(struct st_myisam_info *file);
294 extern int mi_status(struct st_myisam_info *info, MI_ISAMINFO *x, uint flag);
295 extern int mi_lock_database(struct st_myisam_info *file,int lock_type);
296 extern int mi_create(const char *name,uint keys,MI_KEYDEF *keydef,
297 		     uint columns, MI_COLUMNDEF *columndef,
298 		     uint uniques, MI_UNIQUEDEF *uniquedef,
299 		     MI_CREATE_INFO *create_info, uint flags);
300 extern int mi_delete_table(const char *name);
301 extern int mi_rename(const char *from, const char *to);
302 extern int mi_extra(struct st_myisam_info *file,
303 		    enum ha_extra_function function,
304 		    void *extra_arg);
305 extern int mi_reset(struct st_myisam_info *file);
306 extern ha_rows mi_records_in_range(MI_INFO *info, int inx,
307                                    key_range *min_key, key_range *max_key);
308 extern int mi_log(int activate_log);
309 extern int mi_is_changed(struct st_myisam_info *info);
310 extern int mi_delete_all_rows(struct st_myisam_info *info);
311 extern ulong _mi_calc_blob_length(uint length , const uchar *pos);
312 extern uint mi_get_pointer_length(ulonglong file_length, uint def);
313 
314 #define MEMMAP_EXTRA_MARGIN     7       /* Write this as a suffix for mmap file */
315 /* this is used to pass to mysql_myisamchk_table */
316 
317 #define   MYISAMCHK_REPAIR 1  /* equivalent to myisamchk -r */
318 #define   MYISAMCHK_VERIFY 2  /* Verify, run repair if failure */
319 
320 /*
321   Flags used by myisamchk.c or/and ha_myisam.cc that are NOT passed
322   to mi_check.c follows:
323 */
324 
325 #define TT_USEFRM               1
326 #define TT_FOR_UPGRADE          2
327 
328 #define O_NEW_INDEX	1		/* Bits set in out_flag */
329 #define O_NEW_DATA	2
330 #define O_DATA_LOST	4
331 
332 /* these struct is used by my_check to tell it what to do */
333 
334 typedef struct st_sort_key_blocks		/* Used when sorting */
335 {
336   uchar *buff,*end_pos;
337   uchar lastkey[MI_MAX_POSSIBLE_KEY_BUFF];
338   uint last_length;
339   int inited;
340 } SORT_KEY_BLOCKS;
341 
342 
343 /*
344   MyISAM supports several statistics collection methods. Currently statistics
345   collection method is not stored in MyISAM file and has to be specified for
346   each table analyze/repair operation in  MI_CHECK::stats_method.
347 */
348 
349 typedef enum
350 {
351   /* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */
352   MI_STATS_METHOD_NULLS_NOT_EQUAL,
353   /* Treat NULLs as equal when collecting statistics (like 4.0 did) */
354   MI_STATS_METHOD_NULLS_EQUAL,
355   /* Ignore NULLs - count only tuples without NULLs in the index components */
356   MI_STATS_METHOD_IGNORE_NULLS
357 } enum_mi_stats_method;
358 
359 typedef struct st_mi_check_param
360 {
361   ulonglong auto_increment_value;
362   ulonglong max_data_file_length;
363   ulonglong keys_in_use;
364   ulonglong max_record_length;
365   ulonglong sort_buffer_length;
366   my_off_t search_after_block;
367   my_off_t new_file_pos,key_file_blocks;
368   my_off_t keydata,totaldata,key_blocks,start_check_pos;
369   ha_rows total_records,total_deleted;
370   ha_checksum record_checksum,glob_crc;
371   ulonglong use_buffers;
372   ulong read_buffer_length, write_buffer_length, sort_key_blocks;
373   uint out_flag,warning_printed,error_printed,verbose;
374   uint opt_sort_key,total_files,max_level;
375   uint testflag, key_cache_block_size;
376   uint16 language;
377   my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
378   my_bool retry_repair, force_sort;
379   char temp_filename[FN_REFLEN],*isam_file_name;
380   MY_TMPDIR *tmpdir;
381   int tmpfile_createflag;
382   myf myf_rw;
383   IO_CACHE read_cache;
384 
385   /*
386     The next two are used to collect statistics, see update_key_parts for
387     description.
388   */
389   ulonglong unique_count[MI_MAX_KEY_SEG+1];
390   ulonglong notnull_count[MI_MAX_KEY_SEG+1];
391 
392   ha_checksum key_crc[HA_MAX_POSSIBLE_KEY];
393   ulong rec_per_key_part[MI_MAX_KEY_SEG*HA_MAX_POSSIBLE_KEY];
394   void *thd;
395   const char *db_name, *table_name;
396   const char *op_name;
397   enum_mi_stats_method stats_method;
398   mysql_mutex_t print_msg_mutex;
399   my_bool need_print_msg_lock;
400 } MI_CHECK;
401 
402 typedef struct st_sort_ft_buf
403 {
404   uchar *buf, *end;
405   int   count;
406   uchar lastkey[MI_MAX_KEY_BUFF];
407 } SORT_FT_BUF;
408 
409 typedef struct st_sort_info
410 {
411   my_off_t filelength,dupp,buff_length;
412   ha_rows max_records;
413   uint current_key, total_keys;
414   myf myf_rw;
415   enum data_file_type new_data_file_type;
416   MI_INFO *info;
417   MI_CHECK *param;
418   uchar *buff;
419   SORT_KEY_BLOCKS *key_block,*key_block_end;
420   SORT_FT_BUF *ft_buf;
421   /* sync things */
422   uint got_error, threads_running;
423   mysql_mutex_t mutex;
424   mysql_cond_t  cond;
425 } SORT_INFO;
426 
427 /* functions in mi_check */
428 void myisamchk_init(MI_CHECK *param);
429 int chk_status(MI_CHECK *param, MI_INFO *info);
430 int chk_del(MI_CHECK *param, MI_INFO *info, uint test_flag);
431 int chk_size(MI_CHECK *param, MI_INFO *info);
432 int chk_key(MI_CHECK *param, MI_INFO *info);
433 int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend);
434 int mi_repair(MI_CHECK *param, MI_INFO *info,
435 	      char * name, int rep_quick, my_bool no_copy_stat);
436 int mi_sort_index(MI_CHECK *param, MI_INFO *info, char * name,
437                   my_bool no_copy_stat);
438 int mi_repair_by_sort(MI_CHECK *param, MI_INFO *info,
439 		      const char * name, int rep_quick, my_bool no_copy_stat);
440 int mi_repair_parallel(MI_CHECK *param, MI_INFO *info,
441                        const char * name, int rep_quick, my_bool no_copy_stat);
442 int change_to_newfile(const char * filename, const char * old_ext,
443 		      const char * new_ext, myf myflags);
444 int lock_file(MI_CHECK *param, File file, my_off_t start, int lock_type,
445 	      const char *filetype, const char *filename);
446 void lock_memory(MI_CHECK *param);
447 void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
448 			       my_bool repair);
449 int update_state_info(MI_CHECK *param, MI_INFO *info,uint update);
450 void update_key_parts(MI_KEYDEF *keyinfo, ulong *rec_per_key_part,
451                       ulonglong *unique, ulonglong *notnull,
452                       ulonglong records);
453 int filecopy(MI_CHECK *param, File to,File from,my_off_t start,
454 	     my_off_t length, const char *type);
455 int movepoint(MI_INFO *info,uchar *record,my_off_t oldpos,
456 	      my_off_t newpos, uint prot_key);
457 int write_data_suffix(SORT_INFO *sort_info, my_bool fix_datafile);
458 int test_if_almost_full(MI_INFO *info);
459 int recreate_table(MI_CHECK *param, MI_INFO **org_info, char *filename);
460 void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
461 my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
462 			    my_bool force);
463 
464 int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
465 void mi_flush_bulk_insert(MI_INFO *info, uint inx);
466 void mi_end_bulk_insert(MI_INFO *info);
467 int mi_assign_to_key_cache(MI_INFO *info, ulonglong key_map,
468 			   KEY_CACHE *key_cache);
469 void mi_change_key_cache(KEY_CACHE *old_key_cache,
470 			 KEY_CACHE *new_key_cache);
471 int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves);
472 
473 extern st_keycache_thread_var main_thread_keycache_var;
474 st_keycache_thread_var *keycache_thread_var();
475 #ifdef	__cplusplus
476 }
477 #endif
478 #endif
479