Commit c2a70c80 authored by Eugene Kosov's avatar Eugene Kosov Committed by GitHub

SQL, IB: option to drop historical rows on ALTER [closes #249]

parent a6aaa4fe
......@@ -533,6 +533,29 @@ Table Create Table
t CREATE TABLE `t` (
`a` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
set versioning_alter_history = DROP;
create or replace table t (a int) with system versioning engine innodb;
insert into t values (1);
update t set a = 2;
select * from t for system_time all;
a
2
1
alter table t add column b int;
select * from t for system_time all;
a b
2 NULL
create or replace table t (a int) with system versioning engine myisam;
insert into t values (1);
update t set a = 2;
select * from t for system_time all;
a
2
1
alter table t add column b int;
select * from t for system_time all;
a b
2 NULL
call verify_vtq;
No A B C D
1 1 1 1 1
......@@ -546,6 +569,9 @@ No A B C D
9 1 1 1 1
10 1 1 1 1
11 1 1 1 1
12 1 1 1 1
13 1 1 1 1
14 1 1 1 1
drop table t;
drop procedure verify_vtq;
drop procedure innodb_verify_vtq;
......
......@@ -82,7 +82,7 @@ create procedure drop_last_historical(table_name_arg varchar(255))
begin
call concat_exec2('drop table ', get_historical_table_name(table_name_arg));
end~~
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t (a int) with system versioning;
insert into t values (1);
update t set a=2 where a=1;
......@@ -106,10 +106,10 @@ call concat_exec3('select @tm=sys_trx_end from ', get_historical_table_name('t')
@tm=sys_trx_end
1
call drop_last_historical('t');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t_vtmd;
drop table t;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t (a int) with system versioning;
insert into t values (1);
update t set a=2 where a=1;
......@@ -133,10 +133,10 @@ call concat_exec3('select @tm=sys_trx_end from ', get_historical_table_name('t')
@tm=sys_trx_end
1
call drop_last_historical('t');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t_vtmd;
drop table t;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t (a int) with system versioning engine innodb;
insert into t values (1);
update t set a=2 where a=1;
......@@ -160,15 +160,15 @@ call concat_exec3('select @tm=sys_trx_end from ', get_historical_table_name('t')
@tm=sys_trx_end
1
call drop_last_historical('t');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t_vtmd;
drop table t;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t (a int) with system versioning engine innodb;
insert into t values (1);
update t set a=2 where a=1;
alter table t add column b int, algorithm=inplace;
set versioning_ddl_survival = 0;
set versioning_alter_history = keep;
drop procedure concat_exec2;
drop procedure concat_exec3;
drop function get_historical_table_name;
......
......@@ -44,12 +44,12 @@ substr(archive_name, 1, instr(archive_name, '_')) as C_archive_name
from tmp_vtmd for system_time all;
drop table tmp_vtmd;
end~~
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
create or replace table t0 (x int) with system versioning;
show tables;
Tables_in_test
t0
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t0 (x int) with system versioning;
show tables;
Tables_in_test
......@@ -72,9 +72,9 @@ call check_vtmd('t0_vtmd');
1
A_start B_end name C_archive_name
1 1 t0 NULL
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t0;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t0 (x int) with system versioning;
ERROR HY000: VTMD error: `test.t0_vtmd` exists and not empty!
alter table t0 add column (y int);
......@@ -93,19 +93,19 @@ call check_vtmd('t0_vtmd');
A_start B_end name C_archive_name
1 1 t0 t0_
call drop_archives('t0_vtmd');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop tables t0, t0_vtmd;
set versioning_ddl_survival= on;
set versioning_ddl_survival= off;
set versioning_alter_history= survive;
set versioning_alter_history= keep;
create or replace table x0 (x int) with system versioning;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
rename table x0 to d0;
show tables;
Tables_in_test
d0
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table d0;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table x0 (x int) with system versioning;
rename table x0 to d0;
show tables;
......@@ -118,9 +118,9 @@ call check_vtmd('d0_vtmd');
A_start B_end name C_archive_name
1 0 x0 NULL
1 1 d0 NULL
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table d0;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table x0 (x int) with system versioning;
rename table x0 to d0;
ERROR HY000: VTMD error: `test.d0_vtmd` table already exists!
......
......@@ -52,7 +52,7 @@ end~~
create table t (a int) with system versioning;
show create table t for system_time as of now;
ERROR 42S02: Table 'test.t_vtmd' doesn't exist
set versioning_ddl_survival=on;
set versioning_alter_history=survive;
create or replace table t (a int) with system versioning;
show create table t for system_time between timestamp @tm1 and timestamp @tm1;
ERROR HY000: SYSTEM_TIME range selector is prohibited
......
......@@ -257,6 +257,22 @@ select * from t;
alter table t without system versioning;
show create table t;
set versioning_alter_history = DROP;
create or replace table t (a int) with system versioning engine innodb;
insert into t values (1);
update t set a = 2;
select * from t for system_time all;
alter table t add column b int;
select * from t for system_time all;
create or replace table t (a int) with system versioning engine myisam;
insert into t values (1);
update t set a = 2;
select * from t for system_time all;
alter table t add column b int;
select * from t for system_time all;
call verify_vtq;
drop table t;
......
......@@ -30,7 +30,7 @@ end~~
delimiter ;~~
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t (a int) with system versioning;
insert into t values (1);
......@@ -49,10 +49,10 @@ call concat_exec3('select @tm=sys_trx_end from ', get_historical_table_name('t')
call drop_last_historical('t');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t_vtmd;
drop table t;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
# same for INNODB ALGORITHM=COPY
create or replace table t (a int) with system versioning;
......@@ -72,10 +72,10 @@ call concat_exec3('select @tm=sys_trx_end from ', get_historical_table_name('t')
call drop_last_historical('t');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t_vtmd;
drop table t;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
# same for INNODB default ALGORITHM
create or replace table t (a int) with system versioning engine innodb;
......@@ -95,10 +95,10 @@ call concat_exec3('select @tm=sys_trx_end from ', get_historical_table_name('t')
call drop_last_historical('t');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t_vtmd;
drop table t;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
# no DDL for INNODB explicit ALGORITHM=INPLACE
create or replace table t (a int) with system versioning engine innodb;
......@@ -106,7 +106,7 @@ insert into t values (1);
update t set a=2 where a=1;
alter table t add column b int, algorithm=inplace;
set versioning_ddl_survival = 0;
set versioning_alter_history = keep;
drop procedure concat_exec2;
drop procedure concat_exec3;
......
......@@ -57,18 +57,18 @@ end~~
delimiter ;~~
# create
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
create or replace table t0 (x int) with system versioning;
show tables;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table t0 (x int) with system versioning;
show tables;
show create table t0_vtmd;
call check_vtmd('t0_vtmd');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table t0;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
--error ER_VERS_VTMD_ERROR
create or replace table t0 (x int) with system versioning;
......@@ -82,28 +82,28 @@ alter table t0 drop column y;
call check_vtmd('t0_vtmd');
call drop_archives('t0_vtmd');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop tables t0, t0_vtmd;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
# rename
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
create or replace table x0 (x int) with system versioning;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
rename table x0 to d0;
show tables;
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table d0;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table x0 (x int) with system versioning;
rename table x0 to d0;
show tables;
call check_vtmd('d0_vtmd');
set versioning_ddl_survival= off;
set versioning_alter_history= keep;
drop table d0;
set versioning_ddl_survival= on;
set versioning_alter_history= survive;
create or replace table x0 (x int) with system versioning;
--error ER_VERS_VTMD_ERROR
......
......@@ -68,7 +68,7 @@ create table t (a int) with system versioning;
--error ER_NO_SUCH_TABLE
show create table t for system_time as of now;
set versioning_ddl_survival=on;
set versioning_alter_history=survive;
create or replace table t (a int) with system versioning;
--error ER_VERS_RANGE_PROHIBITED
......
......@@ -23,7 +23,7 @@ set sql_mode='';
set @orig_storage_engine=@@storage_engine;
set storage_engine=myisam;
set versioning_ddl_survival=off;
set versioning_alter_history=keep;
set @have_innodb= (select count(engine) from information_schema.engines where engine='INNODB' and support != 'NO');
SET @innodb_or_myisam=IF(@have_innodb <> 0, 'InnoDB', 'MyISAM');
......
......@@ -2119,6 +2119,8 @@ class Alter_inplace_info
static const HA_ALTER_FLAGS ALTER_DROP_CHECK_CONSTRAINT= 1ULL << 40;
static const HA_ALTER_FLAGS ALTER_DROP_HISTORICAL = 1ULL << 41;
/**
Create options (like MAX_ROWS) for the new version of table.
......
......@@ -208,6 +208,13 @@ enum vers_hide_enum
VERS_HIDE_FULL,
VERS_HIDE_NEVER
};
enum vers_alter_history_enum
{
VERS_ALTER_HISTORY_KEEP,
VERS_ALTER_HISTORY_SURVIVE,
VERS_ALTER_HISTORY_DROP
};
/* System Versioning end */
extern char *mysql_home_ptr, *pidfile_name_ptr;
......
......@@ -711,7 +711,7 @@ typedef struct system_variables
my_bool vers_force;
ulong vers_hide;
my_bool vers_innodb_algorithm_simple;
my_bool vers_ddl_survival;
ulong vers_alter_history;
} SV;
/**
......
......@@ -300,7 +300,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
(void) rename_table_in_stat_tables(thd, &db_name, &table_name,
&new_db_name, &new_table);
VTMD_rename vtmd(*ren_table);
if (thd->variables.vers_ddl_survival)
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE)
{
rc= vtmd.try_rename(thd, new_db_name, new_table);
if (rc)
......@@ -313,7 +313,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
new_alias);
if (rc)
{
if (thd->variables.vers_ddl_survival)
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE)
vtmd.revert_rename(thd, new_db_name);
revert_table_name:
/*
......
......@@ -2477,8 +2477,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
*(end= path + path_length - reg_ext_length)= '\0';
if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
thd->variables.vers_ddl_survival &&
table_type && table_type != view_pseudo_hton)
thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE &&
table_type && table_type != view_pseudo_hton)
{
error= vtmd.check_exists(thd);
if (error)
......@@ -5075,7 +5075,8 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
}
}
if (create_info->versioned() && thd->variables.vers_ddl_survival)
if (create_info->versioned() &&
thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE)
{
VTMD_table vtmd(*create_table);
if (vtmd.update(thd))
......@@ -6372,6 +6373,8 @@ static bool fill_alter_inplace_info(THD *thd,
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_ADD_CHECK_CONSTRAINT;
if (alter_info->flags & Alter_info::ALTER_DROP_CHECK_CONSTRAINT)
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_DROP_CHECK_CONSTRAINT;
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_DROP)
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_DROP_HISTORICAL;
/*
If we altering table with old VARCHAR fields we will be automatically
......@@ -8561,8 +8564,11 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
else
{
VTMD_rename vtmd(*table_list);
if (thd->variables.vers_ddl_survival && vtmd.try_rename(thd, new_db_name, new_table_name))
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE &&
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,
......@@ -8570,7 +8576,7 @@ simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
alter_ctx->new_db,
alter_ctx->new_alias))
{
if (thd->variables.vers_ddl_survival)
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE)
vtmd.revert_rename(thd, new_db_name);
revert_table_name:
(void) mysql_rename_table(old_db_type,
......@@ -8711,7 +8717,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
thd->open_options&= ~HA_OPEN_FOR_ALTER;
bool versioned= table_list->table && table_list->table->versioned();
bool vers_data_mod= versioned &&
thd->variables.vers_ddl_survival &&
thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE &&
alter_info->vers_data_modifying();
if (vers_data_mod)
......@@ -9949,11 +9955,14 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
else if (keep_versioned)
{
to->file->vers_auto_decrement= 0xffffffffffffffff;
if (thd->variables.vers_ddl_survival)
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE)
{
query_start= thd->query_start_TIME();
from_sys_trx_end= from->vers_end_field();
to_sys_trx_start= to->vers_start_field();
} else if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_DROP)
{
from_sys_trx_end= from->vers_end_field();
}
}
......@@ -10011,6 +10020,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
copy_ptr->do_copy(copy_ptr);
}
if (thd->variables.vers_alter_history == VERS_ALTER_HISTORY_DROP &&
from_sys_trx_end && !from_sys_trx_end->is_max())
{
continue;
}
if (make_versioned)
{
to_sys_trx_start->set_notnull();
......@@ -10022,7 +10037,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (!from_sys_trx_end->is_max())
continue; // Drop history rows.
}
else if (keep_versioned && thd->variables.vers_ddl_survival)
else if (keep_versioned &&
thd->variables.vers_alter_history == VERS_ALTER_HISTORY_SURVIVE)
{
if (!from_sys_trx_end->is_max())
continue; // Do not copy history rows.
......@@ -10048,13 +10064,13 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
break;
}
if (keep_versioned && to->versioned_by_engine() &&
!thd->variables.vers_ddl_survival)
thd->variables.vers_alter_history != VERS_ALTER_HISTORY_SURVIVE)
{
to->s->versioned= false;
}
error= to->file->ha_write_row(to->record[0]);
if (keep_versioned && to->versioned_by_engine() &&
!thd->variables.vers_ddl_survival)
thd->variables.vers_alter_history != VERS_ALTER_HISTORY_SURVIVE)
{
to->s->versioned= true;
}
......
......@@ -15660,6 +15660,12 @@ set_expr_or_default:
if ($$ == NULL)
MYSQL_YYABORT;
}
| DROP
{
$$=new (thd->mem_root) Item_string_sys(thd, "DROP", 4);
if ($$ == NULL)
MYSQL_YYABORT;
}
;
/* Lock function */
......
......@@ -406,9 +406,12 @@ static Sys_var_mybool Sys_vers_innodb_algorithm_simple(
SESSION_VAR(vers_innodb_algorithm_simple), CMD_LINE(OPT_ARG),
DEFAULT(TRUE));
static Sys_var_mybool Sys_vers_ddl_survival(
"versioning_ddl_survival", "Use system versioning DDL survival feature",
SESSION_VAR(vers_ddl_survival), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
static const char *vers_alter_history_keywords[]= {"KEEP", "SURVIVE", "DROP",
NULL};
static Sys_var_enum Sys_vers_alter_history(
"versioning_alter_history", "Versioning ALTER TABLE mode",
SESSION_VAR(vers_alter_history), CMD_LINE(OPT_ARG),
vers_alter_history_keywords, DEFAULT(VERS_ALTER_HISTORY_KEEP));
static Sys_var_ulonglong Sys_binlog_cache_size(
"binlog_cache_size", "The size of the transactional cache for "
......
......@@ -6450,7 +6450,8 @@ ha_innobase::inplace_alter_table(
ctx->add_index, ctx->add_key_numbers, ctx->num_to_add_index,
altered_table, ctx->add_cols, ctx->col_map,
ctx->add_autoinc, ctx->sequence, ctx->skip_pk_sort,
ctx->m_stage, add_v, eval_table);
ctx->m_stage, add_v, eval_table,
ha_alter_info->handler_flags & Alter_inplace_info::ALTER_DROP_HISTORICAL);
if (s_templ) {
ut_ad(ctx->need_rebuild() || ctx->num_to_add_vcol > 0
......
......@@ -349,7 +349,8 @@ row_merge_build_indexes(
bool skip_pk_sort,
ut_stage_alter_t* stage,
const dict_add_v_col_t* add_v,
struct TABLE* eval_table)
struct TABLE* eval_table,
bool drop_historical)
MY_ATTRIBUTE((warn_unused_result));
/********************************************************************//**
......
......@@ -1797,7 +1797,8 @@ row_merge_read_clustered_index(
double pct_cost,
fil_space_crypt_t* crypt_data,
row_merge_block_t* crypt_block,
struct TABLE* eval_table)
struct TABLE* eval_table,
bool drop_historical)
{
dict_index_t* clust_index; /* Clustered index */
......@@ -2237,7 +2238,7 @@ row_merge_read_clustered_index(
ut_ad(add_autoinc
< dict_table_get_n_user_cols(new_table));
bool row_is_historic = false;
bool historical_row = false;
if (DICT_TF2_FLAG_IS_SET(
new_table, DICT_TF2_VERSIONED)) {
const dfield_t *dfield = dtuple_get_nth_field(
......@@ -2245,7 +2246,7 @@ row_merge_read_clustered_index(
const byte *data = static_cast<const byte *>(
dfield_get_data(dfield));
ut_ad(dfield_get_len(dfield) == 8);
row_is_historic =
historical_row =
mach_read_from_8(data) != TRX_ID_MAX;
}
......@@ -2270,7 +2271,7 @@ row_merge_read_clustered_index(
}
ulonglong value;
if (likely(!row_is_historic))
if (likely(!historical_row))
value = sequence++;
else
value = historic_auto_decrement--;
......@@ -2302,8 +2303,9 @@ row_merge_read_clustered_index(
}
if (DICT_TF2_FLAG_IS_SET(old_table, DICT_TF2_VERSIONED)) {
if (DICT_TF2_FLAG_IS_SET(
new_table, DICT_TF2_VERSIONED)) {
if (DICT_TF2_FLAG_IS_SET(new_table,
DICT_TF2_VERSIONED) &&
!drop_historical) {
dfield_t *end = dtuple_get_nth_field(
row, new_table->vers_row_end);
byte *data = static_cast<byte *>(
......@@ -4674,7 +4676,8 @@ row_merge_build_indexes(
bool skip_pk_sort,
ut_stage_alter_t* stage,
const dict_add_v_col_t* add_v,
struct TABLE* eval_table)
struct TABLE* eval_table,
bool drop_historical)
{
merge_file_t* merge_files;
row_merge_block_t* block;
......@@ -4848,7 +4851,8 @@ row_merge_build_indexes(
fts_sort_idx, psort_info, merge_files, key_numbers,
n_indexes, add_cols, add_v, col_map, add_autoinc,
sequence, block, skip_pk_sort, &tmpfd, stage,
pct_cost, crypt_data, crypt_block, eval_table);
pct_cost, crypt_data, crypt_block, eval_table,
drop_historical);
stage->end_phase_read_pk();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment