drop function if exists execute_undo; drop function if exists add_operation; drop function if exists get_current_operation; create function get_current_operation() returns integer as $$ select id from current_operation as result; $$ language sql; create function add_operation(redo_sql text, undo_sql text, redo_cs jsonb, undo_cs jsonb) returns void as $$ declare parent_id integer; op_id integer; begin parent_id := get_current_operation(); insert into operation (id, redo, undo, parent, redo_change_set, undo_change_set) values (default, redo_sql, undo_sql, parent_id, redo_cs, undo_cs); select max(id) into op_id from operation; update current_operation set id = op_id where id = parent_id; end; $$ language plpgsql; create function execute_undo(discard boolean) returns jsonb as $$ #print_strict_params on declare op_row operation%ROWTYPE; begin select * into strict op_row from operation where id = get_current_operation(); if op_row.undo = '' then return '{}'::jsonb; end if; execute op_row.undo; -- update foreign key update current_operation set id = op_row.parent where id = op_row.id; if discard then -- update foreign key update operation set redo_child = null where id = op_row.parent; -- on delete cascade => child & snapshot delete from operation where id = op_row.id; else update operation set redo_child = op_row.id where id = op_row.parent; end if; return op_row.undo_change_set; end; $$ language plpgsql; -- create function execute_redo() returns jsonb as -- $$ -- #print_strict_params on -- -- declare -- op_id integer; -- redo_c integer; -- redo_row operation%ROWTYPE; -- -- begin -- op_id := get_current_operation(); -- -- select redo_child into redo_c from operation where id = op_id; -- -- end; -- $$ -- language plpgsql;