Files
TJWaterServer/script/script/api/create/operation.sql
2022-09-03 17:29:50 +08:00

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;