diff options
Diffstat (limited to 'src/include/utils/elog.h')
-rw-r--r-- | src/include/utils/elog.h | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index ba0b7f6f79c..853c2e0709e 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -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) /* |