1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-26 01:22:12 +03:00

PG_FINALLY

This gives an alternative way of catching exceptions, for the common
case where the cleanup code is the same in the error and non-error
cases.  So instead of

    PG_TRY();
    {
        ... code that might throw ereport(ERROR) ...
    }
    PG_CATCH();
    {
        cleanup();
	PG_RE_THROW();
    }
    PG_END_TRY();
    cleanup();

one can write

    PG_TRY();
    {
        ... code that might throw ereport(ERROR) ...
    }
    PG_FINALLY();
    {
        cleanup();
    }
    PG_END_TRY();

Discussion: https://www.postgresql.org/message-id/flat/95a822c3-728b-af0e-d7e5-71890507ae0c%402ndquadrant.com
This commit is contained in:
Peter Eisentraut
2019-11-01 11:09:52 +01:00
parent 7302514088
commit 604bd36711
32 changed files with 91 additions and 245 deletions

View File

@ -277,6 +277,25 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack;
* (sub)transaction abort. Failure to do so may leave the system in an
* inconsistent state for further processing.
*
* For the common case that the error recovery code and the cleanup in the
* normal code path are identical, the following can be used instead:
*
* PG_TRY();
* {
* ... code that might throw ereport(ERROR) ...
* }
* PG_FINALLY();
* {
* ... cleanup code ...
* }
* PG_END_TRY();
*
* The cleanup code will be run in either case, and any error will be rethrown
* afterwards.
*
* You cannot use both PG_CATCH() and PG_FINALLY() in the same
* PG_TRY()/PG_END_TRY() block.
*
* Note: while the system will correctly propagate any new ereport(ERROR)
* occurring in the recovery section, there is a small limit on the number
* of levels this will work for. It's best to keep the error recovery
@ -300,24 +319,33 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack;
*/
#define PG_TRY() \
do { \
sigjmp_buf *save_exception_stack = PG_exception_stack; \
ErrorContextCallback *save_context_stack = error_context_stack; \
sigjmp_buf local_sigjmp_buf; \
if (sigsetjmp(local_sigjmp_buf, 0) == 0) \
sigjmp_buf *_save_exception_stack = PG_exception_stack; \
ErrorContextCallback *_save_context_stack = error_context_stack; \
sigjmp_buf _local_sigjmp_buf; \
bool _do_rethrow = false; \
if (sigsetjmp(_local_sigjmp_buf, 0) == 0) \
{ \
PG_exception_stack = &local_sigjmp_buf
PG_exception_stack = &_local_sigjmp_buf
#define PG_CATCH() \
} \
else \
{ \
PG_exception_stack = save_exception_stack; \
error_context_stack = save_context_stack
PG_exception_stack = _save_exception_stack; \
error_context_stack = _save_context_stack
#define PG_FINALLY() \
} \
else \
_do_rethrow = true; \
{
#define PG_END_TRY() \
} \
PG_exception_stack = save_exception_stack; \
error_context_stack = save_context_stack; \
PG_exception_stack = _save_exception_stack; \
error_context_stack = _save_context_stack; \
if (_do_rethrow) \
PG_RE_THROW(); \
} while (0)
/*