1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

SQL, IB: (0.10) VTMD tracking [closes #124]

IB: Fixes in logic when to do versioned or usual row updates. Now it is
able to do unversioned updates for versioned tables just by disabling
`TABLE_SHARE::versioned` flag.

SQL: DDL tracking for:
* RENAME TABLE, ALTER TABLE .. RENAME TO;
* DROP TABLE;
* data-modifying operations (f.ex. ALTER TABLE .. ADD/DROP COLUMN).
This commit is contained in:
Aleksey Midenkov
2017-06-15 16:02:32 +03:00
parent efaa0d66da
commit 448374a228
26 changed files with 1536 additions and 51 deletions

View File

@@ -56,6 +56,7 @@
#include "sql_audit.h"
#include "sql_sequence.h"
#include "tztime.h"
#include "vtmd.h" // System Versioning
#ifdef __WIN__
@@ -2276,6 +2277,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db;
size_t db_length= table->db_length;
handlerton *table_type= 0;
VTMD_drop vtmd(*table);
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: 0x%lx s: 0x%lx",
table->db, table->table_name, (long) table->table,
@@ -2474,8 +2476,24 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
// Remove extension for delete
*(end= path + path_length - reg_ext_length)= '\0';
error= ha_delete_table(thd, table_type, path, db, table->table_name,
!dont_log_query);
if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
thd->variables.vers_ddl_survival &&
table_type && table_type != view_pseudo_hton)
{
error= vtmd.check_exists(thd);
if (error)
goto non_tmp_err;
if (!vtmd.exists)
goto drop_table;
error= mysql_rename_table(table_type, table->db, table->table_name,
table->db, vtmd.archive_name(thd), NO_FK_CHECKS);
}
else
{
drop_table:
error= ha_delete_table(thd, table_type, path, db, table->table_name,
!dont_log_query);
}
if (!error)
{
@@ -2510,8 +2528,18 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
else if (frm_delete_error && if_exists)
thd->clear_error();
}
non_tmp_err:
non_tmp_error|= MY_TEST(error);
}
if (!error && vtmd.exists)
{
error= vtmd.update(thd);
if (error)
mysql_rename_table(table_type, table->db, vtmd.archive_name(),
table->db, table->table_name, NO_FK_CHECKS);
}
if (error)
{
if (wrong_tables.length())
@@ -5040,6 +5068,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
{
thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
result= 1;
goto err;
}
else
{
@@ -5048,6 +5077,16 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
}
}
if (create_info->versioned() && thd->variables.vers_ddl_survival)
{
VTMD_table vtmd(*create_table);
if (vtmd.update(thd))
{
result= 1;
goto err;
}
}
err:
/* In RBR we don't need to log CREATE TEMPORARY TABLE */
if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
@@ -5155,15 +5194,6 @@ static void make_unique_constraint_name(THD *thd, LEX_STRING *name,
** Alter a table definition
****************************************************************************/
static void vers_table_name_date(THD *thd, const char *table_name,
char *new_name, size_t new_name_size)
{
const MYSQL_TIME now= thd->query_start_TIME();
my_snprintf(new_name, new_name_size, "%s_%04d%02d%02d_%02d%02d%02d_%06d",
table_name, now.year, now.month, now.day, now.hour, now.minute,
now.second, now.second_part);
}
bool operator!=(const MYSQL_TIME &lhs, const MYSQL_TIME &rhs)
{
return lhs.year != rhs.year || lhs.month != rhs.month || lhs.day != rhs.day ||
@@ -5466,6 +5496,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
/* Replace type of source table with one specified in the statement. */
local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
local_create_info.options|= create_info->tmp_table();
local_create_info.options|= create_info->options;
/* Reset auto-increment counter for the new table. */
local_create_info.auto_increment_value= 0;
/*
@@ -8529,18 +8560,27 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
if (mysql_rename_table(old_db_type, alter_ctx->db, alter_ctx->table_name,
alter_ctx->new_db, alter_ctx->new_alias, 0))
error= -1;
else if (Table_triggers_list::change_table_name(thd,
alter_ctx->db,
alter_ctx->alias,
alter_ctx->table_name,
alter_ctx->new_db,
alter_ctx->new_alias))
else
{
(void) mysql_rename_table(old_db_type,
alter_ctx->new_db, alter_ctx->new_alias,
alter_ctx->db, alter_ctx->table_name,
NO_FK_CHECKS);
error= -1;
VTMD_rename vtmd(*table_list);
if (thd->variables.vers_ddl_survival && vtmd.try_rename(thd, new_db_name, new_table_name))
goto revert_table_name;
else if (Table_triggers_list::change_table_name(thd,
alter_ctx->db,
alter_ctx->alias,
alter_ctx->table_name,
alter_ctx->new_db,
alter_ctx->new_alias))
{
if (thd->variables.vers_ddl_survival)
vtmd.revert_rename(thd, new_db_name);
revert_table_name:
(void) mysql_rename_table(old_db_type,
alter_ctx->new_db, alter_ctx->new_alias,
alter_ctx->db, alter_ctx->table_name,
NO_FK_CHECKS);
error= -1;
}
}
}
@@ -8672,7 +8712,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
&alter_prelocking_strategy);
thd->open_options&= ~HA_OPEN_FOR_ALTER;
bool versioned= table_list->table && table_list->table->versioned();
if (versioned && thd->variables.vers_ddl_survival)
bool vers_data_mod= versioned &&
thd->variables.vers_ddl_survival &&
alter_info->vers_data_modifying();
if (vers_data_mod)
{
table_list->set_lock_type(thd, TL_WRITE);
if (thd->mdl_context.upgrade_shared_lock(table_list->table->mdl_ticket,
@@ -9003,7 +9047,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
Upgrade from MDL_SHARED_UPGRADABLE to MDL_SHARED_NO_WRITE.
Afterwards it's safe to take the table level lock.
*/
if ((!(versioned && thd->variables.vers_ddl_survival) &&
if ((!vers_data_mod &&
thd->mdl_context.upgrade_shared_lock(
mdl_ticket, MDL_SHARED_NO_WRITE,
thd->variables.lock_wait_timeout)) ||
@@ -9435,8 +9479,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
alter_info->keys_onoff,
&alter_ctx))
{
if (table->versioned_by_sql() && new_versioned &&
thd->variables.vers_ddl_survival)
if (vers_data_mod && new_versioned && table->versioned_by_sql())
{
// Failure of this function may result in corruption of an original table.
vers_reset_alter_copy(thd, table);
@@ -9538,8 +9581,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
anything goes wrong while renaming the new table.
*/
char backup_name[FN_LEN];
if (versioned && thd->variables.vers_ddl_survival)
vers_table_name_date(thd, alter_ctx.table_name, backup_name,
if (vers_data_mod)
VTMD_table::archive_name(thd, alter_ctx.table_name, backup_name,
sizeof(backup_name));
else
my_snprintf(backup_name, sizeof(backup_name), "%s2-%lx-%lx",
@@ -9572,6 +9615,17 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err_with_mdl;
}
if (vers_data_mod && new_versioned)
{
DBUG_ASSERT(alter_info && table_list);
VTMD_rename vtmd(*table_list);
bool rc= alter_info->flags & Alter_info::ALTER_RENAME ?
vtmd.try_rename(thd, alter_ctx.new_db, alter_ctx.new_alias, backup_name) :
vtmd.update(thd, backup_name);
if (rc)
goto err_after_rename;
}
// Check if we renamed the table and if so update trigger files.
if (alter_ctx.is_table_renamed())
{
@@ -9582,6 +9636,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
alter_ctx.new_db,
alter_ctx.new_alias))
{
err_after_rename:
// Rename succeeded, delete the new table.
(void) quick_rm_table(thd, new_db_type,
alter_ctx.new_db, alter_ctx.new_alias, 0);
@@ -9596,7 +9651,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
// ALTER TABLE succeeded, delete the backup of the old table.
if (!(versioned && new_versioned && thd->variables.vers_ddl_survival) &&
if (!(vers_data_mod && new_versioned) &&
quick_rm_table(thd, old_db_type, alter_ctx.db, backup_name, FN_IS_TMP))
{
/*