mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
SQL, Tests: FOR SYSTEM_TIME for VIEWs [closes #98]
This commit is contained in:
@ -76,16 +76,12 @@ set @str= concat('
|
||||
engine ', engine);
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
create view vt1_1 as select x, y from t1;
|
||||
create view vt1_2 as select x, y, sys_end from t1;
|
||||
insert into t1(x, y) values(8001, 9001);
|
||||
insert into vt1_1(x, y) values(1001, 2001);
|
||||
insert into vt1_1 values(1002, 2002);
|
||||
insert into vt1_2(x, y) values(3001, 4001);
|
||||
set @str= concat('select x, y, ', fields, ' from t1');
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
select x, y from vt1_1;
|
||||
set @str= concat('select x, y, ', fields, ' from vt1_2');
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
end~~
|
||||
create procedure test_04(
|
||||
sys_type varchar(255),
|
||||
@ -176,47 +172,23 @@ x y sys_end
|
||||
8001 9001 2038-01-19 03:14:07.000000
|
||||
1001 2001 2038-01-19 03:14:07.000000
|
||||
1002 2002 2038-01-19 03:14:07.000000
|
||||
3001 4001 2038-01-19 03:14:07.000000
|
||||
x y
|
||||
8001 9001
|
||||
1001 2001
|
||||
1002 2002
|
||||
3001 4001
|
||||
x y sys_end
|
||||
8001 9001 2038-01-19 03:14:07.000000
|
||||
1001 2001 2038-01-19 03:14:07.000000
|
||||
1002 2002 2038-01-19 03:14:07.000000
|
||||
3001 4001 2038-01-19 03:14:07.000000
|
||||
insert into t1(x, y, sys_end) values(8001, 9001, '2015-1-1 1:1:1');
|
||||
ERROR HY000: System field `sys_end` is read-only
|
||||
insert into vt1_2 values(3002, 4002, '2015-2-2 2:2:2');
|
||||
ERROR HY000: System field `sys_end` is read-only
|
||||
drop table t1;
|
||||
drop view vt1_1;
|
||||
drop view vt1_2;
|
||||
call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
x y vtq_commit_ts(sys_end)
|
||||
8001 9001 2038-01-19 03:14:07.000000
|
||||
1001 2001 2038-01-19 03:14:07.000000
|
||||
1002 2002 2038-01-19 03:14:07.000000
|
||||
3001 4001 2038-01-19 03:14:07.000000
|
||||
x y
|
||||
8001 9001
|
||||
1001 2001
|
||||
1002 2002
|
||||
3001 4001
|
||||
x y vtq_commit_ts(sys_end)
|
||||
8001 9001 2038-01-19 03:14:07.000000
|
||||
1001 2001 2038-01-19 03:14:07.000000
|
||||
1002 2002 2038-01-19 03:14:07.000000
|
||||
3001 4001 2038-01-19 03:14:07.000000
|
||||
insert into t1(x, y, sys_end) values(8001, 9001, 1111111);
|
||||
ERROR HY000: System field `sys_end` is read-only
|
||||
insert into vt1_2 values(3002, 4002, 2222222);
|
||||
ERROR HY000: System field `sys_end` is read-only
|
||||
drop table t1;
|
||||
drop view vt1_1;
|
||||
drop view vt1_2;
|
||||
call test_04('timestamp(6)', 'myisam', 'sys_end');
|
||||
id a b
|
||||
1 1 1
|
||||
@ -304,7 +276,6 @@ No A B C D
|
||||
13 1 1 1 1
|
||||
14 1 1 1 1
|
||||
15 1 1 1 1
|
||||
16 1 1 1 1
|
||||
create table t1(
|
||||
x int unsigned,
|
||||
sys_start bigint unsigned generated always as row start,
|
||||
|
@ -12,10 +12,10 @@ set @vt2= concat("create view vt2 as select * from t1 for system_time as of time
|
||||
prepare stmt from @vt2;
|
||||
execute stmt;
|
||||
drop prepare stmt;
|
||||
select * from vt1;
|
||||
select * from vt1 for system_time all;
|
||||
x
|
||||
1
|
||||
select * from vt2;
|
||||
select * from vt2 for system_time all;
|
||||
x
|
||||
2
|
||||
select * from t1;
|
||||
@ -23,7 +23,94 @@ x
|
||||
create or replace view vt1 as select * from t1;
|
||||
show create view vt1;
|
||||
View Create View character_set_client collation_connection
|
||||
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x` from `t1` where `t1`.`sys_trx_end` = 18446744073709551615 query for system_time all latin1 latin1_swedish_ci
|
||||
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from `t1` FOR SYSTEM_TIME ALL where `t1`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci
|
||||
drop view vt1;
|
||||
drop view vt2;
|
||||
create view vt1 as select * from t1 for system_time all;
|
||||
select * from vt1 for system_time all;
|
||||
x
|
||||
2
|
||||
1
|
||||
prepare stmt from 'select * from vt1 for system_time all';
|
||||
execute stmt;
|
||||
x
|
||||
2
|
||||
1
|
||||
drop prepare stmt;
|
||||
select * from vt1;
|
||||
x
|
||||
2
|
||||
1
|
||||
prepare stmt from 'select * from vt1';
|
||||
execute stmt;
|
||||
x
|
||||
drop prepare stmt;
|
||||
select * from t1 for system_time as of timestamp @t1;
|
||||
x
|
||||
1
|
||||
select * from vt1 for system_time as of timestamp @t1;
|
||||
x
|
||||
2
|
||||
1
|
||||
prepare stmt from 'select * from vt1 for system_time as of timestamp @t1';
|
||||
execute stmt;
|
||||
x
|
||||
drop prepare stmt;
|
||||
create or replace view vt1 as select * from t1;
|
||||
select * from vt1 for system_time all;
|
||||
x
|
||||
prepare stmt from 'select * from vt1 for system_time all';
|
||||
execute stmt;
|
||||
x
|
||||
drop prepare stmt;
|
||||
insert into vt1 values (3);
|
||||
select * from t1;
|
||||
x
|
||||
3
|
||||
select * from vt1;
|
||||
x
|
||||
3
|
||||
select * from t1 for system_time all;
|
||||
x
|
||||
2
|
||||
1
|
||||
3
|
||||
select * from vt1 for system_time all;
|
||||
x
|
||||
3
|
||||
create view error_view as select *, sys_trx_start from t1;
|
||||
ERROR 42S21: Duplicate column name 'sys_trx_start'
|
||||
create view error_view as select *, sys_trx_end from t1;
|
||||
ERROR 42S21: Duplicate column name 'sys_trx_end'
|
||||
create or replace table t1 (x int) with system versioning;
|
||||
insert into t1 values (1), (2);
|
||||
set @t1=now(6);
|
||||
delete from t1 where x=2;
|
||||
set @t2=now(6);
|
||||
delete from t1 where x=1;
|
||||
set @t3=now(6);
|
||||
set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'");
|
||||
prepare stmt from @tmp;
|
||||
execute stmt;
|
||||
drop prepare stmt;
|
||||
set @tmp= concat("create or replace view vvt1 as select * from vt1 for system_time as of timestamp '", @t2, "'");
|
||||
prepare stmt from @tmp;
|
||||
execute stmt;
|
||||
drop prepare stmt;
|
||||
set @tmp= concat("create or replace view vvvt1 as select * from vvt1 for system_time as of timestamp '", @t3, "'");
|
||||
prepare stmt from @tmp;
|
||||
execute stmt;
|
||||
drop prepare stmt;
|
||||
select * from vt1 for system_time all;
|
||||
x
|
||||
1
|
||||
2
|
||||
select * from vvt1 for system_time all;
|
||||
x
|
||||
1
|
||||
select * from vvvt1 for system_time all;
|
||||
x
|
||||
drop view vvvt1;
|
||||
drop view vvt1;
|
||||
drop view vt1;
|
||||
drop table t1;
|
||||
|
@ -64,16 +64,12 @@ begin
|
||||
engine ', engine);
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
create view vt1_1 as select x, y from t1;
|
||||
create view vt1_2 as select x, y, sys_end from t1;
|
||||
insert into t1(x, y) values(8001, 9001);
|
||||
insert into vt1_1(x, y) values(1001, 2001);
|
||||
insert into vt1_1 values(1002, 2002);
|
||||
insert into vt1_2(x, y) values(3001, 4001);
|
||||
set @str= concat('select x, y, ', fields, ' from t1');
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
select x, y from vt1_1;
|
||||
set @str= concat('select x, y, ', fields, ' from vt1_2');
|
||||
prepare stmt from @str; execute stmt; drop prepare stmt;
|
||||
end~~
|
||||
|
||||
create procedure test_04(
|
||||
@ -150,22 +146,12 @@ call test_02('timestamp(6)', 'myisam', 'sys_end');
|
||||
call test_02('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
|
||||
call test_03('timestamp(6)', 'myisam', 'sys_end');
|
||||
--ERROR ER_VERS_READONLY_FIELD
|
||||
insert into t1(x, y, sys_end) values(8001, 9001, '2015-1-1 1:1:1');
|
||||
--ERROR ER_VERS_READONLY_FIELD
|
||||
insert into vt1_2 values(3002, 4002, '2015-2-2 2:2:2');
|
||||
drop table t1;
|
||||
drop view vt1_1;
|
||||
drop view vt1_2;
|
||||
|
||||
call test_03('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
--ERROR ER_VERS_READONLY_FIELD
|
||||
insert into t1(x, y, sys_end) values(8001, 9001, 1111111);
|
||||
--ERROR ER_VERS_READONLY_FIELD
|
||||
insert into vt1_2 values(3002, 4002, 2222222);
|
||||
drop table t1;
|
||||
drop view vt1_1;
|
||||
drop view vt1_2;
|
||||
|
||||
call test_04('timestamp(6)', 'myisam', 'sys_end');
|
||||
call test_04('bigint unsigned', 'innodb', 'vtq_commit_ts(sys_end)');
|
||||
|
@ -15,8 +15,8 @@ prepare stmt from @vt1; execute stmt; drop prepare stmt;
|
||||
set @vt2= concat("create view vt2 as select * from t1 for system_time as of timestamp '", @t2, "'");
|
||||
prepare stmt from @vt2; execute stmt; drop prepare stmt;
|
||||
|
||||
select * from vt1;
|
||||
select * from vt2;
|
||||
select * from vt1 for system_time all;
|
||||
select * from vt2 for system_time all;
|
||||
select * from t1;
|
||||
|
||||
create or replace view vt1 as select * from t1;
|
||||
@ -24,5 +24,53 @@ show create view vt1;
|
||||
|
||||
drop view vt1;
|
||||
drop view vt2;
|
||||
drop table t1;
|
||||
|
||||
create view vt1 as select * from t1 for system_time all;
|
||||
select * from vt1 for system_time all;
|
||||
prepare stmt from 'select * from vt1 for system_time all'; execute stmt; drop prepare stmt;
|
||||
|
||||
select * from vt1;
|
||||
prepare stmt from 'select * from vt1'; execute stmt; drop prepare stmt;
|
||||
|
||||
select * from t1 for system_time as of timestamp @t1;
|
||||
select * from vt1 for system_time as of timestamp @t1;
|
||||
prepare stmt from 'select * from vt1 for system_time as of timestamp @t1'; execute stmt; drop prepare stmt;
|
||||
|
||||
create or replace view vt1 as select * from t1;
|
||||
select * from vt1 for system_time all;
|
||||
prepare stmt from 'select * from vt1 for system_time all'; execute stmt; drop prepare stmt;
|
||||
|
||||
insert into vt1 values (3);
|
||||
select * from t1;
|
||||
select * from vt1;
|
||||
select * from t1 for system_time all;
|
||||
select * from vt1 for system_time all;
|
||||
|
||||
--error ER_DUP_FIELDNAME
|
||||
create view error_view as select *, sys_trx_start from t1;
|
||||
--error ER_DUP_FIELDNAME
|
||||
create view error_view as select *, sys_trx_end from t1;
|
||||
|
||||
create or replace table t1 (x int) with system versioning;
|
||||
insert into t1 values (1), (2);
|
||||
set @t1=now(6);
|
||||
delete from t1 where x=2;
|
||||
set @t2=now(6);
|
||||
delete from t1 where x=1;
|
||||
set @t3=now(6);
|
||||
|
||||
set @tmp= concat("create or replace view vt1 as select * from t1 for system_time as of timestamp '", @t1, "'");
|
||||
prepare stmt from @tmp; execute stmt; drop prepare stmt;
|
||||
set @tmp= concat("create or replace view vvt1 as select * from vt1 for system_time as of timestamp '", @t2, "'");
|
||||
prepare stmt from @tmp; execute stmt; drop prepare stmt;
|
||||
set @tmp= concat("create or replace view vvvt1 as select * from vvt1 for system_time as of timestamp '", @t3, "'");
|
||||
prepare stmt from @tmp; execute stmt; drop prepare stmt;
|
||||
|
||||
select * from vt1 for system_time all;
|
||||
select * from vvt1 for system_time all;
|
||||
select * from vvvt1 for system_time all;
|
||||
|
||||
drop view vvvt1;
|
||||
drop view vvt1;
|
||||
drop view vt1;
|
||||
drop table t1;
|
||||
|
@ -7576,6 +7576,19 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
if (f->field->flags & HIDDEN_FLAG)
|
||||
continue;
|
||||
}
|
||||
if (item->type() == Item::REF_ITEM)
|
||||
{
|
||||
Item *i= item;
|
||||
while (i->type() == Item::REF_ITEM)
|
||||
i= *((Item_ref *)i)->ref;
|
||||
if (i->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
Item_field *f= (Item_field *)i;
|
||||
DBUG_ASSERT(f->field);
|
||||
if (f->field->flags & HIDDEN_FLAG)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* cache the table for the Item_fields inserted by expanding stars */
|
||||
if (item->type() == Item::FIELD_ITEM && tables->cacheable_table)
|
||||
|
@ -684,6 +684,11 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr,
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
while (tables && tables->is_view() && !thd->stmt_arena->is_stmt_prepare())
|
||||
{
|
||||
tables= tables->view->select_lex.table_list.first;
|
||||
}
|
||||
|
||||
for (table= tables; table; table= table->next_local)
|
||||
{
|
||||
if (table->table && table->table->versioned())
|
||||
@ -790,10 +795,7 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr,
|
||||
}
|
||||
|
||||
if (vers_conditions.type == FOR_SYSTEM_TIME_ALL)
|
||||
{
|
||||
vers_conditions.unwrapped= true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
COND** dst_cond= where_expr;
|
||||
@ -954,8 +956,6 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr,
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
slex->vers_conditions.unwrapped= true;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
#undef newx
|
||||
}
|
||||
@ -16728,6 +16728,8 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
|
||||
List_iterator_fast<Item> li(fields);
|
||||
Item *item;
|
||||
Field **tmp_from_field=from_field;
|
||||
Field *sys_trx_start= NULL;
|
||||
Field *sys_trx_end= NULL;
|
||||
while ((item=li++))
|
||||
{
|
||||
Item::Type type=item->type();
|
||||
@ -16843,6 +16845,20 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
|
||||
goto err; // Got OOM
|
||||
continue; // Some kind of const item
|
||||
}
|
||||
|
||||
if (type == Item::FIELD_ITEM)
|
||||
{
|
||||
Item_field *item_field= (Item_field *)item;
|
||||
Field *field= item_field->field;
|
||||
TABLE_SHARE *s= field->table->s;
|
||||
if (s->versioned)
|
||||
{
|
||||
if (field->flags & VERS_SYS_START_FLAG)
|
||||
sys_trx_start= new_field;
|
||||
else if (field->flags & VERS_SYS_END_FLAG)
|
||||
sys_trx_end= new_field;
|
||||
}
|
||||
}
|
||||
if (type == Item::SUM_FUNC_ITEM)
|
||||
{
|
||||
Item_sum *agg_item= (Item_sum *) item;
|
||||
@ -16923,6 +16939,17 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
|
||||
total_uneven_bit_length= 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (sys_trx_start && sys_trx_end)
|
||||
{
|
||||
sys_trx_start->flags|= VERS_SYS_START_FLAG | HIDDEN_FLAG;
|
||||
sys_trx_end->flags|= VERS_SYS_END_FLAG | HIDDEN_FLAG;
|
||||
share->versioned= true;
|
||||
share->field= table->field;
|
||||
share->row_start_field= field_count - 2;
|
||||
share->row_end_field= field_count - 1;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(fieldnr == (uint) (reg_field - table->field));
|
||||
DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
|
||||
field_count= fieldnr;
|
||||
@ -25416,6 +25443,11 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
|
||||
|
||||
append_identifier(thd, str, t_alias, strlen(t_alias));
|
||||
}
|
||||
if (table && table->versioned())
|
||||
{
|
||||
// versioning conditions are already unwrapped to WHERE clause
|
||||
str->append(" FOR SYSTEM_TIME ALL");
|
||||
}
|
||||
|
||||
if (index_hints)
|
||||
{
|
||||
@ -25576,12 +25608,6 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type)
|
||||
str->append(having_value != Item::COND_FALSE ? "1" : "0");
|
||||
}
|
||||
|
||||
if (vers_conditions.unwrapped)
|
||||
{
|
||||
// versioning conditions are already unwrapped to WHERE clause
|
||||
str->append(STRING_WITH_LEN(" query for system_time all "));
|
||||
}
|
||||
|
||||
if (order_list.elements)
|
||||
{
|
||||
str->append(STRING_WITH_LEN(" order by "));
|
||||
|
@ -453,6 +453,26 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Implicitly add versioning fields if needed */
|
||||
{
|
||||
TABLE_LIST *tl = tables;
|
||||
while (tl && tl->is_view())
|
||||
tl = tl->view->select_lex.table_list.first;
|
||||
if (tl && tl->table)
|
||||
{
|
||||
TABLE_SHARE *s= tl->table->s;
|
||||
if (s->versioned)
|
||||
{
|
||||
select_lex->item_list.push_back(new (thd->mem_root) Item_field(
|
||||
thd, &select_lex->context, NULL, NULL,
|
||||
s->vers_start_field()->field_name));
|
||||
select_lex->item_list.push_back(new (thd->mem_root) Item_field(
|
||||
thd, &select_lex->context, NULL, NULL,
|
||||
s->vers_end_field()->field_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view= lex->unlink_first_table(&link_to_local);
|
||||
|
||||
if (check_db_dir_existence(view->db))
|
||||
@ -605,14 +625,22 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
||||
view->table_name, item->name) &
|
||||
VIEW_ANY_ACL);
|
||||
|
||||
if (fld && !fld->field->table->s->tmp_table)
|
||||
if (!fld)
|
||||
continue;
|
||||
TABLE_SHARE *s= fld->field->table->s;
|
||||
const char *field_name= fld->field->field_name;
|
||||
if (s->tmp_table ||
|
||||
(s->versioned &&
|
||||
(!strcmp(field_name, s->vers_start_field()->field_name) ||
|
||||
!strcmp(field_name, s->vers_end_field()->field_name))))
|
||||
{
|
||||
|
||||
final_priv&= fld->have_privileges;
|
||||
|
||||
if (~fld->have_privileges & priv)
|
||||
report_item= item;
|
||||
continue;
|
||||
}
|
||||
|
||||
final_priv&= fld->have_privileges;
|
||||
|
||||
if (~fld->have_privileges & priv)
|
||||
report_item= item;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2027,7 +2055,14 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view)
|
||||
{
|
||||
Item_field *fld;
|
||||
if ((fld= entry->item->field_for_view_update()))
|
||||
{
|
||||
TABLE_SHARE *s= fld->context->table_list->table->s;
|
||||
if (s->versioned &&
|
||||
(!strcmp(fld->name, s->vers_start_field()->field_name) ||
|
||||
!strcmp(fld->name, s->vers_end_field()->field_name)))
|
||||
continue;
|
||||
list->push_back(fld, thd->mem_root);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT");
|
||||
|
@ -1864,14 +1864,11 @@ struct vers_select_conds_t
|
||||
vers_range_unit_t unit;
|
||||
Item *start, *end;
|
||||
|
||||
bool unwrapped;
|
||||
|
||||
void empty()
|
||||
{
|
||||
type= FOR_SYSTEM_TIME_UNSPECIFIED;
|
||||
unit= UNIT_TIMESTAMP;
|
||||
start= end= NULL;
|
||||
unwrapped= false;
|
||||
}
|
||||
|
||||
void init(
|
||||
@ -1884,7 +1881,6 @@ struct vers_select_conds_t
|
||||
unit= u;
|
||||
start= s;
|
||||
end= e;
|
||||
unwrapped= false;
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user