From e4d05fba0b2e97f7344c77b17a3b8aa6378ded8f Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 13 Dec 2018 11:19:07 +0100 Subject: [PATCH] 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(); }); --- contrib/auto_explain/auto_explain.c | 16 ++----- contrib/dblink/dblink.c | 31 +++----------- contrib/hstore_plpython/hstore_plpython.c | 8 +--- .../pg_stat_statements/pg_stat_statements.c | 24 +++-------- contrib/pg_trgm/trgm_regexp.c | 9 +--- contrib/postgres_fdw/connection.c | 9 +--- contrib/sepgsql/hooks.c | 8 +--- contrib/sepgsql/label.c | 42 +++++-------------- contrib/sepgsql/selinux.c | 8 +--- contrib/sepgsql/uavc.c | 9 +--- src/backend/catalog/index.c | 16 ++----- src/backend/commands/async.c | 18 +------- src/backend/commands/copy.c | 8 +--- src/backend/commands/event_trigger.c | 18 ++------ src/backend/commands/extension.c | 10 +---- src/backend/commands/matview.c | 8 +--- src/backend/commands/subscriptioncmds.c | 21 ++-------- src/backend/commands/trigger.c | 8 +--- src/backend/commands/vacuum.c | 10 +---- src/backend/libpq/be-fsstubs.c | 8 +--- src/backend/tcop/utility.c | 18 ++------ src/backend/utils/adt/xml.c | 25 +++-------- src/include/utils/elog.h | 30 +++++++++++++ src/pl/plperl/plperl.c | 24 ++--------- src/pl/plpgsql/src/pl_handler.c | 13 ++---- src/pl/plpython/plpy_cursorobject.c | 8 +--- src/pl/plpython/plpy_elog.c | 16 +------ src/pl/plpython/plpy_exec.c | 20 ++------- src/pl/plpython/plpy_spi.c | 7 +--- src/pl/plpython/plpy_typeio.c | 8 +--- src/pl/tcl/pltcl.c | 17 ++------ 31 files changed, 126 insertions(+), 349 deletions(-) diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c index 646cd0d42c..54d9a8c5e5 100644 --- a/contrib/auto_explain/auto_explain.c +++ b/contrib/auto_explain/auto_explain.c @@ -295,14 +295,10 @@ explain_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, prev_ExecutorRun(queryDesc, direction, count, execute_once); else standard_ExecutorRun(queryDesc, direction, count, execute_once); - nesting_level--; } - PG_CATCH(); - { + PG_FINALLY({ nesting_level--; - PG_RE_THROW(); - } - PG_END_TRY(); + }); } /* @@ -318,14 +314,10 @@ explain_ExecutorFinish(QueryDesc *queryDesc) prev_ExecutorFinish(queryDesc); else standard_ExecutorFinish(queryDesc); - nesting_level--; } - PG_CATCH(); - { + PG_FINALLY({ nesting_level--; - PG_RE_THROW(); - } - PG_END_TRY(); + }); } /* diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 3b73ff13f1..068c2c602c 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -776,18 +776,11 @@ dblink_record_internal(FunctionCallInfo fcinfo, bool is_async) } } } - PG_CATCH(); - { + PG_FINALLY({ /* if needed, close the connection to the database */ if (freeconn) PQfinish(conn); - PG_RE_THROW(); - } - PG_END_TRY(); - - /* if needed, close the connection to the database */ - if (freeconn) - PQfinish(conn); + }); return (Datum) 0; } @@ -952,16 +945,11 @@ materializeResult(FunctionCallInfo fcinfo, PGconn *conn, PGresult *res) /* clean up and return the tuplestore */ tuplestore_donestoring(tupstore); } - - PQclear(res); } - PG_CATCH(); - { + PG_FINALLY({ /* be sure to release the libpq result */ PQclear(res); - PG_RE_THROW(); - } - PG_END_TRY(); + }); } /* @@ -1466,18 +1454,11 @@ dblink_exec(PG_FUNCTION_ARGS) errmsg("statement returning results not allowed"))); } } - PG_CATCH(); - { + PG_FINALLY({ /* if needed, close the connection to the database */ if (freeconn) PQfinish(conn); - PG_RE_THROW(); - } - PG_END_TRY(); - - /* if needed, close the connection to the database */ - if (freeconn) - PQfinish(conn); + }); PG_RETURN_TEXT_P(sql_cmd_status); } diff --git a/contrib/hstore_plpython/hstore_plpython.c b/contrib/hstore_plpython/hstore_plpython.c index 2f24090ff3..9c5acd0ea1 100644 --- a/contrib/hstore_plpython/hstore_plpython.c +++ b/contrib/hstore_plpython/hstore_plpython.c @@ -177,17 +177,13 @@ plpython_to_hstore(PG_FUNCTION_ARGS) pairs[i].isnull = false; } } - Py_DECREF(items_v); pcount = hstoreUniquePairs(pairs, pcount, &buflen); out = hstorePairs(pairs, pcount, buflen); } - PG_CATCH(); - { + PG_FINALLY({ Py_DECREF(items_v); - PG_RE_THROW(); - } - PG_END_TRY(); + }); PG_RETURN_POINTER(out); } diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 33f9a79f54..a6b19e6403 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -890,14 +890,10 @@ pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, prev_ExecutorRun(queryDesc, direction, count, execute_once); else standard_ExecutorRun(queryDesc, direction, count, execute_once); - nested_level--; } - PG_CATCH(); - { + PG_FINALLY({ nested_level--; - PG_RE_THROW(); - } - PG_END_TRY(); + }); } /* @@ -913,14 +909,10 @@ pgss_ExecutorFinish(QueryDesc *queryDesc) prev_ExecutorFinish(queryDesc); else standard_ExecutorFinish(queryDesc); - nested_level--; } - PG_CATCH(); - { + PG_FINALLY({ nested_level--; - PG_RE_THROW(); - } - PG_END_TRY(); + }); } /* @@ -1005,14 +997,10 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, standard_ProcessUtility(pstmt, queryString, context, params, queryEnv, dest, completionTag); - nested_level--; } - PG_CATCH(); - { + PG_FINALLY({ nested_level--; - PG_RE_THROW(); - } - PG_END_TRY(); + }); INSTR_TIME_SET_CURRENT(duration); INSTR_TIME_SUBTRACT(duration, start); diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c index 547e7c094f..17743f5a8e 100644 --- a/contrib/pg_trgm/trgm_regexp.c +++ b/contrib/pg_trgm/trgm_regexp.c @@ -557,14 +557,9 @@ createTrgmNFA(text *text_re, Oid collation, { trg = createTrgmNFAInternal(®ex, graph, rcontext); } - PG_CATCH(); - { + PG_FINALLY({ pg_regfree(®ex); - PG_RE_THROW(); - } - PG_END_TRY(); - - pg_regfree(®ex); + }); /* Clean up all the cruft we created */ MemoryContextSwitchTo(oldcontext); diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index a6509932dc..067fc53d59 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -633,15 +633,10 @@ pgfdw_report_error(int elevel, PGresult *res, PGconn *conn, message_context ? errcontext("%s", message_context) : 0, sql ? errcontext("remote SQL command: %s", sql) : 0)); } - PG_CATCH(); - { + PG_FINALLY({ if (clear) PQclear(res); - PG_RE_THROW(); - } - PG_END_TRY(); - if (clear) - PQclear(res); + }); } /* diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c index 4249ed552c..430d179a2c 100644 --- a/contrib/sepgsql/hooks.c +++ b/contrib/sepgsql/hooks.c @@ -373,13 +373,9 @@ sepgsql_utility_command(PlannedStmt *pstmt, context, params, queryEnv, dest, completionTag); } - PG_CATCH(); - { + PG_FINALLY({ sepgsql_context_info = saved_context_info; - PG_RE_THROW(); - } - PG_END_TRY(); - sepgsql_context_info = saved_context_info; + }); } /* diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c index acffc468d2..938eb72001 100644 --- a/contrib/sepgsql/label.c +++ b/contrib/sepgsql/label.c @@ -474,14 +474,9 @@ sepgsql_get_label(Oid classId, Oid objectId, int32 subId) { label = pstrdup(unlabeled); } - PG_CATCH(); - { + PG_FINALLY({ freecon(unlabeled); - PG_RE_THROW(); - } - PG_END_TRY(); - - freecon(unlabeled); + }); } return label; } @@ -609,13 +604,9 @@ sepgsql_mcstrans_in(PG_FUNCTION_ARGS) { result = pstrdup(raw_label); } - PG_CATCH(); - { + PG_FINALLY({ freecon(raw_label); - PG_RE_THROW(); - } - PG_END_TRY(); - freecon(raw_label); + }); PG_RETURN_TEXT_P(cstring_to_text(result)); } @@ -649,13 +640,9 @@ sepgsql_mcstrans_out(PG_FUNCTION_ARGS) { result = pstrdup(qual_label); } - PG_CATCH(); - { + PG_FINALLY({ freecon(qual_label); - PG_RE_THROW(); - } - PG_END_TRY(); - freecon(qual_label); + }); PG_RETURN_TEXT_P(cstring_to_text(result)); } @@ -860,13 +847,9 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId) SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, context); } - PG_CATCH(); - { + PG_FINALLY({ freecon(context); - PG_RE_THROW(); - } - PG_END_TRY(); - freecon(context); + }); } else if (errno == ENOENT) ereport(WARNING, @@ -946,14 +929,9 @@ sepgsql_restorecon(PG_FUNCTION_ARGS) exec_object_restorecon(sehnd, AttributeRelationId); exec_object_restorecon(sehnd, ProcedureRelationId); } - PG_CATCH(); - { + PG_FINALLY({ selabel_close(sehnd); - PG_RE_THROW(); - } - PG_END_TRY(); - - selabel_close(sehnd); + }); PG_RETURN_BOOL(true); } diff --git a/contrib/sepgsql/selinux.c b/contrib/sepgsql/selinux.c index 47def00a46..db70d77bc2 100644 --- a/contrib/sepgsql/selinux.c +++ b/contrib/sepgsql/selinux.c @@ -873,13 +873,9 @@ sepgsql_compute_create(const char *scontext, { result = pstrdup(ncontext); } - PG_CATCH(); - { + PG_FINALLY({ freecon(ncontext); - PG_RE_THROW(); - } - PG_END_TRY(); - freecon(ncontext); + }); return result; } diff --git a/contrib/sepgsql/uavc.c b/contrib/sepgsql/uavc.c index ea276ee0cc..37ceed8340 100644 --- a/contrib/sepgsql/uavc.c +++ b/contrib/sepgsql/uavc.c @@ -187,14 +187,9 @@ sepgsql_avc_unlabeled(void) { avc_unlabeled = MemoryContextStrdup(avc_mem_cxt, unlabeled); } - PG_CATCH(); - { + PG_FINALLY({ freecon(unlabeled); - PG_RE_THROW(); - } - PG_END_TRY(); - - freecon(unlabeled); + }); } return avc_unlabeled; } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 8709e8c22c..62e1b4dc73 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3705,14 +3705,10 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence, /* Note: we do not need to re-establish pkey setting */ index_build(heapRelation, iRel, indexInfo, false, true, true); } - PG_CATCH(); - { + PG_FINALLY({ /* Make sure flag gets cleared on error exit */ ResetReindexProcessing(); - PG_RE_THROW(); - } - PG_END_TRY(); - ResetReindexProcessing(); + }); /* * If the index is marked invalid/not-ready/dead (ie, it's from a failed @@ -3954,14 +3950,10 @@ reindex_relation(Oid relid, int flags, int options) doneIndexes = lappend_oid(doneIndexes, indexOid); } } - PG_CATCH(); - { + PG_FINALLY({ /* Make sure list gets cleared on error exit */ ResetReindexPending(); - PG_RE_THROW(); - } - PG_END_TRY(); - ResetReindexPending(); + }); if (is_pg_class) RelationSetIndexList(rel, indexIds); diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index ee7c6d41b4..247cbf98a8 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -1867,8 +1867,7 @@ asyncQueueReadAllNotifications(void) snapshot); } while (!reachedStop); } - PG_CATCH(); - { + PG_FINALLY({ /* Update shared state */ LWLockAcquire(AsyncQueueLock, LW_SHARED); QUEUE_BACKEND_POS(MyBackendId) = pos; @@ -1878,20 +1877,7 @@ asyncQueueReadAllNotifications(void) /* If we were the laziest backend, try to advance the tail pointer */ if (advanceTail) asyncQueueAdvanceTail(); - - PG_RE_THROW(); - } - PG_END_TRY(); - - /* Update shared state */ - LWLockAcquire(AsyncQueueLock, LW_SHARED); - QUEUE_BACKEND_POS(MyBackendId) = pos; - advanceTail = QUEUE_POS_EQUAL(oldpos, QUEUE_TAIL); - LWLockRelease(AsyncQueueLock); - - /* If we were the laziest backend, try to advance the tail pointer */ - if (advanceTail) - asyncQueueAdvanceTail(); + }); /* Done with snapshot */ UnregisterSnapshot(snapshot); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 4aa8890fe8..de10453b4a 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1850,13 +1850,9 @@ BeginCopyTo(ParseState *pstate, { cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W); } - PG_CATCH(); - { + PG_FINALLY({ umask(oumask); - PG_RE_THROW(); - } - PG_END_TRY(); - umask(oumask); + }); if (cstate->copy_file == NULL) { /* copy errno because ereport subfunctions might change it */ diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 3e7c1067d8..0e5bfc5f5b 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -935,13 +935,9 @@ EventTriggerSQLDrop(Node *parsetree) { EventTriggerInvoke(runlist, &trigdata); } - PG_CATCH(); - { + PG_FINALLY({ currentEventTriggerState->in_sql_drop = false; - PG_RE_THROW(); - } - PG_END_TRY(); - currentEventTriggerState->in_sql_drop = false; + }); /* Cleanup. */ list_free(runlist); @@ -1008,16 +1004,10 @@ EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason) { EventTriggerInvoke(runlist, &trigdata); } - PG_CATCH(); - { + PG_FINALLY({ currentEventTriggerState->table_rewrite_oid = InvalidOid; currentEventTriggerState->table_rewrite_reason = 0; - PG_RE_THROW(); - } - PG_END_TRY(); - - currentEventTriggerState->table_rewrite_oid = InvalidOid; - currentEventTriggerState->table_rewrite_reason = 0; + }); /* Cleanup. */ list_free(runlist); diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 87e4dd8245..a9d64dc2f3 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -922,16 +922,10 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, execute_sql_string(c_sql); } - PG_CATCH(); - { + PG_FINALLY({ creating_extension = false; CurrentExtensionObject = InvalidOid; - PG_RE_THROW(); - } - PG_END_TRY(); - - creating_extension = false; - CurrentExtensionObject = InvalidOid; + }); /* * Restore the GUC variables we set above. diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index a171ebabf8..bc67f9932c 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -320,13 +320,9 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, refresh_by_match_merge(matviewOid, OIDNewHeap, relowner, save_sec_context); } - PG_CATCH(); - { + PG_FINALLY({ matview_maintenance_depth = old_depth; - PG_RE_THROW(); - } - PG_END_TRY(); - Assert(matview_maintenance_depth == old_depth); + }); } else { diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 9021463a4c..49fe891e48 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -474,16 +474,9 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel) slotname))); } } - PG_CATCH(); - { - /* Close the connection in case of failure. */ + PG_FINALLY({ walrcv_disconnect(wrconn); - PG_RE_THROW(); - } - PG_END_TRY(); - - /* And we are done with the remote side. */ - walrcv_disconnect(wrconn); + }); } else ereport(WARNING, @@ -1002,15 +995,9 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) walrcv_clear_result(res); } - PG_CATCH(); - { - /* Close the connection in case of failure */ + PG_FINALLY({ walrcv_disconnect(wrconn); - PG_RE_THROW(); - } - PG_END_TRY(); - - walrcv_disconnect(wrconn); + }); pfree(cmd.data); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index bcdd86ce92..eb3a5fb48d 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2413,13 +2413,9 @@ ExecCallTriggerFunc(TriggerData *trigdata, { result = FunctionCallInvoke(&fcinfo); } - PG_CATCH(); - { + PG_FINALLY({ MyTriggerDepth--; - PG_RE_THROW(); - } - PG_END_TRY(); - MyTriggerDepth--; + }); pgstat_end_function_usage(&fcusage, true); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 25b3b0312c..897967a7ec 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -365,16 +365,10 @@ vacuum(int options, List *relations, VacuumParams *params, } } } - PG_CATCH(); - { + PG_FINALLY({ in_vacuum = false; VacuumCostActive = false; - PG_RE_THROW(); - } - PG_END_TRY(); - - in_vacuum = false; - VacuumCostActive = false; + }); /* * Finish up processing. diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c index 0b802b54e4..fa5e4c6596 100644 --- a/src/backend/libpq/be-fsstubs.c +++ b/src/backend/libpq/be-fsstubs.c @@ -498,13 +498,9 @@ be_lo_export(PG_FUNCTION_ARGS) fd = OpenTransientFilePerm(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); } - PG_CATCH(); - { + PG_FINALLY({ umask(oumask); - PG_RE_THROW(); - } - PG_END_TRY(); - umask(oumask); + }); if (fd < 0) ereport(ERROR, (errcode_for_file_access(), diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 970c94ee80..6b9e138414 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1496,13 +1496,9 @@ ProcessUtilitySlow(ParseState *pstate, address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree, queryString, params, completionTag); } - PG_CATCH(); - { + PG_FINALLY({ EventTriggerUndoInhibitCommandCollection(); - PG_RE_THROW(); - } - PG_END_TRY(); - EventTriggerUndoInhibitCommandCollection(); + }); break; case T_CreateTrigStmt: @@ -1694,16 +1690,10 @@ ProcessUtilitySlow(ParseState *pstate, EventTriggerDDLCommandEnd(parsetree); } } - PG_CATCH(); - { + PG_FINALLY({ if (needCleanup) EventTriggerEndCompleteQuery(); - PG_RE_THROW(); - } - PG_END_TRY(); - - if (needCleanup) - EventTriggerEndCompleteQuery(); + }); } /* diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 37d85f71f3..3fe86d2e78 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -3705,15 +3705,10 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt) xmlNodeDump(buf, NULL, cur_copy, 0, 1); result = xmlBuffer_to_xmltype(buf); } - PG_CATCH(); - { + PG_FINALLY({ xmlFreeNode(cur_copy); xmlBufferFree(buf); - PG_RE_THROW(); - } - PG_END_TRY(); - xmlFreeNode(cur_copy); - xmlBufferFree(buf); + }); } else { @@ -3728,13 +3723,9 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt) result = (xmltype *) cstring_to_text(escaped); pfree(escaped); } - PG_CATCH(); - { + PG_FINALLY({ xmlFree(str); - PG_RE_THROW(); - } - PG_END_TRY(); - xmlFree(str); + }); } return result; @@ -4523,13 +4514,9 @@ XmlTableGetValue(TableFuncScanState *state, int colnum, { cstr = pstrdup((char *) str); } - PG_CATCH(); - { + PG_FINALLY({ xmlFree(str); - PG_RE_THROW(); - } - PG_END_TRY(); - xmlFree(str); + }); } else { diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 33c6b53e27..9cf2bcd8a4 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -318,6 +318,36 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; error_context_stack = save_context_stack; \ } while (0) +/*---------- + * Variant API for the common case that the error recovery code and the + * cleanup in the normal code path are identical. Use like so: + * + * PG_TRY(); + * { + * ... code that might throw ereport(ERROR) ... + * } + * PG_FINALLY( + * { + * ... cleanup code ... + * }); + * + * The cleanup code will be run in either case, and any error will be rethrown + * afterwards. Note the slightly different bracketing. + */ +#define PG_FINALLY(code) \ + } \ + else \ + { \ + PG_exception_stack = save_exception_stack; \ + error_context_stack = save_context_stack; \ + do { code } while(0); \ + PG_RE_THROW(); \ + } \ + PG_exception_stack = save_exception_stack; \ + error_context_stack = save_context_stack; \ + do { code } while(0); \ + } while (0) + /* * Some compilers understand pg_attribute_noreturn(); for other compilers, * insert pg_unreachable() so that the compiler gets the point. diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index fe54b20903..4172a399cd 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1851,20 +1851,13 @@ plperl_call_handler(PG_FUNCTION_ARGS) else retval = plperl_func_handler(fcinfo); } - PG_CATCH(); - { + PG_FINALLY({ current_call_data = save_call_data; activate_interpreter(oldinterp); if (this_call_data.prodesc) decrement_prodesc_refcount(this_call_data.prodesc); - PG_RE_THROW(); - } - PG_END_TRY(); + }); - current_call_data = save_call_data; - activate_interpreter(oldinterp); - if (this_call_data.prodesc) - decrement_prodesc_refcount(this_call_data.prodesc); return retval; } @@ -1947,21 +1940,12 @@ plperl_inline_handler(PG_FUNCTION_ARGS) if (SPI_finish() != SPI_OK_FINISH) elog(ERROR, "SPI_finish() failed"); } - PG_CATCH(); - { + PG_FINALLY({ if (desc.reference) SvREFCNT_dec_current(desc.reference); current_call_data = save_call_data; activate_interpreter(oldinterp); - PG_RE_THROW(); - } - PG_END_TRY(); - - if (desc.reference) - SvREFCNT_dec_current(desc.reference); - - current_call_data = save_call_data; - activate_interpreter(oldinterp); + }); error_context_stack = pl_error_context.previous; diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c index 7d3647a12d..9a40111258 100644 --- a/src/pl/plpgsql/src/pl_handler.c +++ b/src/pl/plpgsql/src/pl_handler.c @@ -266,18 +266,11 @@ plpgsql_call_handler(PG_FUNCTION_ARGS) else retval = plpgsql_exec_function(func, fcinfo, NULL, !nonatomic); } - PG_CATCH(); - { - /* Decrement use-count, restore cur_estate, and propagate error */ + PG_FINALLY({ + /* Decrement use-count, restore cur_estate */ func->use_count--; func->cur_estate = save_cur_estate; - PG_RE_THROW(); - } - PG_END_TRY(); - - func->use_count--; - - func->cur_estate = save_cur_estate; + }); /* * Disconnect from SPI manager diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c index 45ac25b2ae..0378d1f049 100644 --- a/src/pl/plpython/plpy_cursorobject.c +++ b/src/pl/plpython/plpy_cursorobject.c @@ -228,13 +228,9 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) plan->values[j] = PLy_output_convert(arg, elem, &isnull); nulls[j] = isnull ? 'n' : ' '; } - PG_CATCH(); - { + PG_FINALLY({ Py_DECREF(elem); - PG_RE_THROW(); - } - PG_END_TRY(); - Py_DECREF(elem); + }); } portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls, diff --git a/src/pl/plpython/plpy_elog.c b/src/pl/plpython/plpy_elog.c index 3814a6c32d..b897c83ba6 100644 --- a/src/pl/plpython/plpy_elog.c +++ b/src/pl/plpython/plpy_elog.c @@ -141,7 +141,7 @@ PLy_elog_impl(int elevel, const char *fmt,...) (constraint_name) ? err_generic_string(PG_DIAG_CONSTRAINT_NAME, constraint_name) : 0)); } - PG_CATCH(); + PG_FINALLY( { if (fmt) pfree(emsg.data); @@ -151,19 +151,7 @@ PLy_elog_impl(int elevel, const char *fmt,...) pfree(tbmsg); Py_XDECREF(exc); Py_XDECREF(val); - - PG_RE_THROW(); - } - PG_END_TRY(); - - if (fmt) - pfree(emsg.data); - if (xmsg) - pfree(xmsg); - if (tbmsg) - pfree(tbmsg); - Py_XDECREF(exc); - Py_XDECREF(val); + }); } /* diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c index 47ed95dcc6..9f601daec7 100644 --- a/src/pl/plpython/plpy_exec.c +++ b/src/pl/plpython/plpy_exec.c @@ -402,17 +402,10 @@ PLy_exec_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc) } } } - PG_CATCH(); - { + PG_FINALLY({ Py_XDECREF(plargs); Py_XDECREF(plrv); - - PG_RE_THROW(); - } - PG_END_TRY(); - - Py_DECREF(plargs); - Py_DECREF(plrv); + }); return rv; } @@ -1037,14 +1030,9 @@ PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs) */ Assert(list_length(explicit_subtransactions) >= save_subxact_level); } - PG_CATCH(); - { + PG_FINALLY({ PLy_abort_open_subtransactions(save_subxact_level); - PG_RE_THROW(); - } - PG_END_TRY(); - - PLy_abort_open_subtransactions(save_subxact_level); + }); /* If the Python code returned an error, propagate it */ if (rv == NULL) diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c index 41155fc81e..9dc0e7c3f1 100644 --- a/src/pl/plpython/plpy_spi.c +++ b/src/pl/plpython/plpy_spi.c @@ -249,13 +249,10 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit) plan->values[j] = PLy_output_convert(arg, elem, &isnull); nulls[j] = isnull ? 'n' : ' '; } - PG_CATCH(); + PG_FINALLY( { Py_DECREF(elem); - PG_RE_THROW(); - } - PG_END_TRY(); - Py_DECREF(elem); + }); } rv = SPI_execute_plan(plan->plan, plan->values, nulls, diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c index d6a6a849c3..99e8fc0602 100644 --- a/src/pl/plpython/plpy_typeio.c +++ b/src/pl/plpython/plpy_typeio.c @@ -918,14 +918,10 @@ PLyObject_ToBytea(PLyObToDatum *arg, PyObject *plrv, memcpy(VARDATA(result), plrv_sc, len); rv = PointerGetDatum(result); } - PG_CATCH(); + PG_FINALLY( { Py_XDECREF(plrv_so); - PG_RE_THROW(); - } - PG_END_TRY(); - - Py_XDECREF(plrv_so); + }); return rv; } diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 3b1454f833..e7f0a39014 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -765,9 +765,10 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted) retval = pltcl_func_handler(fcinfo, ¤t_call_state, pltrusted); } } - PG_CATCH(); + PG_FINALLY( { /* Restore static pointer, then clean up the prodesc refcount if any */ + /* (We're being paranoid in case an error is thrown in context deletion) */ pltcl_current_call_state = save_call_state; if (current_call_state.prodesc != NULL) { @@ -775,19 +776,7 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted) if (--current_call_state.prodesc->fn_refcount == 0) MemoryContextDelete(current_call_state.prodesc->fn_cxt); } - PG_RE_THROW(); - } - PG_END_TRY(); - - /* Restore static pointer, then clean up the prodesc refcount if any */ - /* (We're being paranoid in case an error is thrown in context deletion) */ - pltcl_current_call_state = save_call_state; - if (current_call_state.prodesc != NULL) - { - Assert(current_call_state.prodesc->fn_refcount > 0); - if (--current_call_state.prodesc->fn_refcount == 0) - MemoryContextDelete(current_call_state.prodesc->fn_cxt); - } + }); return retval; } -- 2.20.0