summaryrefslogtreecommitdiffstats
path: root/sql/table.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 18:07:14 +0000
commita175314c3e5827eb193872241446f2f8f5c9d33c (patch)
treecd3d60ca99ae00829c52a6ca79150a5b6e62528b /sql/table.h
parentInitial commit. (diff)
downloadmariadb-10.5-a175314c3e5827eb193872241446f2f8f5c9d33c.tar.xz
mariadb-10.5-a175314c3e5827eb193872241446f2f8f5c9d33c.zip
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--sql/table.h3397
1 files changed, 3397 insertions, 0 deletions
diff --git a/sql/table.h b/sql/table.h
new file mode 100644
index 00000000..d063a3f2
--- /dev/null
+++ b/sql/table.h
@@ -0,0 +1,3397 @@
+#ifndef TABLE_INCLUDED
+#define TABLE_INCLUDED
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2020, MariaDB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#include "sql_plist.h"
+#include "sql_list.h" /* Sql_alloc */
+#include "mdl.h"
+#include "datadict.h"
+#include "sql_string.h" /* String */
+#include "lex_string.h"
+
+#ifndef MYSQL_CLIENT
+
+#include "my_cpu.h" /* LF_BACKOFF() */
+#include "hash.h" /* HASH */
+#include "handler.h" /* row_type, ha_choice, handler */
+#include "mysql_com.h" /* enum_field_types */
+#include "thr_lock.h" /* thr_lock_type */
+#include "filesort_utils.h"
+#include "parse_file.h"
+#include "sql_i_s.h"
+#include "sql_type.h" /* vers_kind_t */
+#include "privilege.h" /* privilege_t */
+
+/* Structs that defines the TABLE */
+
+class Item; /* Needed by ORDER */
+typedef Item (*Item_ptr);
+class Item_subselect;
+class Item_field;
+class GRANT_TABLE;
+class st_select_lex_unit;
+class st_select_lex;
+class partition_info;
+class COND_EQUAL;
+class Security_context;
+struct TABLE_LIST;
+class ACL_internal_schema_access;
+class ACL_internal_table_access;
+class Field;
+class Table_statistics;
+class With_element;
+struct TDC_element;
+class Virtual_column_info;
+class Table_triggers_list;
+class TMP_TABLE_PARAM;
+class SEQUENCE;
+class Range_rowid_filter_cost_info;
+class derived_handler;
+class Pushdown_derived;
+struct Name_resolution_context;
+
+/*
+ Used to identify NESTED_JOIN structures within a join (applicable only to
+ structures that have not been simplified away and embed more the one
+ element)
+*/
+typedef ulonglong nested_join_map;
+
+
+#define tmp_file_prefix "#sql" /**< Prefix for tmp tables */
+#define tmp_file_prefix_length 4
+#define TMP_TABLE_KEY_EXTRA 8
+
+/**
+ Enumerate possible types of a table from re-execution
+ standpoint.
+ TABLE_LIST class has a member of this type.
+ At prepared statement prepare, this member is assigned a value
+ as of the current state of the database. Before (re-)execution
+ of a prepared statement, we check that the value recorded at
+ prepare matches the type of the object we obtained from the
+ table definition cache.
+
+ @sa check_and_update_table_version()
+ @sa Execute_observer
+ @sa Prepared_statement::reprepare()
+*/
+
+enum enum_table_ref_type
+{
+ /** Initial value set by the parser */
+ TABLE_REF_NULL= 0,
+ TABLE_REF_VIEW,
+ TABLE_REF_BASE_TABLE,
+ TABLE_REF_I_S_TABLE,
+ TABLE_REF_TMP_TABLE
+};
+
+
+/*************************************************************************/
+
+/**
+ Object_creation_ctx -- interface for creation context of database objects
+ (views, stored routines, events, triggers). Creation context -- is a set
+ of attributes, that should be fixed at the creation time and then be used
+ each time the object is parsed or executed.
+*/
+
+class Object_creation_ctx
+{
+public:
+ Object_creation_ctx *set_n_backup(THD *thd);
+
+ void restore_env(THD *thd, Object_creation_ctx *backup_ctx);
+
+protected:
+ Object_creation_ctx() {}
+ virtual Object_creation_ctx *create_backup_ctx(THD *thd) const = 0;
+
+ virtual void change_env(THD *thd) const = 0;
+
+public:
+ virtual ~Object_creation_ctx()
+ { }
+};
+
+/*************************************************************************/
+
+/**
+ Default_object_creation_ctx -- default implementation of
+ Object_creation_ctx.
+*/
+
+class Default_object_creation_ctx : public Object_creation_ctx
+{
+public:
+ CHARSET_INFO *get_client_cs()
+ {
+ return m_client_cs;
+ }
+
+ CHARSET_INFO *get_connection_cl()
+ {
+ return m_connection_cl;
+ }
+
+protected:
+ Default_object_creation_ctx(THD *thd);
+
+ Default_object_creation_ctx(CHARSET_INFO *client_cs,
+ CHARSET_INFO *connection_cl);
+
+protected:
+ virtual Object_creation_ctx *create_backup_ctx(THD *thd) const;
+
+ virtual void change_env(THD *thd) const;
+
+protected:
+ /**
+ client_cs stores the value of character_set_client session variable.
+ The only character set attribute is used.
+
+ Client character set is included into query context, because we save
+ query in the original character set, which is client character set. So,
+ in order to parse the query properly we have to switch client character
+ set on parsing.
+ */
+ CHARSET_INFO *m_client_cs;
+
+ /**
+ connection_cl stores the value of collation_connection session
+ variable. Both character set and collation attributes are used.
+
+ Connection collation is included into query context, becase it defines
+ the character set and collation of text literals in internal
+ representation of query (item-objects).
+ */
+ CHARSET_INFO *m_connection_cl;
+};
+
+class Query_arena;
+
+/*************************************************************************/
+
+/**
+ View_creation_ctx -- creation context of view objects.
+*/
+
+class View_creation_ctx : public Default_object_creation_ctx,
+ public Sql_alloc
+{
+public:
+ static View_creation_ctx *create(THD *thd);
+
+ static View_creation_ctx *create(THD *thd,
+ TABLE_LIST *view);
+
+private:
+ View_creation_ctx(THD *thd)
+ : Default_object_creation_ctx(thd)
+ { }
+};
+
+/*************************************************************************/
+
+/* Order clause list element */
+
+typedef int (*fast_field_copier)(Field *to, Field *from);
+
+
+typedef struct st_order {
+ struct st_order *next;
+ Item **item; /* Point at item in select fields */
+ Item *item_ptr; /* Storage for initial item */
+ /*
+ Reference to the function we are trying to optimize copy to
+ a temporary table
+ */
+ fast_field_copier fast_field_copier_func;
+ /* Field for which above optimizer function setup */
+ Field *fast_field_copier_setup;
+ int counter; /* position in SELECT list, correct
+ only if counter_used is true*/
+ enum enum_order {
+ ORDER_NOT_RELEVANT,
+ ORDER_ASC,
+ ORDER_DESC
+ };
+
+ enum_order direction; /* Requested direction of ordering */
+ bool in_field_list; /* true if in select field list */
+ bool counter_used; /* parameter was counter of columns */
+ Field *field; /* If tmp-table group */
+ char *buff; /* If tmp-table group */
+ table_map used; /* NOTE: the below is only set to 0 but is still used by eq_ref_table */
+ table_map depend_map;
+} ORDER;
+
+/**
+ State information for internal tables grants.
+ This structure is part of the TABLE_LIST, and is updated
+ during the ACL check process.
+ @sa GRANT_INFO
+*/
+struct st_grant_internal_info
+{
+ /** True if the internal lookup by schema name was done. */
+ bool m_schema_lookup_done;
+ /** Cached internal schema access. */
+ const ACL_internal_schema_access *m_schema_access;
+ /** True if the internal lookup by table name was done. */
+ bool m_table_lookup_done;
+ /** Cached internal table access. */
+ const ACL_internal_table_access *m_table_access;
+};
+typedef struct st_grant_internal_info GRANT_INTERNAL_INFO;
+
+/**
+ @brief The current state of the privilege checking process for the current
+ user, SQL statement and SQL object.
+
+ @details The privilege checking process is divided into phases depending on
+ the level of the privilege to be checked and the type of object to be
+ accessed. Due to the mentioned scattering of privilege checking
+ functionality, it is necessary to keep track of the state of the
+ process. This information is stored in privilege, want_privilege, and
+ orig_want_privilege.
+
+ A GRANT_INFO also serves as a cache of the privilege hash tables. Relevant
+ members are grant_table and version.
+ */
+typedef struct st_grant_info
+{
+ /**
+ @brief A copy of the privilege information regarding the current host,
+ database, object and user.
+
+ @details The version of this copy is found in GRANT_INFO::version.
+ */
+ GRANT_TABLE *grant_table_user;
+ GRANT_TABLE *grant_table_role;
+ /**
+ @brief Used for cache invalidation when caching privilege information.
+
+ @details The privilege information is stored on disk, with dedicated
+ caches residing in memory: table-level and column-level privileges,
+ respectively, have their own dedicated caches.
+
+ The GRANT_INFO works as a level 1 cache with this member updated to the
+ current value of the global variable @c grant_version (@c static variable
+ in sql_acl.cc). It is updated Whenever the GRANT_INFO is refreshed from
+ the level 2 cache. The level 2 cache is the @c column_priv_hash structure
+ (@c static variable in sql_acl.cc)
+
+ @see grant_version
+ */
+ uint version;
+ /**
+ @brief The set of privileges that the current user has fulfilled for a
+ certain host, database, and object.
+
+ @details This field is continually updated throughout the access checking
+ process. In each step the "wanted privilege" is checked against the
+ fulfilled privileges. When/if the intersection of these sets is empty,
+ access is granted.
+
+ The set is implemented as a bitmap, with the bits defined in sql_acl.h.
+ */
+ privilege_t privilege;
+ /**
+ @brief the set of privileges that the current user needs to fulfil in
+ order to carry out the requested operation.
+ */
+ privilege_t want_privilege;
+ /**
+ Stores the requested access acl of top level tables list. Is used to
+ check access rights to the underlying tables of a view.
+ */
+ privilege_t orig_want_privilege;
+ /** The grant state for internal tables. */
+ GRANT_INTERNAL_INFO m_internal;
+
+ st_grant_info()
+ :privilege(NO_ACL),
+ want_privilege(NO_ACL),
+ orig_want_privilege(NO_ACL)
+ { }
+} GRANT_INFO;
+
+enum tmp_table_type
+{
+ NO_TMP_TABLE= 0, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE,
+ INTERNAL_TMP_TABLE, SYSTEM_TMP_TABLE
+};
+enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP };
+
+
+enum vcol_init_mode
+{
+ VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING= 1,
+ VCOL_INIT_DEPENDENCY_FAILURE_IS_ERROR= 2
+ /*
+ There may be new flags here.
+ e.g. to automatically remove sql_mode dependency:
+ GENERATED ALWAYS AS (char_col) ->
+ GENERATED ALWAYS AS (RTRIM(char_col))
+ */
+};
+
+
+enum enum_vcol_update_mode
+{
+ VCOL_UPDATE_FOR_READ= 0,
+ VCOL_UPDATE_FOR_WRITE,
+ VCOL_UPDATE_FOR_DELETE,
+ VCOL_UPDATE_INDEXED,
+ VCOL_UPDATE_INDEXED_FOR_UPDATE,
+ VCOL_UPDATE_FOR_REPLACE
+};
+
+/* Field visibility enums */
+
+enum field_visibility_t {
+ VISIBLE= 0,
+ INVISIBLE_USER,
+ /* automatically added by the server. Can be queried explicitly
+ in SELECT, otherwise invisible from anything" */
+ INVISIBLE_SYSTEM,
+ INVISIBLE_FULL
+};
+
+#define INVISIBLE_MAX_BITS 3
+#define HA_HASH_FIELD_LENGTH 8
+#define HA_HASH_KEY_LENGTH_WITHOUT_NULL 8
+#define HA_HASH_KEY_LENGTH_WITH_NULL 9
+
+
+int fields_in_hash_keyinfo(KEY *keyinfo);
+
+void setup_keyinfo_hash(KEY *key_info);
+
+void re_setup_keyinfo_hash(KEY *key_info);
+
+/**
+ Category of table found in the table share.
+*/
+enum enum_table_category
+{
+ /**
+ Unknown value.
+ */
+ TABLE_UNKNOWN_CATEGORY=0,
+
+ /**
+ Temporary table.
+ The table is visible only in the session.
+ Therefore,
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ do not apply to this table.
+ Note that LOCK TABLE t FOR READ/WRITE
+ can be used on temporary tables.
+ Temporary tables are not part of the table cache.
+ */
+ TABLE_CATEGORY_TEMPORARY=1,
+
+ /**
+ User table.
+ These tables do honor:
+ - LOCK TABLE t FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ User tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_USER=2,
+
+ /**
+ System table, maintained by the server.
+ These tables do honor:
+ - LOCK TABLE t FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ Typically, writes to system tables are performed by
+ the server implementation, not explicitly be a user.
+ System tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_SYSTEM=3,
+
+ /**
+ Log tables.
+ These tables are an interface provided by the system
+ to inspect the system logs.
+ These tables do *not* honor:
+ - LOCK TABLE t FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ as there is no point in locking explicitly
+ a LOG table.
+ An example of LOG tables are:
+ - mysql.slow_log
+ - mysql.general_log,
+ which *are* updated even when there is either
+ a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect.
+ User queries do not write directly to these tables
+ (there are exceptions for log tables).
+ The server implementation perform writes.
+ Log tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_LOG=4,
+
+ /*
+ Types below are read only tables, not affected by FLUSH TABLES or
+ MDL locks.
+ */
+ /**
+ Information schema tables.
+ These tables are an interface provided by the system
+ to inspect the system metadata.
+ These tables do *not* honor:
+ - LOCK TABLE t FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ as there is no point in locking explicitly
+ an INFORMATION_SCHEMA table.
+ Nothing is directly written to information schema tables.
+ Note that this value is not used currently,
+ since information schema tables are not shared,
+ but implemented as session specific temporary tables.
+ */
+ /*
+ TODO: Fixing the performance issues of I_S will lead
+ to I_S tables in the table cache, which should use
+ this table type.
+ */
+ TABLE_CATEGORY_INFORMATION=5,
+
+ /**
+ Performance schema tables.
+ These tables are an interface provided by the system
+ to inspect the system performance data.
+ These tables do *not* honor:
+ - LOCK TABLE t FOR READ/WRITE
+ - FLUSH TABLES WITH READ LOCK
+ - SET GLOBAL READ_ONLY = ON
+ as there is no point in locking explicitly
+ a PERFORMANCE_SCHEMA table.
+ An example of PERFORMANCE_SCHEMA tables are:
+ - performance_schema.*
+ which *are* updated (but not using the handler interface)
+ even when there is either
+ a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect.
+ User queries do not write directly to these tables
+ (there are exceptions for SETUP_* tables).
+ The server implementation perform writes.
+ Performance tables are cached in the table cache.
+ */
+ TABLE_CATEGORY_PERFORMANCE=6
+};
+
+typedef enum enum_table_category TABLE_CATEGORY;
+
+TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
+ const LEX_CSTRING *name);
+
+
+typedef struct st_table_field_type
+{
+ LEX_CSTRING name;
+ LEX_CSTRING type;
+ LEX_CSTRING cset;
+} TABLE_FIELD_TYPE;
+
+
+typedef struct st_table_field_def
+{
+ uint count;
+ const TABLE_FIELD_TYPE *field;
+ uint primary_key_parts;
+ const uint *primary_key_columns;
+} TABLE_FIELD_DEF;
+
+
+class Table_check_intact
+{
+protected:
+ bool has_keys;
+ virtual void report_error(uint code, const char *fmt, ...)= 0;
+
+public:
+ Table_check_intact(bool keys= false) : has_keys(keys) {}
+ virtual ~Table_check_intact() {}
+
+ /** Checks whether a table is intact. */
+ bool check(TABLE *table, const TABLE_FIELD_DEF *table_def);
+};
+
+
+/*
+ If the table isn't valid, report the error to the server log only.
+*/
+class Table_check_intact_log_error : public Table_check_intact
+{
+protected:
+ void report_error(uint, const char *fmt, ...);
+public:
+ Table_check_intact_log_error() : Table_check_intact(true) {}
+};
+
+
+/**
+ Class representing the fact that some thread waits for table
+ share to be flushed. Is used to represent information about
+ such waits in MDL deadlock detector.
+*/
+
+class Wait_for_flush : public MDL_wait_for_subgraph
+{
+ MDL_context *m_ctx;
+ TABLE_SHARE *m_share;
+ uint m_deadlock_weight;
+public:
+ Wait_for_flush(MDL_context *ctx_arg, TABLE_SHARE *share_arg,
+ uint deadlock_weight_arg)
+ : m_ctx(ctx_arg), m_share(share_arg),
+ m_deadlock_weight(deadlock_weight_arg)
+ {}
+
+ MDL_context *get_ctx() const { return m_ctx; }
+
+ virtual bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor);
+
+ virtual uint get_deadlock_weight() const;
+
+ /**
+ Pointers for participating in the list of waiters for table share.
+ */
+ Wait_for_flush *next_in_share;
+ Wait_for_flush **prev_in_share;
+};
+
+
+typedef I_P_List <Wait_for_flush,
+ I_P_List_adapter<Wait_for_flush,
+ &Wait_for_flush::next_in_share,
+ &Wait_for_flush::prev_in_share> >
+ Wait_for_flush_list;
+
+
+enum open_frm_error {
+ OPEN_FRM_OK = 0,
+ OPEN_FRM_OPEN_ERROR,
+ OPEN_FRM_READ_ERROR,
+ OPEN_FRM_CORRUPTED,
+ OPEN_FRM_DISCOVER,
+ OPEN_FRM_ERROR_ALREADY_ISSUED,
+ OPEN_FRM_NOT_A_VIEW,
+ OPEN_FRM_NOT_A_TABLE,
+ OPEN_FRM_NEEDS_REBUILD
+};
+
+/**
+ Control block to access table statistics loaded
+ from persistent statistical tables
+*/
+
+class TABLE_STATISTICS_CB
+{
+ class Statistics_state
+ {
+ enum state_codes
+ {
+ EMPTY, /** data is not loaded */
+ LOADING, /** data is being loaded in some connection */
+ READY /** data is loaded and available for use */
+ };
+ int32 state;
+
+ public:
+ /** No state copy */
+ Statistics_state &operator=(const Statistics_state &) { return *this; }
+
+ /** Checks if data loading have been completed */
+ bool is_ready() const
+ {
+ return my_atomic_load32_explicit(const_cast<int32*>(&state),
+ MY_MEMORY_ORDER_ACQUIRE) == READY;
+ }
+
+ /**
+ Sets mutual exclusion for data loading
+
+ If stats are in LOADING state, waits until state change.
+
+ @return
+ @retval true atomic EMPTY -> LOADING transfer completed, ok to load
+ @retval false stats are in READY state, no need to load
+ */
+ bool start_load()
+ {
+ for (;;)
+ {
+ int32 expected= EMPTY;
+ if (my_atomic_cas32_weak_explicit(&state, &expected, LOADING,
+ MY_MEMORY_ORDER_RELAXED,
+ MY_MEMORY_ORDER_RELAXED))
+ return true;
+ if (expected == READY)
+ return false;
+ (void) LF_BACKOFF();
+ }
+ }
+
+ /** Marks data available for subsequent use */
+ void end_load()
+ {
+ DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) ==
+ LOADING);
+ my_atomic_store32_explicit(&state, READY, MY_MEMORY_ORDER_RELEASE);
+ }
+
+ /** Restores empty state on error (e.g. OOM) */
+ void abort_load()
+ {
+ DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) ==
+ LOADING);
+ my_atomic_store32_explicit(&state, EMPTY, MY_MEMORY_ORDER_RELAXED);
+ }
+ };
+
+ class Statistics_state stats_state;
+ class Statistics_state hist_state;
+
+public:
+ MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */
+ Table_statistics *table_stats; /* Structure to access the statistical data */
+ ulong total_hist_size; /* Total size of all histograms */
+
+ bool histograms_are_ready() const
+ {
+ return !total_hist_size || hist_state.is_ready();
+ }
+
+ bool start_histograms_load()
+ {
+ return total_hist_size && hist_state.start_load();
+ }
+
+ void end_histograms_load() { hist_state.end_load(); }
+ void abort_histograms_load() { hist_state.abort_load(); }
+ bool stats_are_ready() const { return stats_state.is_ready(); }
+ bool start_stats_load() { return stats_state.start_load(); }
+ void end_stats_load() { stats_state.end_load(); }
+ void abort_stats_load() { stats_state.abort_load(); }
+};
+
+/**
+ This structure is shared between different table objects. There is one
+ instance of table share per one table in the database.
+*/
+
+struct TABLE_SHARE
+{
+ TABLE_SHARE() {} /* Remove gcc warning */
+
+ /** Category of this table. */
+ TABLE_CATEGORY table_category;
+
+ /* hash of field names (contains pointers to elements of field array) */
+ HASH name_hash; /* hash of field names */
+ MEM_ROOT mem_root;
+ TYPELIB keynames; /* Pointers to keynames */
+ TYPELIB fieldnames; /* Pointer to fieldnames */
+ TYPELIB *intervals; /* pointer to interval info */
+ mysql_mutex_t LOCK_ha_data; /* To protect access to ha_data */
+ mysql_mutex_t LOCK_share; /* To protect TABLE_SHARE */
+
+ TDC_element *tdc;
+
+ LEX_CUSTRING tabledef_version;
+
+ engine_option_value *option_list; /* text options for table */
+ ha_table_option_struct *option_struct; /* structure with parsed options */
+
+ /* The following is copied to each TABLE on OPEN */
+ Field **field;
+ Field **found_next_number_field;
+ KEY *key_info; /* data of keys in database */
+ Virtual_column_info **check_constraints;
+ uint *blob_field; /* Index to blobs in Field arrray*/
+ LEX_CUSTRING vcol_defs; /* definitions of generated columns */
+
+ TABLE_STATISTICS_CB stats_cb;
+
+ uchar *default_values; /* row with default values */
+ LEX_CSTRING comment; /* Comment about table */
+ CHARSET_INFO *table_charset; /* Default charset of string fields */
+
+ MY_BITMAP *check_set; /* Fields used by check constrant */
+ MY_BITMAP all_set;
+ /*
+ Key which is used for looking-up table in table cache and in the list
+ of thread's temporary tables. Has the form of:
+ "database_name\0table_name\0" + optional part for temporary tables.
+
+ Note that all three 'table_cache_key', 'db' and 'table_name' members
+ must be set (and be non-zero) for tables in table cache. They also
+ should correspond to each other.
+ To ensure this one can use set_table_cache() methods.
+ */
+ LEX_CSTRING table_cache_key;
+ LEX_CSTRING db; /* Pointer to db */
+ LEX_CSTRING table_name; /* Table name (for open) */
+ LEX_CSTRING path; /* Path to .frm file (from datadir) */
+ LEX_CSTRING normalized_path; /* unpack_filename(path) */
+ LEX_CSTRING connect_string;
+
+ /*
+ Set of keys in use, implemented as a Bitmap.
+ Excludes keys disabled by ALTER TABLE ... DISABLE KEYS.
+ */
+ key_map keys_in_use;
+ key_map keys_for_keyread;
+ ha_rows min_rows, max_rows; /* create information */
+ ulong avg_row_length; /* create information */
+ ulong mysql_version; /* 0 if .frm is created before 5.0 */
+ ulong reclength; /* Recordlength */
+ /* Stored record length. No generated-only virtual fields are included */
+ ulong stored_rec_length;
+
+ plugin_ref db_plugin; /* storage engine plugin */
+ inline handlerton *db_type() const /* table_type for handler */
+ {
+ return is_view ? view_pseudo_hton :
+ db_plugin ? plugin_hton(db_plugin) : NULL;
+ }
+ enum row_type row_type; /* How rows are stored */
+ enum Table_type table_type;
+ enum tmp_table_type tmp_table;
+
+ /** Transactional or not. */
+ enum ha_choice transactional;
+ /** Per-page checksums or not. */
+ enum ha_choice page_checksum;
+
+ uint key_block_size; /* create key_block_size, if used */
+ uint stats_sample_pages; /* number of pages to sample during
+ stats estimation, if used, otherwise 0. */
+ enum_stats_auto_recalc stats_auto_recalc; /* Automatic recalc of stats. */
+ uint null_bytes, last_null_bit_pos;
+ /*
+ Same as null_bytes, except that if there is only a 'delete-marker' in
+ the record then this value is 0.
+ */
+ uint null_bytes_for_compare;
+ uint fields; /* number of fields */
+ /* number of stored fields, purely virtual not included */
+ uint stored_fields;
+ uint virtual_fields; /* number of purely virtual fields */
+ /* number of purely virtual not stored blobs */
+ uint virtual_not_stored_blob_fields;
+ uint null_fields; /* number of null fields */
+ uint blob_fields; /* number of blob fields */
+ uint varchar_fields; /* number of varchar fields */
+ uint default_fields; /* number of default fields */
+ uint visible_fields; /* number of visible fields */
+
+ uint default_expressions;
+ uint table_check_constraints, field_check_constraints;
+
+ uint rec_buff_length; /* Size of table->record[] buffer */
+ uint keys, key_parts;
+ uint ext_key_parts; /* Total number of key parts in extended keys */
+ uint max_key_length, max_unique_length;
+ uint uniques; /* Number of UNIQUE index */
+ uint db_create_options; /* Create options from database */
+ uint db_options_in_use; /* Options in use */
+ uint db_record_offset; /* if HA_REC_IN_SEQ */
+ uint rowid_field_offset; /* Field_nr +1 to rowid field */
+ /* Primary key index number, used in TABLE::key_info[] */
+ uint primary_key;
+ uint next_number_index; /* autoincrement key number */
+ uint next_number_key_offset; /* autoinc keypart offset in a key */
+ uint next_number_keypart; /* autoinc keypart number in a key */
+ enum open_frm_error error; /* error from open_table_def() */
+ uint open_errno; /* error from open_table_def() */
+ uint column_bitmap_size;
+ uchar frm_version;
+
+ enum enum_v_keys { NOT_INITIALIZED=0, NO_V_KEYS, V_KEYS };
+ enum_v_keys check_set_initialized;
+
+ bool use_ext_keys; /* Extended keys can be used */
+ bool null_field_first;
+ bool system; /* Set if system table (one record) */
+ bool not_usable_by_query_cache;
+ bool online_backup; /* Set if on-line backup supported */
+ /*
+ This is used by log tables, for tables that have their own internal
+ binary logging or for tables that doesn't support statement or row logging
+ */
+ bool no_replicate;
+ bool crashed;
+ bool is_view;
+ bool can_cmp_whole_record;
+ /* This is set for temporary tables where CREATE was binary logged */
+ bool table_creation_was_logged;
+ bool non_determinstic_insert;
+ bool vcols_need_refixing;
+ bool has_update_default_function;
+ bool can_do_row_logging; /* 1 if table supports RBR */
+ bool long_unique_table;
+
+ ulong table_map_id; /* for row-based replication */
+
+ /*
+ Things that are incompatible between the stored version and the
+ current version. This is a set of HA_CREATE... bits that can be used
+ to modify create_info->used_fields for ALTER TABLE.
+ */
+ ulong incompatible_version;
+
+ /**
+ For shares representing views File_parser object with view
+ definition read from .FRM file.
+ */
+ const File_parser *view_def;
+
+ /* For sequence tables, the current sequence state */
+ SEQUENCE *sequence;
+
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ /* filled in when reading from frm */
+ bool auto_partitioned;
+ char *partition_info_str;
+ uint partition_info_str_len;
+ uint partition_info_buffer_size;
+ plugin_ref default_part_plugin;
+#endif
+
+ /**
+ System versioning and application-time periods support.
+ */
+ struct period_info_t
+ {
+ uint16 start_fieldno;
+ uint16 end_fieldno;
+ Lex_ident name;
+ Lex_ident constr_name;
+ uint unique_keys;
+ Field *start_field(TABLE_SHARE *s) const
+ {
+ return s->field[start_fieldno];
+ }
+ Field *end_field(TABLE_SHARE *s) const
+ {
+ return s->field[end_fieldno];
+ }
+ };
+
+ vers_kind_t versioned;
+ period_info_t vers;
+ period_info_t period;
+
+ bool init_period_from_extra2(period_info_t *period, const uchar *data,
+ const uchar *end);
+
+ Field *vers_start_field()
+ {
+ DBUG_ASSERT(versioned);
+ return field[vers.start_fieldno];
+ }
+
+ Field *vers_end_field()
+ {
+ DBUG_ASSERT(versioned);
+ return field[vers.end_fieldno];
+ }
+
+ Field *period_start_field() const
+ {
+ DBUG_ASSERT(period.name);
+ return field[period.start_fieldno];
+ }
+
+ Field *period_end_field() const
+ {
+ DBUG_ASSERT(period.name);
+ return field[period.end_fieldno];
+ }
+
+ /**
+ Cache the checked structure of this table.
+
+ The pointer data is used to describe the structure that
+ a instance of the table must have. Each element of the
+ array specifies a field that must exist on the table.
+
+ The pointer is cached in order to perform the check only
+ once -- when the table is loaded from the disk.
+ */
+ const TABLE_FIELD_DEF *table_field_def_cache;
+
+ /** Main handler's share */
+ Handler_share *ha_share;
+
+ /** Instrumentation for this table share. */
+ PSI_table_share *m_psi;
+
+ inline void reset() { bzero((void*)this, sizeof(*this)); }
+
+ /*
+ Set share's table cache key and update its db and table name appropriately.
+
+ SYNOPSIS
+ set_table_cache_key()
+ key_buff Buffer with already built table cache key to be
+ referenced from share.
+ key_length Key length.
+
+ NOTES
+ Since 'key_buff' buffer will be referenced from share it should has same
+ life-time as share itself.
+ This method automatically ensures that TABLE_SHARE::table_name/db have
+ appropriate values by using table cache key as their source.
+ */
+
+ void set_table_cache_key(char *key_buff, uint key_length)
+ {
+ table_cache_key.str= key_buff;
+ table_cache_key.length= key_length;
+ /*
+ Let us use the fact that the key is "db/0/table_name/0" + optional
+ part for temporary tables.
+ */
+ db.str= table_cache_key.str;
+ db.length= strlen(db.str);
+ table_name.str= db.str + db.length + 1;
+ table_name.length= strlen(table_name.str);
+ }
+
+
+ /*
+ Set share's table cache key and update its db and table name appropriately.
+
+ SYNOPSIS
+ set_table_cache_key()
+ key_buff Buffer to be used as storage for table cache key
+ (should be at least key_length bytes).
+ key Value for table cache key.
+ key_length Key length.
+
+ NOTE
+ Since 'key_buff' buffer will be used as storage for table cache key
+ it should has same life-time as share itself.
+ */
+
+ void set_table_cache_key(char *key_buff, const char *key, uint key_length)
+ {
+ memcpy(key_buff, key, key_length);
+ set_table_cache_key(key_buff, key_length);
+ }
+
+ inline bool require_write_privileges()
+ {
+ return (table_category == TABLE_CATEGORY_LOG);
+ }
+
+ inline ulong get_table_def_version()
+ {
+ return table_map_id;
+ }
+
+ /**
+ Convert unrelated members of TABLE_SHARE to one enum
+ representing its type.
+
+ @todo perhaps we need to have a member instead of a function.
+ */
+ enum enum_table_ref_type get_table_ref_type() const
+ {
+ if (is_view)
+ return TABLE_REF_VIEW;
+ switch (tmp_table) {
+ case NO_TMP_TABLE:
+ return TABLE_REF_BASE_TABLE;
+ case SYSTEM_TMP_TABLE:
+ return TABLE_REF_I_S_TABLE;
+ default:
+ return TABLE_REF_TMP_TABLE;
+ }
+ }
+ /**
+ Return a table metadata version.
+ * for base tables and views, we return table_map_id.
+ It is assigned from a global counter incremented for each
+ new table loaded into the table definition cache (TDC).
+ * for temporary tables it's table_map_id again. But for
+ temporary tables table_map_id is assigned from
+ thd->query_id. The latter is assigned from a thread local
+ counter incremented for every new SQL statement. Since
+ temporary tables are thread-local, each temporary table
+ gets a unique id.
+ * for everything else (e.g. information schema tables),
+ the version id is zero.
+
+ This choice of version id is a large compromise
+ to have a working prepared statement validation in 5.1. In
+ future version ids will be persistent, as described in WL#4180.
+
+ Let's try to explain why and how this limited solution allows
+ to validate prepared statements.
+
+ Firstly, sets (in mathematical sense) of version numbers
+ never intersect for different table types. Therefore,
+ version id of a temporary table is never compared with
+ a version id of a view, and vice versa.
+
+ Secondly, for base tables and views, we know that each DDL flushes
+ the respective share from the TDC. This ensures that whenever
+ a table is altered or dropped and recreated, it gets a new
+ version id.
+ Unfortunately, since elements of the TDC are also flushed on
+ LRU basis, this choice of version ids leads to false positives.
+ E.g. when the TDC size is too small, we may have a SELECT
+ * FROM INFORMATION_SCHEMA.TABLES flush all its elements, which
+ in turn will lead to a validation error and a subsequent
+ reprepare of all prepared statements. This is
+ considered acceptable, since as long as prepared statements are
+ automatically reprepared, spurious invalidation is only
+ a performance hit. Besides, no better simple solution exists.
+
+ For temporary tables, using thd->query_id ensures that if
+ a temporary table was altered or recreated, a new version id is
+ assigned. This suits validation needs very well and will perhaps
+ never change.
+
+ Metadata of information schema tables never changes.
+ Thus we can safely assume 0 for a good enough version id.
+
+ Finally, by taking into account table type, we always
+ track that a change has taken place when a view is replaced
+ with a base table, a base table is replaced with a temporary
+ table and so on.
+
+ @sa TABLE_LIST::is_table_ref_id_equal()
+ */
+ ulong get_table_ref_version() const
+ {
+ return (tmp_table == SYSTEM_TMP_TABLE) ? 0 : table_map_id;
+ }
+
+ bool visit_subgraph(Wait_for_flush *waiting_ticket,
+ MDL_wait_for_graph_visitor *gvisitor);
+
+ bool wait_for_old_version(THD *thd, struct timespec *abstime,
+ uint deadlock_weight);
+ /** Release resources and free memory occupied by the table share. */
+ void destroy();
+
+ void set_use_ext_keys_flag(bool fl)
+ {
+ use_ext_keys= fl;
+ }
+
+ uint actual_n_key_parts(THD *thd);
+
+ LEX_CUSTRING *frm_image; ///< only during CREATE TABLE (@sa ha_create_table)
+
+ /*
+ populates TABLE_SHARE from the table description in the binary frm image.
+ if 'write' is true, this frm image is also written into a corresponding
+ frm file, that serves as a persistent metadata cache to avoid
+ discovering the table over and over again
+ */
+ int init_from_binary_frm_image(THD *thd, bool write,
+ const uchar *frm_image, size_t frm_length,
+ const uchar *par_image=0,
+ size_t par_length=0);
+
+ /*
+ populates TABLE_SHARE from the table description, specified as the
+ complete CREATE TABLE sql statement.
+ if 'write' is true, this frm image is also written into a corresponding
+ frm file, that serves as a persistent metadata cache to avoid
+ discovering the table over and over again
+ */
+ int init_from_sql_statement_string(THD *thd, bool write,
+ const char *sql, size_t sql_length);
+ /*
+ writes the frm image to an frm file, corresponding to this table
+ */
+ bool write_frm_image(const uchar *frm_image, size_t frm_length);
+ bool write_par_image(const uchar *par_image, size_t par_length);
+
+ /* Only used by tokudb */
+ bool write_frm_image(void)
+ { return frm_image ? write_frm_image(frm_image->str, frm_image->length) : 0; }
+
+ /*
+ returns an frm image for this table.
+ the memory is allocated and must be freed later
+ */
+ bool read_frm_image(const uchar **frm_image, size_t *frm_length);
+
+ /* frees the memory allocated in read_frm_image */
+ void free_frm_image(const uchar *frm);
+
+ void set_overlapped_keys();
+};
+
+/* not NULL, but cannot be dereferenced */
+#define UNUSABLE_TABLE_SHARE ((TABLE_SHARE*)1)
+
+/**
+ Class is used as a BLOB field value storage for
+ intermediate GROUP_CONCAT results. Used only for
+ GROUP_CONCAT with DISTINCT or ORDER BY options.
+ */
+
+class Blob_mem_storage: public Sql_alloc
+{
+private:
+ MEM_ROOT storage;
+ /**
+ Sign that some values were cut
+ during saving into the storage.
+ */
+ bool truncated_value;
+public:
+ Blob_mem_storage() :truncated_value(false)
+ {
+ init_alloc_root(key_memory_blob_mem_storage,
+ &storage, MAX_FIELD_VARCHARLENGTH, 0, MYF(0));
+ }
+ ~ Blob_mem_storage()
+ {
+ free_root(&storage, MYF(0));
+ }
+ void reset()
+ {
+ free_root(&storage, MYF(MY_MARK_BLOCKS_FREE));
+ truncated_value= false;
+ }
+ /**
+ Fuction creates duplicate of 'from'
+ string in 'storage' MEM_ROOT.
+
+ @param from string to copy
+ @param length string length
+
+ @retval Pointer to the copied string.
+ @retval 0 if an error occurred.
+ */
+ char *store(const char *from, size_t length)
+ {
+ return (char*) memdup_root(&storage, from, length);
+ }
+ void set_truncated_value(bool is_truncated_value)
+ {
+ truncated_value= is_truncated_value;
+ }
+ bool is_truncated_value() { return truncated_value; }
+};
+
+
+/* Information for one open table */
+enum index_hint_type
+{
+ INDEX_HINT_IGNORE,
+ INDEX_HINT_USE,
+ INDEX_HINT_FORCE
+};
+
+struct st_cond_statistic;
+
+#define CHECK_ROW_FOR_NULLS_TO_REJECT (1 << 0)
+#define REJECT_ROW_DUE_TO_NULL_FIELDS (1 << 1)
+
+class SplM_opt_info;
+
+struct vers_select_conds_t;
+
+struct TABLE
+{
+ TABLE() {} /* Remove gcc warning */
+
+ TABLE_SHARE *s;
+ handler *file;
+ TABLE *next, *prev;
+
+private:
+ /**
+ Links for the list of all TABLE objects for this share.
+ Declared as private to avoid direct manipulation with those objects.
+ One should use methods of I_P_List template instead.
+ */
+ TABLE *share_all_next, **share_all_prev;
+ TABLE *global_free_next, **global_free_prev;
+ friend struct All_share_tables;
+ friend struct Table_cache_instance;
+
+public:
+
+ uint32 instance; /** Table cache instance this TABLE is belonging to */
+ THD *in_use; /* Which thread uses this */
+
+ uchar *record[3]; /* Pointer to records */
+ uchar *write_row_record; /* Used as optimisation in
+ THD::write_row */
+ uchar *insert_values; /* used by INSERT ... UPDATE */
+ /*
+ Map of keys that can be used to retrieve all data from this table
+ needed by the query without reading the row.
+ */
+ key_map covering_keys, intersect_keys;
+ /*
+ A set of keys that can be used in the query that references this
+ table.
+
+ All indexes disabled on the table's TABLE_SHARE (see TABLE::s) will be
+ subtracted from this set upon instantiation. Thus for any TABLE t it holds
+ that t.keys_in_use_for_query is a subset of t.s.keys_in_use. Generally we
+ must not introduce any new keys here (see setup_tables).
+
+ The set is implemented as a bitmap.
+ */
+ key_map keys_in_use_for_query;
+ /* Map of keys that can be used to calculate GROUP BY without sorting */
+ key_map keys_in_use_for_group_by;
+ /* Map of keys that can be used to calculate ORDER BY without sorting */
+ key_map keys_in_use_for_order_by;
+ /* Map of keys dependent on some constraint */
+ key_map constraint_dependent_keys;
+ KEY *key_info; /* data of keys in database */
+
+ Field **field; /* Pointer to fields */
+ Field **vfield; /* Pointer to virtual fields*/
+ Field **default_field; /* Fields with non-constant DEFAULT */
+ Field *next_number_field; /* Set if next_number is activated */
+ Field *found_next_number_field; /* Set on open */
+ Virtual_column_info **check_constraints;
+
+ /* Table's triggers, 0 if there are no of them */
+ Table_triggers_list *triggers;
+ TABLE_LIST *pos_in_table_list;/* Element referring to this table */
+ /* Position in thd->locked_table_list under LOCK TABLES */
+ TABLE_LIST *pos_in_locked_tables;
+ /* Tables used in DEFAULT and CHECK CONSTRAINT (normally sequence tables) */
+ TABLE_LIST *internal_tables;
+
+ /*
+ Not-null for temporary tables only. Non-null values means this table is
+ used to compute GROUP BY, it has a unique of GROUP BY columns.
+ (set by create_tmp_table)
+ */
+ ORDER *group;
+ String alias; /* alias or table name */
+ uchar *null_flags;
+ MY_BITMAP def_read_set, def_write_set, tmp_set;
+ MY_BITMAP def_rpl_write_set;
+ MY_BITMAP eq_join_set; /* used to mark equi-joined fields */
+ MY_BITMAP cond_set; /* used to mark fields from sargable conditions*/
+ /* Active column sets */
+ MY_BITMAP *read_set, *write_set, *rpl_write_set;
+ /* On INSERT: fields that the user specified a value for */
+ MY_BITMAP has_value_set;
+
+ /*
+ The ID of the query that opened and is using this table. Has different
+ meanings depending on the table type.
+
+ Temporary tables:
+
+ table->query_id is set to thd->query_id for the duration of a statement
+ and is reset to 0 once it is closed by the same statement. A non-zero
+ table->query_id means that a statement is using the table even if it's
+ not the current statement (table is in use by some outer statement).
+
+ Non-temporary tables:
+
+ Under pre-locked or LOCK TABLES mode: query_id is set to thd->query_id
+ for the duration of a statement and is reset to 0 once it is closed by
+ the same statement. A non-zero query_id is used to control which tables
+ in the list of pre-opened and locked tables are actually being used.
+ */
+ query_id_t query_id;
+
+ /*
+ This structure is used for statistical data on the table that
+ is collected by the function collect_statistics_for_table
+ */
+ Table_statistics *collected_stats;
+
+ /* The estimate of the number of records in the table used by optimizer */
+ ha_rows used_stat_records;
+
+ key_map opt_range_keys;
+ /*
+ The following structure is filled for each key that has
+ opt_range_keys.is_set(key) == TRUE
+ */
+ struct OPT_RANGE
+ {
+ uint key_parts;
+ uint ranges;
+ ha_rows rows;
+ double cost;
+ /*
+ If there is a range access by i-th index then the cost of
+ index only access for it is stored in index_only_costs[i]
+ */
+ double index_only_cost;
+ } *opt_range;
+ /*
+ Bitmaps of key parts that =const for the duration of join execution. If
+ we're in a subquery, then the constant may be different across subquery
+ re-executions.
+ */
+ key_part_map *const_key_parts;
+
+ /*
+ Estimate of number of records that satisfy SARGable part of the table
+ condition, or table->file->records if no SARGable condition could be
+ constructed.
+ This value is used by join optimizer as an estimate of number of records
+ that will pass the table condition (condition that depends on fields of
+ this table and constants)
+ */
+ ha_rows opt_range_condition_rows;
+
+ double cond_selectivity;
+ List<st_cond_statistic> *cond_selectivity_sampling_explain;
+
+ table_map map; /* ID bit of table (1,2,4,8,16...) */
+
+ uint lock_position; /* Position in MYSQL_LOCK.table */
+ uint lock_data_start; /* Start pos. in MYSQL_LOCK.locks */
+ uint lock_count; /* Number of locks */
+ uint tablenr,used_fields;
+ uint temp_pool_slot; /* Used by intern temp tables */
+ uint status; /* What's in record[0] */
+ uint db_stat; /* mode of file as in handler.h */
+ /* number of select if it is derived table */
+ uint derived_select_number;
+ /*
+ Possible values:
+ - 0 by default
+ - JOIN_TYPE_{LEFT|RIGHT} if the table is inner w.r.t an outer join
+ operation
+ - 1 if the SELECT has mixed_implicit_grouping=1. example:
+ select max(col1), col2 from t1. In this case, the query produces
+ one row with all columns having NULL values.
+
+ Interpetation: If maybe_null!=0, all fields of the table are considered
+ NULLable (and have NULL values when null_row=true)
+ */
+ uint maybe_null;
+ int current_lock; /* Type of lock on table */
+ bool copy_blobs; /* copy_blobs when storing */
+ /*
+ Set if next_number_field is in the UPDATE fields of INSERT ... ON DUPLICATE
+ KEY UPDATE.
+ */
+ bool next_number_field_updated;
+
+ /*
+ If true, the current table row is considered to have all columns set to
+ NULL, including columns declared as "not null" (see maybe_null).
+ */
+ bool null_row;
+ /*
+ No rows that contain null values can be placed into this table.
+ Currently this flag can be set to true only for a temporary table
+ that used to store the result of materialization of a subquery.
+ */
+ bool no_rows_with_nulls;
+ /*
+ This field can contain two bit flags:
+ CHECK_ROW_FOR_NULLS_TO_REJECT
+ REJECT_ROW_DUE_TO_NULL_FIELDS
+ The first flag is set for the dynamic contexts where it is prohibited
+ to write any null into the table.
+ The second flag is set only if the first flag is set on.
+ The informs the outer scope that there was an attept to write null
+ into a field of the table in the context where it is prohibited.
+ This flag should be set off as soon as the first flag is set on.
+ Currently these flags are used only the tables tno_rows_with_nulls set
+ to true.
+ */
+ uint8 null_catch_flags;
+
+ /*
+ TODO: Each of the following flags take up 8 bits. They can just as easily
+ be put into one single unsigned long and instead of taking up 18
+ bytes, it would take up 4.
+ */
+ bool force_index;
+
+ /**
+ Flag set when the statement contains FORCE INDEX FOR ORDER BY
+ See TABLE_LIST::process_index_hints().
+ */
+ bool force_index_order;
+
+ /**
+ Flag set when the statement contains FORCE INDEX FOR GROUP BY
+ See TABLE_LIST::process_index_hints().
+ */
+ bool force_index_group;
+ /*
+ TRUE<=> this table was created with create_tmp_table(... distinct=TRUE..)
+ call
+ */
+ bool distinct;
+ bool const_table,no_rows, used_for_duplicate_elimination;
+ /**
+ Forces DYNAMIC Aria row format for internal temporary tables.
+ */
+ bool keep_row_order;
+
+ bool no_keyread;
+ /**
+ If set, indicate that the table is not replicated by the server.
+ */
+ bool locked_by_logger;
+ bool locked_by_name;
+ bool fulltext_searched;
+ bool no_cache;
+ /* To signal that the table is associated with a HANDLER statement */
+ bool open_by_handler;
+ /*
+ To indicate that a non-null value of the auto_increment field
+ was provided by the user or retrieved from the current record.
+ Used only in the MODE_NO_AUTO_VALUE_ON_ZERO mode.
+ */
+ bool auto_increment_field_not_null;
+ bool insert_or_update; /* Can be used by the handler */
+ bool alias_name_used; /* true if table_name is alias */
+ bool get_fields_in_item_tree; /* Signal to fix_field */
+private:
+ bool m_needs_reopen;
+ bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/
+public:
+#ifdef HAVE_REPLICATION
+ /* used in RBR Triggers */
+ bool master_had_triggers;
+#endif
+
+ REGINFO reginfo; /* field connections */
+ MEM_ROOT mem_root;
+ /**
+ Initialized in Item_func_group_concat::setup for appropriate
+ temporary table if GROUP_CONCAT is used with ORDER BY | DISTINCT
+ and BLOB field count > 0.
+ */
+ Blob_mem_storage *blob_storage;
+ GRANT_INFO grant;
+ /*
+ The arena which the items for expressions from the table definition
+ are associated with.
+ Currently only the items of the expressions for virtual columns are
+ associated with this arena.
+ TODO: To attach the partitioning expressions to this arena.
+ */
+ Query_arena *expr_arena;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ partition_info *part_info; /* Partition related information */
+ /* If true, all partitions have been pruned away */
+ bool all_partitions_pruned_away;
+#endif
+ uint max_keys; /* Size of allocated key_info array. */
+ bool stats_is_read; /* Persistent statistics is read for the table */
+ bool histograms_are_read;
+ MDL_ticket *mdl_ticket;
+
+ /*
+ This is used only for potentially splittable materialized tables and it
+ points to the info used by the optimizer to apply splitting optimization
+ */
+ SplM_opt_info *spl_opt_info;
+ key_map keys_usable_for_splitting;
+
+ /*
+ Conjunction of the predicates of the form IS NOT NULL(f) where f refers to
+ a column of this TABLE such that they can be inferred from the condition
+ of the WHERE clause or from some ON expression of the processed select
+ and can be useful for range optimizer.
+ */
+ Item *notnull_cond;
+
+ inline void reset() { bzero((void*)this, sizeof(*this)); }
+ void init(THD *thd, TABLE_LIST *tl);
+ bool fill_item_list(List<Item> *item_list) const;
+ void reset_item_list(List<Item> *item_list, uint skip) const;
+ void clear_column_bitmaps(void);
+ void prepare_for_position(void);
+ MY_BITMAP *prepare_for_keyread(uint index, MY_BITMAP *map);
+ MY_BITMAP *prepare_for_keyread(uint index)
+ { return prepare_for_keyread(index, &tmp_set); }
+ void mark_index_columns(uint index, MY_BITMAP *bitmap);
+ void mark_index_columns_no_reset(uint index, MY_BITMAP *bitmap);
+ void mark_index_columns_for_read(uint index);
+ void restore_column_maps_after_keyread(MY_BITMAP *backup);
+ void mark_auto_increment_column(void);
+ void mark_columns_needed_for_update(void);
+ void mark_columns_needed_for_delete(void);
+ void mark_columns_needed_for_insert(void);
+ void mark_columns_per_binlog_row_image(void);
+ inline bool mark_column_with_deps(Field *field);
+ inline bool mark_virtual_column_with_deps(Field *field);
+ inline void mark_virtual_column_deps(Field *field);
+ bool mark_virtual_columns_for_write(bool insert_fl);
+ bool check_virtual_columns_marked_for_read();
+ bool check_virtual_columns_marked_for_write();
+ void mark_default_fields_for_write(bool insert_fl);
+ void mark_columns_used_by_virtual_fields(void);
+ void mark_check_constraint_columns_for_read(void);
+ int verify_constraints(bool ignore_failure);
+ inline void column_bitmaps_set(MY_BITMAP *read_set_arg)
+ {
+ read_set= read_set_arg;
+ if (file)
+ file->column_bitmaps_signal();
+ }
+ inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
+ MY_BITMAP *write_set_arg)
+ {
+ read_set= read_set_arg;
+ write_set= write_set_arg;
+ if (file)
+ file->column_bitmaps_signal();
+ }
+ inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg,
+ MY_BITMAP *write_set_arg)
+ {
+ read_set= read_set_arg;
+ write_set= write_set_arg;
+ }
+ inline void use_all_columns()
+ {
+ column_bitmaps_set(&s->all_set, &s->all_set);
+ }
+ inline void use_all_stored_columns();
+ inline void default_column_bitmaps()
+ {
+ read_set= &def_read_set;
+ write_set= &def_write_set;
+ rpl_write_set= 0;
+ }
+ /** Should this instance of the table be reopened? */
+ inline bool needs_reopen()
+ { return !db_stat || m_needs_reopen; }
+ /*
+ Mark that all current connection instances of the table should be
+ reopen at end of statement
+ */
+ void mark_table_for_reopen();
+ /* Should only be called from Locked_tables_list::mark_table_for_reopen() */
+ void internal_set_needs_reopen(bool value)
+ {
+ m_needs_reopen= value;
+ }
+
+ bool alloc_keys(uint key_count);
+ bool check_tmp_key(uint key, uint key_parts,
+ uint (*next_field_no) (uchar *), uchar *arg);
+ bool add_tmp_key(uint key, uint key_parts,
+ uint (*next_field_no) (uchar *), uchar *arg,
+ bool unique);
+ void create_key_part_by_field(KEY_PART_INFO *key_part_info,
+ Field *field, uint fieldnr);
+ void use_index(int key_to_save);
+ void set_table_map(table_map map_arg, uint tablenr_arg)
+ {
+ map= map_arg;
+ tablenr= tablenr_arg;
+ }
+
+ /// Return true if table is instantiated, and false otherwise.
+ bool is_created() const { return created; }
+
+ /**
+ Set the table as "created", and enable flags in storage engine
+ that could not be enabled without an instantiated table.
+ */
+ void set_created()
+ {
+ if (created)
+ return;
+ if (file->keyread_enabled())
+ file->extra(HA_EXTRA_KEYREAD);
+ created= true;
+ }
+
+ /*
+ Returns TRUE if the table is filled at execution phase (and so, the
+ optimizer must not do anything that depends on the contents of the table,
+ like range analysis or constant table detection)
+ */
+ bool is_filled_at_execution();
+
+ bool update_const_key_parts(COND *conds);
+
+ inline void initialize_opt_range_structures();
+
+ my_ptrdiff_t default_values_offset() const
+ { return (my_ptrdiff_t) (s->default_values - record[0]); }
+
+ void move_fields(Field **ptr, const uchar *to, const uchar *from);
+ void remember_blob_values(String *blob_storage);
+ void restore_blob_values(String *blob_storage);
+
+ uint actual_n_key_parts(KEY *keyinfo);
+ ulong actual_key_flags(KEY *keyinfo);
+ int update_virtual_field(Field *vf);
+ int update_virtual_fields(handler *h, enum_vcol_update_mode update_mode);
+ int update_default_fields(bool ignore_errors);
+ void evaluate_update_default_function();
+ void reset_default_fields();
+ inline ha_rows stat_records() { return used_stat_records; }
+
+ void prepare_triggers_for_insert_stmt_or_event();
+ bool prepare_triggers_for_delete_stmt_or_event();
+ bool prepare_triggers_for_update_stmt_or_event();
+
+ Field **field_to_fill();
+ bool validate_default_values_of_unset_fields(THD *thd) const;
+
+ bool insert_all_rows_into_tmp_table(THD *thd,
+ TABLE *tmp_table,
+ TMP_TABLE_PARAM *tmp_table_param,
+ bool with_cleanup);
+ int fix_vcol_exprs(THD *thd);
+ Field *find_field_by_name(LEX_CSTRING *str) const;
+ bool export_structure(THD *thd, class Row_definition_list *defs);
+ bool is_splittable() { return spl_opt_info != NULL; }
+ void set_spl_opt_info(SplM_opt_info *spl_info);
+ void deny_splitting();
+ double get_materialization_cost(); // Now used only if is_splittable()==true
+ void add_splitting_info_for_key_field(struct KEY_FIELD *key_field);
+
+ key_map with_impossible_ranges;
+
+ /* Number of cost info elements for possible range filters */
+ uint range_rowid_filter_cost_info_elems;
+ /* Pointer to the array of cost info elements for range filters */
+ Range_rowid_filter_cost_info *range_rowid_filter_cost_info;
+ /* The array of pointers to cost info elements for range filters */
+ Range_rowid_filter_cost_info **range_rowid_filter_cost_info_ptr;
+
+ void init_cost_info_for_usable_range_rowid_filters(THD *thd);
+ void prune_range_rowid_filters();
+ void trace_range_rowid_filters(THD *thd) const;
+ Range_rowid_filter_cost_info *
+ best_range_rowid_filter_for_partial_join(uint access_key_no,
+ double records,
+ double access_cost_factor);
+
+ /**
+ System Versioning support
+ */
+ bool vers_write;
+
+ bool versioned() const
+ {
+ return s->versioned;
+ }
+
+ bool versioned(vers_kind_t type) const
+ {
+ DBUG_ASSERT(type);
+ return s->versioned == type;
+ }
+
+ bool versioned_write() const
+ {
+ DBUG_ASSERT(versioned() || !vers_write);
+ return versioned() ? vers_write : false;
+ }
+
+ bool versioned_write(vers_kind_t type) const
+ {
+ DBUG_ASSERT(type);
+ DBUG_ASSERT(versioned() || !vers_write);
+ return versioned(type) ? vers_write : false;
+ }
+
+ Field *vers_start_field() const
+ {
+ DBUG_ASSERT(s->versioned);
+ return field[s->vers.start_fieldno];
+ }
+
+ Field *vers_end_field() const
+ {
+ DBUG_ASSERT(s->versioned);
+ return field[s->vers.end_fieldno];
+ }
+
+ Field *period_start_field() const
+ {
+ DBUG_ASSERT(s->period.name);
+ return field[s->period.start_fieldno];
+ }
+
+ Field *period_end_field() const
+ {
+ DBUG_ASSERT(s->period.name);
+ return field[s->period.end_fieldno];
+ }
+
+
+ ulonglong vers_start_id() const;
+ ulonglong vers_end_id() const;
+
+ int update_generated_fields();
+ int period_make_insert(Item *src, Field *dst);
+ int insert_portion_of_time(THD *thd, const vers_select_conds_t &period_conds,
+ ha_rows *rows_inserted);
+ bool vers_check_update(List<Item> &items);
+ static bool check_period_overlaps(const KEY &key, const uchar *lhs, const uchar *rhs);
+ int delete_row();
+ void vers_update_fields();
+ void vers_update_end();
+ void find_constraint_correlated_indexes();
+
+/** Number of additional fields used in versioned tables */
+#define VERSIONING_FIELDS 2
+};
+
+
+/**
+ Helper class which specifies which members of TABLE are used for
+ participation in the list of used/unused TABLE objects for the share.
+*/
+
+struct TABLE_share
+{
+ static inline TABLE **next_ptr(TABLE *l)
+ {
+ return &l->next;
+ }
+ static inline TABLE ***prev_ptr(TABLE *l)
+ {
+ return (TABLE ***) &l->prev;
+ }
+};
+
+struct All_share_tables
+{
+ static inline TABLE **next_ptr(TABLE *l)
+ {
+ return &l->share_all_next;
+ }
+ static inline TABLE ***prev_ptr(TABLE *l)
+ {
+ return &l->share_all_prev;
+ }
+};
+
+typedef I_P_List <TABLE, All_share_tables> All_share_tables_list;
+
+enum enum_schema_table_state
+{
+ NOT_PROCESSED= 0,
+ PROCESSED_BY_CREATE_SORT_INDEX,
+ PROCESSED_BY_JOIN_EXEC
+};
+
+enum enum_fk_option { FK_OPTION_UNDEF, FK_OPTION_RESTRICT, FK_OPTION_CASCADE,
+ FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_SET_DEFAULT};
+
+typedef struct st_foreign_key_info
+{
+ LEX_CSTRING *foreign_id;
+ LEX_CSTRING *foreign_db;
+ LEX_CSTRING *foreign_table;
+ LEX_CSTRING *referenced_db;
+ LEX_CSTRING *referenced_table;
+ enum_fk_option update_method;
+ enum_fk_option delete_method;
+ LEX_CSTRING *referenced_key_name;
+ List<LEX_CSTRING> foreign_fields;
+ List<LEX_CSTRING> referenced_fields;
+} FOREIGN_KEY_INFO;
+
+LEX_CSTRING *fk_option_name(enum_fk_option opt);
+bool fk_modifies_child(enum_fk_option opt);
+
+class IS_table_read_plan;
+
+/*
+ Types of derived tables. The ending part is a bitmap of phases that are
+ applicable to a derived table of the type.
+*/
+#define DTYPE_ALGORITHM_UNDEFINED 0U
+#define DTYPE_VIEW 1U
+#define DTYPE_TABLE 2U
+#define DTYPE_MERGE 4U
+#define DTYPE_MATERIALIZE 8U
+#define DTYPE_MULTITABLE 16U
+#define DTYPE_MASK (DTYPE_VIEW|DTYPE_TABLE|DTYPE_MULTITABLE)
+
+/*
+ Phases of derived tables/views handling, see sql_derived.cc
+ Values are used as parts of a bitmap attached to derived table types.
+*/
+#define DT_INIT 1U
+#define DT_PREPARE 2U
+#define DT_OPTIMIZE 4U
+#define DT_MERGE 8U
+#define DT_MERGE_FOR_INSERT 16U
+#define DT_CREATE 32U
+#define DT_FILL 64U
+#define DT_REINIT 128U
+#define DT_PHASES 8U
+/* Phases that are applicable to all derived tables. */
+#define DT_COMMON (DT_INIT + DT_PREPARE + DT_REINIT + DT_OPTIMIZE)
+/* Phases that are applicable only to materialized derived tables. */
+#define DT_MATERIALIZE (DT_CREATE + DT_FILL)
+
+#define DT_PHASES_MERGE (DT_COMMON | DT_MERGE | DT_MERGE_FOR_INSERT)
+#define DT_PHASES_MATERIALIZE (DT_COMMON | DT_MATERIALIZE)
+
+#define VIEW_ALGORITHM_UNDEFINED 0
+/* Special value for ALTER VIEW: inherit original algorithm. */
+#define VIEW_ALGORITHM_INHERIT DTYPE_VIEW
+#define VIEW_ALGORITHM_MERGE (DTYPE_VIEW | DTYPE_MERGE)
+#define VIEW_ALGORITHM_TMPTABLE (DTYPE_VIEW | DTYPE_MATERIALIZE)
+
+/*
+ View algorithm values as stored in the FRM. Values differ from in-memory
+ representation for backward compatibility.
+*/
+
+#define VIEW_ALGORITHM_UNDEFINED_FRM 0U
+#define VIEW_ALGORITHM_MERGE_FRM 1U
+#define VIEW_ALGORITHM_TMPTABLE_FRM 2U
+
+#define JOIN_TYPE_LEFT 1U
+#define JOIN_TYPE_RIGHT 2U
+#define JOIN_TYPE_OUTER 4U /* Marker that this is an outer join */
+
+/* view WITH CHECK OPTION parameter options */
+#define VIEW_CHECK_NONE 0
+#define VIEW_CHECK_LOCAL 1
+#define VIEW_CHECK_CASCADED 2
+
+/* result of view WITH CHECK OPTION parameter check */
+#define VIEW_CHECK_OK 0
+#define VIEW_CHECK_ERROR 1
+#define VIEW_CHECK_SKIP 2
+
+/** The threshold size a blob field buffer before it is freed */
+#define MAX_TDC_BLOB_SIZE 65536
+
+/** number of bytes used by field positional indexes in frm */
+constexpr uint frm_fieldno_size= 2;
+/** number of bytes used by key position number in frm */
+constexpr uint frm_keyno_size= 2;
+static inline uint16 read_frm_fieldno(const uchar *data)
+{ return uint2korr(data); }
+static inline void store_frm_fieldno(uchar *data, uint16 fieldno)
+{ int2store(data, fieldno); }
+static inline uint16 read_frm_keyno(const uchar *data)
+{ return uint2korr(data); }
+static inline void store_frm_keyno(uchar *data, uint16 fieldno)
+{ int2store(data, fieldno); }
+static inline size_t extra2_str_size(size_t len)
+{ return (len > 255 ? 3 : 1) + len; }
+
+class select_unit;
+class TMP_TABLE_PARAM;
+
+Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
+ LEX_CSTRING *name);
+
+struct Field_translator
+{
+ Item *item;
+ LEX_CSTRING name;
+};
+
+
+/*
+ Column reference of a NATURAL/USING join. Since column references in
+ joins can be both from views and stored tables, may point to either a
+ Field (for tables), or a Field_translator (for views).
+*/
+
+class Natural_join_column: public Sql_alloc
+{
+public:
+ Field_translator *view_field; /* Column reference of merge view. */
+ Item_field *table_field; /* Column reference of table or temp view. */
+ TABLE_LIST *table_ref; /* Original base table/view reference. */
+ /*
+ True if a common join column of two NATURAL/USING join operands. Notice
+ that when we have a hierarchy of nested NATURAL/USING joins, a column can
+ be common at some level of nesting but it may not be common at higher
+ levels of nesting. Thus this flag may change depending on at which level
+ we are looking at some column.
+ */
+ bool is_common;
+public:
+ Natural_join_column(Field_translator *field_param, TABLE_LIST *tab);
+ Natural_join_column(Item_field *field_param, TABLE_LIST *tab);
+ LEX_CSTRING *name();
+ Item *create_item(THD *thd);
+ Field *field();
+ const char *safe_table_name();
+ const char *safe_db_name();
+ GRANT_INFO *grant();
+};
+
+
+/**
+ Type of table which can be open for an element of table list.
+*/
+
+enum enum_open_type
+{
+ OT_TEMPORARY_OR_BASE= 0, OT_TEMPORARY_ONLY, OT_BASE_ONLY
+};
+
+
+class SJ_MATERIALIZATION_INFO;
+class Index_hint;
+class Item_in_subselect;
+
+/* trivial class, for %union in sql_yacc.yy */
+struct vers_history_point_t
+{
+ vers_kind_t unit;
+ Item *item;
+};
+
+class Vers_history_point : public vers_history_point_t
+{
+ void fix_item();
+
+public:
+ Vers_history_point() { empty(); }
+ Vers_history_point(vers_kind_t unit_arg, Item *item_arg)
+ {
+ unit= unit_arg;
+ item= item_arg;
+ fix_item();
+ }
+ Vers_history_point(vers_history_point_t p)
+ {
+ unit= p.unit;
+ item= p.item;
+ fix_item();
+ }
+ void empty() { unit= VERS_TIMESTAMP; item= NULL; }
+ void print(String *str, enum_query_type, const char *prefix, size_t plen) const;
+ bool check_unit(THD *thd);
+ void bad_expression_data_type_error(const char *type) const;
+ bool eq(const vers_history_point_t &point) const;
+};
+
+struct vers_select_conds_t
+{
+ vers_system_time_t type;
+ vers_system_time_t orig_type;
+ bool used:1;
+ bool delete_history:1;
+ Vers_history_point start;
+ Vers_history_point end;
+ Lex_ident name;
+
+ Item_field *field_start;
+ Item_field *field_end;
+
+ const TABLE_SHARE::period_info_t *period;
+
+ void empty()
+ {
+ type= SYSTEM_TIME_UNSPECIFIED;
+ orig_type= SYSTEM_TIME_UNSPECIFIED;
+ used= false;
+ delete_history= false;
+ start.empty();
+ end.empty();
+ }
+
+ void init(vers_system_time_t _type,
+ Vers_history_point _start= Vers_history_point(),
+ Vers_history_point _end= Vers_history_point(),
+ Lex_ident _name= "SYSTEM_TIME")
+ {
+ type= _type;
+ orig_type= _type;
+ used= false;
+ delete_history= (type == SYSTEM_TIME_HISTORY ||
+ type == SYSTEM_TIME_BEFORE);
+ start= _start;
+ end= _end;
+ name= _name;
+ }
+
+ void set_all()
+ {
+ type= SYSTEM_TIME_ALL;
+ name= "SYSTEM_TIME";
+ }
+
+ void print(String *str, enum_query_type query_type) const;
+
+ bool init_from_sysvar(THD *thd);
+
+ bool is_set() const
+ {
+ return type != SYSTEM_TIME_UNSPECIFIED;
+ }
+ bool check_units(THD *thd);
+ bool was_set() const
+ {
+ return orig_type != SYSTEM_TIME_UNSPECIFIED;
+ }
+ bool need_setup() const
+ {
+ return type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL;
+ }
+ bool eq(const vers_select_conds_t &conds) const;
+};
+
+/*
+ Table reference in the FROM clause.
+
+ These table references can be of several types that correspond to
+ different SQL elements. Below we list all types of TABLE_LISTs with
+ the necessary conditions to determine when a TABLE_LIST instance
+ belongs to a certain type.
+
+ 1) table (TABLE_LIST::view == NULL)
+ - base table
+ (TABLE_LIST::derived == NULL)
+ - FROM-clause subquery - TABLE_LIST::table is a temp table
+ (TABLE_LIST::derived != NULL)
+ - information schema table
+ (TABLE_LIST::schema_table != NULL)
+ NOTICE: for schema tables TABLE_LIST::field_translation may be != NULL
+ 2) view (TABLE_LIST::view != NULL)
+ - merge (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_MERGE)
+ also (TABLE_LIST::field_translation != NULL)
+ - tmptable (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_TMPTABLE)
+ also (TABLE_LIST::field_translation == NULL)
+ 2.5) TODO: Add derived tables description here
+ 3) nested table reference (TABLE_LIST::nested_join != NULL)
+ - table sequence - e.g. (t1, t2, t3)
+ TODO: how to distinguish from a JOIN?
+ - general JOIN
+ TODO: how to distinguish from a table sequence?
+ - NATURAL JOIN
+ (TABLE_LIST::natural_join != NULL)
+ - JOIN ... USING
+ (TABLE_LIST::join_using_fields != NULL)
+ - semi-join nest (sj_on_expr!= NULL && sj_subq_pred!=NULL)
+ 4) jtbm semi-join (jtbm_subselect != NULL)
+*/
+
+/** last_leaf_for_name_resolutioning support. */
+
+struct LEX;
+class Index_hint;
+
+/*
+ @struct TABLE_CHAIN
+ @brief Subchain of global chain of table references
+
+ The structure contains a pointer to the address of the next_global
+ pointer to the first TABLE_LIST objectof the subchain and the address
+ of the next_global pointer to the element right after the last
+ TABLE_LIST object of the subchain. For an empty subchain both pointers
+ have the same value.
+*/
+
+struct TABLE_CHAIN
+{
+ TABLE_CHAIN() {}
+
+ TABLE_LIST **start_pos;
+ TABLE_LIST ** end_pos;
+
+ void set_start_pos(TABLE_LIST **pos) { start_pos= pos; }
+ void set_end_pos(TABLE_LIST **pos) { end_pos= pos; }
+};
+
+struct TABLE_LIST
+{
+ TABLE_LIST() {} /* Remove gcc warning */
+
+ enum prelocking_types
+ {
+ PRELOCK_NONE, PRELOCK_ROUTINE, PRELOCK_FK
+ };
+
+ /**
+ Prepare TABLE_LIST that consists of one table instance to use in
+ open_and_lock_tables
+ */
+ inline void reset() { bzero((void*)this, sizeof(*this)); }
+ inline void init_one_table(const LEX_CSTRING *db_arg,
+ const LEX_CSTRING *table_name_arg,
+ const LEX_CSTRING *alias_arg,
+ enum thr_lock_type lock_type_arg)
+ {
+ enum enum_mdl_type mdl_type;
+ if (lock_type_arg >= TL_WRITE_ALLOW_WRITE)
+ mdl_type= MDL_SHARED_WRITE;
+ else if (lock_type_arg == TL_READ_NO_INSERT)
+ mdl_type= MDL_SHARED_NO_WRITE;
+ else
+ mdl_type= MDL_SHARED_READ;
+
+ reset();
+ DBUG_ASSERT(!db_arg->str || strlen(db_arg->str) == db_arg->length);
+ DBUG_ASSERT(!table_name_arg->str || strlen(table_name_arg->str) == table_name_arg->length);
+ DBUG_ASSERT(!alias_arg || strlen(alias_arg->str) == alias_arg->length);
+ db= *db_arg;
+ table_name= *table_name_arg;
+ alias= (alias_arg ? *alias_arg : *table_name_arg);
+ lock_type= lock_type_arg;
+ updating= lock_type >= TL_WRITE_ALLOW_WRITE;
+ MDL_REQUEST_INIT(&mdl_request, MDL_key::TABLE, db.str, table_name.str,
+ mdl_type, MDL_TRANSACTION);
+ }
+
+ TABLE_LIST(TABLE *table_arg, thr_lock_type lock_type)
+ {
+ DBUG_ASSERT(table_arg->s);
+ init_one_table(&table_arg->s->db, &table_arg->s->table_name,
+ NULL, lock_type);
+ table= table_arg;
+ vers_conditions.name= table->s->vers.name;
+ }
+
+ inline void init_one_table_for_prelocking(const LEX_CSTRING *db_arg,
+ const LEX_CSTRING *table_name_arg,
+ const LEX_CSTRING *alias_arg,
+ enum thr_lock_type lock_type_arg,
+ prelocking_types prelocking_type,
+ TABLE_LIST *belong_to_view_arg,
+ uint8 trg_event_map_arg,
+ TABLE_LIST ***last_ptr,
+ my_bool insert_data)
+
+ {
+ init_one_table(db_arg, table_name_arg, alias_arg, lock_type_arg);
+ cacheable_table= 1;
+ prelocking_placeholder= prelocking_type;
+ open_type= (prelocking_type == PRELOCK_ROUTINE ?
+ OT_TEMPORARY_OR_BASE :
+ OT_BASE_ONLY);
+ belong_to_view= belong_to_view_arg;
+ trg_event_map= trg_event_map_arg;
+ /* MDL is enough for read-only FK checks, we don't need the table */
+ if (prelocking_type == PRELOCK_FK && lock_type < TL_WRITE_ALLOW_WRITE)
+ open_strategy= OPEN_STUB;
+
+ **last_ptr= this;
+ prev_global= *last_ptr;
+ *last_ptr= &next_global;
+ for_insert_data= insert_data;
+ }
+
+
+ /*
+ List of tables local to a subquery (used by SQL_I_List). Considers
+ views as leaves (unlike 'next_leaf' below). Created at parse time
+ in st_select_lex::add_table_to_list() -> table_list.link_in_list().
+ */
+ TABLE_LIST *next_local;
+ /* link in a global list of all queries tables */
+ TABLE_LIST *next_global, **prev_global;
+ LEX_CSTRING db;
+ LEX_CSTRING table_name;
+ LEX_CSTRING schema_table_name;
+ LEX_CSTRING alias;
+ const char *option; /* Used by cache index */
+ Item *on_expr; /* Used with outer join */
+ Name_resolution_context *on_context; /* For ON expressions */
+
+ Item *sj_on_expr;
+ /*
+ (Valid only for semi-join nests) Bitmap of tables that are within the
+ semi-join (this is different from bitmap of all nest's children because
+ tables that were pulled out of the semi-join nest remain listed as
+ nest's children).
+ */
+ table_map sj_inner_tables;
+ /* Number of IN-compared expressions */
+ uint sj_in_exprs;
+
+ /* If this is a non-jtbm semi-join nest: corresponding subselect predicate */
+ Item_in_subselect *sj_subq_pred;
+
+ table_map original_subq_pred_used_tables;
+
+ /* If this is a jtbm semi-join object: corresponding subselect predicate */
+ Item_in_subselect *jtbm_subselect;
+ /* TODO: check if this can be joined with tablenr_exec */
+ uint jtbm_table_no;
+
+ SJ_MATERIALIZATION_INFO *sj_mat_info;
+
+ /*
+ The structure of ON expression presented in the member above
+ can be changed during certain optimizations. This member
+ contains a snapshot of AND-OR structure of the ON expression
+ made after permanent transformations of the parse tree, and is
+ used to restore ON clause before every reexecution of a prepared
+ statement or stored procedure.
+ */
+ Item *prep_on_expr;
+ COND_EQUAL *cond_equal; /* Used with outer join */
+ /*
+ During parsing - left operand of NATURAL/USING join where 'this' is
+ the right operand. After parsing (this->natural_join == this) iff
+ 'this' represents a NATURAL or USING join operation. Thus after
+ parsing 'this' is a NATURAL/USING join iff (natural_join != NULL).
+ */
+ TABLE_LIST *natural_join;
+ /*
+ True if 'this' represents a nested join that is a NATURAL JOIN.
+ For one of the operands of 'this', the member 'natural_join' points
+ to the other operand of 'this'.
+ */
+ bool is_natural_join;
+ /* Field names in a USING clause for JOIN ... USING. */
+ List<String> *join_using_fields;
+ /*
+ Explicitly store the result columns of either a NATURAL/USING join or
+ an operand of such a join.
+ */
+ List<Natural_join_column> *join_columns;
+ /* TRUE if join_columns contains all columns of this table reference. */
+ bool is_join_columns_complete;
+
+ /*
+ List of nodes in a nested join tree, that should be considered as
+ leaves with respect to name resolution. The leaves are: views,
+ top-most nodes representing NATURAL/USING joins, subqueries, and
+ base tables. All of these TABLE_LIST instances contain a
+ materialized list of columns. The list is local to a subquery.
+ */
+ TABLE_LIST *next_name_resolution_table;
+ /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */
+ List<Index_hint> *index_hints;
+ TABLE *table; /* opened table */
+ ulonglong table_id; /* table id (from binlog) for opened table */
+ /*
+ select_result for derived table to pass it from table creation to table
+ filling procedure
+ */
+ select_unit *derived_result;
+ /* Stub used for materialized derived tables. */
+ table_map map; /* ID bit of table (1,2,4,8,16...) */
+ table_map get_map()
+ {
+ return jtbm_subselect? table_map(1) << jtbm_table_no : table->map;
+ }
+ uint get_tablenr()
+ {
+ return jtbm_subselect? jtbm_table_no : table->tablenr;
+ }
+ void set_tablenr(uint new_tablenr)
+ {
+ if (jtbm_subselect)
+ {
+ jtbm_table_no= new_tablenr;
+ }
+ if (table)
+ {
+ table->tablenr= new_tablenr;
+ table->map= table_map(1) << new_tablenr;
+ }
+ }
+ /*
+ Reference from aux_tables to local list entry of main select of
+ multi-delete statement:
+ delete t1 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+ here it will be reference of first occurrence of t1 to second (as you
+ can see this lists can't be merged)
+ */
+ TABLE_LIST *correspondent_table;
+ /**
+ @brief Normally, this field is non-null for anonymous derived tables only.
+
+ @details This field is set to non-null for
+
+ - Anonymous derived tables, In this case it points to the SELECT_LEX_UNIT
+ representing the derived table. E.g. for a query
+
+ @verbatim SELECT * FROM (SELECT a FROM t1) b @endverbatim
+
+ For the @c TABLE_LIST representing the derived table @c b, @c derived
+ points to the SELECT_LEX_UNIT representing the result of the query within
+ parenteses.
+
+ - Views. This is set for views with @verbatim ALGORITHM = TEMPTABLE
+ @endverbatim by mysql_make_view().
+
+ @note Inside views, a subquery in the @c FROM clause is not allowed.
+ @note Do not use this field to separate views/base tables/anonymous
+ derived tables. Use TABLE_LIST::is_anonymous_derived_table().
+ */
+ st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
+ With_element *with; /* With element defining this table (if any) */
+ /* Bitmap of the defining with element */
+ table_map with_internal_reference_map;
+ TABLE_LIST * next_with_rec_ref;
+ bool is_derived_with_recursive_reference;
+ bool block_handle_derived;
+ /* The interface employed to materialize the table by a foreign engine */
+ derived_handler *dt_handler;
+ /* The text of the query specifying the derived table */
+ LEX_CSTRING derived_spec;
+ /*
+ The object used to organize execution of the query that specifies
+ the derived table by a foreign engine
+ */
+ Pushdown_derived *pushdown_derived;
+ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
+ st_select_lex *schema_select_lex;
+ /*
+ True when the view field translation table is used to convert
+ schema table fields for backwards compatibility with SHOW command.
+ */
+ bool schema_table_reformed;
+ TMP_TABLE_PARAM *schema_table_param;
+ /* link to select_lex where this table was used */
+ st_select_lex *select_lex;
+ LEX *view; /* link on VIEW lex for merging */
+ Field_translator *field_translation; /* array of VIEW fields */
+ /* pointer to element after last one in translation table above */
+ Field_translator *field_translation_end;
+ bool field_translation_updated;
+ /*
+ List (based on next_local) of underlying tables of this view. I.e. it
+ does not include the tables of subqueries used in the view. Is set only
+ for merged views.
+ */
+ TABLE_LIST *merge_underlying_list;
+ /*
+ - 0 for base tables
+ - in case of the view it is the list of all (not only underlying
+ tables but also used in subquery ones) tables of the view.
+ */
+ List<TABLE_LIST> *view_tables;
+ /* most upper view this table belongs to */
+ TABLE_LIST *belong_to_view;
+ /* A derived table this table belongs to */
+ TABLE_LIST *belong_to_derived;
+ /*
+ The view directly referencing this table
+ (non-zero only for merged underlying tables of a view).
+ */
+ TABLE_LIST *referencing_view;
+
+ table_map view_used_tables;
+ table_map map_exec;
+ /* TODO: check if this can be joined with jtbm_table_no */
+ uint tablenr_exec;
+ uint maybe_null_exec;
+
+ /* Ptr to parent MERGE table list item. See top comment in ha_myisammrg.cc */
+ TABLE_LIST *parent_l;
+ /*
+ Security context (non-zero only for tables which belong
+ to view with SQL SECURITY DEFINER)
+ */
+ Security_context *security_ctx;
+ /*
+ This view security context (non-zero only for views with
+ SQL SECURITY DEFINER)
+ */
+ Security_context *view_sctx;
+ bool allowed_show;
+ Item *where; /* VIEW WHERE clause condition */
+ Item *check_option; /* WITH CHECK OPTION condition */
+ LEX_STRING select_stmt; /* text of (CREATE/SELECT) statement */
+ LEX_CSTRING md5; /* md5 of query text */
+ LEX_CSTRING source; /* source of CREATE VIEW */
+ LEX_CSTRING view_db; /* saved view database */
+ LEX_CSTRING view_name; /* saved view name */
+ LEX_STRING timestamp; /* GMT time stamp of last operation */
+ LEX_USER definer; /* definer of view */
+ ulonglong file_version; /* version of file's field set */
+ ulonglong mariadb_version; /* version of server on creation */
+ ulonglong updatable_view; /* VIEW can be updated */
+ /**
+ @brief The declared algorithm, if this is a view.
+ @details One of
+ - VIEW_ALGORITHM_UNDEFINED
+ - VIEW_ALGORITHM_TMPTABLE
+ - VIEW_ALGORITHM_MERGE
+ @to do Replace with an enum
+ */
+ ulonglong algorithm;
+ ulonglong view_suid; /* view is suid (TRUE dy default) */
+ ulonglong with_check; /* WITH CHECK OPTION */
+ /*
+ effective value of WITH CHECK OPTION (differ for temporary table
+ algorithm)
+ */
+ uint8 effective_with_check;
+ /**
+ @brief The view algorithm that is actually used, if this is a view.
+ @details One of
+ - VIEW_ALGORITHM_UNDEFINED
+ - VIEW_ALGORITHM_TMPTABLE
+ - VIEW_ALGORITHM_MERGE
+ @to do Replace with an enum
+ */
+ uint8 derived_type;
+ GRANT_INFO grant;
+ /* data need by some engines in query cache*/
+ ulonglong engine_data;
+ /* call back function for asking handler about caching in query cache */
+ qc_engine_callback callback_func;
+ thr_lock_type lock_type;
+
+ /*
+ Two fields below are set during parsing this table reference in the cases
+ when the table reference can be potentially a reference to a CTE table.
+ In this cases the fact that the reference is a reference to a CTE or not
+ will be ascertained at the very end of parsing of the query when referencies
+ to CTE are resolved. For references to CTE and to derived tables no mdl
+ requests are needed while for other table references they are. If a request
+ is possibly postponed the info that allows to issue this request must be
+ saved in 'mdl_type' and 'table_options'.
+ */
+ enum_mdl_type mdl_type;
+ ulong table_options;
+
+ uint outer_join; /* Which join type */
+ uint shared; /* Used in multi-upd */
+ bool updatable; /* VIEW/TABLE can be updated now */
+ bool straight; /* optimize with prev table */
+ bool updating; /* for replicate-do/ignore table */
+ bool force_index; /* prefer index over table scan */
+ bool ignore_leaves; /* preload only non-leaf nodes */
+ bool crashed; /* Table was found crashed */
+ table_map dep_tables; /* tables the table depends on */
+ table_map on_expr_dep_tables; /* tables on expression depends on */
+ struct st_nested_join *nested_join; /* if the element is a nested join */
+ TABLE_LIST *embedding; /* nested join containing the table */
+ List<TABLE_LIST> *join_list;/* join list the table belongs to */
+ bool lifted; /* set to true when the table is moved to
+ the upper level at the parsing stage */
+ bool cacheable_table; /* stop PS caching */
+ /* used in multi-upd/views privilege check */
+ bool table_in_first_from_clause;
+ /**
+ Specifies which kind of table should be open for this element
+ of table list.
+ */
+ enum enum_open_type open_type;
+ /* TRUE if this merged view contain auto_increment field */
+ bool contain_auto_increment;
+ bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */
+ /* view where processed */
+ bool where_processed;
+ /* TRUE <=> VIEW CHECK OPTION expression has been processed */
+ bool check_option_processed;
+ /* TABLE_TYPE_UNKNOWN if any type is acceptable */
+ Table_type required_type;
+ handlerton *db_type; /* table_type for handler */
+ char timestamp_buffer[MAX_DATETIME_WIDTH + 1];
+ /*
+ This TABLE_LIST object is just placeholder for prelocking, it will be
+ used for implicit LOCK TABLES only and won't be used in real statement.
+ */
+ prelocking_types prelocking_placeholder;
+ /**
+ Indicates that if TABLE_LIST object corresponds to the table/view
+ which requires special handling.
+ */
+ enum enum_open_strategy
+ {
+ /* Normal open. */
+ OPEN_NORMAL= 0,
+ /* Associate a table share only if the the table exists. */
+ OPEN_IF_EXISTS,
+ /* Don't associate a table share. */
+ OPEN_STUB
+ } open_strategy;
+ /** TRUE if an alias for this table was specified in the SQL. */
+ bool is_alias;
+ /** TRUE if the table is referred to in the statement using a fully
+ qualified name (<db_name>.<table_name>).
+ */
+ bool is_fqtn;
+
+ /* TRUE <=> derived table should be filled right after optimization. */
+ bool fill_me;
+ /* TRUE <=> view/DT is merged. */
+ /* TODO: replace with derived_type */
+ bool merged;
+ bool merged_for_insert;
+ bool sequence; /* Part of NEXTVAL/CURVAL/LASTVAL */
+
+ /*
+ Items created by create_view_field and collected to change them in case
+ of materialization of the view/derived table
+ */
+ List<Item> used_items;
+ /* Sublist (tail) of persistent used_items */
+ List<Item> persistent_used_items;
+
+ /* View creation context. */
+
+ View_creation_ctx *view_creation_ctx;
+
+ /*
+ Attributes to save/load view creation context in/from frm-file.
+
+ Ther are required only to be able to use existing parser to load
+ view-definition file. As soon as the parser parsed the file, view
+ creation context is initialized and the attributes become redundant.
+
+ These attributes MUST NOT be used for any purposes but the parsing.
+ */
+
+ LEX_CSTRING view_client_cs_name;
+ LEX_CSTRING view_connection_cl_name;
+
+ /*
+ View definition (SELECT-statement) in the UTF-form.
+ */
+
+ LEX_CSTRING view_body_utf8;
+
+ /* End of view definition context. */
+
+ /**
+ Indicates what triggers we need to pre-load for this TABLE_LIST
+ when opening an associated TABLE. This is filled after
+ the parsed tree is created.
+
+ slave_fk_event_map is filled on the slave side with bitmaps value
+ representing row-based event operation to help find and prelock
+ possible FK constrain-related child tables.
+ */
+ uint8 trg_event_map, slave_fk_event_map;
+ /* TRUE <=> this table is a const one and was optimized away. */
+ bool optimized_away;
+
+ /**
+ TRUE <=> already materialized. Valid only for materialized derived
+ tables/views.
+ */
+ bool materialized;
+ /* I_S: Flags to open_table (e.g. OPEN_TABLE_ONLY or OPEN_VIEW_ONLY) */
+ uint i_s_requested_object;
+
+ bool prohibit_cond_pushdown;
+
+ /*
+ I_S: how to read the tables (SKIP_OPEN_TABLE/OPEN_FRM_ONLY/OPEN_FULL_TABLE)
+ */
+ uint table_open_method;
+ /*
+ I_S: where the schema table was filled
+ (this is a hack. The code should be able to figure out whether reading
+ from I_S should be done by create_sort_index() or by JOIN::exec.)
+ */
+ enum enum_schema_table_state schema_table_state;
+
+ /* Something like a "query plan" for reading INFORMATION_SCHEMA table */
+ IS_table_read_plan *is_table_read_plan;
+
+ MDL_request mdl_request;
+
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ /* List to carry partition names from PARTITION (...) clause in statement */
+ List<String> *partition_names;
+#endif /* WITH_PARTITION_STORAGE_ENGINE */
+
+ void calc_md5(const char *buffer);
+ int view_check_option(THD *thd, bool ignore_failure);
+ bool create_field_translation(THD *thd);
+ bool setup_underlying(THD *thd);
+ void cleanup_items();
+ bool placeholder()
+ {
+ return derived || view || schema_table || !table;
+ }
+ void print(THD *thd, table_map eliminated_tables, String *str,
+ enum_query_type query_type);
+ bool check_single_table(TABLE_LIST **table, table_map map,
+ TABLE_LIST *view);
+ bool set_insert_values(MEM_ROOT *mem_root);
+ void hide_view_error(THD *thd);
+ TABLE_LIST *find_underlying_table(TABLE *table);
+ TABLE_LIST *first_leaf_for_name_resolution();
+ TABLE_LIST *last_leaf_for_name_resolution();
+
+ /* System Versioning */
+ vers_select_conds_t vers_conditions;
+ vers_select_conds_t period_conditions;
+
+ bool has_period() const
+ {
+ return period_conditions.is_set();
+ }
+
+ my_bool for_insert_data;
+
+ /**
+ @brief
+ Find the bottom in the chain of embedded table VIEWs.
+
+ @detail
+ This is used for single-table UPDATE/DELETE when they are modifying a
+ single-table VIEW.
+ */
+ TABLE_LIST *find_table_for_update()
+ {
+ TABLE_LIST *tbl= this;
+ while(!tbl->is_multitable() && tbl->single_table_updatable() &&
+ tbl->merge_underlying_list)
+ {
+ tbl= tbl->merge_underlying_list;
+ }
+ return tbl;
+ }
+ TABLE *get_real_join_table();
+ bool is_leaf_for_name_resolution();
+ inline TABLE_LIST *top_table()
+ { return belong_to_view ? belong_to_view : this; }
+ inline bool prepare_check_option(THD *thd)
+ {
+ bool res= FALSE;
+ if (effective_with_check)
+ res= prep_check_option(thd, effective_with_check);
+ return res;
+ }
+ inline bool prepare_where(THD *thd, Item **conds,
+ bool no_where_clause)
+ {
+ if (!view || is_merged_derived())
+ return prep_where(thd, conds, no_where_clause);
+ return FALSE;
+ }
+
+ void register_want_access(privilege_t want_access);
+ bool prepare_security(THD *thd);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ Security_context *find_view_security_context(THD *thd);
+ bool prepare_view_security_context(THD *thd);
+#endif
+ /*
+ Cleanup for re-execution in a prepared statement or a stored
+ procedure.
+ */
+ void reinit_before_use(THD *thd);
+ Item_subselect *containing_subselect();
+
+ /*
+ Compiles the tagged hints list and fills up TABLE::keys_in_use_for_query,
+ TABLE::keys_in_use_for_group_by, TABLE::keys_in_use_for_order_by,
+ TABLE::force_index and TABLE::covering_keys.
+ */
+ bool process_index_hints(TABLE *table);
+
+ /**
+ Compare the version of metadata from the previous execution
+ (if any) with values obtained from the current table
+ definition cache element.
+
+ @sa check_and_update_table_version()
+ */
+ inline bool is_table_ref_id_equal(TABLE_SHARE *s) const
+ {
+ return (m_table_ref_type == s->get_table_ref_type() &&
+ m_table_ref_version == s->get_table_ref_version());
+ }
+
+ /**
+ Record the value of metadata version of the corresponding
+ table definition cache element in this parse tree node.
+
+ @sa check_and_update_table_version()
+ */
+ inline void set_table_ref_id(TABLE_SHARE *s)
+ { set_table_ref_id(s->get_table_ref_type(), s->get_table_ref_version()); }
+
+ inline void set_table_ref_id(enum_table_ref_type table_ref_type_arg,
+ ulong table_ref_version_arg)
+ {
+ m_table_ref_type= table_ref_type_arg;
+ m_table_ref_version= table_ref_version_arg;
+ }
+
+ /* Set of functions returning/setting state of a derived table/view. */
+ bool is_non_derived() const { return (!derived_type); }
+ bool is_view_or_derived() const { return derived_type; }
+ bool is_view() const { return (derived_type & DTYPE_VIEW); }
+ bool is_derived() const { return (derived_type & DTYPE_TABLE); }
+ bool is_with_table();
+ bool is_recursive_with_table();
+ bool is_with_table_recursive_reference();
+ void register_as_derived_with_rec_ref(With_element *rec_elem);
+ bool is_nonrecursive_derived_with_rec_ref();
+ bool fill_recursive(THD *thd);
+
+ inline void set_view()
+ {
+ derived_type= DTYPE_VIEW;
+ }
+ inline void set_derived()
+ {
+ derived_type= DTYPE_TABLE;
+ }
+ bool is_merged_derived() const { return (derived_type & DTYPE_MERGE); }
+ inline void set_merged_derived()
+ {
+ DBUG_ENTER("set_merged_derived");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (alias.str ? alias.str : "<NULL>"),
+ get_unit()));
+ derived_type= static_cast<uint8>((derived_type & DTYPE_MASK) |
+ DTYPE_TABLE | DTYPE_MERGE);
+ set_check_merged();
+ DBUG_VOID_RETURN;
+ }
+ bool is_materialized_derived() const
+ {
+ return (derived_type & DTYPE_MATERIALIZE);
+ }
+ void set_materialized_derived()
+ {
+ DBUG_ENTER("set_materialized_derived");
+ DBUG_PRINT("enter", ("Alias: '%s' Unit: %p",
+ (alias.str ? alias.str : "<NULL>"),
+ get_unit()));
+ derived= get_unit();
+ derived_type= static_cast<uint8>((derived_type &
+ (derived ? DTYPE_MASK : DTYPE_VIEW)) |
+ DTYPE_TABLE | DTYPE_MATERIALIZE);
+ set_check_materialized();
+ DBUG_VOID_RETURN;
+ }
+ bool is_multitable() const { return (derived_type & DTYPE_MULTITABLE); }
+ inline void set_multitable()
+ {
+ derived_type|= DTYPE_MULTITABLE;
+ }
+ bool set_as_with_table(THD *thd, With_element *with_elem);
+ void reset_const_table();
+ bool handle_derived(LEX *lex, uint phases);
+
+ /**
+ @brief True if this TABLE_LIST represents an anonymous derived table,
+ i.e. the result of a subquery.
+ */
+ bool is_anonymous_derived_table() const { return derived && !view; }
+
+ /**
+ @brief Returns the name of the database that the referenced table belongs
+ to.
+ */
+ const char *get_db_name() const { return view != NULL ? view_db.str : db.str; }
+
+ /**
+ @brief Returns the name of the table that this TABLE_LIST represents.
+
+ @details The unqualified table name or view name for a table or view,
+ respectively.
+ */
+ const char *get_table_name() const { return view != NULL ? view_name.str : table_name.str; }
+ bool is_active_sjm();
+ bool is_jtbm() { return MY_TEST(jtbm_subselect != NULL); }
+ st_select_lex_unit *get_unit();
+ st_select_lex *get_single_select();
+ void wrap_into_nested_join(List<TABLE_LIST> &join_list);
+ bool init_derived(THD *thd, bool init_view);
+ int fetch_number_of_rows();
+ bool change_refs_to_fields();
+
+ bool single_table_updatable();
+
+ bool is_inner_table_of_outer_join()
+ {
+ for (TABLE_LIST *tbl= this; tbl; tbl= tbl->embedding)
+ {
+ if (tbl->outer_join)
+ return true;
+ }
+ return false;
+ }
+ void set_lock_type(THD* thd, enum thr_lock_type lock);
+
+ derived_handler *find_derived_handler(THD *thd);
+ TABLE_LIST *get_first_table();
+
+ void remove_join_columns()
+ {
+ if (join_columns)
+ {
+ join_columns->empty();
+ join_columns= NULL;
+ is_join_columns_complete= FALSE;
+ }
+ }
+
+private:
+ bool prep_check_option(THD *thd, uint8 check_opt_type);
+ bool prep_where(THD *thd, Item **conds, bool no_where_clause);
+ void set_check_materialized();
+#ifndef DBUG_OFF
+ void set_check_merged();
+#else
+ inline void set_check_merged() {}
+#endif
+ /** See comments for set_table_ref_id() */
+ enum enum_table_ref_type m_table_ref_type;
+ /** See comments for set_table_ref_id() */
+ ulong m_table_ref_version;
+};
+
+class Item;
+
+/*
+ Iterator over the fields of a generic table reference.
+*/
+
+class Field_iterator: public Sql_alloc
+{
+public:
+ Field_iterator() {} /* Remove gcc warning */
+ virtual ~Field_iterator() {}
+ virtual void set(TABLE_LIST *)= 0;
+ virtual void next()= 0;
+ virtual bool end_of_fields()= 0; /* Return 1 at end of list */
+ virtual LEX_CSTRING *name()= 0;
+ virtual Item *create_item(THD *)= 0;
+ virtual Field *field()= 0;
+};
+
+
+/*
+ Iterator over the fields of a base table, view with temporary
+ table, or subquery.
+*/
+
+class Field_iterator_table: public Field_iterator
+{
+ Field **ptr;
+public:
+ Field_iterator_table() :ptr(0) {}
+ void set(TABLE_LIST *table) { ptr= table->table->field; }
+ void set_table(TABLE *table) { ptr= table->field; }
+ void next() { ptr++; }
+ bool end_of_fields() { return *ptr == 0; }
+ LEX_CSTRING *name();
+ Item *create_item(THD *thd);
+ Field *field() { return *ptr; }
+};
+
+
+/* Iterator over the fields of a merge view. */
+
+class Field_iterator_view: public Field_iterator
+{
+ Field_translator *ptr, *array_end;
+ TABLE_LIST *view;
+public:
+ Field_iterator_view() :ptr(0), array_end(0) {}
+ void set(TABLE_LIST *table);
+ void next() { ptr++; }
+ bool end_of_fields() { return ptr == array_end; }
+ LEX_CSTRING *name();
+ Item *create_item(THD *thd);
+ Item **item_ptr() {return &ptr->item; }
+ Field *field() { return 0; }
+ inline Item *item() { return ptr->item; }
+ Field_translator *field_translator() { return ptr; }
+};
+
+
+/*
+ Field_iterator interface to the list of materialized fields of a
+ NATURAL/USING join.
+*/
+
+class Field_iterator_natural_join: public Field_iterator
+{
+ List_iterator_fast<Natural_join_column> column_ref_it;
+ Natural_join_column *cur_column_ref;
+public:
+ Field_iterator_natural_join() :cur_column_ref(NULL) {}
+ ~Field_iterator_natural_join() {}
+ void set(TABLE_LIST *table);
+ void next();
+ bool end_of_fields() { return !cur_column_ref; }
+ LEX_CSTRING *name() { return cur_column_ref->name(); }
+ Item *create_item(THD *thd) { return cur_column_ref->create_item(thd); }
+ Field *field() { return cur_column_ref->field(); }
+ Natural_join_column *column_ref() { return cur_column_ref; }
+};
+
+
+/*
+ Generic iterator over the fields of an arbitrary table reference.
+
+ DESCRIPTION
+ This class unifies the various ways of iterating over the columns
+ of a table reference depending on the type of SQL entity it
+ represents. If such an entity represents a nested table reference,
+ this iterator encapsulates the iteration over the columns of the
+ members of the table reference.
+
+ IMPLEMENTATION
+ The implementation assumes that all underlying NATURAL/USING table
+ references already contain their result columns and are linked into
+ the list TABLE_LIST::next_name_resolution_table.
+*/
+
+class Field_iterator_table_ref: public Field_iterator
+{
+ TABLE_LIST *table_ref, *first_leaf, *last_leaf;
+ Field_iterator_table table_field_it;
+ Field_iterator_view view_field_it;
+ Field_iterator_natural_join natural_join_it;
+ Field_iterator *field_it;
+ void set_field_iterator();
+public:
+ Field_iterator_table_ref() :field_it(NULL) {}
+ void set(TABLE_LIST *table);
+ void next();
+ bool end_of_fields()
+ { return (table_ref == last_leaf && field_it->end_of_fields()); }
+ LEX_CSTRING *name() { return field_it->name(); }
+ const char *get_table_name();
+ const char *get_db_name();
+ GRANT_INFO *grant();
+ Item *create_item(THD *thd) { return field_it->create_item(thd); }
+ Field *field() { return field_it->field(); }
+ Natural_join_column *get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref);
+ Natural_join_column *get_natural_column_ref();
+};
+
+
+#define JOIN_OP_NEST 1
+#define REBALANCED_NEST 2
+
+typedef struct st_nested_join
+{
+ List<TABLE_LIST> join_list; /* list of elements in the nested join */
+ /*
+ Currently the valid values for nest type are:
+ JOIN_OP_NEST - for nest created for JOIN operation used as an operand in
+ a join expression, contains 2 elements;
+ JOIN_OP_NEST | REBALANCED_NEST - nest created after tree re-balancing
+ in st_select_lex::add_cross_joined_table(), contains 1 element;
+ 0 - for all other nests.
+ Examples:
+ 1. SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a;
+ Here the nest created for LEFT JOIN at first has nest_type==JOIN_OP_NEST.
+ After re-balancing in st_select_lex::add_cross_joined_table() this nest
+ has nest_type==JOIN_OP_NEST | REBALANCED_NEST. The nest for JOIN created
+ in st_select_lex::add_cross_joined_table() has nest_type== JOIN_OP_NEST.
+ 2. SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a)
+ Here the nest created for LEFT JOIN has nest_type==0, because it's not
+ an operand in a join expression. The nest created for JOIN has nest_type
+ set to JOIN_OP_NEST.
+ */
+ uint nest_type;
+ /*
+ Bitmap of tables within this nested join (including those embedded within
+ its children), including tables removed by table elimination.
+ */
+ table_map used_tables;
+ table_map not_null_tables; /* tables that rejects nulls */
+ /**
+ Used for pointing out the first table in the plan being covered by this
+ join nest. It is used exclusively within make_outerjoin_info().
+ */
+ struct st_join_table *first_nested;
+ /*
+ Used to count tables in the nested join in 2 isolated places:
+ 1. In make_outerjoin_info().
+ 2. check_interleaving_with_nj/restore_prev_nj_state (these are called
+ by the join optimizer.
+ Before each use the counters are zeroed by reset_nj_counters.
+ */
+ uint counter;
+
+ /*
+ Number of elements in join_list that participate in the join plan choice:
+ - Base tables that were not removed by table elimination
+ - Join nests that were not removed by mark_join_nest_as_const
+ */
+ uint n_tables;
+ nested_join_map nj_map; /* Bit used to identify this nested join*/
+ /*
+ (Valid only for semi-join nests) Bitmap of tables outside the semi-join
+ that are used within the semi-join's ON condition.
+ */
+ table_map sj_depends_on;
+ /* Outer non-trivially correlated tables */
+ table_map sj_corr_tables;
+ List<Item_ptr> sj_outer_expr_list;
+ /**
+ True if this join nest node is completely covered by the query execution
+ plan. This means two things.
+
+ 1. All tables on its @c join_list are covered by the plan.
+
+ 2. All child join nest nodes are fully covered.
+ */
+ bool is_fully_covered() const { return n_tables == counter; }
+} NESTED_JOIN;
+
+
+typedef struct st_changed_table_list
+{
+ struct st_changed_table_list *next;
+ char *key;
+ size_t key_length;
+} CHANGED_TABLE_LIST;
+
+
+typedef struct st_open_table_list{
+ struct st_open_table_list *next;
+ char *db,*table;
+ uint32 in_use,locked;
+} OPEN_TABLE_LIST;
+
+
+static inline MY_BITMAP *tmp_use_all_columns(TABLE *table,
+ MY_BITMAP **bitmap)
+{
+ MY_BITMAP *old= *bitmap;
+ *bitmap= &table->s->all_set;
+ return old;
+}
+
+
+static inline void tmp_restore_column_map(MY_BITMAP **bitmap,
+ MY_BITMAP *old)
+{
+ *bitmap= old;
+}
+
+/* The following is only needed for debugging */
+
+static inline MY_BITMAP *dbug_tmp_use_all_columns(TABLE *table,
+ MY_BITMAP **bitmap)
+{
+#ifdef DBUG_ASSERT_EXISTS
+ return tmp_use_all_columns(table, bitmap);
+#else
+ return 0;
+#endif
+}
+
+static inline void dbug_tmp_restore_column_map(MY_BITMAP **bitmap,
+ MY_BITMAP *old)
+{
+#ifdef DBUG_ASSERT_EXISTS
+ tmp_restore_column_map(bitmap, old);
+#endif
+}
+
+
+/*
+ Variant of the above : handle both read and write sets.
+ Provide for the possiblity of the read set being the same as the write set
+*/
+static inline void dbug_tmp_use_all_columns(TABLE *table,
+ MY_BITMAP **save,
+ MY_BITMAP **read_set,
+ MY_BITMAP **write_set)
+{
+#ifdef DBUG_ASSERT_EXISTS
+ save[0]= *read_set;
+ save[1]= *write_set;
+ (void) tmp_use_all_columns(table, read_set);
+ (void) tmp_use_all_columns(table, write_set);
+#endif
+}
+
+
+static inline void dbug_tmp_restore_column_maps(MY_BITMAP **read_set,
+ MY_BITMAP **write_set,
+ MY_BITMAP **old)
+{
+#ifdef DBUG_ASSERT_EXISTS
+ tmp_restore_column_map(read_set, old[0]);
+ tmp_restore_column_map(write_set, old[1]);
+#endif
+}
+
+bool ok_for_lower_case_names(const char *names);
+
+enum get_table_share_flags {
+ GTS_TABLE = 1,
+ GTS_VIEW = 2,
+ GTS_NOLOCK = 4,
+ GTS_USE_DISCOVERY = 8,
+ GTS_FORCE_DISCOVERY = 16
+};
+
+size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data);
+
+void init_mdl_requests(TABLE_LIST *table_list);
+
+enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
+ const LEX_CSTRING *alias, uint db_stat, uint prgflag,
+ uint ha_open_flags, TABLE *outparam,
+ bool is_create_table,
+ List<String> *partitions_to_open= NULL);
+bool copy_keys_from_share(TABLE *outparam, MEM_ROOT *root);
+bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol);
+bool fix_session_vcol_expr_for_read(THD *thd, Field *field,
+ Virtual_column_info *vcol);
+bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
+ bool *error_reported, vcol_init_mode expr);
+TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
+ const char *key, uint key_length);
+void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
+ uint key_length,
+ const char *table_name, const char *path);
+void free_table_share(TABLE_SHARE *share);
+enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share,
+ uint flags = GTS_TABLE);
+
+void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
+ int db_errno);
+void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form);
+bool check_db_name(LEX_STRING *db);
+bool check_column_name(const char *name);
+bool check_table_name(const char *name, size_t length, bool check_for_path_chars);
+int rename_file_ext(const char * from,const char * to,const char * ext);
+char *get_field(MEM_ROOT *mem, Field *field);
+bool get_field(MEM_ROOT *mem, Field *field, class String *res);
+
+bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
+ uint err_code, const char *name);
+
+int closefrm(TABLE *table);
+void free_blobs(TABLE *table);
+void free_field_buffers_larger_than(TABLE *table, uint32 size);
+ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
+void append_unescaped(String *res, const char *pos, size_t length);
+void prepare_frm_header(THD *thd, uint reclength, uchar *fileinfo,
+ HA_CREATE_INFO *create_info, uint keys, KEY *key_info);
+const char *fn_frm_ext(const char *name);
+
+/* Check that the integer is in the internal */
+static inline int set_zone(int nr,int min_zone,int max_zone)
+{
+ if (nr <= min_zone)
+ return min_zone;
+ if (nr >= max_zone)
+ return max_zone;
+ return nr;
+}
+
+/* performance schema */
+extern LEX_CSTRING PERFORMANCE_SCHEMA_DB_NAME;
+
+extern LEX_CSTRING GENERAL_LOG_NAME;
+extern LEX_CSTRING SLOW_LOG_NAME;
+extern LEX_CSTRING TRANSACTION_REG_NAME;
+
+/* information schema */
+extern LEX_CSTRING INFORMATION_SCHEMA_NAME;
+extern LEX_CSTRING MYSQL_SCHEMA_NAME;
+
+/* table names */
+extern LEX_CSTRING MYSQL_PROC_NAME;
+
+inline bool is_infoschema_db(const LEX_CSTRING *name)
+{
+ return lex_string_eq(&INFORMATION_SCHEMA_NAME, name);
+}
+
+inline bool is_perfschema_db(const LEX_CSTRING *name)
+{
+ return lex_string_eq(&PERFORMANCE_SCHEMA_DB_NAME, name);
+}
+
+inline void mark_as_null_row(TABLE *table)
+{
+ table->null_row=1;
+ table->status|=STATUS_NULL_ROW;
+ if (table->s->null_bytes)
+ bfill(table->null_flags,table->s->null_bytes,255);
+}
+
+inline void unmark_as_null_row(TABLE *table)
+{
+ table->null_row=0;
+ table->status= STATUS_NO_RECORD;
+}
+
+bool is_simple_order(ORDER *order);
+
+class Open_tables_backup;
+
+/** Transaction Registry Table (TRT)
+
+ This table holds transaction IDs, their corresponding times and other
+ transaction-related data which is used for transaction order resolution.
+ When versioned table marks its records lifetime with transaction IDs,
+ TRT is used to get their actual timestamps. */
+
+class TR_table: public TABLE_LIST
+{
+ THD *thd;
+ Open_tables_backup *open_tables_backup;
+
+public:
+ enum field_id_t {
+ FLD_TRX_ID= 0,
+ FLD_COMMIT_ID,
+ FLD_BEGIN_TS,
+ FLD_COMMIT_TS,
+ FLD_ISO_LEVEL,
+ FIELD_COUNT
+ };
+
+ enum enabled {NO, MAYBE, YES};
+ static enum enabled use_transaction_registry;
+
+ /**
+ @param[in,out] Thread handle
+ @param[in] Current transaction is read-write.
+ */
+ TR_table(THD *_thd, bool rw= false);
+ /**
+ Opens a transaction_registry table.
+
+ @retval true on error, false otherwise.
+ */
+ bool open();
+ ~TR_table();
+ /**
+ @retval current thd
+ */
+ THD *get_thd() const { return thd; }
+ /**
+ Stores value to internal transaction_registry TABLE object.
+
+ @param[in] field number in a TABLE
+ @param[in] value to store
+ */
+ void store(uint field_id, ulonglong val);
+ /**
+ Stores value to internal transaction_registry TABLE object.
+
+ @param[in] field number in a TABLE
+ @param[in] value to store
+ */
+ void store(uint field_id, timeval ts);
+ /**
+ Update the transaction_registry right before commit.
+ @param start_id transaction identifier at start
+ @param end_id transaction identifier at commit
+
+ @retval false on success
+ @retval true on error (the transaction must be rolled back)
+ */
+ bool update(ulonglong start_id, ulonglong end_id);
+ // return true if found; false if not found or error
+ bool query(ulonglong trx_id);
+ /**
+ Gets a row from transaction_registry with the closest commit_timestamp to
+ first argument. We can search for a value which a lesser or greater than
+ first argument. Also loads a row into an internal TABLE object.
+
+ @param[in] timestamp
+ @param[in] true if we search for a lesser timestamp, false if greater
+ @retval true if exists, false it not exists or an error occurred
+ */
+ bool query(MYSQL_TIME &commit_time, bool backwards);
+ /**
+ Checks whether transaction1 sees transaction0.
+
+ @param[out] true if transaction1 sees transaction0, undefined on error and
+ when transaction1=transaction0 and false otherwise
+ @param[in] transaction_id of transaction1
+ @param[in] transaction_id of transaction0
+ @param[in] commit time of transaction1 or 0 if we want it to be queried
+ @param[in] isolation level (from handler.h) of transaction1
+ @param[in] commit time of transaction0 or 0 if we want it to be queried
+ @retval true on error, false otherwise
+ */
+ bool query_sees(bool &result, ulonglong trx_id1, ulonglong trx_id0,
+ ulonglong commit_id1= 0,
+ enum_tx_isolation iso_level1= ISO_READ_UNCOMMITTED,
+ ulonglong commit_id0= 0);
+
+ /**
+ @retval transaction isolation level of a row from internal TABLE object.
+ */
+ enum_tx_isolation iso_level() const;
+ /**
+ Stores transactioin isolation level to internal TABLE object.
+ */
+ void store_iso_level(enum_tx_isolation iso_level)
+ {
+ DBUG_ASSERT(iso_level <= ISO_SERIALIZABLE);
+ store(FLD_ISO_LEVEL, iso_level + 1);
+ }
+
+ /**
+ Writes a message to MariaDB log about incorrect transaction_registry schema.
+
+ @param[in] a message explained what's incorrect in schema
+ */
+ void warn_schema_incorrect(const char *reason);
+ /**
+ Checks whether transaction_registry table has a correct schema.
+
+ @retval true if schema is incorrect and false otherwise
+ */
+ bool check(bool error);
+
+ TABLE * operator-> () const
+ {
+ return table;
+ }
+ Field * operator[] (uint field_id) const
+ {
+ DBUG_ASSERT(field_id < FIELD_COUNT);
+ return table->field[field_id];
+ }
+ operator bool () const
+ {
+ return table;
+ }
+ bool operator== (const TABLE_LIST &subj) const
+ {
+ return (!cmp(&db, &subj.db) && !cmp(&table_name, &subj.table_name));
+ }
+ bool operator!= (const TABLE_LIST &subj) const
+ {
+ return !(*this == subj);
+ }
+};
+
+#endif /* MYSQL_CLIENT */
+
+#endif /* TABLE_INCLUDED */