S
S
Sergey2017-04-10 20:03:07
PostgreSQL
Sergey, 2017-04-10 20:03:07

How to roll back all actions in a procedure when handling an error?

Good afternoon.
There is a database on Firebird 3.
Task: to execute a SQL script with DDL statements inside and, in case of an error, completely roll back.
Having carefully studied the documentation , I came to the conclusion that the implementation of such an undertaking is quite possible.
The script is installed using the procedure:

create or alter procedure EXECUTE_SCRIPT (
    I_SCRIPT blob sub_type 1 segment size 80 not null)
returns (
    ERR smallint)
as
declare variable V_COMMAND blob sub_type 1 segment size 80;
begin
  ERR = 0;
  begin
    for
      select COMMAND
      from SPLIT_SCRIPT(:I_SCRIPT)
      into :V_COMMAND
    do
      execute statement(V_COMMAND);

    when any do
      ERR = 1;
  end
end

In this case, it SPLIT_SCRIPTsplits the original script into separate commands, removes the terminator change at the beginning, the commit at the end, and removes the terminator itself at the end of the commands.
Here is the script I want to execute:
Full text of the script
set term ^;

create table test_table1 (
    id integer,
    name varchar(30)
)^

create or alter procedure test_proc1 (
    I_ID integer,
    I_NAME varchar(30) character set UTF8)
returns (
    O_MSG varchar(30) character set UTF8)
as
begin
  insert into test1 (id, name)
  values(:i_id, :i_name);
  o_msg = 'Запись №' || i_id || ' с именем ' || i_name || ' вставлена!';
  suspend;
end^

commit^

The result of executing the SPLIT_SCRIPT procedure
create table test_table1 (
    id integer,
    name varchar(30)
)

create or alter procedure test_proc1 (
    I_ID integer,
    I_NAME varchar(30))
returns (
    O_MSG varchar(30))
as
begin
  insert into test1 (id, name)
  values(:i_id, :i_name);
  o_msg = 'Запись №' || i_id || ' с именем ' || i_name || ' вставлена!';
  suspend;
end


As you can see, the second command (creating the procedure) intentionally misspelled the table name on insertion to throw an exception.
Here are some quotes from the documentation (p. 495):
Internally, automatic savepoints are used to:
• cancel all actions within the BEGIN ... END block where an exception occurs;

By itself, the BEGIN..END block does not create an automatic savepoint. It is
only created in blocks that have a WHEN block to handle exceptions or errors.

At first glance, the conditions are met, nothing criminal, however, when the procedure is performed EXECUTE_SCRIPTand the subsequent commit, the table is still created, which should not be.
Or am I missing something?

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question