diff --git a/mysql-test/suite/versioning/r/truncate_history.result b/mysql-test/suite/versioning/r/truncate_history.result index d71354bcc36..667fb002d4b 100644 --- a/mysql-test/suite/versioning/r/truncate_history.result +++ b/mysql-test/suite/versioning/r/truncate_history.result @@ -111,5 +111,53 @@ select * from t for system_time all; a 9 8 +create or replace table t (a int) with system versioning; +insert into t values (1), (2); +update t set a=11 where a=1; +set @ts1=now(6); +update t set a=22 where a=2; +select * from t for system_time all; +a +11 +22 +1 +2 +truncate t for system_time before timestamp @ts1; +select * from t for system_time all; +a +11 +22 +2 +truncate t for system_time before timestamp now(6); +select * from t for system_time all; +a +11 +22 +create or replace table t (a int) with system versioning engine=innodb; +insert into t values (1), (2); +update t set a=11 where a=1; +set @ts1=now(6); +update t set a=22 where a=2; +select * from t for system_time all; +a +11 +22 +1 +2 +truncate t for system_time before timestamp @ts1; +select * from t for system_time all; +a +11 +22 +1 +2 +truncate t for system_time before timestamp now(6); +select * from t for system_time all; +a +11 +22 +2 +select * from t for system_time before timestamp now(); +ERROR HY000: `FOR SYSTEM_TIME BEFORE` works only with `TRUNCATE` query type drop table t; drop procedure truncate_history_of_t; diff --git a/mysql-test/suite/versioning/t/truncate_history.test b/mysql-test/suite/versioning/t/truncate_history.test index 42f60f51d46..d112af63df3 100644 --- a/mysql-test/suite/versioning/t/truncate_history.test +++ b/mysql-test/suite/versioning/t/truncate_history.test @@ -90,5 +90,30 @@ update t set a=9; truncate t for system_time timestamp between '1-1-1' and @ts2; select * from t for system_time all; +create or replace table t (a int) with system versioning; +insert into t values (1), (2); +update t set a=11 where a=1; +set @ts1=now(6); +update t set a=22 where a=2; +select * from t for system_time all; +truncate t for system_time before timestamp @ts1; +select * from t for system_time all; +truncate t for system_time before timestamp now(6); +select * from t for system_time all; + +create or replace table t (a int) with system versioning engine=innodb; +insert into t values (1), (2); +update t set a=11 where a=1; +set @ts1=now(6); +update t set a=22 where a=2; +select * from t for system_time all; +truncate t for system_time before timestamp @ts1; +select * from t for system_time all; +truncate t for system_time before timestamp now(6); +select * from t for system_time all; + +--error ER_VERS_WRONG_QUERY_TYPE +select * from t for system_time before timestamp now(); + drop table t; drop procedure truncate_history_of_t; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index daca9b4ce52..b30240f64c3 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7525,3 +7525,6 @@ WARN_VERS_PART_ROTATION ER_VERS_NOT_ALLOWED eng "%`s is not allowed for versioned table" + +ER_VERS_WRONG_QUERY_TYPE + eng "%`s works only with %`s query type" diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5d62b54b297..7d59d5164e1 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -283,11 +283,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_RETURN(TRUE); // trx_sees() in InnoDB reads sys_trx_start - if (!table->versioned_by_sql() && - (select_lex->vers_conditions.type == FOR_SYSTEM_TIME_BETWEEN || - select_lex->vers_conditions.type == FOR_SYSTEM_TIME_FROM_TO)) - { - bitmap_set_bit(table->read_set, table->vers_start_field()->field_index); + if (!table->versioned_by_sql()) { + if (select_lex->vers_conditions.type == FOR_SYSTEM_TIME_BETWEEN || + select_lex->vers_conditions.type == FOR_SYSTEM_TIME_FROM_TO) + { + bitmap_set_bit(table->read_set, table->vers_start_field()->field_index); + } + else if (select_lex->vers_conditions.type == FOR_SYSTEM_TIME_BEFORE) + { + bitmap_set_bit(table->read_set, table->vers_end_field()->field_index); + } } } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a00304760de..2d4d603c078 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -762,6 +762,14 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr, table->vers_conditions.type == FOR_SYSTEM_TIME_UNSPECIFIED ? slex->vers_conditions : table->vers_conditions; + if (vers_conditions.type == FOR_SYSTEM_TIME_BEFORE && + thd->lex->sql_command != SQLCOM_TRUNCATE) + { + my_error(ER_VERS_WRONG_QUERY_TYPE, MYF(0), "FOR SYSTEM_TIME BEFORE", + "TRUNCATE"); + DBUG_RETURN(-1); + } + if (vers_conditions.type != FOR_SYSTEM_TIME_UNSPECIFIED) { switch (slex->lock_type) @@ -869,6 +877,10 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr, cond2= newx Item_func_ge(thd, row_end, vers_conditions.start); break; + case FOR_SYSTEM_TIME_BEFORE: + cond1= newx Item_func_lt(thd, row_end, + vers_conditions.start); + break; default: DBUG_ASSERT(0); } @@ -912,6 +924,12 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr, newx Item_func_vtq_trx_sees_eq(thd, trx_id1, row_start); cond2= newx Item_func_vtq_trx_sees_eq(thd, row_end, trx_id0); break; + case FOR_SYSTEM_TIME_BEFORE: + trx_id0= vers_conditions.unit == UNIT_TIMESTAMP ? + newx Item_func_vtq_id(thd, vers_conditions.start, VTQ_TRX_ID) : + vers_conditions.start; + cond1= newx Item_func_lt(thd, row_end, trx_id0); + break; default: DBUG_ASSERT(0); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 11f4b53eb8b..2f1346eeb40 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8880,6 +8880,12 @@ for_system_time_expr: { Lex->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $1, $3, $5); } + | BEFORE_SYM + trans_or_timestamp + simple_expr + { + Lex->vers_conditions.init(FOR_SYSTEM_TIME_BEFORE, $2, $3); + } ; select_option_list: diff --git a/sql/table.h b/sql/table.h index a13de8d7128..cb24d211261 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1847,7 +1847,8 @@ enum vers_range_type_t FOR_SYSTEM_TIME_AS_OF, FOR_SYSTEM_TIME_FROM_TO, FOR_SYSTEM_TIME_BETWEEN, - FOR_SYSTEM_TIME_ALL + FOR_SYSTEM_TIME_ALL, + FOR_SYSTEM_TIME_BEFORE }; enum vers_range_unit_t