Commit e6230e84 authored by Nikita Malyavin's avatar Nikita Malyavin Committed by Sergei Golubchik

MDEV-15951 system versioning by trx id doesn't work with partitioning

Fix partitioning for trx_id-versioned tables.
`partition by hash`, `range` and others now work.
`partition by system_time` is forbidden.
Currently we cannot use row_start and row_end in `partition by`, because
insertion of versioned field is done by engine's handler, as well as
row_start/row_end's value set up, which is a transaction id -- so it's
also forbidden.

The drawback is that it's now impossible to use `partition by key()`
without parameters for such tables, because it references row_start and
row_end implicitly.

* add handler::vers_can_native()
* drop Table_scope_and_contents_source_st::vers_native()
* drop partition_element::find_engine_flag as unused
* forbid versioning partitioning for trx_id as not supported
* adopt vers tests for trx_id partitioning
* forbid any row_end referencing in `partition by` clauses,
  including implicit `by key()`
parent f6ee1324
set system_versioning_alter_history=keep;
# Check conventional partitioning on temporal tables
create table t1 (x int)
create or replace table t1 (
x int,
row_start SYS_DATATYPE as row start invisible,
row_end SYS_DATATYPE as row end invisible,
period for system_time(row_start, row_end))
with system versioning
partition by range columns (x) (
partition p0 values less than (100),
......@@ -34,7 +38,13 @@ select * from t1 partition (p1) for system_time all;
x
300
# Engine change native <-> non-native versioning prohibited
create or replace table t1 (i int) engine=DEFAULT_ENGINE with system versioning partition by hash(i);
create or replace table t1 (
i int,
row_start SYS_DATATYPE as row start invisible,
row_end SYS_DATATYPE as row end invisible,
period for system_time(row_start, row_end))
engine=DEFAULT_ENGINE
with system versioning partition by hash(i);
alter table t1 engine=NON_DEFAULT_ENGINE;
ERROR HY000: Not allowed for system-versioned `test`.`t1`. Change to/from native system versioning engine is not supported.
## CREATE TABLE
......@@ -322,14 +332,21 @@ select * from t1 partition (p1sp0);
x
select * from t1 partition (p1sp1);
x
create or replace table t1 (a bigint)
create or replace table t1 (
a bigint,
row_start SYS_DATATYPE as row start invisible,
row_end SYS_DATATYPE as row end invisible,
period for system_time(row_start, row_end))
with system versioning
partition by range (a)
(partition p0 values less than (20) engine innodb,
partition p1 values less than maxvalue engine innodb);
insert into t1 values (1);
create or replace table t1 (
f_int1 integer default 0
f_int1 integer default 0,
row_start SYS_DATATYPE as row start invisible,
row_end SYS_DATATYPE as row end invisible,
period for system_time(row_start, row_end)
) with system versioning
partition by range(f_int1)
subpartition by hash(f_int1)
......@@ -338,7 +355,11 @@ subpartition by hash(f_int1)
subpartition subpart12 storage engine = 'innodb'));
insert into t1 values (1);
create or replace table t1 (i int) engine=innodb partition by key(i);
alter table t1 add system versioning;
alter table t1
add column row_start SYS_DATATYPE as row start invisible,
add column row_end SYS_DATATYPE as row end invisible,
add period for system_time(row_start, row_end),
add system versioning;
insert into t1 values();
# MDEV-14722 Assertion in ha_commit_trans for sub-statement
create or replace table t1 (i int) with system versioning
......
# MDEV-15951 system versioning by trx id doesn't work with partitioning
# currently trx_id does not support partitioning by system_time
create or replace table t1(
i int,
row_start bigint unsigned generated always as row start,
row_end bigint unsigned generated always as row end,
period for system_time(row_start, row_end)
) engine=InnoDB with system versioning partition by system_time (
partition p0 history,
partition pn current
);
ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1`
create or replace table t1(
i int,
row_start bigint unsigned generated always as row start,
row_end bigint unsigned generated always as row end,
period for system_time(row_start, row_end)
) engine=InnoDB with system versioning;
alter table t1 partition by system_time (
partition p0 history,
partition pn current
);
ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `#sql-temporary`
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by key() (
partition p1,
partition p2
);
ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by key(a, row_start) (
partition p1,
partition p2
);
ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by hash(a + row_end * 2) (
partition p1,
partition p2
);
ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by range columns (a, row_start) (
partition p1 values less than (100, 100)
);
ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END
# Test cleanup
drop database test;
create database test;
[timestamp]
default-storage-engine=innodb
[myisam]
default-storage-engine=myisam
-- source include/have_partition.inc
-- source suite/versioning/common.inc
-- source suite/versioning/engines.inc
set system_versioning_alter_history=keep;
--echo # Check conventional partitioning on temporal tables
create table t1 (x int)
--replace_result $sys_datatype_expl SYS_DATATYPE
eval create or replace table t1 (
x int,
row_start $sys_datatype_expl as row start invisible,
row_end $sys_datatype_expl as row end invisible,
period for system_time(row_start, row_end))
with system versioning
partition by range columns (x) (
partition p0 values less than (100),
......@@ -24,8 +30,14 @@ select * from t1 partition (p0) for system_time all;
select * from t1 partition (p1) for system_time all;
--echo # Engine change native <-> non-native versioning prohibited
--replace_result $default_engine DEFAULT_ENGINE
eval create or replace table t1 (i int) engine=$default_engine with system versioning partition by hash(i);
--replace_result $sys_datatype_expl SYS_DATATYPE $default_engine DEFAULT_ENGINE
eval create or replace table t1 (
i int,
row_start $sys_datatype_expl as row start invisible,
row_end $sys_datatype_expl as row end invisible,
period for system_time(row_start, row_end))
engine=$default_engine
with system versioning partition by hash(i);
--replace_result $non_default_engine NON_DEFAULT_ENGINE
--error ER_VERS_ALTER_ENGINE_PROHIBITED
eval alter table t1 engine=$non_default_engine;
......@@ -273,15 +285,24 @@ select * from t1 partition (p0sp1);
select * from t1 partition (p1sp0);
select * from t1 partition (p1sp1);
create or replace table t1 (a bigint)
--replace_result $sys_datatype_expl SYS_DATATYPE
eval create or replace table t1 (
a bigint,
row_start $sys_datatype_expl as row start invisible,
row_end $sys_datatype_expl as row end invisible,
period for system_time(row_start, row_end))
with system versioning
partition by range (a)
(partition p0 values less than (20) engine innodb,
partition p1 values less than maxvalue engine innodb);
insert into t1 values (1);
create or replace table t1 (
f_int1 integer default 0
--replace_result $sys_datatype_expl SYS_DATATYPE
eval create or replace table t1 (
f_int1 integer default 0,
row_start $sys_datatype_expl as row start invisible,
row_end $sys_datatype_expl as row end invisible,
period for system_time(row_start, row_end)
) with system versioning
partition by range(f_int1)
subpartition by hash(f_int1)
......@@ -291,7 +312,12 @@ subpartition subpart12 storage engine = 'innodb'));
insert into t1 values (1);
create or replace table t1 (i int) engine=innodb partition by key(i);
alter table t1 add system versioning;
--replace_result $sys_datatype_expl SYS_DATATYPE
eval alter table t1
add column row_start $sys_datatype_expl as row start invisible,
add column row_end $sys_datatype_expl as row end invisible,
add period for system_time(row_start, row_end),
add system versioning;
insert into t1 values();
--echo # MDEV-14722 Assertion in ha_commit_trans for sub-statement
......
--source include/have_innodb.inc
--source include/have_partition.inc
--echo # MDEV-15951 system versioning by trx id doesn't work with partitioning
--echo # currently trx_id does not support partitioning by system_time
--error ER_VERS_FIELD_WRONG_TYPE
create or replace table t1(
i int,
row_start bigint unsigned generated always as row start,
row_end bigint unsigned generated always as row end,
period for system_time(row_start, row_end)
) engine=InnoDB with system versioning partition by system_time (
partition p0 history,
partition pn current
);
create or replace table t1(
i int,
row_start bigint unsigned generated always as row start,
row_end bigint unsigned generated always as row end,
period for system_time(row_start, row_end)
) engine=InnoDB with system versioning;
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/
--error ER_VERS_FIELD_WRONG_TYPE
alter table t1 partition by system_time (
partition p0 history,
partition pn current
);
--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by key() (
partition p1,
partition p2
);
--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by key(a, row_start) (
partition p1,
partition p2
);
--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by hash(a + row_end * 2) (
partition p1,
partition p2
);
--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
create or replace table t (
a int primary key,
row_start bigint unsigned as row start invisible,
row_end bigint unsigned as row end invisible,
period for system_time(row_start, row_end)
) engine=innodb with system versioning
partition by range columns (a, row_start) (
partition p1 values less than (100, 100)
);
--echo # Test cleanup
drop database test;
create database test;
......@@ -412,6 +412,22 @@ class ha_partition :public handler
virtual void return_record_by_parent();
virtual bool vers_can_native(THD *thd)
{
if (thd->lex->part_info)
{
// PARTITION BY SYSTEM_TIME is not supported for now
return thd->lex->part_info->part_type != VERSIONING_PARTITION;
}
else
{
bool can= true;
for (uint i= 0; i < m_tot_parts && can; i++)
can= can && m_file[i]->vers_can_native(thd);
return can;
}
}
/*
-------------------------------------------------------------------------
MODULE create/delete handler object
......
......@@ -7035,28 +7035,6 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info)
return false;
}
bool Table_scope_and_contents_source_pod_st::vers_native(THD *thd) const
{
if (ha_check_storage_engine_flag(db_type, HTON_NATIVE_SYS_VERSIONING))
return true;
#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *info= thd->work_part_info;
if (info && !(used_fields & HA_CREATE_USED_ENGINE))
{
if (handlerton *hton= info->default_engine_type)
return ha_check_storage_engine_flag(hton, HTON_NATIVE_SYS_VERSIONING);
List_iterator_fast<partition_element> it(info->partitions);
while (partition_element *partition_element= it++)
{
if (partition_element->find_engine_flag(HTON_NATIVE_SYS_VERSIONING))
return true;
}
}
#endif
return false;
}
bool Table_scope_and_contents_source_st::vers_fix_system_fields(
THD *thd, Alter_info *alter_info, const TABLE_LIST &create_table,
......@@ -7133,7 +7111,7 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields(
if (!(options & HA_VERSIONED_TABLE))
return false;
return vers_info.check_sys_fields(create_table.table_name, create_table.db,
alter_info, vers_native(thd));
alter_info);
}
......@@ -7242,8 +7220,7 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
if (alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING)
{
bool native= create_info->vers_native(thd);
if (check_sys_fields(table_name, share->db, alter_info, native))
if (check_sys_fields(table_name, share->db, alter_info))
return true;
}
......@@ -7350,7 +7327,7 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db,
Alter_info *alter_info, bool native)
Alter_info *alter_info)
{
if (check_conditions(table_name, db))
return true;
......@@ -7381,8 +7358,7 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
{
f_check_unit= VERS_TIMESTAMP;
}
else if (native
&& f->type_handler() == &type_handler_longlong
else if (f->type_handler() == &type_handler_longlong
&& (f->flags & UNSIGNED_FLAG)
&& f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1))
{
......
......@@ -1993,7 +1993,7 @@ struct Vers_parse_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, bool native);
Alter_info *alter_info);
/**
At least one field was specified 'WITH/WITHOUT SYSTEM VERSIONING'.
......@@ -2077,8 +2077,6 @@ struct Table_scope_and_contents_source_pod_st // For trivial members
bool table_was_deleted;
sequence_definition *seq_create_info;
bool vers_native(THD *thd) const;
void init()
{
bzero(this, sizeof(*this));
......@@ -3456,6 +3454,10 @@ class handler :public Sql_alloc
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
......
......@@ -176,21 +176,6 @@ class partition_element :public Sql_alloc
DBUG_ASSERT(ev->col_val_array);
return ev->col_val_array[idx];
}
bool find_engine_flag(uint32 flag)
{
if (ha_check_storage_engine_flag(engine_type, flag))
return true;
List_iterator_fast<partition_element> it(subpartitions);
while (partition_element *element= it++)
{
if (element->find_engine_flag(flag))
return true;
}
return false;
}
};
#endif /* PARTITION_ELEMENT_INCLUDED */
......@@ -7907,8 +7907,8 @@ ER_UNUSED_24
ER_VERS_TEMPORARY
eng "TEMPORARY tables do not support system versioning"
ER_VERS_NOT_SUPPORTED
eng "%s is not supported for %s system-versioned tables"
ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
eng "Transactional system versioned tables do not support partitioning by ROW START or ROW END"
ER_INDEX_FILE_FULL
eng "The index file for table '%-.192s' is full"
ER_UPDATED_COLUMN_ONLY_ONCE
......
......@@ -341,7 +341,15 @@ static bool set_up_field_array(THD *thd, TABLE *table,
while ((field= *(ptr++)))
{
if (field->flags & GET_FIXED_FIELDS_FLAG)
{
if (table->versioned(VERS_TRX_ID)
&& unlikely(field->flags & VERS_SYSTEM_FIELD))
{
my_error(ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED, MYF(0));
DBUG_RETURN(TRUE);
}
num_fields++;
}
}
if (unlikely(num_fields > MAX_REF_PARTS))
{
......
......@@ -1781,7 +1781,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
goto err;
DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end));
versioned= VERS_TIMESTAMP;
vers_can_native= plugin_hton(se_plugin)->flags & HTON_NATIVE_SYS_VERSIONING;
vers_can_native= handler_file->vers_can_native(thd);
row_start_field= row_start;
row_end_field= row_end;
status_var_increment(thd->status_var.feature_system_versioning);
......
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