Issue with ReRaise in PG

From: Piyush Newe <piyush(dot)newe(at)enterprisedb(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: Issue with ReRaise in PG
Date: 2010-04-23 09:30:42
Message-ID: g2n3b3d33c91004230230red8eaab7sdd69005dc4efa6c9@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

Please consider the following test case

> CREATE OR REPLACE FUNCTION raisetest() returns void AS $$
BEGIN
BEGIN
RAISE syntax_error;
EXCEPTION
WHEN syntax_error THEN
BEGIN
raise notice 'exception thrown in inner block, reraising';
RAISE;
EXCEPTION
WHEN OTHERS THEN
raise notice 'RIGHT - exception caught in innermost
block';
END;
END;
EXCEPTION
WHEN OTHERS THEN
raise notice 'WRONG - exception caught in outer block';
END;
$$ LANGUAGE plpgsql;

> select raisetest();
NOTICE: exception thrown in inner block, reraising
NOTICE: WRONG - exception caught in outer block
block
raisetest
-----------

(1 row)

The output of the above function seems to be wrong. Ideally the Exception
should have caught in the inner most block instead of the outer block.

Below I am sharing my obsevation while debuging this issue.
When we give RAISE without the exception name statement, it is internally
returning PLPGSQL_RC_RERAISE instead of jumping to the EXCEPTION block of
the current Begin-End Block. This will force engine to eliminate/skip the
current block's EXCEPTION block. This is the reason its got caught in the
next exception block.

To fix this, instead of returning PLPGSQL_RC_RERAISE from the function, we
will rethrow the exception if their is no EXCEPTION name given to the RAISE
statement. When their is RAISE (without exception name) statement, it is
been assume that their must be some exception already raised earlier. We are
now storing the 'errordata' into the 'estate' structure, while raising the
exception.

Now since we are not returning PLPGSQL_RC_RERAISE statement, I have also
removed the related redundunt code in the pl_exec.c.

The testcase mentioned above is behaving correctly like

postgres=# select raisetest();
NOTICE: exception thrown in inner block, reraising
NOTICE: RIGHT - exception caught in innermost
block
raisetest
-----------

(1 row)

Please find attached patch generated on the current branch to fix the
problem.

--
Piyush S Newe
Principal Engineer
EnterpriseDB
office: +91 20 3058 9500
www.enterprisedb.com

Website: www.enterprisedb.com
EnterpriseDB Blog: http://blogs.enterprisedb.com/
Follow us on Twitter: http://www.twitter.com/enterprisedb

This e-mail message (and any attachment) is intended for the use of the
individual or entity to whom it is addressed. This message contains
information from EnterpriseDB Corporation that may be privileged,
confidential, or exempt from disclosure under applicable law. If you are not
the intended recipient or authorized to receive this for the intended
recipient, any use, dissemination, distribution, retention, archiving, or
copying of this communication is strictly prohibited. If you have received
this e-mail in error, please notify the sender immediately by reply e-mail
and delete this message.

Attachment Content-Type Size
reraise_issue_PG_v1.patch text/x-diff 5.1 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Robert Haas 2010-04-23 10:44:39 Re: recovery_connections cannot start (was Re: master in standby mode croaks)
Previous Message Heikki Linnakangas 2010-04-23 09:24:43 Re: recovery_connections cannot start (was Re: master in standby mode croaks)