summaryrefslogtreecommitdiffstats
path: root/sql/ddl_log.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/ddl_log.h')
-rw-r--r--sql/ddl_log.h358
1 files changed, 358 insertions, 0 deletions
diff --git a/sql/ddl_log.h b/sql/ddl_log.h
new file mode 100644
index 00000000..88f6695f
--- /dev/null
+++ b/sql/ddl_log.h
@@ -0,0 +1,358 @@
+/*
+ Copyright (c) 2000, 2019, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2021, 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
+*/
+
+/* External interfaces to ddl log functions */
+
+#ifndef DDL_LOG_INCLUDED
+#define DDL_LOG_INCLUDED
+
+enum ddl_log_entry_code
+{
+ /*
+ DDL_LOG_UNKOWN
+ Here mainly to detect blocks that are all zero
+
+ DDL_LOG_EXECUTE_CODE:
+ This is a code that indicates that this is a log entry to
+ be executed, from this entry a linked list of log entries
+ can be found and executed.
+ DDL_LOG_ENTRY_CODE:
+ An entry to be executed in a linked list from an execute log
+ entry.
+ DDL_LOG_IGNORE_ENTRY_CODE:
+ An entry that is to be ignored
+ */
+ DDL_LOG_UNKNOWN= 0,
+ DDL_LOG_EXECUTE_CODE= 1,
+ DDL_LOG_ENTRY_CODE= 2,
+ DDL_LOG_IGNORE_ENTRY_CODE= 3,
+ DDL_LOG_ENTRY_CODE_LAST= 4
+};
+
+
+/*
+ When adding things below, also add an entry to ddl_log_action_names and
+ ddl_log_entry_phases in ddl_log.cc
+*/
+
+enum ddl_log_action_code
+{
+ /*
+ The type of action that a DDL_LOG_ENTRY_CODE entry is to
+ perform.
+ */
+ DDL_LOG_UNKNOWN_ACTION= 0,
+
+ /* Delete a .frm file or a table in the partition engine */
+ DDL_LOG_DELETE_ACTION= 1,
+
+ /* Rename a .frm fire a table in the partition engine */
+ DDL_LOG_RENAME_ACTION= 2,
+
+ /*
+ Rename an entity after removing the previous entry with the
+ new name, that is replace this entry.
+ */
+ DDL_LOG_REPLACE_ACTION= 3,
+
+ /* Exchange two entities by renaming them a -> tmp, b -> a, tmp -> b */
+ DDL_LOG_EXCHANGE_ACTION= 4,
+ /*
+ log do_rename(): Rename of .frm file, table, stat_tables and triggers
+ */
+ DDL_LOG_RENAME_TABLE_ACTION= 5,
+ DDL_LOG_RENAME_VIEW_ACTION= 6,
+ DDL_LOG_DROP_INIT_ACTION= 7,
+ DDL_LOG_DROP_TABLE_ACTION= 8,
+ DDL_LOG_DROP_VIEW_ACTION= 9,
+ DDL_LOG_DROP_TRIGGER_ACTION= 10,
+ DDL_LOG_DROP_DB_ACTION=11,
+ DDL_LOG_CREATE_TABLE_ACTION=12,
+ DDL_LOG_CREATE_VIEW_ACTION=13,
+ DDL_LOG_DELETE_TMP_FILE_ACTION=14,
+ DDL_LOG_CREATE_TRIGGER_ACTION=15,
+ DDL_LOG_ALTER_TABLE_ACTION=16,
+ DDL_LOG_STORE_QUERY_ACTION=17,
+ DDL_LOG_LAST_ACTION /* End marker */
+};
+
+
+/* Number of phases for each ddl_log_action_code */
+extern const uchar ddl_log_entry_phases[DDL_LOG_LAST_ACTION];
+
+
+enum enum_ddl_log_exchange_phase {
+ EXCH_PHASE_NAME_TO_TEMP= 0,
+ EXCH_PHASE_FROM_TO_NAME= 1,
+ EXCH_PHASE_TEMP_TO_FROM= 2,
+ EXCH_PHASE_END
+};
+
+enum enum_ddl_log_rename_table_phase {
+ DDL_RENAME_PHASE_TRIGGER= 0,
+ DDL_RENAME_PHASE_STAT,
+ DDL_RENAME_PHASE_TABLE,
+ DDL_RENAME_PHASE_END
+};
+
+enum enum_ddl_log_drop_table_phase {
+ DDL_DROP_PHASE_TABLE=0,
+ DDL_DROP_PHASE_TRIGGER,
+ DDL_DROP_PHASE_BINLOG,
+ DDL_DROP_PHASE_RESET, /* Reset found list of dropped tables */
+ DDL_DROP_PHASE_END
+};
+
+enum enum_ddl_log_drop_db_phase {
+ DDL_DROP_DB_PHASE_INIT=0,
+ DDL_DROP_DB_PHASE_LOG,
+ DDL_DROP_DB_PHASE_END
+};
+
+enum enum_ddl_log_create_table_phase {
+ DDL_CREATE_TABLE_PHASE_INIT=0,
+ DDL_CREATE_TABLE_PHASE_LOG,
+ DDL_CREATE_TABLE_PHASE_END
+};
+
+enum enum_ddl_log_create_view_phase {
+ DDL_CREATE_VIEW_PHASE_NO_OLD_VIEW,
+ DDL_CREATE_VIEW_PHASE_DELETE_VIEW_COPY,
+ DDL_CREATE_VIEW_PHASE_OLD_VIEW_COPIED,
+ DDL_CREATE_VIEW_PHASE_END
+};
+
+enum enum_ddl_log_create_trigger_phase {
+ DDL_CREATE_TRIGGER_PHASE_NO_OLD_TRIGGER,
+ DDL_CREATE_TRIGGER_PHASE_DELETE_COPY,
+ DDL_CREATE_TRIGGER_PHASE_OLD_COPIED,
+ DDL_CREATE_TRIGGER_PHASE_END
+};
+
+enum enum_ddl_log_alter_table_phase {
+ DDL_ALTER_TABLE_PHASE_INIT,
+ DDL_ALTER_TABLE_PHASE_RENAME_FAILED,
+ DDL_ALTER_TABLE_PHASE_INPLACE_COPIED,
+ DDL_ALTER_TABLE_PHASE_INPLACE,
+ DDL_ALTER_TABLE_PHASE_PREPARE_INPLACE,
+ DDL_ALTER_TABLE_PHASE_CREATED,
+ DDL_ALTER_TABLE_PHASE_COPIED,
+ DDL_ALTER_TABLE_PHASE_OLD_RENAMED,
+ DDL_ALTER_TABLE_PHASE_UPDATE_TRIGGERS,
+ DDL_ALTER_TABLE_PHASE_UPDATE_STATS,
+ DDL_ALTER_TABLE_PHASE_UPDATE_BINARY_LOG,
+ DDL_ALTER_TABLE_PHASE_END
+};
+
+
+/*
+ Flags stored in DDL_LOG_ENTRY.flags
+ The flag values can be reused for different commands
+*/
+#define DDL_LOG_FLAG_ALTER_RENAME (1 << 0)
+#define DDL_LOG_FLAG_ALTER_ENGINE_CHANGED (1 << 1)
+#define DDL_LOG_FLAG_ONLY_FRM (1 << 2)
+#define DDL_LOG_FLAG_UPDATE_STAT (1 << 3)
+/*
+ Set when using ALTER TABLE on a partitioned table and the table
+ engine is not changed
+*/
+#define DDL_LOG_FLAG_ALTER_PARTITION (1 << 4)
+
+/*
+ Setting ddl_log_entry.phase to this has the same effect as setting
+ the phase to the maximum phase (..PHASE_END) for an entry.
+*/
+
+#define DDL_LOG_FINAL_PHASE ((uchar) 0xff)
+
+typedef struct st_ddl_log_entry
+{
+ LEX_CSTRING name;
+ LEX_CSTRING from_name;
+ LEX_CSTRING handler_name;
+ LEX_CSTRING db;
+ LEX_CSTRING from_db;
+ LEX_CSTRING from_handler_name;
+ LEX_CSTRING tmp_name; /* frm file or temporary file name */
+ LEX_CSTRING extra_name; /* Backup table name */
+ uchar uuid[MY_UUID_SIZE]; // UUID for new frm file
+
+ ulonglong xid; // Xid stored in the binary log
+ /*
+ unique_id can be used to store a unique number to check current state.
+ Currently it is used to store new size of frm file, link to another ddl log
+ entry or store an a uniq version for a storage engine in alter table.
+ For execute entries this is reused as an execute counter to ensure we
+ don't repeat an entry too many times if executing the entry fails.
+ */
+ ulonglong unique_id;
+ uint next_entry;
+ uint entry_pos; // Set by write_dll_log_entry()
+ uint16 flags; // Flags unique for each command
+ enum ddl_log_entry_code entry_type; // Set automatically
+ enum ddl_log_action_code action_type;
+ /*
+ Most actions have only one phase. REPLACE does however have two
+ phases. The first phase removes the file with the new name if
+ there was one there before and the second phase renames the
+ old name to the new name.
+ */
+ uchar phase; // set automatically
+} DDL_LOG_ENTRY;
+
+typedef struct st_ddl_log_memory_entry
+{
+ uint entry_pos;
+ struct st_ddl_log_memory_entry *next_log_entry;
+ struct st_ddl_log_memory_entry *prev_log_entry;
+ struct st_ddl_log_memory_entry *next_active_log_entry;
+} DDL_LOG_MEMORY_ENTRY;
+
+
+/*
+ State of the ddl log during execution of a DDL.
+
+ A ddl log state has one execute entry (main entry pointing to the first
+ action entry) and many 'action entries' linked in a list in the order
+ they should be executed.
+ One recovery the log is parsed and all execute entries will be executed.
+
+ All entries are stored as separate blocks in the ddl recovery file.
+*/
+
+typedef struct st_ddl_log_state
+{
+ /* List of ddl log entries */
+ DDL_LOG_MEMORY_ENTRY *list;
+ /* One execute entry per list */
+ DDL_LOG_MEMORY_ENTRY *execute_entry;
+ /*
+ Entry used for PHASE updates. Normally same as first in 'list', but in
+ case of a query log event, this points to the main event.
+ */
+ DDL_LOG_MEMORY_ENTRY *main_entry;
+ uint16 flags; /* Cache for flags */
+ bool is_active() { return list != 0; }
+} DDL_LOG_STATE;
+
+
+/* These functions are for recovery */
+bool ddl_log_initialize();
+void ddl_log_release();
+bool ddl_log_close_binlogged_events(HASH *xids);
+int ddl_log_execute_recovery();
+
+/* functions for updating the ddl log */
+bool ddl_log_write_entry(DDL_LOG_ENTRY *ddl_log_entry,
+ DDL_LOG_MEMORY_ENTRY **active_entry);
+
+bool ddl_log_write_execute_entry(uint first_entry, uint cond_entry,
+ DDL_LOG_MEMORY_ENTRY** active_entry);
+inline
+bool ddl_log_write_execute_entry(uint first_entry,
+ DDL_LOG_MEMORY_ENTRY **active_entry)
+{
+ return ddl_log_write_execute_entry(first_entry, 0, active_entry);
+}
+bool ddl_log_disable_execute_entry(DDL_LOG_MEMORY_ENTRY **active_entry);
+
+void ddl_log_complete(DDL_LOG_STATE *ddl_log_state);
+bool ddl_log_revert(THD *thd, DDL_LOG_STATE *ddl_log_state);
+
+bool ddl_log_update_phase(DDL_LOG_STATE *entry, uchar phase);
+bool ddl_log_add_flag(DDL_LOG_STATE *entry, uint16 flag);
+bool ddl_log_update_unique_id(DDL_LOG_STATE *state, ulonglong id);
+bool ddl_log_update_xid(DDL_LOG_STATE *state, ulonglong xid);
+bool ddl_log_disable_entry(DDL_LOG_STATE *state);
+bool ddl_log_increment_phase(uint entry_pos);
+void ddl_log_release_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry);
+bool ddl_log_sync();
+bool ddl_log_execute_entry(THD *thd, uint first_entry);
+
+void ddl_log_add_entry(DDL_LOG_STATE *state, DDL_LOG_MEMORY_ENTRY *log_entry);
+void ddl_log_release_entries(DDL_LOG_STATE *ddl_log_state);
+bool ddl_log_rename_table(DDL_LOG_STATE *ddl_state,
+ handlerton *hton,
+ const LEX_CSTRING *org_db,
+ const LEX_CSTRING *org_alias,
+ const LEX_CSTRING *new_db,
+ const LEX_CSTRING *new_alias);
+bool ddl_log_rename_view(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *org_db,
+ const LEX_CSTRING *org_alias,
+ const LEX_CSTRING *new_db,
+ const LEX_CSTRING *new_alias);
+bool ddl_log_drop_table_init(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *comment);
+bool ddl_log_drop_view_init(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db);
+bool ddl_log_drop_table(DDL_LOG_STATE *ddl_state,
+ handlerton *hton,
+ const LEX_CSTRING *path,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table);
+bool ddl_log_drop_view(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *path,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table);
+bool ddl_log_drop_trigger(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table,
+ const LEX_CSTRING *trigger_name,
+ const LEX_CSTRING *query);
+bool ddl_log_drop_view(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *path,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table);
+bool ddl_log_drop_db(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db, const LEX_CSTRING *path);
+bool ddl_log_create_table(DDL_LOG_STATE *ddl_state,
+ handlerton *hton,
+ const LEX_CSTRING *path,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table,
+ bool only_frm);
+bool ddl_log_create_view(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *path,
+ enum_ddl_log_create_view_phase phase);
+bool ddl_log_delete_tmp_file(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *path,
+ DDL_LOG_STATE *depending_state);
+bool ddl_log_create_trigger(DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db, const LEX_CSTRING *table,
+ const LEX_CSTRING *trigger_name,
+ enum_ddl_log_create_trigger_phase phase);
+bool ddl_log_alter_table(DDL_LOG_STATE *ddl_state,
+ handlerton *org_hton,
+ const LEX_CSTRING *db, const LEX_CSTRING *table,
+ handlerton *new_hton,
+ handlerton *partition_underlying_hton,
+ const LEX_CSTRING *new_db,
+ const LEX_CSTRING *new_table,
+ const LEX_CSTRING *frm_path,
+ const LEX_CSTRING *backup_table_name,
+ const LEX_CUSTRING *version,
+ ulonglong table_version,
+ bool is_renamed);
+bool ddl_log_store_query(THD *thd, DDL_LOG_STATE *ddl_log_state,
+ const char *query, size_t length);
+bool ddl_log_delete_frm(DDL_LOG_STATE *ddl_state, const char *to_path);
+extern mysql_mutex_t LOCK_gdl;
+#endif /* DDL_LOG_INCLUDED */