Re: try/catch macros for Postgres backend - Mailing list pgsql-hackers
From | Gavin Sherry |
---|---|
Subject | Re: try/catch macros for Postgres backend |
Date | |
Msg-id | Pine.LNX.4.58.0407291326260.625@linuxworld.com.au Whole thread Raw |
In response to | try/catch macros for Postgres backend (Tom Lane <tgl@sss.pgh.pa.us>) |
List | 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 .... DECLAREinvalid EXCEPTION;count INT; BEGINSELECT INTO count COUNT(*) FROM ...IF count < 10 -- we shouldn't have been called RAISE EXCEPTION invalid; ... EXCEPTIONWHEN 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
pgsql-hackers by date: