Re: try/catch macros for Postgres backend

From: Gavin Sherry <swm(at)linuxworld(dot)com(dot)au>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: try/catch macros for Postgres backend
Date: 2004-07-29 03:46:20
Message-ID: Pine.LNX.4.58.0407291326260.625@linuxworld.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Wed, 28 Jul 2004, Tom Lane wrote:

> In service of the refactoring of error handling that I was talking about
> a few days ago, I'm finding that there are several places that really
> ought to catch longjmps and clean up after themselves, instead of
> expecting that whatever mess they've made will be cleaned up for them
> when control gets back to PostgresMain(). If we have functions that can
> catch errors, control might *not* go right back to PostgresMain(), and
> so throwing random cleanup actions into the sigsetjmp branch there is
> No Good.
>
> This is no big deal since pltcl and plpython already do much the same
> thing, but I'm starting to think that instead of directly hacking on
> Warn_restart, it would be good to have some macros hiding the details.
> The syntax I'm toying with is
>
> PG_TRY();
> {
> ... code that might elog ...
> }
> PG_CATCH();
> {
> ... recovery code here ...
> PG_RE_THROW(); // optional
> }
> PG_END_CATCH();

Cool.

[snip]

> Also, the memcpy technique for saving/restoring Warn_restart is what
> pltcl and plpython currently use, and it works, but it seems
> unnecessarily inefficient. A further improvement would be to replace
> Warn_restart by a pointer defined like
> extern sigjmp_buf *exception_stack_top;
>
> and then the macro expansion would be something more like
>
> do {
> sigjmp_buf *save_exception_stack = exception_stack_top;
> sigjmp_buf local_sigjmp_buf;
>
> if (sigsetjmp(local_sigjmp_buf) == 0)
> {
> exception_stack_top = &local_sigjmp_buf;
> ... code that might elog ...
> exception_stack_top = save_exception_stack;
> }
> else
> {
> exception_stack_top = save_exception_stack;
> ... recovery code here ...
> }
>
> } while(0)

I've been thinking about is allow users to trigger named exceptions in
PL/PgSQL. This would work something like this:

CREATE FUNCTION ....
DECLARE
invalid EXCEPTION;
count INT;
BEGIN
SELECT INTO count COUNT(*) FROM ...
IF count < 10 -- we shouldn't have been called
RAISE EXCEPTION invalid;

...

EXCEPTION
WHEN invalid THEN
....
ELSE
RAISE NOTICE 'Unknown exception raised';
END...

Another thing I've been thinking about is if an error is generated in
PL/PgSQL, what state is the system in when control is handed to the
excecption handler? That is, should we roll back to the state at the start
of the function? most recent save point?

Another thing I like about exceptions in some languages is the ability for
a subroutine to generate an exception, hand control back to the caller and
have the caller raise the exception. I'm wondering how hard that would be
in PL/PgSQL?

These are specific to PL/PgSQL and we may need something specific to that
code but I thought I'd raise these thoughts now as I intend to work on
them for 7.6.

Thanks,

Gavin

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Alvaro Herrera Munoz 2004-07-29 04:10:12 Re: try/catch macros for Postgres backend
Previous Message Tom Lane 2004-07-29 00:19:17 try/catch macros for Postgres backend