109 lines
2.8 KiB
PL/PgSQL
109 lines
2.8 KiB
PL/PgSQL
create function tj.add_operation(redo text, undo text) returns void as
|
|
$$
|
|
declare
|
|
parent_id int;
|
|
curr_id int;
|
|
begin
|
|
select id into parent_id from tj.current_operation;
|
|
insert into tj.operation (id, redo, undo, parent) values (default, redo, undo, parent_id);
|
|
select max(id) into curr_id from tj.operation;
|
|
update tj.current_operation set id = curr_id where id = parent_id;
|
|
end;
|
|
$$ language plpgsql;
|
|
|
|
create function tj.have_transaction() returns boolean as
|
|
$$
|
|
declare
|
|
tran_count int;
|
|
begin
|
|
select count(*) into tran_count from tj.transaction_operation;
|
|
return tran_count > 0;
|
|
end;
|
|
$$ language plpgsql;
|
|
|
|
create function tj.execute_undo(discard boolean) returns void as
|
|
$$
|
|
declare
|
|
curr_id int;
|
|
have_tran boolean;
|
|
tran_id int;
|
|
strict_mode boolean;
|
|
undo_sql text;
|
|
parent_id int;
|
|
begin
|
|
select id into curr_id from tj.current_operation;
|
|
|
|
select tj.have_transaction() into have_tran;
|
|
if have_tran then
|
|
select strict into strict_mode from tj.transaction_operation;
|
|
if strict_mode then
|
|
return; -- strict mode disallow undo
|
|
else
|
|
select id into tran_id from tj.transaction_operation;
|
|
if tran_id >= curr_id then
|
|
return; -- # normal mode disallow undo start point, and there is foreign key constraint
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
select undo into undo_sql from tj.operation where id = curr_id;
|
|
if undo_sql = '' then
|
|
return;
|
|
end if;
|
|
|
|
select parent into parent_id from tj.operation where id = curr_id;
|
|
if discard then
|
|
update tj.operation set redo_child = null where id = parent_id;
|
|
else
|
|
update tj.operation set redo_child = curr_id where id = parent_id;
|
|
end if;
|
|
|
|
execute undo_sql;
|
|
|
|
update tj.current_operation set id = parent_id where id = curr_id;
|
|
|
|
if discard then
|
|
delete from tj.transaction_operation where id = curr_id;
|
|
delete from tj.snapshot_operation where id = curr_id;
|
|
delete from tj.operation where id = curr_id;
|
|
end if;
|
|
end;
|
|
$$ language plpgsql;
|
|
|
|
create function tj.undo() returns void as
|
|
$$
|
|
declare
|
|
begin
|
|
perform tj.execute_undo(false);
|
|
end;
|
|
$$ language plpgsql;
|
|
|
|
create function tj.discard_undo() returns void as
|
|
$$
|
|
declare
|
|
begin
|
|
perform tj.execute_undo(true);
|
|
end;
|
|
$$ language plpgsql;
|
|
|
|
create function tj.redo() returns void as
|
|
$$
|
|
declare
|
|
curr_id int;
|
|
child_id int;
|
|
redo_sql text;
|
|
begin
|
|
select id into curr_id from tj.current_operation;
|
|
|
|
select redo_child into child_id from tj.operation where id = curr_id;
|
|
if child_id = null then
|
|
return;
|
|
end if;
|
|
|
|
select redo into redo_sql from tj.operation where id = child_id;
|
|
|
|
execute redo_sql;
|
|
|
|
update tj.current_operation set id = child_id where id = curr_id;
|
|
end;
|
|
$$ language plpgsql; |