1/*****************************************************************************
2
3Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2013, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/* The InnoDB handler: the interface between MySQL and InnoDB. */
21
22/** "GEN_CLUST_INDEX" is the name reserved for InnoDB default
23system clustered index when there is no primary key. */
24extern const char innobase_index_reserve_name[];
25
26/* Structure defines translation table between mysql index and InnoDB
27index structures */
28struct innodb_idx_translate_t {
29
30 ulint index_count; /*!< number of valid index entries
31 in the index_mapping array */
32
33 ulint array_size; /*!< array size of index_mapping */
34
35 dict_index_t** index_mapping; /*!< index pointer array directly
36 maps to index in InnoDB from MySQL
37 array index */
38};
39
40/** InnoDB table share */
41typedef struct st_innobase_share {
42 THR_LOCK lock;
43 const char* table_name; /*!< InnoDB table name */
44 uint use_count; /*!< reference count,
45 incremented in get_share()
46 and decremented in
47 free_share() */
48 void* table_name_hash;
49 /*!< hash table chain node */
50 innodb_idx_translate_t
51 idx_trans_tbl; /*!< index translation table between
52 MySQL and InnoDB */
53} INNOBASE_SHARE;
54
55/** Prebuilt structures in an InnoDB table handle used within MySQL */
56struct row_prebuilt_t;
57
58/** Engine specific table options are defined using this struct */
59struct ha_table_option_struct
60{
61 bool page_compressed; /*!< Table is using page compression
62 if this option is true. */
63 ulonglong page_compression_level; /*!< Table page compression level
64 0-9. */
65 uint atomic_writes; /*!< Use atomic writes for this
66 table if this options is ON or
67 in DEFAULT if
68 srv_use_atomic_writes=1.
69 Atomic writes are not used if
70 value OFF.*/
71 uint encryption; /*!< DEFAULT, ON, OFF */
72 ulonglong encryption_key_id; /*!< encryption key id */
73};
74/* JAN: TODO: MySQL 5.7 handler.h */
75struct st_handler_tablename
76{
77 const char *db;
78 const char *tablename;
79};
80/** The class defining a handle to an Innodb table */
81class ha_innobase: public handler
82{
83public:
84 ha_innobase(handlerton* hton, TABLE_SHARE* table_arg);
85 ~ha_innobase();
86
87 /** Get the row type from the storage engine. If this method returns
88 ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used. */
89 enum row_type get_row_type() const;
90
91 const char* table_type() const;
92
93 const char* index_type(uint key_number);
94
95 const char** bas_ext() const;
96
97 Table_flags table_flags() const;
98
99 ulong index_flags(uint idx, uint part, bool all_parts) const;
100
101 uint max_supported_keys() const;
102
103 uint max_supported_key_length() const;
104
105 uint max_supported_key_part_length() const;
106
107 const key_map* keys_to_use_for_scanning();
108
109 void column_bitmaps_signal();
110
111 /** Opens dictionary table object using table name. For partition, we need to
112 try alternative lower/upper case names to support moving data files across
113 platforms.
114 @param[in] table_name name of the table/partition
115 @param[in] norm_name normalized name of the table/partition
116 @param[in] is_partition if this is a partition of a table
117 @param[in] ignore_err error to ignore for loading dictionary object
118 @return dictionary table object or NULL if not found */
119 static dict_table_t* open_dict_table(
120 const char* table_name,
121 const char* norm_name,
122 bool is_partition,
123 dict_err_ignore_t ignore_err);
124
125 int open(const char *name, int mode, uint test_if_locked);
126
127 handler* clone(const char *name, MEM_ROOT *mem_root);
128
129 int close(void);
130
131 double scan_time();
132
133 double read_time(uint index, uint ranges, ha_rows rows);
134
135 int delete_all_rows();
136
137 int write_row(uchar * buf);
138
139 int update_row(const uchar * old_data, const uchar * new_data);
140
141 int delete_row(const uchar * buf);
142
143 bool was_semi_consistent_read();
144
145 void try_semi_consistent_read(bool yes);
146
147 void unlock_row();
148
149 int index_init(uint index, bool sorted);
150
151 int index_end();
152
153 int index_read(
154 uchar* buf,
155 const uchar* key,
156 uint key_len,
157 ha_rkey_function find_flag);
158
159 int index_read_last(uchar * buf, const uchar * key, uint key_len);
160
161 int index_next(uchar * buf);
162
163 int index_next_same(uchar * buf, const uchar *key, uint keylen);
164
165 int index_prev(uchar * buf);
166
167 int index_first(uchar * buf);
168
169 int index_last(uchar * buf);
170
171 /* Copy a cached MySQL row. If requested, also avoids
172 overwriting non-read columns. */
173 void copy_cached_row(uchar *to_rec, const uchar *from_rec,
174 uint rec_length);
175 int rnd_init(bool scan);
176
177 int rnd_end();
178
179 int rnd_next(uchar *buf);
180
181 int rnd_pos(uchar * buf, uchar *pos);
182
183 int ft_init();
184
185 void ft_end();
186
187 FT_INFO* ft_init_ext(uint flags, uint inx, String* key);
188
189 int ft_read(uchar* buf);
190
191 void position(const uchar *record);
192
193 int info(uint);
194
195 int analyze(THD* thd,HA_CHECK_OPT* check_opt);
196
197 int optimize(THD* thd,HA_CHECK_OPT* check_opt);
198
199 int discard_or_import_tablespace(my_bool discard);
200
201 int extra(ha_extra_function operation);
202
203 int reset();
204
205 int external_lock(THD *thd, int lock_type);
206
207 int start_stmt(THD *thd, thr_lock_type lock_type);
208
209 void position(uchar *record);
210
211 ha_rows records_in_range(
212 uint inx,
213 key_range* min_key,
214 key_range* max_key);
215
216 ha_rows estimate_rows_upper_bound();
217
218 void update_create_info(HA_CREATE_INFO* create_info);
219
220 int create(
221 const char* name,
222 TABLE* form,
223 HA_CREATE_INFO* create_info);
224
225 const char* check_table_options(THD *thd, TABLE* table,
226 HA_CREATE_INFO* create_info, const bool use_tablespace, const ulint file_format);
227
228 int truncate();
229
230 int delete_table(const char *name);
231
232 int rename_table(const char* from, const char* to);
233 int defragment_table(const char* name, const char* index_name,
234 bool async);
235 int check(THD* thd, HA_CHECK_OPT* check_opt);
236 char* update_table_comment(const char* comment);
237
238 char* get_foreign_key_create_info();
239
240 int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
241
242 int get_parent_foreign_key_list(
243 THD* thd,
244 List<FOREIGN_KEY_INFO>* f_key_list);
245 int get_cascade_foreign_key_table_list(
246 THD* thd,
247 List<st_handler_tablename>* fk_table_list);
248
249
250 bool can_switch_engines();
251
252 uint referenced_by_foreign_key();
253
254 void free_foreign_key_create_info(char* str);
255
256 uint lock_count(void) const;
257
258 THR_LOCK_DATA** store_lock(
259 THD* thd,
260 THR_LOCK_DATA** to,
261 thr_lock_type lock_type);
262
263 void init_table_handle_for_HANDLER();
264
265 virtual void get_auto_increment(
266 ulonglong offset,
267 ulonglong increment,
268 ulonglong nb_desired_values,
269 ulonglong* first_value,
270 ulonglong* nb_reserved_values);
271 int reset_auto_increment(ulonglong value);
272
273 virtual bool get_error_message(int error, String *buf);
274
275 virtual bool get_foreign_dup_key(char*, uint, char*, uint);
276
277 uint8 table_cache_type();
278
279 /**
280 Ask handler about permission to cache table during query registration
281 */
282 my_bool register_query_cache_table(
283 THD* thd,
284 const char* table_key,
285 uint key_length,
286 qc_engine_callback* call_back,
287 ulonglong* engine_data);
288
289 bool primary_key_is_clustered();
290
291 int cmp_ref(const uchar* ref1, const uchar* ref2);
292
293 /** On-line ALTER TABLE interface @see handler0alter.cc @{ */
294
295 /** Check if InnoDB supports a particular alter table in-place
296 @param altered_table TABLE object for new version of table.
297 @param ha_alter_info Structure describing changes to be done
298 by ALTER TABLE and holding data used during in-place alter.
299
300 @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported
301 @retval HA_ALTER_INPLACE_INSTANT
302 MDL_EXCLUSIVE is needed for executing prepare_inplace_alter_table()
303 and commit_inplace_alter_table(). inplace_alter_table()
304 will not be called.
305 @retval HA_ALTER_INPLACE_COPY_NO_LOCK
306 MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
307 to LOCK=NONE for rebuilding the table in inplace_alter_table()
308 @retval HA_ALTER_INPLACE_COPY_LOCK
309 MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
310 to LOCK=SHARED for rebuilding the table in inplace_alter_table()
311 @retval HA_ALTER_INPLACE_NOCOPY_NO_LOCK
312 MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
313 to LOCK=NONE for inplace_alter_table() which will not rebuild the table
314 @retval HA_ALTER_INPLACE_NOCOPY_LOCK
315 MDL_EXCLUSIVE in prepare_inplace_alter_table(), which can be downgraded
316 to LOCK=SHARED for inplace_alter_table() which will not rebuild
317 the table. */
318
319 enum_alter_inplace_result check_if_supported_inplace_alter(
320 TABLE* altered_table,
321 Alter_inplace_info* ha_alter_info);
322
323 /** Allows InnoDB to update internal structures with concurrent
324 writes blocked (provided that check_if_supported_inplace_alter()
325 did not return HA_ALTER_INPLACE_NO_LOCK).
326 This will be invoked before inplace_alter_table().
327
328 @param altered_table TABLE object for new version of table.
329 @param ha_alter_info Structure describing changes to be done
330 by ALTER TABLE and holding data used during in-place alter.
331
332 @retval true Failure
333 @retval false Success
334 */
335 bool prepare_inplace_alter_table(
336 TABLE* altered_table,
337 Alter_inplace_info* ha_alter_info);
338
339 /** Alter the table structure in-place with operations
340 specified using HA_ALTER_FLAGS and Alter_inplace_information.
341 The level of concurrency allowed during this operation depends
342 on the return value from check_if_supported_inplace_alter().
343
344 @param altered_table TABLE object for new version of table.
345 @param ha_alter_info Structure describing changes to be done
346 by ALTER TABLE and holding data used during in-place alter.
347
348 @retval true Failure
349 @retval false Success
350 */
351 bool inplace_alter_table(
352 TABLE* altered_table,
353 Alter_inplace_info* ha_alter_info);
354
355 /** Commit or rollback the changes made during
356 prepare_inplace_alter_table() and inplace_alter_table() inside
357 the storage engine. Note that the allowed level of concurrency
358 during this operation will be the same as for
359 inplace_alter_table() and thus might be higher than during
360 prepare_inplace_alter_table(). (E.g concurrent writes were
361 blocked during prepare, but might not be during commit).
362 @param altered_table TABLE object for new version of table.
363 @param ha_alter_info Structure describing changes to be done
364 by ALTER TABLE and holding data used during in-place alter.
365 @param commit true => Commit, false => Rollback.
366 @retval true Failure
367 @retval false Success
368 */
369 bool commit_inplace_alter_table(
370 TABLE* altered_table,
371 Alter_inplace_info* ha_alter_info,
372 bool commit);
373 /** @} */
374
375 bool check_if_incompatible_data(
376 HA_CREATE_INFO* info,
377 uint table_changes);
378
379 /** @name Multi Range Read interface @{ */
380
381 /** Initialize multi range read @see DsMrr_impl::dsmrr_init
382 @param seq
383 @param seq_init_param
384 @param n_ranges
385 @param mode
386 @param buf */
387 int multi_range_read_init(
388 RANGE_SEQ_IF* seq,
389 void* seq_init_param,
390 uint n_ranges,
391 uint mode,
392 HANDLER_BUFFER* buf);
393
394 /** Process next multi range read @see DsMrr_impl::dsmrr_next
395 @param range_info */
396 int multi_range_read_next(range_id_t *range_info);
397
398 /** Initialize multi range read and get information.
399 @see ha_myisam::multi_range_read_info_const
400 @see DsMrr_impl::dsmrr_info_const
401 @param keyno
402 @param seq
403 @param seq_init_param
404 @param n_ranges
405 @param bufsz
406 @param flags
407 @param cost */
408 ha_rows multi_range_read_info_const(
409 uint keyno,
410 RANGE_SEQ_IF* seq,
411 void* seq_init_param,
412 uint n_ranges,
413 uint* bufsz,
414 uint* flags,
415 Cost_estimate* cost);
416
417 /** Initialize multi range read and get information.
418 @see DsMrr_impl::dsmrr_info
419 @param keyno
420 @param seq
421 @param seq_init_param
422 @param n_ranges
423 @param bufsz
424 @param flags
425 @param cost */
426 ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
427 uint key_parts, uint* bufsz, uint* flags,
428 Cost_estimate* cost);
429
430 int multi_range_read_explain_info(uint mrr_mode,
431 char *str, size_t size);
432
433 /** Attempt to push down an index condition.
434 @param[in] keyno MySQL key number
435 @param[in] idx_cond Index condition to be checked
436 @return idx_cond if pushed; NULL if not pushed */
437 Item* idx_cond_push(uint keyno, Item* idx_cond);
438 /* @} */
439
440 /* An helper function for index_cond_func_innodb: */
441 bool is_thd_killed();
442
443protected:
444
445 /**
446 MySQL calls this method at the end of each statement. This method
447 exists for readability only, called from reset(). The name reset()
448 doesn't give any clue that it is called at the end of a statement. */
449 int end_stmt();
450
451 dberr_t innobase_get_autoinc(ulonglong* value);
452 dberr_t innobase_lock_autoinc();
453 ulonglong innobase_peek_autoinc();
454 dberr_t innobase_set_max_autoinc(ulonglong auto_inc);
455 dberr_t innobase_reset_autoinc(ulonglong auto_inc);
456
457 /** Resets a query execution 'template'.
458 @see build_template() */
459 void reset_template();
460
461protected:
462 inline void update_thd(THD* thd);
463 void update_thd();
464
465 int general_fetch(uchar* buf, uint direction, uint match_mode);
466 int change_active_index(uint keynr);
467 dict_index_t* innobase_get_index(uint keynr);
468
469#ifdef WITH_WSREP
470 int wsrep_append_keys(THD *thd, bool shared,
471 const uchar* record0, const uchar* record1);
472#endif
473 /** Builds a 'template' to the prebuilt struct.
474
475 The template is used in fast retrieval of just those column
476 values MySQL needs in its processing.
477 @param whole_row true if access is needed to a whole row,
478 false if accessing individual fields is enough */
479 void build_template(bool whole_row);
480
481 virtual int info_low(uint, bool);
482
483 /** The multi range read session object */
484 DsMrr_impl m_ds_mrr;
485
486 /** Save CPU time with prebuilt/cached data structures */
487 row_prebuilt_t* m_prebuilt;
488
489 /** prebuilt pointer for the right prebuilt. For native
490 partitioning, points to the current partition prebuilt. */
491 row_prebuilt_t** m_prebuilt_ptr;
492
493 /** Thread handle of the user currently using the handler;
494 this is set in external_lock function */
495 THD* m_user_thd;
496
497 THR_LOCK_DATA lock;
498
499 /** information for MySQL table locking */
500 INNOBASE_SHARE* m_share;
501
502 /** buffer used in updates */
503 uchar* m_upd_buf;
504
505 /** the size of upd_buf in bytes */
506 ulint m_upd_buf_size;
507
508 /** Flags that specificy the handler instance (table) capability. */
509 Table_flags m_int_table_flags;
510
511 /** Index into the server's primkary keye meta-data table->key_info{} */
512 uint m_primary_key;
513
514 /** this is set to 1 when we are starting a table scan but have
515 not yet fetched any row, else false */
516 bool m_start_of_scan;
517
518 /*!< match mode of the latest search: ROW_SEL_EXACT,
519 ROW_SEL_EXACT_PREFIX, or undefined */
520 uint m_last_match_mode;
521
522 /** If mysql has locked with external_lock() */
523 bool m_mysql_has_locked;
524};
525
526
527/* Some accessor functions which the InnoDB plugin needs, but which
528can not be added to mysql/plugin.h as part of the public interface;
529the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */
530
531#ifndef INNODB_COMPATIBILITY_HOOKS
532#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
533#endif
534
535LEX_STRING* thd_query_string(MYSQL_THD thd);
536size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen);
537
538extern "C" {
539
540struct charset_info_st *thd_charset(MYSQL_THD thd);
541
542/** Check if a user thread is a replication slave thread
543@param thd user thread
544@retval 0 the user thread is not a replication slave thread
545@retval 1 the user thread is a replication slave thread */
546int thd_slave_thread(const MYSQL_THD thd);
547
548/** Check if a user thread is running a non-transactional update
549@param thd user thread
550@retval 0 the user thread is not running a non-transactional update
551@retval 1 the user thread is running a non-transactional update */
552int thd_non_transactional_update(const MYSQL_THD thd);
553
554/** Get high resolution timestamp for the current query start time.
555The timestamp is not anchored to any specific point in time,
556but can be used for comparison.
557@param thd user thread
558@retval timestamp in microseconds precision
559*/
560unsigned long long thd_start_utime(const MYSQL_THD thd);
561
562/** Get the user thread's binary logging format
563@param thd user thread
564@return Value to be used as index into the binlog_format_names array */
565int thd_binlog_format(const MYSQL_THD thd);
566
567/** Check if binary logging is filtered for thread's current db.
568@param thd Thread handle
569@retval 1 the query is not filtered, 0 otherwise. */
570bool thd_binlog_filter_ok(const MYSQL_THD thd);
571
572/** Check if the query may generate row changes which may end up in the binary.
573@param thd Thread handle
574@retval 1 the query may generate row changes, 0 otherwise.
575*/
576bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd);
577
578/** Is strict sql_mode set.
579@param thd Thread object
580@return True if sql_mode has strict mode (all or trans), false otherwise. */
581bool thd_is_strict_mode(const MYSQL_THD thd);
582
583} /* extern "C" */
584
585/** Get the file name and position of the MySQL binlog corresponding to the
586 * current commit.
587 */
588extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
589
590/** Get the partition_info working copy.
591@param thd Thread object.
592@return NULL or pointer to partition_info working copy. */
593/* JAN: TODO: MySQL 5.7 Partitioning
594partition_info*
595thd_get_work_part_info(
596 THD* thd);
597*/
598
599struct trx_t;
600#ifdef WITH_WSREP
601#include <mysql/service_wsrep.h>
602//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
603
604extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
605
606
607extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
608extern "C" void wsrep_thd_set_query_state(
609 THD *thd, enum wsrep_query_state state);
610
611extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
612
613extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
614extern "C" time_t wsrep_thd_query_start(THD *thd);
615extern "C" query_id_t wsrep_thd_query_id(THD *thd);
616extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
617extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
618#endif
619
620extern const struct _ft_vft ft_vft_result;
621
622/** Structure Returned by ha_innobase::ft_init_ext() */
623typedef struct new_ft_info
624{
625 struct _ft_vft *please;
626 struct _ft_vft_ext *could_you;
627 row_prebuilt_t* ft_prebuilt;
628 fts_result_t* ft_result;
629} NEW_FT_INFO;
630
631/**
632Allocates an InnoDB transaction for a MySQL handler object.
633@return InnoDB transaction handle */
634trx_t*
635innobase_trx_allocate(
636 MYSQL_THD thd); /*!< in: user thread handle */
637
638/** Match index columns between MySQL and InnoDB.
639This function checks whether the index column information
640is consistent between KEY info from mysql and that from innodb index.
641@param[in] key_info Index info from mysql
642@param[in] index_info Index info from InnoDB
643@return true if all column types match. */
644bool
645innobase_match_index_columns(
646 const KEY* key_info,
647 const dict_index_t* index_info);
648
649/*********************************************************************//**
650This function checks each index name for a table against reserved
651system default primary index name 'GEN_CLUST_INDEX'. If a name
652matches, this function pushes an warning message to the client,
653and returns true.
654@return true if the index name matches the reserved name */
655bool
656innobase_index_name_is_reserved(
657 THD* thd, /*!< in/out: MySQL connection */
658 const KEY* key_info, /*!< in: Indexes to be created */
659 ulint num_of_keys) /*!< in: Number of indexes to
660 be created. */
661 MY_ATTRIBUTE((nonnull(1), warn_unused_result));
662
663#ifdef WITH_WSREP
664//extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
665#endif
666
667/** Parse hint for table and its indexes, and update the information
668in dictionary.
669@param[in] thd Connection thread
670@param[in,out] table Target table
671@param[in] table_share Table definition */
672void
673innobase_parse_hint_from_comment(
674 THD* thd,
675 dict_table_t* table,
676 const TABLE_SHARE* table_share);
677
678/** Class for handling create table information. */
679class create_table_info_t
680{
681public:
682 /** Constructor.
683 Used in two ways:
684 - all but file_per_table is used, when creating the table.
685 - all but name/path is used, when validating options and using flags. */
686 create_table_info_t(
687 THD* thd,
688 TABLE* form,
689 HA_CREATE_INFO* create_info,
690 char* table_name,
691 char* remote_path)
692 :m_thd(thd),
693 m_form(form),
694 m_create_info(create_info),
695 m_table_name(table_name), m_table(NULL),
696 m_remote_path(remote_path),
697 m_innodb_file_per_table(srv_file_per_table)
698 {}
699
700 /** Initialize the object. */
701 int initialize();
702
703 /** Set m_tablespace_type. */
704 void set_tablespace_type(bool table_being_altered_is_file_per_table);
705
706 /** Create the internal innodb table. */
707 int create_table();
708
709 /** Update the internal data dictionary. */
710 int create_table_update_dict();
711
712 /** Validates the create options. Checks that the options
713 KEY_BLOCK_SIZE, ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE
714 are compatible with each other and other settings.
715 These CREATE OPTIONS are not validated here unless innodb_strict_mode
716 is on. With strict mode, this function will report each problem it
717 finds using a custom message with error code
718 ER_ILLEGAL_HA_CREATE_OPTION, not its built-in message.
719 @return NULL if valid, string name of bad option if not. */
720 const char* create_options_are_invalid();
721
722 bool gcols_in_fulltext_or_spatial();
723
724 /** Validates engine specific table options not handled by
725 SQL-parser.
726 @return NULL if valid, string name of bad option if not. */
727 const char* check_table_options();
728
729 /** Validate DATA DIRECTORY option. */
730 bool create_option_data_directory_is_valid();
731
732 /** Validate TABLESPACE option. */
733 bool create_option_tablespace_is_valid();
734
735 /** Prepare to create a table. */
736 int prepare_create_table(const char* name);
737
738 void allocate_trx();
739
740 /** Determines InnoDB table flags.
741 If strict_mode=OFF, this will adjust the flags to what should be assumed.
742 @retval true if successful, false if error */
743 bool innobase_table_flags();
744
745 /** Set flags and append '/' to remote path if necessary. */
746 void set_remote_path_flags();
747
748 /** Get table flags. */
749 ulint flags() const
750 { return(m_flags); }
751
752 /** Get table flags2. */
753 ulint flags2() const
754 { return(m_flags2); }
755
756 /** Get trx. */
757 trx_t* trx() const
758 { return(m_trx); }
759
760 /** Return table name. */
761 const char* table_name() const
762 { return(m_table_name); }
763
764 THD* thd() const
765 { return(m_thd); }
766
767 /** Normalizes a table name string.
768 A normalized name consists of the database name catenated to '/' and
769 table name. An example: test/mytable. On Windows normalization puts
770 both the database name and the table name always to lower case if
771 "set_lower_case" is set to true.
772 @param[in,out] norm_name Buffer to return the normalized name in.
773 @param[in] name Table name string.
774 @param[in] set_lower_case True if we want to set name to lower
775 case. */
776 static void normalize_table_name_low(
777 char* norm_name,
778 const char* name,
779 ibool set_lower_case);
780
781private:
782 /** Parses the table name into normal name and either temp path or
783 remote path if needed.*/
784 int
785 parse_table_name(
786 const char* name);
787
788 /** Create the internal innodb table definition. */
789 int create_table_def();
790
791 /** Connection thread handle. */
792 THD* m_thd;
793
794 /** InnoDB transaction handle. */
795 trx_t* m_trx;
796
797 /** Information on table columns and indexes. */
798 const TABLE* m_form;
799
800 /** Create options. */
801 HA_CREATE_INFO* m_create_info;
802
803 /** Table name */
804 char* m_table_name;
805 /** Table */
806 dict_table_t* m_table;
807
808 /** Remote path (DATA DIRECTORY) or zero length-string */
809 char* m_remote_path;
810
811 /** Local copy of srv_file_per_table. */
812 bool m_innodb_file_per_table;
813
814 /** Allow file_per_table for this table either because:
815 1) the setting innodb_file_per_table=on,
816 2) it was explicitly requested by tablespace=innodb_file_per_table.
817 3) the table being altered is currently file_per_table */
818 bool m_allow_file_per_table;
819
820 /** After all considerations, this shows whether we will actually
821 create a table and tablespace using file-per-table. */
822 bool m_use_file_per_table;
823
824 /** Using DATA DIRECTORY */
825 bool m_use_data_dir;
826
827 /** Table flags */
828 ulint m_flags;
829
830 /** Table flags2 */
831 ulint m_flags2;
832};
833
834/**
835Initialize the table FTS stopword list
836@return TRUE if success */
837ibool
838innobase_fts_load_stopword(
839/*=======================*/
840 dict_table_t* table, /*!< in: Table has the FTS */
841 trx_t* trx, /*!< in: transaction */
842 THD* thd) /*!< in: current thread */
843 MY_ATTRIBUTE((warn_unused_result));
844
845/** Some defines for innobase_fts_check_doc_id_index() return value */
846enum fts_doc_id_index_enum {
847 FTS_INCORRECT_DOC_ID_INDEX,
848 FTS_EXIST_DOC_ID_INDEX,
849 FTS_NOT_EXIST_DOC_ID_INDEX
850};
851
852/**
853Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
854on the Doc ID column.
855@return the status of the FTS_DOC_ID index */
856fts_doc_id_index_enum
857innobase_fts_check_doc_id_index(
858 const dict_table_t* table, /*!< in: table definition */
859 const TABLE* altered_table, /*!< in: MySQL table
860 that is being altered */
861 ulint* fts_doc_col_no) /*!< out: The column number for
862 Doc ID */
863 MY_ATTRIBUTE((warn_unused_result));
864
865/**
866Check whether the table has a unique index with FTS_DOC_ID_INDEX_NAME
867on the Doc ID column in MySQL create index definition.
868@return FTS_EXIST_DOC_ID_INDEX if there exists the FTS_DOC_ID index,
869FTS_INCORRECT_DOC_ID_INDEX if the FTS_DOC_ID index is of wrong format */
870fts_doc_id_index_enum
871innobase_fts_check_doc_id_index_in_def(
872 ulint n_key, /*!< in: Number of keys */
873 const KEY* key_info) /*!< in: Key definitions */
874 MY_ATTRIBUTE((warn_unused_result));
875
876/**
877Copy table flags from MySQL's TABLE_SHARE into an InnoDB table object.
878Those flags are stored in .frm file and end up in the MySQL table object,
879but are frequently used inside InnoDB so we keep their copies into the
880InnoDB table object. */
881void
882innobase_copy_frm_flags_from_table_share(
883 dict_table_t* innodb_table, /*!< in/out: InnoDB table */
884 const TABLE_SHARE* table_share); /*!< in: table share */
885
886/** Set up base columns for virtual column
887@param[in] table the InnoDB table
888@param[in] field MySQL field
889@param[in,out] v_col virtual column to be set up */
890void
891innodb_base_col_setup(
892 dict_table_t* table,
893 const Field* field,
894 dict_v_col_t* v_col);
895
896/** Set up base columns for stored column
897@param[in] table InnoDB table
898@param[in] field MySQL field
899@param[in,out] s_col stored column */
900void
901innodb_base_col_setup_for_stored(
902 const dict_table_t* table,
903 const Field* field,
904 dict_s_col_t* s_col);
905
906/** whether this is a stored column */
907#define innobase_is_s_fld(field) ((field)->vcol_info && (field)->stored_in_db())
908/** whether this is a computed virtual column */
909#define innobase_is_v_fld(field) ((field)->vcol_info && !(field)->stored_in_db())
910
911/** Always normalize table name to lower case on Windows */
912#ifdef _WIN32
913#define normalize_table_name(norm_name, name) \
914 create_table_info_t::normalize_table_name_low(norm_name, name, TRUE)
915#else
916#define normalize_table_name(norm_name, name) \
917 create_table_info_t::normalize_table_name_low(norm_name, name, FALSE)
918#endif /* _WIN32 */
919
920/** Converts a search mode flag understood by MySQL to a flag understood
921by InnoDB.
922@param[in] find_flag MySQL search mode flag.
923@return InnoDB search mode flag. */
924page_cur_mode_t
925convert_search_mode_to_innobase(
926 enum ha_rkey_function find_flag);
927
928/** Commits a transaction in an InnoDB database.
929@param[in] trx Transaction handle. */
930void
931innobase_commit_low(
932 trx_t* trx);
933
934extern my_bool innobase_stats_on_metadata;
935
936/** Calculate Record Per Key value.
937Need to exclude the NULL value if innodb_stats_method is set to "nulls_ignored"
938@param[in] index InnoDB index.
939@param[in] i The column we are calculating rec per key.
940@param[in] records Estimated total records.
941@return estimated record per key value */
942/* JAN: TODO: MySQL 5.7 */
943typedef float rec_per_key_t;
944rec_per_key_t
945innodb_rec_per_key(
946 dict_index_t* index,
947 ulint i,
948 ha_rows records);
949
950/** Build template for the virtual columns and their base columns
951@param[in] table MySQL TABLE
952@param[in] ib_table InnoDB dict_table_t
953@param[in,out] s_templ InnoDB template structure
954@param[in] add_v new virtual columns added along with
955 add index call
956@param[in] locked true if innobase_share_mutex is held */
957void
958innobase_build_v_templ(
959 const TABLE* table,
960 const dict_table_t* ib_table,
961 dict_vcol_templ_t* s_templ,
962 const dict_add_v_col_t* add_v,
963 bool locked);
964
965/** callback used by MySQL server layer to initialized
966the table virtual columns' template
967@param[in] table MySQL TABLE
968@param[in,out] ib_table InnoDB dict_table_t */
969void
970innobase_build_v_templ_callback(
971 const TABLE* table,
972 void* ib_table);
973
974/** Callback function definition, used by MySQL server layer to initialized
975the table virtual columns' template */
976typedef void (*my_gcolumn_templatecallback_t)(const TABLE*, void*);
977
978/** Convert MySQL column number to dict_table_t::cols[] offset.
979@param[in] field non-virtual column
980@return column number relative to dict_table_t::cols[] */
981unsigned
982innodb_col_no(const Field* field)
983 MY_ATTRIBUTE((nonnull, warn_unused_result));
984
985/********************************************************************//**
986Helper function to push frm mismatch error to error log and
987if needed to sql-layer. */
988UNIV_INTERN
989void
990ib_push_frm_error(
991/*==============*/
992 THD* thd, /*!< in: MySQL thd */
993 dict_table_t* ib_table, /*!< in: InnoDB table */
994 TABLE* table, /*!< in: MySQL table */
995 ulint n_keys, /*!< in: InnoDB #keys */
996 bool push_warning); /*!< in: print warning ? */
997