diff options
Diffstat (limited to 'sql/handler.h')
-rw-r--r-- | sql/handler.h | 943 |
1 files changed, 716 insertions, 227 deletions
diff --git a/sql/handler.h b/sql/handler.h index a777b7c595a..1c336e7e35f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -25,7 +25,6 @@ #pragma interface /* gcc class implementation */ #endif -#include <my_global.h> /* For handlers */ #include "sql_const.h" #include "sql_basic_types.h" #include "mysqld.h" /* server_id */ @@ -35,6 +34,7 @@ #include "structs.h" /* SHOW_COMP_OPTION */ #include "sql_array.h" /* Dynamic_array<> */ #include "mdl.h" +#include "vers_string.h" #include "sql_analyze_stmt.h" // for Exec_time_tracker @@ -42,9 +42,11 @@ #include <ft_global.h> #include <keycache.h> #include <mysql/psi/mysql_table.h> +#include "sql_sequence.h" class Alter_info; class Virtual_column_info; +class sequence_definition; // the following is for checking tables @@ -71,11 +73,14 @@ class Virtual_column_info; */ enum enum_alter_inplace_result { HA_ALTER_ERROR, + HA_ALTER_INPLACE_COPY_NO_LOCK, + HA_ALTER_INPLACE_COPY_LOCK, + HA_ALTER_INPLACE_NOCOPY_LOCK, + HA_ALTER_INPLACE_NOCOPY_NO_LOCK, + HA_ALTER_INPLACE_INSTANT, HA_ALTER_INPLACE_NOT_SUPPORTED, HA_ALTER_INPLACE_EXCLUSIVE_LOCK, - HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE, HA_ALTER_INPLACE_SHARED_LOCK, - HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE, HA_ALTER_INPLACE_NO_LOCK }; @@ -146,7 +151,6 @@ 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) /* 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) @@ -160,6 +164,7 @@ enum enum_alter_inplace_result { */ #define HA_BINLOG_ROW_CAPABLE (1ULL << 34) #define HA_BINLOG_STMT_CAPABLE (1ULL << 35) + /* When a multiple key conflict happens in a REPLACE command mysql expects the conflicts to be reported in the ascending order of @@ -262,11 +267,43 @@ enum enum_alter_inplace_result { #define HA_CONCURRENT_OPTIMIZE (1ULL << 46) /* + If the storage engine support tables that will not roll back on commit + In addition the table should not lock rows and support READ and WRITE + UNCOMMITTED. + This is useful for implementing things like SEQUENCE but can also in + the future be useful to do logging that should never roll back. +*/ +#define HA_CAN_TABLES_WITHOUT_ROLLBACK (1ULL << 47) + +/* + Mainly for usage by SEQUENCE engine. Setting this flag means + that the table will never roll back and that all operations + for this table should stored in the non transactional log + space that will always be written, even on rollback. +*/ + +#define HA_PERSISTENT_TABLE (1ULL << 48) + +/* Set of all binlog flags. Currently only contain the capabilities flags. */ #define HA_BINLOG_FLAGS (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE) +/* The following are used by Spider */ +#define HA_CAN_FORCE_BULK_UPDATE (1ULL << 50) +#define HA_CAN_FORCE_BULK_DELETE (1ULL << 51) +#define HA_CAN_DIRECT_UPDATE_AND_DELETE (1ULL << 52) + +/* The following is for partition handler */ +#define HA_CAN_MULTISTEP_MERGE (1LL << 53) + +/* calling cmp_ref() on the engine is expensive */ +#define HA_CMP_REF_IS_EXPENSIVE (1ULL << 54) + +/* Engine wants primary keys for everything except sequences */ +#define HA_WANTS_PRIMARY_KEY (1ULL << 55) + /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ #define HA_READ_PREV 2 /* supports ::index_prev */ @@ -386,6 +423,8 @@ enum enum_alter_inplace_result { #define HA_LEX_CREATE_TMP_TABLE 1U #define HA_CREATE_TMP_ALTER 8U +#define HA_LEX_CREATE_SEQUENCE 16U +#define HA_VERSIONED_TABLE 32U #define HA_MAX_REC_LENGTH 65535 @@ -421,6 +460,12 @@ static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4; #define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE) #define HA_CHECK_ALL (~0U) +/* Options for info_push() */ +#define INFO_KIND_UPDATE_FIELDS 101 +#define INFO_KIND_UPDATE_VALUES 102 +#define INFO_KIND_FORCE_LIMIT_BEGIN 103 +#define INFO_KIND_FORCE_LIMIT_END 104 + enum legacy_db_type { /* note these numerical values are fixed and can *not* be changed */ @@ -440,7 +485,8 @@ enum legacy_db_type DB_TYPE_PERFORMANCE_SCHEMA=28, DB_TYPE_ARIA=42, DB_TYPE_TOKUDB=43, - DB_TYPE_FIRST_DYNAMIC=44, + DB_TYPE_SEQUENCE=44, + DB_TYPE_FIRST_DYNAMIC=45, DB_TYPE_DEFAULT=127 // Must be last }; /* @@ -528,6 +574,187 @@ given at all. */ */ #define HA_CREATE_USED_STATS_SAMPLE_PAGES (1UL << 24) +/* Create a sequence */ +#define HA_CREATE_USED_SEQUENCE (1UL << 25) + +typedef ulonglong alter_table_operations; + +/* + These flags are set by the parser and describes the type of + operation(s) specified by the ALTER TABLE statement. +*/ + +// Set by parser for ADD [COLUMN] +#define ALTER_PARSER_ADD_COLUMN (1ULL << 0) +// Set by parser for DROP [COLUMN] +#define ALTER_PARSER_DROP_COLUMN (1ULL << 1) +// Set for CHANGE [COLUMN] | MODIFY [CHANGE] & mysql_recreate_table +#define ALTER_CHANGE_COLUMN (1ULL << 2) +// Set for ADD INDEX | ADD KEY | ADD PRIMARY KEY | ADD UNIQUE KEY | +// ADD UNIQUE INDEX | ALTER ADD [COLUMN] +#define ALTER_ADD_INDEX (1ULL << 3) +// Set for DROP PRIMARY KEY | DROP FOREIGN KEY | DROP KEY | DROP INDEX +#define ALTER_DROP_INDEX (1ULL << 4) +// Set for RENAME [TO] +#define ALTER_RENAME (1ULL << 5) +// Set for ORDER BY +#define ALTER_ORDER (1ULL << 6) +// Set for table_options, like table comment +#define ALTER_OPTIONS (1ULL << 7) +// Set for ALTER [COLUMN] ... SET DEFAULT ... | DROP DEFAULT +#define ALTER_CHANGE_COLUMN_DEFAULT (1ULL << 8) +// Set for DISABLE KEYS | ENABLE KEYS +#define ALTER_KEYS_ONOFF (1ULL << 9) +// Set for FORCE, ENGINE(same engine), by mysql_recreate_table() +#define ALTER_RECREATE (1ULL << 10) +// Set for ADD FOREIGN KEY +#define ALTER_ADD_FOREIGN_KEY (1ULL << 21) +// Set for DROP FOREIGN KEY +#define ALTER_DROP_FOREIGN_KEY (1ULL << 22) +// Set for ADD [COLUMN] FIRST | AFTER +#define ALTER_COLUMN_ORDER (1ULL << 25) +#define ALTER_ADD_CHECK_CONSTRAINT (1ULL << 27) +#define ALTER_DROP_CHECK_CONSTRAINT (1ULL << 28) +#define ALTER_RENAME_COLUMN (1ULL << 29) +#define ALTER_COLUMN_UNVERSIONED (1ULL << 30) +#define ALTER_ADD_SYSTEM_VERSIONING (1ULL << 31) +#define ALTER_DROP_SYSTEM_VERSIONING (1ULL << 32) +#define ALTER_ADD_PERIOD (1ULL << 33) +#define ALTER_DROP_PERIOD (1ULL << 34) + +/* + Following defines are used by ALTER_INPLACE_TABLE + + They do describe in more detail the type operation(s) to be executed + by the storage engine. For example, which type of type of index to be + added/dropped. These are set by fill_alter_inplace_info(). +*/ + +#define ALTER_RECREATE_TABLE ALTER_RECREATE +#define ALTER_CHANGE_CREATE_OPTION ALTER_OPTIONS +#define ALTER_ADD_COLUMN (ALTER_ADD_VIRTUAL_COLUMN | \ + ALTER_ADD_STORED_BASE_COLUMN | \ + ALTER_ADD_STORED_GENERATED_COLUMN) +#define ALTER_DROP_COLUMN (ALTER_DROP_VIRTUAL_COLUMN | \ + ALTER_DROP_STORED_COLUMN) +#define ALTER_COLUMN_DEFAULT ALTER_CHANGE_COLUMN_DEFAULT + +// Add non-unique, non-primary index +#define ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX (1ULL << 35) + +// Drop non-unique, non-primary index +#define ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX (1ULL << 36) + +// Add unique, non-primary index +#define ALTER_ADD_UNIQUE_INDEX (1ULL << 37) + +// Drop unique, non-primary index +#define ALTER_DROP_UNIQUE_INDEX (1ULL << 38) + +// Add primary index +#define ALTER_ADD_PK_INDEX (1ULL << 39) + +// Drop primary index +#define ALTER_DROP_PK_INDEX (1ULL << 40) + +// Virtual generated column +#define ALTER_ADD_VIRTUAL_COLUMN (1ULL << 41) +// Stored base (non-generated) column +#define ALTER_ADD_STORED_BASE_COLUMN (1ULL << 42) +// Stored generated column +#define ALTER_ADD_STORED_GENERATED_COLUMN (1ULL << 43) + +// Drop column +#define ALTER_DROP_VIRTUAL_COLUMN (1ULL << 44) +#define ALTER_DROP_STORED_COLUMN (1ULL << 45) + +// Rename column (verified; ALTER_RENAME_COLUMN may use original name) +#define ALTER_COLUMN_NAME (1ULL << 46) + +// Change column datatype +#define ALTER_VIRTUAL_COLUMN_TYPE (1ULL << 47) +#define ALTER_STORED_COLUMN_TYPE (1ULL << 48) + +/** + Change column datatype in such way that new type has compatible + packed representation with old type, so it is theoretically + possible to perform change by only updating data dictionary + without changing table rows. +*/ +#define ALTER_COLUMN_EQUAL_PACK_LENGTH (1ULL << 49) + +// Reorder column +#define ALTER_STORED_COLUMN_ORDER (1ULL << 50) + +// Reorder column +#define ALTER_VIRTUAL_COLUMN_ORDER (1ULL << 51) + +// Change column from NOT NULL to NULL +#define ALTER_COLUMN_NULLABLE (1ULL << 52) + +// Change column from NULL to NOT NULL +#define ALTER_COLUMN_NOT_NULLABLE (1ULL << 53) + +// Change column generation expression +#define ALTER_VIRTUAL_GCOL_EXPR (1ULL << 54) +#define ALTER_STORED_GCOL_EXPR (1ULL << 55) + +// column's engine options changed, something in field->option_struct +#define ALTER_COLUMN_OPTION (1ULL << 56) + +// MySQL alias for the same thing: +#define ALTER_COLUMN_STORAGE_TYPE ALTER_COLUMN_OPTION + +// Change the column format of column +#define ALTER_COLUMN_COLUMN_FORMAT (1ULL << 57) + +/** + Changes in generated columns that affect storage, + for example, when a vcol type or expression changes + and this vcol is indexed or used in a partitioning expression +*/ +#define ALTER_COLUMN_VCOL (1ULL << 58) + +/** + ALTER TABLE for a partitioned table. The engine needs to commit + online alter of all partitions atomically (using group_commit_ctx) +*/ +#define ALTER_PARTITIONED (1ULL << 59) + +/** + Change in index length such that it doesn't require index rebuild. +*/ +#define ALTER_COLUMN_INDEX_LENGTH (1ULL << 60) + +/* + Flags set in partition_flags when altering partitions +*/ + +// Set for ADD PARTITION +#define ALTER_PARTITION_ADD (1ULL << 1) +// Set for DROP PARTITION +#define ALTER_PARTITION_DROP (1ULL << 2) +// Set for COALESCE PARTITION +#define ALTER_PARTITION_COALESCE (1ULL << 3) +// Set for REORGANIZE PARTITION ... INTO +#define ALTER_PARTITION_REORGANIZE (1ULL << 4) +// Set for partition_options +#define ALTER_PARTITION_INFO (1ULL << 5) +// Set for LOAD INDEX INTO CACHE ... PARTITION +// Set for CACHE INDEX ... PARTITION +#define ALTER_PARTITION_ADMIN (1ULL << 6) +// Set for REBUILD PARTITION +#define ALTER_PARTITION_REBUILD (1ULL << 7) +// Set for partitioning operations specifying ALL keyword +#define ALTER_PARTITION_ALL (1ULL << 8) +// Set for REMOVE PARTITIONING +#define ALTER_PARTITION_REMOVE (1ULL << 9) +// Set for EXCHANGE PARITION +#define ALTER_PARTITION_EXCHANGE (1ULL << 10) +// Set by Sql_cmd_alter_table_truncate_partition::execute() +#define ALTER_PARTITION_TRUNCATE (1ULL << 11) +// Set for REORGANIZE PARTITION +#define ALTER_PARTITION_TABLE_REORG (1ULL << 12) /* This is master database for most of system tables. However there @@ -634,6 +861,15 @@ struct xid_t { }; typedef struct xid_t XID; +/* + The size of XID string representation in the form + 'gtrid', 'bqual', formatID + see xid_t::get_sql_string() for details. +*/ +#define SQL_XIDSIZE (XIDDATASIZE * 2 + 8 + MY_INT64_NUM_DECIMAL_DIGITS) +/* The 'buf' has to have space for at least SQL_XIDSIZE bytes. */ +uint get_sql_xid(XID *xid, char *buf); + /* for recover() handlerton call */ #define MIN_XID_LIST_SIZE 128 #define MAX_XID_LIST_SIZE (1024*128) @@ -1203,7 +1439,7 @@ struct handlerton bool (*flush_logs)(handlerton *hton); bool (*show_status)(handlerton *hton, THD *thd, stat_print_fn *print, enum ha_stat_type stat); uint (*partition_flags)(); - uint (*alter_table_flags)(uint flags); + alter_table_operations (*alter_table_flags)(alter_table_operations flags); int (*alter_tablespace)(handlerton *hton, THD *thd, st_alter_tablespace *ts_info); int (*fill_is_table)(handlerton *hton, THD *thd, TABLE_LIST *tables, class Item *cond, @@ -1323,7 +1559,7 @@ struct handlerton Returns 0 on success and 1 on error. */ - int (*discover_table_names)(handlerton *hton, LEX_STRING *db, MY_DIR *dir, + int (*discover_table_names)(handlerton *hton, LEX_CSTRING *db, MY_DIR *dir, discovered_list *result); /* @@ -1366,10 +1602,20 @@ struct handlerton */ int (*discover_table_structure)(handlerton *hton, THD* thd, TABLE_SHARE *share, HA_CREATE_INFO *info); + + /* + System Versioning + */ + /** Determine if system-versioned data was modified by the transaction. + @param[in,out] thd current session + @param[out] trx_id transaction start ID + @return transaction commit ID + @retval 0 if no system-versioned data was affected by the transaction */ + ulonglong (*prepare_commit_versioned)(THD *thd, ulonglong *trx_id); }; -static inline LEX_STRING *hton_name(const handlerton *hton) +static inline LEX_CSTRING *hton_name(const handlerton *hton) { return &(hton2plugin[hton->slot]->name); } @@ -1413,10 +1659,15 @@ handlerton *ha_default_tmp_handlerton(THD *thd); */ #define HTON_NO_BINLOG_ROW_OPT (1 << 9) #define HTON_SUPPORTS_EXTENDED_KEYS (1 <<10) //supports extended keys +#define HTON_NATIVE_SYS_VERSIONING (1 << 11) //Engine supports System Versioning // MySQL compatibility. Unused. #define HTON_SUPPORTS_FOREIGN_KEYS (1 << 0) //Foreign key constraint supported. +#define HTON_CAN_MERGE (1 <<11) //Merge type table +// Engine needs to access the main connect string in partitions +#define HTON_CAN_READ_CONNECT_STRING_IN_PARTITION (1 <<12) + class Ha_trx_info; struct THD_TRANS @@ -1465,14 +1716,16 @@ struct THD_TRANS unsigned int m_unsafe_rollback_flags; /* - Define the type of statemens which cannot be rolled back safely. + Define the type of statements which cannot be rolled back safely. Each type occupies one bit in m_unsafe_rollback_flags. */ - 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; + enum unsafe_statement_types + { + CREATED_TEMP_TABLE= 2, + DROPPED_TEMP_TABLE= 4, + DID_WAIT= 8, + DID_DDL= 0x10 + }; void mark_created_temp_table() { @@ -1492,6 +1745,7 @@ struct THD_TRANS bool trans_did_wait() const { return (m_unsafe_rollback_flags & DID_WAIT) != 0; } + bool is_trx_read_write() const; void mark_trans_did_ddl() { m_unsafe_rollback_flags|= DID_DDL; } bool trans_did_ddl() const { return (m_unsafe_rollback_flags & DID_DDL) != 0; @@ -1596,6 +1850,16 @@ private: }; +inline bool THD_TRANS::is_trx_read_write() const +{ + Ha_trx_info *ha_info; + for (ha_info= ha_list; ha_info; ha_info= ha_info->next()) + if (ha_info->is_trx_read_write()) + return TRUE; + return FALSE; +} + + enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED, ISO_REPEATABLE_READ, ISO_SERIALIZABLE}; @@ -1604,6 +1868,7 @@ typedef struct { ulonglong data_file_length; ulonglong max_data_file_length; ulonglong index_file_length; + ulonglong max_index_file_length; ulonglong delete_length; ha_rows records; ulong mean_rec_length; @@ -1645,6 +1910,98 @@ struct Schema_specification_st } }; +class Create_field; + +enum vers_sys_type_t +{ + VERS_UNDEFINED= 0, + VERS_TIMESTAMP, + VERS_TRX_ID +}; + +extern const LEX_CSTRING null_clex_str; + +struct Vers_parse_info +{ + Vers_parse_info() : + check_unit(VERS_UNDEFINED), + versioned_fields(false), + unversioned_fields(false) + {} + + void init() // Deep initialization + { + system_time= start_end_t(null_clex_str, null_clex_str); + as_row= start_end_t(null_clex_str, null_clex_str); + check_unit= VERS_UNDEFINED; + versioned_fields= false; + unversioned_fields= false; + } + + struct start_end_t + { + start_end_t() + {} + start_end_t(LEX_CSTRING _start, LEX_CSTRING _end) : + start(_start), + end(_end) {} + Lex_ident start; + Lex_ident end; + }; + + start_end_t system_time; + start_end_t as_row; + vers_sys_type_t check_unit; + + void set_system_time(Lex_ident start, Lex_ident end) + { + system_time.start= start; + system_time.end= end; + } + +protected: + friend struct Table_scope_and_contents_source_st; + void set_start(const LEX_CSTRING field_name) + { + as_row.start= field_name; + system_time.start= field_name; + } + void set_end(const LEX_CSTRING field_name) + { + as_row.end= field_name; + system_time.end= field_name; + } + bool is_start(const char *name) const; + bool is_end(const char *name) const; + bool is_start(const Create_field &f) const; + bool is_end(const Create_field &f) const; + bool fix_implicit(THD *thd, Alter_info *alter_info); + operator bool() const + { + return as_row.start || as_row.end || system_time.start || system_time.end; + } + bool need_check(const Alter_info *alter_info) const; + bool check_conditions(const Lex_table_name &table_name, + const Lex_table_name &db) const; +public: + static const Lex_ident default_start; + static const Lex_ident default_end; + + bool fix_alter_info(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, TABLE *table); + bool fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_info, + TABLE_LIST &src_table, TABLE_LIST &table); + bool check_sys_fields(const Lex_table_name &table_name, + const Lex_table_name &db, + Alter_info *alter_info); + + /** + At least one field was specified 'WITH/WITHOUT SYSTEM VERSIONING'. + Useful for error handling. + */ + bool versioned_fields : 1; + bool unversioned_fields : 1; +}; /** A helper struct for table DDL statements, e.g.: @@ -1660,15 +2017,15 @@ struct Schema_specification_st - [AS] SELECT ... // Copy structure from a subquery */ -struct Table_scope_and_contents_source_st +struct Table_scope_and_contents_source_pod_st // For trivial members { CHARSET_INFO *table_charset; LEX_CUSTRING tabledef_version; - LEX_STRING connect_string; + LEX_CSTRING connect_string; + LEX_CSTRING comment; + LEX_CSTRING alias; const char *password, *tablespace; - LEX_STRING comment; const char *data_file_name, *index_file_name; - const char *alias; ulonglong max_rows,min_rows; ulonglong auto_increment_value; ulong table_options; ///< HA_OPTION_ values @@ -1703,6 +2060,7 @@ struct Table_scope_and_contents_source_st engine_option_value *option_list; ///< list of table create options enum_stats_auto_recalc stats_auto_recalc; bool varchar; ///< 1 if table has a VARCHAR + bool sequence; // If SEQUENCE=1 was used List<Virtual_column_info> *check_constraint_list; @@ -1714,9 +2072,10 @@ struct Table_scope_and_contents_source_st /* The following is used to remember the old state for CREATE OR REPLACE */ TABLE *table; TABLE_LIST *pos_in_locked_tables; + TABLE_LIST *merge_list; MDL_ticket *mdl_ticket; bool table_was_deleted; - TABLE_LIST *merge_list; + sequence_definition *seq_create_info; void init() { @@ -1728,6 +2087,32 @@ struct Table_scope_and_contents_source_st db_type= tmp_table() ? ha_default_tmp_handlerton(thd) : ha_default_handlerton(thd); } + + bool versioned() const + { + return options & HA_VERSIONED_TABLE; + } +}; + + +struct Table_scope_and_contents_source_st: + public Table_scope_and_contents_source_pod_st +{ + Vers_parse_info vers_info; + + void init() + { + Table_scope_and_contents_source_pod_st::init(); + vers_info.init(); + } + + bool vers_fix_system_fields(THD *thd, Alter_info *alter_info, + const TABLE_LIST &create_table, + bool create_select= false); + + bool vers_check_system_fields(THD *thd, Alter_info *alter_info, + const TABLE_LIST &create_table); + }; @@ -1849,163 +2234,6 @@ public: class Alter_inplace_info { public: - /** - Bits to show in detail what operations the storage engine is - to execute. - - All these operations are supported as in-place operations by the - SQL layer. This means that operations that by their nature must - be performed by copying the table to a temporary table, will not - have their own flags here. - - We generally try to specify handler flags only if there are real - changes. But in cases when it is cumbersome to determine if some - attribute has really changed we might choose to set flag - pessimistically, for example, relying on parser output only. - */ - typedef ulonglong HA_ALTER_FLAGS; - - // Add non-unique, non-primary index - static const HA_ALTER_FLAGS ADD_INDEX = 1ULL << 0; - - // Drop non-unique, non-primary index - static const HA_ALTER_FLAGS DROP_INDEX = 1ULL << 1; - - // Add unique, non-primary index - static const HA_ALTER_FLAGS ADD_UNIQUE_INDEX = 1ULL << 2; - - // Drop unique, non-primary index - static const HA_ALTER_FLAGS DROP_UNIQUE_INDEX = 1ULL << 3; - - // Add primary index - static const HA_ALTER_FLAGS ADD_PK_INDEX = 1ULL << 4; - - // Drop primary index - static const HA_ALTER_FLAGS DROP_PK_INDEX = 1ULL << 5; - - // Virtual generated column - static const HA_ALTER_FLAGS ADD_VIRTUAL_COLUMN = 1ULL << 6; - // Stored base (non-generated) column - static const HA_ALTER_FLAGS ADD_STORED_BASE_COLUMN = 1ULL << 7; - // Stored generated column - static const HA_ALTER_FLAGS ADD_STORED_GENERATED_COLUMN= 1ULL << 8; - // Add generic column (convience constant). - static const HA_ALTER_FLAGS ADD_COLUMN= ADD_VIRTUAL_COLUMN | - ADD_STORED_BASE_COLUMN | - ADD_STORED_GENERATED_COLUMN; - - // Drop column - static const HA_ALTER_FLAGS DROP_VIRTUAL_COLUMN = 1ULL << 9; - static const HA_ALTER_FLAGS DROP_STORED_COLUMN = 1ULL << 10; - static const HA_ALTER_FLAGS DROP_COLUMN= DROP_VIRTUAL_COLUMN | - DROP_STORED_COLUMN; - - // Rename column - static const HA_ALTER_FLAGS ALTER_COLUMN_NAME = 1ULL << 11; - - // Change column datatype - static const HA_ALTER_FLAGS ALTER_VIRTUAL_COLUMN_TYPE = 1ULL << 12; - static const HA_ALTER_FLAGS ALTER_STORED_COLUMN_TYPE = 1ULL << 13; - - /** - Change column datatype in such way that new type has compatible - packed representation with old type, so it is theoretically - possible to perform change by only updating data dictionary - without changing table rows. - */ - static const HA_ALTER_FLAGS ALTER_COLUMN_EQUAL_PACK_LENGTH = 1ULL << 14; - - // Reorder column - static const HA_ALTER_FLAGS ALTER_STORED_COLUMN_ORDER = 1ULL << 15; - - // Reorder column - static const HA_ALTER_FLAGS ALTER_VIRTUAL_COLUMN_ORDER = 1ULL << 16; - - // Change column from NOT NULL to NULL - static const HA_ALTER_FLAGS ALTER_COLUMN_NULLABLE = 1ULL << 17; - - // Change column from NULL to NOT NULL - static const HA_ALTER_FLAGS ALTER_COLUMN_NOT_NULLABLE = 1ULL << 18; - - // Set or remove default column value - static const HA_ALTER_FLAGS ALTER_COLUMN_DEFAULT = 1ULL << 19; - - // Change column generation expression - static const HA_ALTER_FLAGS ALTER_VIRTUAL_GCOL_EXPR = 1ULL << 20; - static const HA_ALTER_FLAGS ALTER_STORED_GCOL_EXPR = 1ULL << 21; - // - // Add foreign key - static const HA_ALTER_FLAGS ADD_FOREIGN_KEY = 1ULL << 22; - - // Drop foreign key - static const HA_ALTER_FLAGS DROP_FOREIGN_KEY = 1ULL << 23; - - // table_options changed, see HA_CREATE_INFO::used_fields for details. - static const HA_ALTER_FLAGS CHANGE_CREATE_OPTION = 1ULL << 24; - - // Table is renamed - static const HA_ALTER_FLAGS ALTER_RENAME = 1ULL << 25; - - // column's engine options changed, something in field->option_struct - static const HA_ALTER_FLAGS ALTER_COLUMN_OPTION = 1ULL << 26; - - // MySQL alias for the same thing: - static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1ULL << 26; - - // Change the column format of column - static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1ULL << 27; - - // Add partition - static const HA_ALTER_FLAGS ADD_PARTITION = 1ULL << 28; - - // Drop partition - static const HA_ALTER_FLAGS DROP_PARTITION = 1ULL << 29; - - // Changing partition options - static const HA_ALTER_FLAGS ALTER_PARTITION = 1ULL << 30; - - // Coalesce partition - static const HA_ALTER_FLAGS COALESCE_PARTITION = 1ULL << 31; - - // Reorganize partition ... into - static const HA_ALTER_FLAGS REORGANIZE_PARTITION = 1ULL << 32; - - // Reorganize partition - static const HA_ALTER_FLAGS ALTER_TABLE_REORG = 1ULL << 33; - - // Remove partitioning - static const HA_ALTER_FLAGS ALTER_REMOVE_PARTITIONING = 1ULL << 34; - - // Partition operation with ALL keyword - static const HA_ALTER_FLAGS ALTER_ALL_PARTITION = 1ULL << 35; - - /** - Recreate the table for ALTER TABLE FORCE, ALTER TABLE ENGINE - and OPTIMIZE TABLE operations. - */ - static const HA_ALTER_FLAGS RECREATE_TABLE = 1ULL << 36; - - /** - Changes in generated columns that affect storage, - for example, when a vcol type or expression changes - and this vcol is indexed or used in a partitioning expression - */ - static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1ULL << 37; - - /** - ALTER TABLE for a partitioned table. The engine needs to commit - online alter of all partitions atomically (using group_commit_ctx) - */ - static const HA_ALTER_FLAGS ALTER_PARTITIONED = 1ULL << 38; - - static const HA_ALTER_FLAGS ALTER_ADD_CHECK_CONSTRAINT = 1ULL << 39; - - static const HA_ALTER_FLAGS ALTER_DROP_CHECK_CONSTRAINT= 1ULL << 40; - - /** - Change in index length such that it doesn't require index rebuild. - */ - static const HA_ALTER_FLAGS ALTER_COLUMN_INDEX_LENGTH= 1ULL << 41; /** Create options (like MAX_ROWS) for the new version of table. @@ -2090,9 +2318,13 @@ public: inplace_alter_handler_ctx **group_commit_ctx; /** - Flags describing in detail which operations the storage engine is to execute. + Flags describing in detail which operations the storage engine is to + execute. Flags are defined in sql_alter.h */ - HA_ALTER_FLAGS handler_flags; + alter_table_operations handler_flags; + + /* Alter operations involving parititons are strored here */ + ulong partition_flags; /** Partition_info taking into account the partition changes to be performed. @@ -2111,8 +2343,7 @@ public: /** Can be set by handler to describe why a given operation cannot be done in-place (HA_ALTER_INPLACE_NOT_SUPPORTED) or why it cannot be done - online (HA_ALTER_INPLACE_NO_LOCK or - HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) + online (HA_ALTER_INPLACE_NO_LOCK or HA_ALTER_INPLACE_COPY_NO_LOCK) If set, it will be used with ER_ALTER_OPERATION_NOT_SUPPORTED_REASON if results from handler::check_if_supported_inplace_alter() doesn't match requirements set by user. If not set, the more generic @@ -2160,7 +2391,7 @@ public: replace not_supported with. */ void report_unsupported_error(const char *not_supported, - const char *try_instead); + const char *try_instead) const; }; @@ -2168,8 +2399,9 @@ typedef struct st_key_create_information { enum ha_key_alg algorithm; ulong block_size; - LEX_STRING parser_name; - LEX_STRING comment; + uint flags; /* HA_USE.. flags */ + LEX_CSTRING parser_name; + LEX_CSTRING comment; /** A flag to determine if we will check for duplicate indexes. This typically means that the key information was specified @@ -2549,6 +2781,7 @@ public: time_t check_time; time_t update_time; uint block_size; /* index block size */ + ha_checksum checksum; /* number of buffer bytes that native mrr implementation needs, @@ -2557,9 +2790,10 @@ public: ha_statistics(): data_file_length(0), max_data_file_length(0), - index_file_length(0), delete_length(0), auto_increment_value(0), - records(0), deleted(0), mean_rec_length(0), create_time(0), - check_time(0), update_time(0), block_size(0), mrr_length_per_rec(0) + index_file_length(0), max_index_file_length(0), delete_length(0), + auto_increment_value(0), records(0), deleted(0), mean_rec_length(0), + create_time(0), check_time(0), update_time(0), block_size(0), + mrr_length_per_rec(0) {} }; @@ -2675,6 +2909,8 @@ public: bool mark_trx_read_write_done; /* mark_trx_read_write was called */ bool check_table_binlog_row_based_done; /* check_table_binlog.. was called */ bool check_table_binlog_row_based_result; /* cached check_table_binlog... */ + /* Set to 1 if handler logged last insert/update/delete operation */ + bool row_already_logged; /* TRUE <=> the engine guarantees that returned records are within the range being scanned. @@ -2688,7 +2924,8 @@ public: /** Length of ref (1-8 or the clustered key length) */ uint ref_length; FT_INFO *ft_handler; - enum {NONE=0, INDEX, RND} inited; + enum init_stat { NONE=0, INDEX, RND }; + init_stat inited, pre_inited; const COND *pushed_cond; /** @@ -2754,6 +2991,11 @@ public: virtual void unbind_psi(); virtual void rebind_psi(); + bool set_top_table_fields; + struct TABLE *top_table; + Field **top_table_field; + uint top_table_fields; + private: /** The lock type set by when calling::ha_external_lock(). This is @@ -2777,17 +3019,20 @@ public: mark_trx_read_write_done(0), check_table_binlog_row_based_done(0), check_table_binlog_row_based_result(0), + row_already_logged(0), in_range_check_pushed_down(FALSE), key_used_on_scan(MAX_KEY), active_index(MAX_KEY), keyread(MAX_KEY), ref_length(sizeof(my_off_t)), - ft_handler(0), inited(NONE), + ft_handler(0), inited(NONE), pre_inited(NONE), 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), - m_psi(NULL), m_lock_type(F_UNLCK), ha_share(NULL) + m_psi(NULL), set_top_table_fields(FALSE), top_table(0), + top_table_field(0), top_table_fields(0), + m_lock_type(F_UNLCK), ha_share(NULL) { DBUG_PRINT("info", ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", @@ -2807,7 +3052,8 @@ public: } /* ha_ methods: pubilc wrappers for private virtual API */ - int ha_open(TABLE *table, const char *name, int mode, uint test_if_locked); + int ha_open(TABLE *table, const char *name, int mode, uint test_if_locked, + MEM_ROOT *mem_root= 0, List<String> *partitions_to_open=NULL); int ha_index_init(uint idx, bool sorted) { DBUG_EXECUTE_IF("ha_index_init_fail", return HA_ERR_TABLE_DEF_CHANGED;); @@ -2880,7 +3126,7 @@ public: */ int ha_external_lock(THD *thd, int lock_type); int ha_write_row(uchar * buf); - int ha_update_row(const uchar * old_data, uchar * new_data); + int ha_update_row(const uchar * old_data, const uchar * new_data); int ha_delete_row(const uchar * buf); void ha_release_auto_increment(); @@ -2918,8 +3164,8 @@ public: int ret= end_bulk_insert(); DBUG_RETURN(ret); } - int ha_bulk_update_row(const uchar *old_data, uchar *new_data, - uint *dup_key_found); + int ha_bulk_update_row(const uchar *old_data, const uchar *new_data, + ha_rows *dup_key_found); int ha_delete_all_rows(); int ha_truncate(); int ha_reset_auto_increment(ulonglong value); @@ -3013,8 +3259,24 @@ public: virtual double keyread_time(uint index, uint ranges, ha_rows rows); virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; } + + /* + True if changes to the table is persistent (no rollback) + This is manly used to decide how to log changes to the table in + the binary log. + */ bool has_transactions() - { return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0; } + { + return ((ha_table_flags() & (HA_NO_TRANSACTIONS | HA_PERSISTENT_TABLE)) + == 0); + } + /* + True if the underlaying table doesn't support transactions + */ + bool has_transaction_manager() + { + return ((ha_table_flags() & HA_NO_TRANSACTIONS) == 0); + } /** This method is used to analyse the error to see whether the error @@ -3044,6 +3306,7 @@ public: Number of rows in table. It will only be called if (table_flags() & (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT)) != 0 */ + virtual int pre_records() { return 0; } virtual ha_rows records() { return stats.records; } /** Return upper bound of current number of records in the table @@ -3100,7 +3363,7 @@ public: @retval 0 Success @retval >0 Error code */ - virtual int exec_bulk_update(uint *dup_key_found) + virtual int exec_bulk_update(ha_rows *dup_key_found) { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; @@ -3109,7 +3372,7 @@ public: Perform any needed clean-up, no outstanding updates are there at the moment. */ - virtual void end_bulk_update() { return; } + virtual int end_bulk_update() { return 0; } /** Execute all outstanding deletes and close down the bulk delete. @@ -3121,6 +3384,83 @@ public: DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; } + virtual int pre_index_read_map(const uchar *key, + key_part_map keypart_map, + enum ha_rkey_function find_flag, + bool use_parallel) + { return 0; } + virtual int pre_index_first(bool use_parallel) + { return 0; } + virtual int pre_index_last(bool use_parallel) + { return 0; } + virtual int pre_index_read_last_map(const uchar *key, + key_part_map keypart_map, + bool use_parallel) + { return 0; } +/* + virtual int pre_read_multi_range_first(KEY_MULTI_RANGE **found_range_p, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, HANDLER_BUFFER *buffer, + bool use_parallel); +*/ + virtual int pre_multi_range_read_next(bool use_parallel) + { return 0; } + virtual int pre_read_range_first(const key_range *start_key, + const key_range *end_key, + bool eq_range, bool sorted, + bool use_parallel) + { return 0; } + virtual int pre_ft_read(bool use_parallel) + { return 0; } + virtual int pre_rnd_next(bool use_parallel) + { return 0; } + int ha_pre_rnd_init(bool scan) + { + int result; + DBUG_ENTER("ha_pre_rnd_init"); + DBUG_ASSERT(pre_inited==NONE || (pre_inited==RND && scan)); + pre_inited= (result= pre_rnd_init(scan)) ? NONE: RND; + DBUG_RETURN(result); + } + int ha_pre_rnd_end() + { + DBUG_ENTER("ha_pre_rnd_end"); + DBUG_ASSERT(pre_inited==RND); + pre_inited=NONE; + DBUG_RETURN(pre_rnd_end()); + } + virtual int pre_rnd_init(bool scan) { return 0; } + virtual int pre_rnd_end() { return 0; } + virtual int pre_index_init(uint idx, bool sorted) { return 0; } + virtual int pre_index_end() { return 0; } + int ha_pre_index_init(uint idx, bool sorted) + { + int result; + DBUG_ENTER("ha_pre_index_init"); + DBUG_ASSERT(pre_inited==NONE); + if (!(result= pre_index_init(idx, sorted))) + pre_inited=INDEX; + DBUG_RETURN(result); + } + int ha_pre_index_end() + { + DBUG_ENTER("ha_pre_index_end"); + DBUG_ASSERT(pre_inited==INDEX); + pre_inited=NONE; + DBUG_RETURN(pre_index_end()); + } + int ha_pre_index_or_rnd_end() + { + return (pre_inited == INDEX ? + ha_pre_index_end() : + pre_inited == RND ? ha_pre_rnd_end() : 0 ); + } + virtual bool vers_can_native(THD *thd) + { + return ht->flags & HTON_NATIVE_SYS_VERSIONING; + } + /** @brief Positions an index cursor to the index specified in the @@ -3153,6 +3493,18 @@ protected: virtual int index_last(uchar * buf) { return HA_ERR_WRONG_COMMAND; } virtual int index_next_same(uchar *buf, const uchar *key, uint keylen); + /** + @brief + The following functions works like index_read, but it find the last + row with the current key value or prefix. + @returns @see index_read_map(). + */ + virtual int index_read_last_map(uchar * buf, const uchar * key, + key_part_map keypart_map) + { + uint key_len= calculate_key_len(table, active_index, key, keypart_map); + return index_read_last(buf, key, key_len); + } virtual int close(void)=0; inline void update_rows_read() { @@ -3229,10 +3581,12 @@ public: int compare_key(key_range *range); int compare_key2(key_range *range) const; virtual int ft_init() { return HA_ERR_WRONG_COMMAND; } - void ft_end() { ft_handler=NULL; } + virtual int pre_ft_init() { return HA_ERR_WRONG_COMMAND; } + virtual void ft_end() {} + virtual int pre_ft_end() { return 0; } virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key) { return NULL; } -private: +public: virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(uchar *buf)=0; virtual int rnd_pos(uchar * buf, uchar *pos)=0; @@ -3260,6 +3614,7 @@ public: /* Same as above, but with statistics */ inline int ha_ft_read(uchar *buf); + inline void ha_ft_end() { ft_end(); ft_handler=NULL; } int ha_rnd_next(uchar *buf); int ha_rnd_pos(uchar *buf, uchar *pos); inline int ha_rnd_pos_by_record(uchar *buf); @@ -3289,6 +3644,9 @@ public: virtual int info(uint)=0; // see my_base.h for full description virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info, uint part_id); + virtual void set_partitions_to_open(List<String> *partition_names) {} + virtual int change_partitions_to_open(List<String> *partition_names) + { return 0; } virtual int extra(enum ha_extra_function operation) { return 0; } virtual int extra_opt(enum ha_extra_function operation, ulong arg) @@ -3317,6 +3675,8 @@ public: virtual void try_semi_consistent_read(bool) {} virtual void unlock_row() {} virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;} + virtual bool need_info_for_auto_inc() { return 0; } + virtual bool can_use_for_auto_inc_init() { return 1; } virtual void get_auto_increment(ulonglong offset, ulonglong increment, ulonglong nb_desired_values, ulonglong *first_value, @@ -3424,6 +3784,7 @@ public: return 0; } virtual void set_part_info(partition_info *part_info) {return;} + virtual void return_record_by_parent() { return; } virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0; @@ -3445,7 +3806,7 @@ public: virtual uint max_supported_key_part_length() const { return 255; } virtual uint min_record_length(uint options) const { return 1; } - virtual uint checksum() const { return 0; } + virtual int calculate_checksum(); virtual bool is_crashed() const { return 0; } virtual bool auto_repair(int error) const { return 0; } @@ -3512,7 +3873,7 @@ public: cached */ - virtual my_bool register_query_cache_table(THD *thd, char *table_key, + virtual my_bool register_query_cache_table(THD *thd, const char *table_key, uint key_length, qc_engine_callback *engine_callback, @@ -3628,6 +3989,41 @@ public: virtual void cond_pop() { return; }; /** + Push metadata for the current operation down to the table handler. + */ + virtual int info_push(uint info_type, void *info) { return 0; }; + + /** + This function is used to get correlating of a parent (table/column) + and children (table/column). When conditions are pushed down to child + table (like child of myisam_merge), child table needs to know about + which table/column is my parent for understanding conditions. + */ + virtual int set_top_table_and_fields(TABLE *top_table, + Field **top_table_field, + uint top_table_fields) + { + if (!set_top_table_fields) + { + set_top_table_fields= TRUE; + this->top_table= top_table; + this->top_table_field= top_table_field; + this->top_table_fields= top_table_fields; + } + return 0; + } + virtual void clear_top_table_fields() + { + if (set_top_table_fields) + { + set_top_table_fields= FALSE; + top_table= NULL; + top_table_field= NULL; + top_table_fields= 0; + } + } + + /** Push down an index condition to the handler. The server will use this method to push down a condition it wants @@ -3660,6 +4056,10 @@ public: pushed_idx_cond_keyno= MAX_KEY; in_range_check_pushed_down= false; } + + /* Needed for partition / spider */ + virtual TABLE_LIST *get_next_global_for_child() { return NULL; } + /** Part of old, deprecated in-place ALTER API. */ @@ -3711,8 +4111,8 @@ public: *) As the first step, we acquire a lock corresponding to the concurrency level which was returned by handler::check_if_supported_inplace_alter() and requested by the user. This lock is held for most of the - duration of in-place ALTER (if HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE - or HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE were returned we acquire an + duration of in-place ALTER (if HA_ALTER_INPLACE_COPY_LOCK + or HA_ALTER_INPLACE_COPY_NO_LOCK were returned we acquire an exclusive lock for duration of the next step only). *) After that we call handler::ha_prepare_inplace_alter_table() to give the storage engine a chance to update its internal structures with a higher @@ -3756,12 +4156,12 @@ public: @retval HA_ALTER_ERROR Unexpected error. @retval HA_ALTER_INPLACE_NOT_SUPPORTED Not supported, must use copy. @retval HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock. - @retval HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE + @retval HA_ALTER_INPLACE_COPY_LOCK Supported, but requires SNW lock during main phase. Prepare phase requires X lock. @retval HA_ALTER_INPLACE_SHARED_LOCK Supported, but requires SNW lock. - @retval HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE + @retval HA_ALTER_INPLACE_COPY_NO_LOCK Supported, concurrent reads/writes allowed. However, prepare phase requires X lock. @@ -3821,10 +4221,9 @@ protected: /** Allows the storage engine to update internal structures with concurrent writes blocked. If check_if_supported_inplace_alter() returns - HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE or - HA_ALTER_INPLACE_SHARED_AFTER_PREPARE, this function is called with - exclusive lock otherwise the same level of locking as for - inplace_alter_table() will be used. + HA_ALTER_INPLACE_COPY_NO_LOCK or HA_ALTER_INPLACE_COPY_LOCK, + this function is called with exclusive lock otherwise the same level + of locking as for inplace_alter_table() will be used. @note Storage engines are responsible for reporting any errors by calling my_error()/print_error() @@ -3934,14 +4333,14 @@ public: but we don't have a primary key */ virtual void use_hidden_primary_key(); - virtual uint alter_table_flags(uint flags) + virtual alter_table_operations alter_table_flags(alter_table_operations flags) { if (ht->alter_table_flags) return ht->alter_table_flags(flags); return 0; } - LEX_STRING *engine_name() { return hton_name(ht); } + virtual LEX_CSTRING *engine_name(); TABLE* get_table() { return table; } TABLE_SHARE* get_table_share() { return table_share; } @@ -3971,7 +4370,8 @@ protected: virtual int delete_table(const char *name); public: - inline bool check_table_binlog_row_based(bool binlog_row); + bool check_table_binlog_row_based(bool binlog_row); + inline void clear_cached_table_binlog_row_based_flag() { check_table_binlog_row_based_done= 0; @@ -3987,6 +4387,8 @@ private: mark_trx_read_write_internal(); } } + +private: void mark_trx_read_write_internal(); bool check_table_binlog_row_based_internal(bool binlog_row); @@ -4033,15 +4435,64 @@ private: message will contain garbage. */ virtual int update_row(const uchar *old_data __attribute__((unused)), - uchar *new_data __attribute__((unused))) + const uchar *new_data __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } + /* + Optimized function for updating the first row. Only used by sequence + tables + */ + virtual int update_first_row(uchar *new_data); + virtual int delete_row(const uchar *buf __attribute__((unused))) { return HA_ERR_WRONG_COMMAND; } + + /* Perform initialization for a direct update request */ +public: + int ha_direct_update_rows(ha_rows *update_rows); + virtual int direct_update_rows_init(List<Item> *update_fields) + { + return HA_ERR_WRONG_COMMAND; + } +private: + virtual int pre_direct_update_rows_init(List<Item> *update_fields) + { + return HA_ERR_WRONG_COMMAND; + } + virtual int direct_update_rows(ha_rows *update_rows __attribute__((unused))) + { + return HA_ERR_WRONG_COMMAND; + } + virtual int pre_direct_update_rows() + { + return HA_ERR_WRONG_COMMAND; + } + + /* Perform initialization for a direct delete request */ +public: + int ha_direct_delete_rows(ha_rows *delete_rows); + virtual int direct_delete_rows_init() + { + return HA_ERR_WRONG_COMMAND; + } +private: + virtual int pre_direct_delete_rows_init() + { + return HA_ERR_WRONG_COMMAND; + } + virtual int direct_delete_rows(ha_rows *delete_rows __attribute__((unused))) + { + return HA_ERR_WRONG_COMMAND; + } + virtual int pre_direct_delete_rows() + { + return HA_ERR_WRONG_COMMAND; + } + /** Reset state of file to after 'open'. This function is called after every statement for all tables used @@ -4099,7 +4550,13 @@ protected: virtual int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag) { return HA_ERR_WRONG_COMMAND; } + virtual int index_read_last(uchar * buf, const uchar * key, uint key_len) + { + my_errno= HA_ERR_WRONG_COMMAND; + return HA_ERR_WRONG_COMMAND; + } friend class ha_partition; + friend class ha_sequence; public: /** This method is similar to update_row, however the handler doesn't need @@ -4114,8 +4571,8 @@ public: @retval 0 Bulk delete used by handler @retval 1 Bulk delete not used, normal operation used */ - virtual int bulk_update_row(const uchar *old_data, uchar *new_data, - uint *dup_key_found) + virtual int bulk_update_row(const uchar *old_data, const uchar *new_data, + ha_rows *dup_key_found) { DBUG_ASSERT(FALSE); return HA_ERR_WRONG_COMMAND; @@ -4166,7 +4623,6 @@ public: virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; } virtual int discard_or_import_tablespace(my_bool discard) { return (my_errno=HA_ERR_WRONG_COMMAND); } - virtual void prepare_for_alter() { return; } virtual void drop_table(const char *name); virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0; @@ -4200,11 +4656,32 @@ public: virtual handlerton *partition_ht() const { return ht; } inline int ha_write_tmp_row(uchar *buf); + inline int ha_delete_tmp_row(uchar *buf); inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data); virtual void set_lock_type(enum thr_lock_type lock); friend enum icp_result handler_index_cond_check(void* h_arg); + + /** + Find unique record by index or unique constrain + + @param record record to find (also will be fillded with + actual record fields) + @param unique_ref index or unique constraiun number (depends + on what used in the engine + + @retval -1 Error + @retval 1 Not found + @retval 0 Found + */ + virtual int find_unique_row(uchar *record, uint unique_ref) + { return -1; /*unsupported */} + + bool native_versioned() const + { DBUG_ASSERT(ht); return partition_ht()->flags & HTON_NATIVE_SYS_VERSIONING; } + virtual void update_partition(uint part_id) + {} protected: Handler_share *get_ha_share_ptr(); void set_ha_share_ptr(Handler_share *arg_ha_share); @@ -4227,7 +4704,7 @@ extern const char *myisam_stats_method_names[]; extern ulong total_ha, total_ha_2pc; /* lookups */ -plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name, bool tmp_table); +plugin_ref ha_resolve_by_name(THD *thd, const LEX_CSTRING *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, @@ -4282,7 +4759,7 @@ int ha_create_table(THD *thd, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, LEX_CUSTRING *frm); int ha_delete_table(THD *thd, handlerton *db_type, const char *path, - const char *db, const char *alias, bool generate_warning); + const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning); /* statistics and info */ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat); @@ -4295,11 +4772,11 @@ class Discovered_table_list: public handlerton::discovered_list const char *wild, *wend; bool with_temps; // whether to include temp tables in the result public: - Dynamic_array<LEX_STRING*> *tables; + Dynamic_array<LEX_CSTRING*> *tables; - Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_STRING*> *tables_arg, - const LEX_STRING *wild_arg); - Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_STRING*> *tables_arg) + Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_CSTRING*> *tables_arg, + const LEX_CSTRING *wild_arg); + Discovered_table_list(THD *thd_arg, Dynamic_array<LEX_CSTRING*> *tables_arg) : thd(thd_arg), wild(NULL), with_temps(true), tables(tables_arg) {} ~Discovered_table_list() {} @@ -4308,13 +4785,20 @@ public: void sort(); void remove_duplicates(); // assumes that the list is sorted +#ifndef DBUG_OFF + /* + Used to find unstable mtr tests querying + INFORMATION_SCHEMA.TABLES without ORDER BY. + */ + void sort_desc(); +#endif }; int ha_discover_table(THD *thd, TABLE_SHARE *share); -int ha_discover_table_names(THD *thd, LEX_STRING *db, MY_DIR *dirp, +int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp, Discovered_table_list *result, bool reusable); -bool ha_table_exists(THD *thd, const char *db, const char *table_name, - handlerton **hton= 0); +bool ha_table_exists(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, + handlerton **hton= 0, bool *is_sequence= 0); #endif /* key cache */ @@ -4364,11 +4848,16 @@ const char *get_canonical_filename(handler *file, const char *path, bool mysql_xa_recover(THD *thd); void commit_checkpoint_notify_ha(handlerton *hton, void *cookie); -inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) +inline const LEX_CSTRING *table_case_name(HA_CREATE_INFO *info, const LEX_CSTRING *name) { - return ((lower_case_table_names == 2 && info->alias) ? info->alias : name); + return ((lower_case_table_names == 2 && info->alias.str) ? &info->alias : name); } +typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*); +int binlog_log_row(TABLE* table, + const uchar *before_record, + const uchar *after_record, + Log_func *log_func); #define TABLE_IO_WAIT(TRACKER, PSI, OP, INDEX, FLAGS, PAYLOAD) \ { \ @@ -4386,5 +4875,5 @@ 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); +int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table); #endif /* HANDLER_INCLUDED */ |