Implement undo in by PL/pgSQL

This commit is contained in:
wqy
2022-09-03 17:07:46 +08:00
parent 133feef4d2
commit 03a0d6cf64
7 changed files with 131 additions and 10 deletions

View File

@@ -1,22 +1,27 @@
-- get_title()
create function get_title() returns text as
create function tj.get_title() returns text as
$$
select value from title;
$$ language sql;
declare
title text;
begin
select value into title from tj.title;
return title;
end;
$$ language plpgsql;
-- update_title()
create function update_title(new_title text) returns void as
create function tj.set_title(new_title text) returns void as
$$
declare
old_title text;
redo text;
undo text;
begin
select get_title() into old_title;
update title set value = new_title where value = old_title;
select tj.get_title() into old_title;
update tj.title set value = new_title where value = old_title;
redo := concat('update title set value = ''', new_title, ''' where value = ''', old_title, '''');
undo := concat('update title set value = ''', old_title, ''' where value = ''', new_title, '''');
insert into operation values (default, redo, undo);
redo := concat('update tj.title set value = ''', new_title, ''' where value = ''', old_title, '''');
undo := concat('update tj.title set value = ''', old_title, ''' where value = ''', new_title, '''');
perform tj.add_operation(redo, undo);
end;
$$ language plpgsql;

View File

@@ -0,0 +1,87 @@
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;

View File

@@ -0,0 +1,9 @@
create function tj.have_project(in_name text) returns boolean as
$$
declare
db_count int;
begin
select count(*) into db_count from pg_database where datname = in_name;
return db_count > 0;
end;
$$ language plpgsql;

View File

@@ -0,0 +1,3 @@
drop function if exists tj.set_title;
drop function if exists tj.get_title;

View File

@@ -0,0 +1,7 @@
drop function if exists tj.discard_undo;
drop function if exists tj.undo;
drop function if exists tj.execute_undo;
drop function if exists tj.have_transaction;
drop function if exists tj.add_operation;

View File

@@ -0,0 +1,6 @@
create function xxx() returns void as
$$
declare
begin
end;
$$ language plpgsql;

View File

@@ -31,10 +31,14 @@ sql_create = [
"table/create/26.labels.sql",
"table/create/27.backdrop.sql",
"table/create/28.end.sql",
"table/create/operation.sql"
"table/create/operation.sql",
"api/create/operation.sql",
"api/create/1.title.sql"
]
sql_drop = [
"api/drop/1.title.sql",
"api/drop/operation.sql",
"table/drop/operation.sql",
"table/drop/28.end.sql",
"table/drop/27.backdrop.sql",