Skip to content

Commit 073c93b

Browse files
FooBarriorvuvova
authored andcommitted
MDEV-17082 Application-time periods: CREATE
* add syntax `CREATE TABLE ... PERIOD FOR <apptime>` * add table period entity
1 parent b636046 commit 073c93b

File tree

18 files changed

+617
-189
lines changed

18 files changed

+617
-189
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
create or replace table t (id int primary key, s date, e date,
2+
period for mytime(s,e));
3+
show create table t;
4+
Table Create Table
5+
t CREATE TABLE `t` (
6+
`id` int(11) NOT NULL,
7+
`s` date NOT NULL,
8+
`e` date NOT NULL,
9+
PRIMARY KEY (`id`),
10+
PERIOD FOR `mytime` (`s`, `e`),
11+
CONSTRAINT `CONSTRAINT_1` CHECK (`s` < `e`)
12+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
13+
create or replace table t (id int primary key, s timestamp(6), e timestamp(6),
14+
period for mytime(s,e));
15+
show create table t;
16+
Table Create Table
17+
t CREATE TABLE `t` (
18+
`id` int(11) NOT NULL,
19+
`s` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
20+
`e` timestamp(6) NOT NULL DEFAULT '0000-00-00 00:00:00.000000',
21+
PRIMARY KEY (`id`),
22+
PERIOD FOR `mytime` (`s`, `e`),
23+
CONSTRAINT `CONSTRAINT_1` CHECK (`s` < `e`)
24+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
25+
# SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)a)
26+
# 2) If a <table period definition> TPD is specified, then:
27+
# a) <table scope> shall not be specified.
28+
create or replace temporary table t (s date, e date, period for mytime(s,e));
29+
ERROR HY000: Application-time period table cannot be temporary
30+
# SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)e)iii)
31+
# The <data type or domain name> contained in CD1 is either DATE or a
32+
# timestamp type and it is equivalent to the <data type or domain name>
33+
# contained in CD2.
34+
create or replace table t (id int primary key, s datetime, e date,
35+
period for mytime(s,e));
36+
ERROR HY000: Fields of PERIOD FOR `mytime` have different types
37+
create or replace table t (s timestamp(2), e timestamp(6),
38+
period for mytime(s,e));
39+
ERROR HY000: Fields of PERIOD FOR `mytime` have different types
40+
create or replace table t (id int primary key, s int, e date,
41+
period for mytime(s,e));
42+
ERROR 42000: Incorrect column specifier for column 's'
43+
create or replace table t (id int primary key, s date, e date,
44+
period for mytime(s,x));
45+
ERROR 42S22: Unknown column 'x' in 'mytime'
46+
create or replace table t (id int primary key, s date, e date,
47+
period for mytime(s,e),
48+
period for mytime2(s,e));
49+
ERROR HY000: Cannot specify more than one application-time period
50+
# SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)d)
51+
# No <column name> in any <column definition> shall be equivalent to PN.
52+
create or replace table t (mytime int, s date, e date,
53+
period for mytime(s,e));
54+
ERROR 42S21: Duplicate column name 'mytime'
55+
# SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)e)v)2)A)
56+
# Neither CD1 nor CD2 shall contain an <identity column specification>, a
57+
# <generation clause>, a <system time period start column specification>,
58+
# or a <system time period end column specification>.
59+
create or replace table t (id int primary key,
60+
s date,
61+
e date generated always as (s+1),
62+
period for mytime(s,e));
63+
ERROR HY000: Period field `e` cannot be GENERATED ALWAYS AS
64+
create or replace table t (id int primary key,
65+
s date,
66+
e date as (s+1) VIRTUAL,
67+
period for mytime(s,e));
68+
ERROR HY000: Period field `e` cannot be GENERATED ALWAYS AS
69+
create or replace table t (id int primary key, s timestamp(6), e timestamp(6),
70+
st timestamp(6) as row start,
71+
en timestamp(6) as row end,
72+
period for system_time (st, en),
73+
period for mytime(st,e)) with system versioning;
74+
ERROR HY000: Period field `st` cannot be GENERATED ALWAYS AS
75+
# SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)
76+
# Let IDCN be an implementation-dependent <constraint name> that is not
77+
# equivalent to the <constraint name> of any table constraint descriptor
78+
# included in S.
79+
create or replace table t (x int, s date, e date,
80+
period for mytime(s, e),
81+
constraint mytime check (x > 1));
82+
show create table t;
83+
Table Create Table
84+
t CREATE TABLE `t` (
85+
`x` int(11) DEFAULT NULL,
86+
`s` date NOT NULL,
87+
`e` date NOT NULL,
88+
PERIOD FOR `mytime` (`s`, `e`),
89+
CONSTRAINT `CONSTRAINT_1` CHECK (`s` < `e`),
90+
CONSTRAINT `mytime` CHECK (`x` > 1)
91+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
92+
create or replace database test;

mysql-test/suite/period/t/create.test

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
create or replace table t (id int primary key, s date, e date,
2+
period for mytime(s,e));
3+
show create table t;
4+
create or replace table t (id int primary key, s timestamp(6), e timestamp(6),
5+
period for mytime(s,e));
6+
show create table t;
7+
8+
--echo # SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)a)
9+
--echo # 2) If a <table period definition> TPD is specified, then:
10+
--echo # a) <table scope> shall not be specified.
11+
--error ER_PERIOD_TEMPORARY_NOT_ALLOWED
12+
create or replace temporary table t (s date, e date, period for mytime(s,e));
13+
14+
--echo # SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)e)iii)
15+
--echo # The <data type or domain name> contained in CD1 is either DATE or a
16+
--echo # timestamp type and it is equivalent to the <data type or domain name>
17+
--echo # contained in CD2.
18+
--error ER_PERIOD_TYPES_MISMATCH
19+
create or replace table t (id int primary key, s datetime, e date,
20+
period for mytime(s,e));
21+
--error ER_PERIOD_TYPES_MISMATCH
22+
create or replace table t (s timestamp(2), e timestamp(6),
23+
period for mytime(s,e));
24+
--error ER_WRONG_FIELD_SPEC
25+
create or replace table t (id int primary key, s int, e date,
26+
period for mytime(s,e));
27+
--error ER_BAD_FIELD_ERROR
28+
create or replace table t (id int primary key, s date, e date,
29+
period for mytime(s,x));
30+
--error ER_MORE_THAN_ONE_PERIOD
31+
create or replace table t (id int primary key, s date, e date,
32+
period for mytime(s,e),
33+
period for mytime2(s,e));
34+
35+
--echo # SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)d)
36+
--echo # No <column name> in any <column definition> shall be equivalent to PN.
37+
--error ER_DUP_FIELDNAME
38+
create or replace table t (mytime int, s date, e date,
39+
period for mytime(s,e));
40+
41+
--echo # SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)e)v)2)A)
42+
--echo # Neither CD1 nor CD2 shall contain an <identity column specification>, a
43+
--echo # <generation clause>, a <system time period start column specification>,
44+
--echo # or a <system time period end column specification>.
45+
--error ER_PERIOD_FIELD_WRONG_ATTRIBUTES
46+
create or replace table t (id int primary key,
47+
s date,
48+
e date generated always as (s+1),
49+
period for mytime(s,e));
50+
51+
--error ER_PERIOD_FIELD_WRONG_ATTRIBUTES
52+
create or replace table t (id int primary key,
53+
s date,
54+
e date as (s+1) VIRTUAL,
55+
period for mytime(s,e));
56+
57+
--error ER_PERIOD_FIELD_WRONG_ATTRIBUTES
58+
create or replace table t (id int primary key, s timestamp(6), e timestamp(6),
59+
st timestamp(6) as row start,
60+
en timestamp(6) as row end,
61+
period for system_time (st, en),
62+
period for mytime(st,e)) with system versioning;
63+
64+
--echo # SQL16, Part 2, 11.3 <table definition>, Syntax Rules, 2)
65+
--echo # Let IDCN be an implementation-dependent <constraint name> that is not
66+
--echo # equivalent to the <constraint name> of any table constraint descriptor
67+
--echo # included in S.
68+
create or replace table t (x int, s date, e date,
69+
period for mytime(s, e),
70+
constraint mytime check (x > 1));
71+
show create table t;
72+
73+
create or replace database test;

sql/field.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4560,6 +4560,8 @@ class Column_definition: public Sql_alloc,
45604560

45614561
enum_column_versioning versioning;
45624562

4563+
Table_period_info *period;
4564+
45634565
Column_definition()
45644566
:Type_handler_hybrid_field_type(&type_handler_null),
45654567
compression_method_ptr(0),
@@ -4568,7 +4570,7 @@ class Column_definition: public Sql_alloc,
45684570
flags(0), pack_length(0), key_length(0),
45694571
option_list(NULL),
45704572
vcol_info(0), default_value(0), check_constraint(0),
4571-
versioning(VERSIONING_NOT_SET)
4573+
versioning(VERSIONING_NOT_SET), period(NULL)
45724574
{
45734575
interval_list.empty();
45744576
}

sql/handler.cc

Lines changed: 102 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7183,8 +7183,8 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info)
71837183

71847184
alter_info->flags|= ALTER_PARSER_ADD_COLUMN;
71857185

7186-
system_time= start_end_t(default_start, default_end);
7187-
as_row= system_time;
7186+
period= start_end_t(default_start, default_end);
7187+
as_row= period;
71887188

71897189
if (vers_create_sys_field(thd, default_start, alter_info, VERS_SYS_START_FLAG) ||
71907190
vers_create_sys_field(thd, default_end, alter_info, VERS_SYS_END_FLAG))
@@ -7375,7 +7375,7 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
73757375
DBUG_ASSERT(end.str);
73767376

73777377
as_row= start_end_t(start, end);
7378-
system_time= as_row;
7378+
period= as_row;
73797379

73807380
if (alter_info->create_list.elements)
73817381
{
@@ -7461,7 +7461,7 @@ Vers_parse_info::fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_
74617461
}
74627462

74637463
as_row= start_end_t(f_start->field_name, f_end->field_name);
7464-
system_time= as_row;
7464+
period= as_row;
74657465

74667466
create_info.options|= HA_VERSIONED_TABLE;
74677467
return false;
@@ -7486,14 +7486,14 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
74867486
return true;
74877487
}
74887488

7489-
if (!system_time.start || !system_time.end)
7489+
if (!period.start || !period.end)
74907490
{
74917491
my_error(ER_MISSING, MYF(0), table_name.str, "PERIOD FOR SYSTEM_TIME");
74927492
return true;
74937493
}
74947494

7495-
if (!as_row.start.streq(system_time.start) ||
7496-
!as_row.end.streq(system_time.end))
7495+
if (!as_row.start.streq(period.start) ||
7496+
!as_row.end.streq(period.end))
74977497
{
74987498
my_error(ER_VERS_PERIOD_COLUMNS, MYF(0), as_row.start.str, as_row.end.str);
74997499
return true;
@@ -7583,3 +7583,98 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
75837583
"ROW END" : found_flag ? "ROW START" : "ROW START/END");
75847584
return true;
75857585
}
7586+
7587+
static bool check_period_field(const Create_field* f, const char* name,
7588+
const char* period_name)
7589+
{
7590+
bool res= false;
7591+
if (!f)
7592+
{
7593+
my_error(ER_BAD_FIELD_ERROR, MYF(0), name, period_name);
7594+
res= true;
7595+
}
7596+
else if (f->type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_ERROR)
7597+
{
7598+
my_error(ER_WRONG_FIELD_SPEC, MYF(0), name);
7599+
res= true;
7600+
}
7601+
else if (f->vcol_info || f->flags & VERS_SYSTEM_FIELD)
7602+
{
7603+
my_error(ER_PERIOD_FIELD_WRONG_ATTRIBUTES, MYF(0),
7604+
f->field_name.str, "GENERATED ALWAYS AS");
7605+
}
7606+
7607+
return res;
7608+
}
7609+
7610+
bool Table_scope_and_contents_source_st::check_fields(
7611+
THD *thd, Alter_info *alter_info, TABLE_LIST &create_table)
7612+
{
7613+
bool res= vers_check_system_fields(thd, alter_info, create_table);
7614+
if (res)
7615+
return true;
7616+
7617+
if (!period_info.name)
7618+
return false;
7619+
7620+
if (tmp_table())
7621+
{
7622+
my_error(ER_PERIOD_TEMPORARY_NOT_ALLOWED, MYF(0));
7623+
return true;
7624+
}
7625+
7626+
Table_period_info::start_end_t &period= period_info.period;
7627+
const Create_field *row_start= NULL;
7628+
const Create_field *row_end= NULL;
7629+
List_iterator<Create_field> it(alter_info->create_list);
7630+
while (const Create_field *f= it++)
7631+
{
7632+
if (period.start.streq(f->field_name)) row_start= f;
7633+
else if (period.end.streq(f->field_name)) row_end= f;
7634+
7635+
if (period_info.name.streq(f->field_name))
7636+
{
7637+
my_error(ER_DUP_FIELDNAME, MYF(0), f->field_name.str);
7638+
return true;
7639+
}
7640+
}
7641+
7642+
res= check_period_field(row_start, period.start.str, period_info.name.str);
7643+
res= res || check_period_field(row_end, period.end.str, period_info.name.str);
7644+
if (res)
7645+
return true;
7646+
7647+
if (row_start->type_handler() != row_end->type_handler()
7648+
|| row_start->length != row_end->length)
7649+
{
7650+
my_error(ER_PERIOD_TYPES_MISMATCH, MYF(0), period_info.name.str);
7651+
res= true;
7652+
}
7653+
7654+
return res;
7655+
}
7656+
7657+
bool
7658+
Table_scope_and_contents_source_st::fix_create_fields(THD *thd,
7659+
Alter_info *alter_info,
7660+
const TABLE_LIST &create_table,
7661+
bool create_select)
7662+
{
7663+
if (vers_fix_system_fields(thd, alter_info, create_table, create_select))
7664+
return true;
7665+
7666+
if (!period_info.name)
7667+
return false;
7668+
7669+
Table_period_info::start_end_t &period= period_info.period;
7670+
List_iterator<Create_field> it(alter_info->create_list);
7671+
while (Create_field *f= it++)
7672+
{
7673+
if (period.start.streq(f->field_name) || period.end.streq(f->field_name))
7674+
{
7675+
f->period= &period_info;
7676+
f->flags|= NOT_NULL_FLAG;
7677+
}
7678+
}
7679+
return false;
7680+
}

0 commit comments

Comments
 (0)