diff options
Diffstat (limited to 'sql/handler.h')
-rw-r--r-- | sql/handler.h | 285 |
1 files changed, 205 insertions, 80 deletions
diff --git a/sql/handler.h b/sql/handler.h index 51b301ae22e..1d4dded3971 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -34,15 +34,13 @@ #include "sql_array.h" /* Dynamic_array<> */ #include "mdl.h" +#include "sql_analyze_stmt.h" // for Exec_time_tracker + #include <my_compare.h> #include <ft_global.h> #include <keycache.h> #include <mysql/psi/mysql_table.h> -#if MAX_KEY > 128 -#error MAX_KEY is too large. Values up to 128 are supported. -#endif - class Alter_info; // the following is for checking tables @@ -131,7 +129,7 @@ enum enum_alter_inplace_result { */ #define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1ULL << 16) #define HA_CAN_RTREEKEYS (1ULL << 17) -#define HA_NOT_DELETE_WITH_CACHE (1ULL << 18) +#define HA_NOT_DELETE_WITH_CACHE (1ULL << 18) /* unused */ /* The following is we need to a primary key to delete (and update) a row. If there is no primary key, all columns needs to be read on update and delete @@ -145,7 +143,7 @@ enum enum_alter_inplace_result { #define HA_HAS_OLD_CHECKSUM (1ULL << 24) /* Table data are stored in separate files (for lower_case_table_names) */ #define HA_FILE_BASED (1ULL << 26) -#define HA_NO_VARCHAR (1ULL << 27) +#define HA_NO_VARCHAR (1ULL << 27) /* unused */ #define HA_CAN_BIT_FIELD (1ULL << 28) /* supports bit fields */ #define HA_NEED_READ_RANGE_BUFFER (1ULL << 29) /* for read_multi_range */ #define HA_ANY_INDEX_MAY_BE_UNIQUE (1ULL << 30) @@ -197,17 +195,11 @@ enum enum_alter_inplace_result { #define HA_RECORD_MUST_BE_CLEAN_ON_WRITE (1ULL << 41) /* - Table condition pushdown must be performed regardless of - 'engine_condition_pushdown' setting. - - This flag is aimed at storage engines that come with "special" predicates - that can only be evaluated inside the storage engine. - For example, when one does - select * from sphinx_table where query='{fulltext_query}' - then the "query=..." condition must be always pushed down into storage - engine. + This storage engine supports condition pushdown */ -#define HA_MUST_USE_TABLE_CONDITION_PUSHDOWN (1ULL << 42) +#define HA_CAN_TABLE_CONDITION_PUSHDOWN (1ULL << 42) +/* old name for the same flag */ +#define HA_MUST_USE_TABLE_CONDITION_PUSHDOWN HA_CAN_TABLE_CONDITION_PUSHDOWN /** The handler supports read before write removal optimization @@ -256,6 +248,15 @@ enum enum_alter_inplace_result { */ #define HA_CAN_EXPORT (1LL << 45) +/* + Storage engine does not require an exclusive metadata lock + on the table during optimize. (TODO and repair?). + It can allow other connections to open the table. + (it does not necessarily mean that other connections can + read or modify the table - this is defined by THR locks and the + ::store_lock() method). +*/ +#define HA_CONCURRENT_OPTIMIZE (1LL << 46) /* Set of all binlog flags. Currently only contain the capabilities @@ -349,9 +350,6 @@ enum enum_alter_inplace_result { /* Note: the following includes binlog and closing 0. - so: innodb + bdb + ndb + binlog + myisam + myisammrg + archive + - example + csv + heap + blackhole + federated + 0 - (yes, the sum is deliberately inaccurate) TODO remove the limit, use dynarrays */ #define MAX_HA 64 @@ -385,10 +383,8 @@ enum enum_alter_inplace_result { #define HA_KEY_BLOB_LENGTH 2 #define HA_LEX_CREATE_TMP_TABLE 1 -#define HA_LEX_CREATE_IF_NOT_EXISTS 2 -#define HA_LEX_CREATE_TABLE_LIKE 4 #define HA_CREATE_TMP_ALTER 8 -#define HA_LEX_CREATE_REPLACE 16 + #define HA_MAX_REC_LENGTH 65535 /* Table caching type */ @@ -431,7 +427,6 @@ enum legacy_db_type DB_TYPE_MYISAM=9, DB_TYPE_MRG_MYISAM=10, DB_TYPE_INNODB=12, - DB_TYPE_NDBCLUSTER=14, DB_TYPE_EXAMPLE_DB=15, DB_TYPE_ARCHIVE_DB=16, DB_TYPE_CSV_DB=17, @@ -441,7 +436,6 @@ enum legacy_db_type DB_TYPE_BINLOG=21, DB_TYPE_PBXT=23, DB_TYPE_PERFORMANCE_SCHEMA=28, - DB_TYPE_WSREP=41, DB_TYPE_ARIA=42, DB_TYPE_TOKUDB=43, DB_TYPE_FIRST_DYNAMIC=44, @@ -627,11 +621,11 @@ struct xid_t { return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+ gtrid_length+bqual_length; } - uchar *key() + uchar *key() const { return (uchar *)>rid_length; } - uint key_length() + uint key_length() const { return sizeof(gtrid_length)+sizeof(bqual_length)+gtrid_length+bqual_length; } @@ -731,7 +725,6 @@ enum enum_schema_tables SCH_ALL_PLUGINS, SCH_APPLICABLE_ROLES, SCH_CHARSETS, - SCH_CLIENT_STATS, SCH_COLLATIONS, SCH_COLLATION_CHARACTER_SET_APPLICABILITY, SCH_COLUMNS, @@ -743,7 +736,6 @@ enum enum_schema_tables SCH_FILES, SCH_GLOBAL_STATUS, SCH_GLOBAL_VARIABLES, - SCH_INDEX_STATS, SCH_KEY_CACHES, SCH_KEY_COLUMN_USAGE, SCH_OPEN_TABLES, @@ -759,18 +751,19 @@ enum enum_schema_tables SCH_SESSION_STATUS, SCH_SESSION_VARIABLES, SCH_STATISTICS, - SCH_STATUS, + SCH_SYSTEM_VARIABLES, SCH_TABLES, SCH_TABLESPACES, SCH_TABLE_CONSTRAINTS, SCH_TABLE_NAMES, SCH_TABLE_PRIVILEGES, - SCH_TABLE_STATS, SCH_TRIGGERS, SCH_USER_PRIVILEGES, - SCH_USER_STATS, - SCH_VARIABLES, - SCH_VIEWS + SCH_VIEWS, +#ifdef HAVE_SPATIAL + SCH_GEOMETRY_COLUMNS, + SCH_SPATIAL_REF_SYS, +#endif /*HAVE_SPATIAL*/ }; struct TABLE_SHARE; @@ -963,6 +956,11 @@ struct handler_iterator { }; class handler; +class group_by_handler; +struct Query; +typedef class st_select_lex SELECT_LEX; +typedef struct st_order ORDER; + /* handlerton is a singleton structure - one instance per storage engine - to provide access to storage engine functionality that works on the @@ -1235,7 +1233,11 @@ struct handlerton enum handler_create_iterator_result (*create_iterator)(handlerton *hton, enum handler_iterator_type type, struct handler_iterator *fill_this_in); - + int (*abort_transaction)(handlerton *hton, THD *bf_thd, + THD *victim_thd, my_bool signal); + int (*set_checkpoint)(handlerton *hton, const XID* xid); + int (*get_checkpoint)(handlerton *hton, XID* xid); + void (*fake_trx_id)(handlerton *hton, THD *thd); /* Optional clauses in the CREATE/ALTER TABLE */ @@ -1261,6 +1263,20 @@ struct handlerton */ const char **tablefile_extensions; // by default - empty list + /********************************************************************** + Functions to intercept queries + **********************************************************************/ + + /* + Create and return a group_by_handler, if the storage engine can execute + the summary / group by query. + If the storage engine can't do that, return NULL. + + The server guaranteeds that all tables in the list belong to this + storage engine. + */ + group_by_handler *(*create_group_by)(THD *thd, Query *query); + /********************************************************************* Table discovery API. It allows the server to "discover" tables that exist in the storage @@ -1348,14 +1364,6 @@ struct handlerton */ int (*discover_table_structure)(handlerton *hton, THD* thd, TABLE_SHARE *share, HA_CREATE_INFO *info); - -#ifdef WITH_WSREP - int (*wsrep_abort_transaction)(handlerton *hton, THD *bf_thd, - THD *victim_thd, my_bool signal); - int (*wsrep_set_checkpoint)(handlerton *hton, const XID* xid); - int (*wsrep_get_checkpoint)(handlerton *hton, XID* xid); - void (*wsrep_fake_trx_id)(handlerton *hton, THD *thd); -#endif /* WITH_WSREP */ }; @@ -1374,6 +1382,8 @@ static inline sys_var *find_hton_sysvar(handlerton *hton, st_mysql_sys_var *var) return find_plugin_sysvar(hton2plugin[hton->slot], var); } +handlerton *ha_default_handlerton(THD *thd); +handlerton *ha_default_tmp_handlerton(THD *thd); /* Possible flags of a handlerton (there can be 32 of them) */ #define HTON_NO_FLAGS 0 @@ -1381,7 +1391,6 @@ static inline sys_var *find_hton_sysvar(handlerton *hton, st_mysql_sys_var *var) #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter #define HTON_CAN_RECREATE (1 << 2) //Delete all is used for truncate #define HTON_HIDDEN (1 << 3) //Engine does not appear in lists -#define HTON_FLUSH_AFTER_RENAME (1 << 4) #define HTON_NOT_USER_SELECTABLE (1 << 5) #define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported #define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables @@ -1444,7 +1453,11 @@ struct THD_TRANS */ bool modified_non_trans_table; - void reset() { no_2pc= FALSE; modified_non_trans_table= FALSE; } + void reset() { + no_2pc= FALSE; + modified_non_trans_table= FALSE; + m_unsafe_rollback_flags= 0; + } bool is_empty() const { return ha_list == NULL; } THD_TRANS() {} /* Remove gcc warning */ @@ -1456,12 +1469,31 @@ struct THD_TRANS static unsigned int const MODIFIED_NON_TRANS_TABLE= 0x01; static unsigned int const CREATED_TEMP_TABLE= 0x02; static unsigned int const DROPPED_TEMP_TABLE= 0x04; + static unsigned int const DID_WAIT= 0x08; + static unsigned int const DID_DDL= 0x10; void mark_created_temp_table() { DBUG_PRINT("debug", ("mark_created_temp_table")); m_unsafe_rollback_flags|= CREATED_TEMP_TABLE; } + void mark_dropped_temp_table() + { + DBUG_PRINT("debug", ("mark_dropped_temp_table")); + m_unsafe_rollback_flags|= DROPPED_TEMP_TABLE; + } + bool has_created_dropped_temp_table() const { + return + (m_unsafe_rollback_flags & (CREATED_TEMP_TABLE|DROPPED_TEMP_TABLE)) != 0; + } + void mark_trans_did_wait() { m_unsafe_rollback_flags|= DID_WAIT; } + bool trans_did_wait() const { + return (m_unsafe_rollback_flags & DID_WAIT) != 0; + } + void mark_trans_did_ddl() { m_unsafe_rollback_flags|= DID_DDL; } + bool trans_did_ddl() const { + return (m_unsafe_rollback_flags & DID_DDL) != 0; + } }; @@ -1593,9 +1625,41 @@ enum enum_stats_auto_recalc { HA_STATS_AUTO_RECALC_DEFAULT= 0, HA_STATS_AUTO_RECALC_ON, HA_STATS_AUTO_RECALC_OFF }; -struct HA_CREATE_INFO +/** + A helper struct for schema DDL statements: + CREATE SCHEMA [IF NOT EXISTS] name [ schema_specification... ] + ALTER SCHEMA name [ schema_specification... ] + + It stores the "schema_specification" part of the CREATE/ALTER statements and + is passed to mysql_create_db() and mysql_alter_db(). + Currently consists only of the schema default character set and collation. +*/ +struct Schema_specification_st +{ + CHARSET_INFO *default_table_charset; + void init() + { + bzero(this, sizeof(*this)); + } +}; + + +/** + A helper struct for table DDL statements, e.g.: + CREATE [OR REPLACE] [TEMPORARY] + TABLE [IF NOT EXISTS] tbl_name table_contents_source; + + Represents a combinations of: + 1. The scope, i.e. TEMPORARY or not TEMPORARY + 2. The "table_contents_source" part of the table DDL statements, + which can be initialized from either of these: + - table_element_list ... // Explicit definition (column and key list) + - LIKE another_table_name ... // Copy structure from another table + - [AS] SELECT ... // Copy structure from a subquery +*/ +struct Table_scope_and_contents_source_st { - CHARSET_INFO *table_charset, *default_table_charset; + CHARSET_INFO *table_charset; LEX_CUSTRING tabledef_version; LEX_STRING connect_string; const char *password, *tablespace; @@ -1615,7 +1679,6 @@ struct HA_CREATE_INFO uint stats_sample_pages; uint null_bits; /* NULL bits at start of record */ uint options; /* OR of HA_CREATE_ options */ - uint org_options; /* original options from query */ uint merge_insert_method; uint extra_size; /* length of extra data segment */ SQL_I_List<TABLE_LIST> merge_list; @@ -1648,7 +1711,32 @@ struct HA_CREATE_INFO MDL_ticket *mdl_ticket; bool table_was_deleted; - bool tmp_table() { return options & HA_LEX_CREATE_TMP_TABLE; } + void init() + { + bzero(this, sizeof(*this)); + } + bool tmp_table() const { return options & HA_LEX_CREATE_TMP_TABLE; } + void use_default_db_type(THD *thd) + { + db_type= tmp_table() ? ha_default_tmp_handlerton(thd) + : ha_default_handlerton(thd); + } +}; + + +/** + This struct is passed to handler table routines, e.g. ha_create(). + It does not include the "OR REPLACE" and "IF NOT EXISTS" parts, as these + parts are handled on the SQL level and are not needed on the handler level. +*/ +struct HA_CREATE_INFO: public Table_scope_and_contents_source_st, + public Schema_specification_st +{ + void init() + { + Table_scope_and_contents_source_st::init(); + Schema_specification_st::init(); + } bool check_conflicting_charset_declarations(CHARSET_INFO *cs); bool add_table_option_default_charset(CHARSET_INFO *cs) { @@ -1680,6 +1768,38 @@ struct HA_CREATE_INFO /** + This struct is passed to mysql_create_table() and similar creation functions, + as well as to show_create_table(). +*/ +struct Table_specification_st: public HA_CREATE_INFO, + public DDL_options_st +{ + // Deep initialization + void init() + { + HA_CREATE_INFO::init(); + DDL_options_st::init(); + } + void init(DDL_options_st::Options options_arg) + { + HA_CREATE_INFO::init(); + DDL_options_st::init(options_arg); + } + /* + Quick initialization, for parser. + Most of the HA_CREATE_INFO is left uninitialized. + It gets fully initialized in sql_yacc.yy, only when the parser + scans a related keyword (e.g. CREATE, ALTER). + */ + void lex_start() + { + HA_CREATE_INFO::options= 0; + DDL_options_st::init(); + } +}; + + +/** In-place alter handler context. This is a superclass intended to be subclassed by individual handlers @@ -2547,6 +2667,13 @@ public: /* One bigger than needed to avoid to test if key == MAX_KEY */ ulonglong index_rows_read[MAX_KEY+1]; +private: + /* ANALYZE time tracker, if present */ + Exec_time_tracker *tracker; +public: + void set_time_tracker(Exec_time_tracker *tracker_arg) { tracker=tracker_arg;} + + Item *pushed_idx_cond; uint pushed_idx_cond_keyno; /* The index which the above condition is for */ @@ -2600,6 +2727,7 @@ public: ft_handler(0), inited(NONE), implicit_emptied(0), pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0), + tracker(NULL), pushed_idx_cond(NULL), pushed_idx_cond_keyno(MAX_KEY), auto_inc_intervals_count(0), @@ -3999,6 +4127,7 @@ protected: }; #include "multi_range_read.h" +#include "group_by_handler.h" bool key_uses_partial_cols(TABLE_SHARE *table, uint keyno); @@ -4007,23 +4136,23 @@ bool key_uses_partial_cols(TABLE_SHARE *table, uint keyno); extern const char *ha_row_type[]; extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[]; extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[]; -#ifdef WITH_WSREP -extern MYSQL_PLUGIN_IMPORT const char *wsrep_binlog_format_names[]; -#endif /* WITH_WSREP */ extern TYPELIB tx_isolation_typelib; extern const char *myisam_stats_method_names[]; extern ulong total_ha, total_ha_2pc; /* lookups */ -handlerton *ha_default_handlerton(THD *thd); -plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name); +plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name, bool tmp_table); plugin_ref ha_lock_engine(THD *thd, const handlerton *hton); handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type); handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, handlerton *db_type); -handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type, - bool no_substitute, bool report_error); +handlerton *ha_checktype(THD *thd, handlerton *hton, bool no_substitute); +static inline handlerton *ha_checktype(THD *thd, enum legacy_db_type type, + bool no_substitute = 0) +{ + return ha_checktype(thd, ha_resolve_by_legacy_type(thd, type), no_substitute); +} static inline enum legacy_db_type ha_legacy_type(const handlerton *db_type) { @@ -4130,9 +4259,11 @@ bool ha_rollback_to_savepoint_can_release_mdl(THD *thd); int ha_savepoint(THD *thd, SAVEPOINT *sv); int ha_release_savepoint(THD *thd, SAVEPOINT *sv); #ifdef WITH_WSREP -int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); -void ha_wsrep_fake_trx_id(THD *thd); -#endif /* WITH_WSREP */ +int ha_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); +void ha_fake_trx_id(THD *thd); +#else +inline void ha_fake_trx_id(THD *thd) { } +#endif /* these are called by storage engines */ void trans_register_ha(THD *thd, bool all, handlerton *ht); @@ -4145,28 +4276,6 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht); #define trans_need_2pc(thd, all) ((total_ha_2pc > 1) && \ !((all ? &thd->transaction.all : &thd->transaction.stmt)->no_2pc)) -#ifdef HAVE_NDB_BINLOG -int ha_reset_logs(THD *thd); -int ha_binlog_index_purge_file(THD *thd, const char *file); -void ha_reset_slave(THD *thd); -void ha_binlog_log_query(THD *thd, handlerton *db_type, - enum_binlog_command binlog_command, - const char *query, uint query_length, - const char *db, const char *table_name); -void ha_binlog_wait(THD *thd); -int ha_binlog_end(THD *thd); -#else -#define ha_reset_logs(a) do {} while (0) -#define ha_binlog_index_purge_file(a,b) do {} while (0) -#define ha_reset_slave(a) do {} while (0) -#define ha_binlog_log_query(a,b,c,d,e,f,g) do {} while (0) -#define ha_binlog_wait(a) do {} while (0) -#define ha_binlog_end(a) do {} while (0) -#endif -#ifdef WITH_WSREP -void wsrep_brute_force_aborts(); -#endif - const char *get_canonical_filename(handler *file, const char *path, char *tmp_path); bool mysql_xa_recover(THD *thd); @@ -4177,6 +4286,22 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) return ((lower_case_table_names == 2 && info->alias) ? info->alias : name); } + +#define TABLE_IO_WAIT(TRACKER, PSI, OP, INDEX, FLAGS, PAYLOAD) \ + { \ + Exec_time_tracker *this_tracker; \ + if (unlikely((this_tracker= tracker))) \ + tracker->start_tracking(); \ + \ + MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD); \ + \ + if (unlikely(this_tracker)) \ + tracker->stop_tracking(); \ + } + void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag); void print_keydup_error(TABLE *table, KEY *key, myf errflag); + +int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info); +int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table); #endif /* HANDLER_INCLUDED */ |