mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-14687 DELETE HISTORY in prepared stmt crash [fixes #421]
Also fixes broken truncate after 617e108fb6
This commit is contained in:
@ -28,15 +28,23 @@ select * from t for system_time all;
|
||||
a
|
||||
11
|
||||
22
|
||||
1
|
||||
2
|
||||
delete history from t before system_time timestamp now(6);
|
||||
prepare stmt from 'delete history from t before system_time timestamp now(6)';
|
||||
execute stmt;
|
||||
drop prepare stmt;
|
||||
select * from t for system_time all;
|
||||
a
|
||||
11
|
||||
22
|
||||
1
|
||||
2
|
||||
delete from t;
|
||||
create or replace procedure truncate_sp()
|
||||
begin
|
||||
delete history from t before system_time timestamp now(6);
|
||||
end~~
|
||||
call truncate_sp;
|
||||
select * from t for system_time all;
|
||||
a
|
||||
drop procedure truncate_sp;
|
||||
### Issue #399, truncate partitioned table is now unimplemented
|
||||
create or replace table t (a int)
|
||||
with system versioning
|
||||
@ -50,12 +58,14 @@ create or replace table t (i int) with system versioning;
|
||||
delete history from t before system_time now();
|
||||
create or replace view v as select * from t;
|
||||
delete history from v before system_time now();
|
||||
ERROR HY000: TRUNCATE table_name TO doesn't work with VIEWs
|
||||
ERROR HY000: DELETE HISTORY from VIEW is prohibited
|
||||
create or replace table t (i int);
|
||||
delete history from t before system_time now();
|
||||
ERROR HY000: Table `t` is not system-versioned
|
||||
create or replace view v as select * from t;
|
||||
delete history from v before system_time now();
|
||||
ERROR HY000: TRUNCATE table_name TO doesn't work with VIEWs
|
||||
ERROR HY000: DELETE HISTORY from VIEW is prohibited
|
||||
prepare stmt from 'delete history from t before system_time now()';
|
||||
ERROR HY000: Table `t` is not system-versioned
|
||||
drop table t;
|
||||
drop view v;
|
||||
|
@ -25,8 +25,21 @@ update t set a=22 where a=2;
|
||||
select * from t for system_time all;
|
||||
delete history from t before system_time timestamp @ts1;
|
||||
select * from t for system_time all;
|
||||
delete history from t before system_time timestamp now(6);
|
||||
prepare stmt from 'delete history from t before system_time timestamp now(6)';
|
||||
execute stmt; drop prepare stmt;
|
||||
select * from t for system_time all;
|
||||
delete from t;
|
||||
|
||||
delimiter ~~;
|
||||
create or replace procedure truncate_sp()
|
||||
begin
|
||||
delete history from t before system_time timestamp now(6);
|
||||
end~~
|
||||
delimiter ;~~
|
||||
call truncate_sp;
|
||||
select * from t for system_time all;
|
||||
|
||||
drop procedure truncate_sp;
|
||||
|
||||
--echo ### Issue #399, truncate partitioned table is now unimplemented
|
||||
|
||||
@ -43,15 +56,17 @@ delete history from t before system_time current_timestamp;
|
||||
create or replace table t (i int) with system versioning;
|
||||
delete history from t before system_time now();
|
||||
create or replace view v as select * from t;
|
||||
--error ER_VERS_TRUNCATE_TO_VIEW
|
||||
--error ER_VERS_TRUNCATE_VIEW
|
||||
delete history from v before system_time now();
|
||||
|
||||
create or replace table t (i int);
|
||||
--error ER_VERS_NOT_VERSIONED
|
||||
delete history from t before system_time now();
|
||||
create or replace view v as select * from t;
|
||||
--error ER_VERS_TRUNCATE_TO_VIEW
|
||||
--error ER_VERS_TRUNCATE_VIEW
|
||||
delete history from v before system_time now();
|
||||
--error ER_VERS_NOT_VERSIONED
|
||||
prepare stmt from 'delete history from t before system_time now()';
|
||||
|
||||
drop table t;
|
||||
drop view v;
|
||||
|
@ -7930,5 +7930,5 @@ ER_VERS_ALREADY_VERSIONED
|
||||
WARN_VERS_TRT_EXPERIMENTAL
|
||||
eng "Transaction-based system versioning is EXPERIMENTAL and is subject to change in future."
|
||||
|
||||
ER_VERS_TRUNCATE_TO_VIEW
|
||||
eng "TRUNCATE table_name TO doesn't work with VIEWs"
|
||||
ER_VERS_TRUNCATE_VIEW
|
||||
eng "DELETE HISTORY from VIEW is prohibited"
|
||||
|
@ -223,25 +223,21 @@ bool Update_plan::save_explain_data_intern(MEM_ROOT *mem_root,
|
||||
|
||||
|
||||
static bool record_should_be_deleted(THD *thd, TABLE *table, SQL_SELECT *sel,
|
||||
Explain_delete *explain)
|
||||
Explain_delete *explain, bool truncate_history)
|
||||
{
|
||||
bool check_delete= true;
|
||||
|
||||
if (table->versioned())
|
||||
{
|
||||
bool row_is_alive= table->vers_end_field()->is_max();
|
||||
/* If we are doing TRUNCATE TABLE with SYSTEM_TIME condition then historical
|
||||
record is deleted and current record is kept. Otherwise alive record is
|
||||
deleted and historical record is kept. */
|
||||
if ((thd->lex->sql_command == SQLCOM_TRUNCATE && table->pos_in_table_list->vers_conditions)
|
||||
? row_is_alive
|
||||
: !row_is_alive)
|
||||
return false;
|
||||
bool historical= !table->vers_end_field()->is_max();
|
||||
check_delete= truncate_history ? historical : !historical;
|
||||
}
|
||||
|
||||
explain->tracker.on_record_read();
|
||||
thd->inc_examined_row_count(1);
|
||||
if (table->vfield)
|
||||
(void) table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_DELETE);
|
||||
if (!sel || sel->skip_record(thd) > 0)
|
||||
if (check_delete && (!sel || sel->skip_record(thd) > 0))
|
||||
{
|
||||
explain->tracker.on_record_after_where();
|
||||
return true;
|
||||
@ -314,7 +310,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
{
|
||||
if (table_list->is_view_or_derived())
|
||||
{
|
||||
my_error(ER_VERS_TRUNCATE_TO_VIEW, MYF(0));
|
||||
my_error(ER_VERS_TRUNCATE_VIEW, MYF(0));
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
@ -329,7 +325,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
}
|
||||
#endif
|
||||
|
||||
DBUG_ASSERT(!conds);
|
||||
DBUG_ASSERT(!conds || thd->stmt_arena->is_stmt_execute());
|
||||
if (select_lex->vers_setup_conds(thd, table_list, &conds))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
@ -708,7 +704,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
while (!(error=info.read_record()) && !thd->killed &&
|
||||
! thd->is_error())
|
||||
{
|
||||
if (record_should_be_deleted(thd, table, select, explain))
|
||||
if (record_should_be_deleted(thd, table, select, explain, truncate_history))
|
||||
{
|
||||
table->file->position(table->record[0]);
|
||||
if ((error= deltempfile->unique_add((char*) table->file->ref)))
|
||||
@ -735,7 +731,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
||||
! thd->is_error())
|
||||
{
|
||||
if (delete_while_scanning)
|
||||
delete_record= record_should_be_deleted(thd, table, select, explain);
|
||||
delete_record= record_should_be_deleted(thd, table, select, explain,
|
||||
truncate_history);
|
||||
if (delete_record)
|
||||
{
|
||||
if (!truncate_history && table->triggers &&
|
||||
@ -945,6 +942,11 @@ l
|
||||
select_lex->leaf_tables, FALSE,
|
||||
DELETE_ACL, SELECT_ACL, TRUE))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (table_list->vers_conditions &&
|
||||
select_lex->vers_setup_conds(thd, table_list, conds))
|
||||
{
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) ||
|
||||
setup_fields(thd, Ref_ptr_array(),
|
||||
field_list, MARK_COLUMNS_READ, NULL, NULL, 0) ||
|
||||
|
Reference in New Issue
Block a user