From be2246f8e239e57498928d55eb7813e59d2df719 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 28 Oct 2019 09:34:12 +0100 Subject: [PATCH v2] 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/c170919d-c78b-3dac-5ff6-9bd12f7a38bc%402ndquadrant.com --- src/include/utils/elog.h | 28 +++++++++++++++++++ contrib/auto_explain/auto_explain.c | 8 ++---- contrib/dblink/dblink.c | 19 ++----------- contrib/hstore_plpython/hstore_plpython.c | 5 +--- contrib/jsonb_plpython/jsonb_plpython.c | 5 +--- .../pg_stat_statements/pg_stat_statements.c | 12 ++------ contrib/pg_trgm/trgm_regexp.c | 5 +--- contrib/postgres_fdw/connection.c | 5 +--- contrib/postgres_fdw/postgres_fdw.c | 25 +++-------------- contrib/sepgsql/hooks.c | 4 +-- contrib/sepgsql/label.c | 22 ++++----------- contrib/sepgsql/selinux.c | 4 +-- contrib/sepgsql/uavc.c | 5 +--- src/backend/catalog/index.c | 8 ++---- src/backend/commands/async.c | 9 +----- src/backend/commands/copy.c | 4 +-- src/backend/commands/event_trigger.c | 10 ++----- src/backend/commands/extension.c | 6 +--- src/backend/commands/subscriptioncmds.c | 13 ++------- src/backend/commands/trigger.c | 4 +-- src/backend/commands/vacuum.c | 6 +--- src/backend/libpq/be-fsstubs.c | 4 +-- src/backend/tcop/utility.c | 10 ++----- src/backend/utils/adt/xml.c | 20 +++---------- src/pl/plperl/plperl.c | 16 ++--------- src/pl/plpgsql/src/pl_handler.c | 9 ++---- src/pl/plpython/plpy_cursorobject.c | 4 +-- src/pl/plpython/plpy_elog.c | 13 +-------- src/pl/plpython/plpy_exec.c | 12 ++------ src/pl/plpython/plpy_spi.c | 4 +-- src/pl/plpython/plpy_typeio.c | 5 +--- src/pl/tcl/pltcl.c | 14 ++-------- 32 files changed, 82 insertions(+), 236 deletions(-) diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index ba0b7f6f79..36406b1cf9 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 @@ -303,6 +322,7 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack; 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 @@ -314,10 +334,18 @@ extern PGDLLIMPORT ErrorContextCallback *error_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; \ + if (do_rethrow) \ + PG_RE_THROW(); \ } while (0) /* diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c index a9536c2de0..f118dbaedd 100644 --- a/contrib/auto_explain/auto_explain.c +++ b/contrib/auto_explain/auto_explain.c @@ -320,12 +320,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(); } @@ -343,12 +341,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 54b7bf952f..7e225589a9 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -776,19 +776,14 @@ 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,14 +947,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(); } @@ -1464,19 +1456,14 @@ 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 4dee569740..39bad55802 100644 --- a/contrib/hstore_plpython/hstore_plpython.c +++ b/contrib/hstore_plpython/hstore_plpython.c @@ -180,14 +180,11 @@ plpython_to_hstore(PG_FUNCTION_ARGS) pcount = hstoreUniquePairs(pairs, pcount, &buflen); out = hstorePairs(pairs, pcount, buflen); } - PG_CATCH(); + PG_FINALLY(); { Py_DECREF(items); - PG_RE_THROW(); } PG_END_TRY(); - Py_DECREF(items); - PG_RETURN_POINTER(out); } diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c index ecaa4c6f92..b41c738ad6 100644 --- a/contrib/jsonb_plpython/jsonb_plpython.c +++ b/contrib/jsonb_plpython/jsonb_plpython.c @@ -307,15 +307,12 @@ PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state) out = pushJsonbValue(jsonb_state, WJB_END_OBJECT, NULL); } - PG_CATCH(); + PG_FINALLY(); { Py_DECREF(items); - PG_RE_THROW(); } PG_END_TRY(); - Py_DECREF(items); - return out; } diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 221b47298c..63b5888ebb 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -892,12 +892,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(); } @@ -915,12 +913,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(); } @@ -1007,12 +1003,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(); diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c index 7965a29c9f..e65e683823 100644 --- a/contrib/pg_trgm/trgm_regexp.c +++ b/contrib/pg_trgm/trgm_regexp.c @@ -555,15 +555,12 @@ 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); MemoryContextDelete(tmpcontext); diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 12f9dd35be..7cd69cc709 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -631,15 +631,12 @@ 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/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 32366641a3..fa142960eb 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -3155,15 +3155,11 @@ get_remote_estimate(const char *sql, PGconn *conn, startup_cost, total_cost, rows, width); if (n != 4) elog(ERROR, "could not interpret EXPLAIN output: \"%s\"", line); - - PQclear(res); - res = NULL; } - PG_CATCH(); + PG_FINALLY(); { if (res) PQclear(res); - PG_RE_THROW(); } PG_END_TRY(); } @@ -3383,15 +3379,11 @@ fetch_more_data(ForeignScanState *node) /* Must be EOF if we didn't get as many tuples as we asked for. */ fsstate->eof_reached = (numrows < fsstate->fetch_size); - - PQclear(res); - res = NULL; } - PG_CATCH(); + PG_FINALLY(); { if (res) PQclear(res); - PG_RE_THROW(); } PG_END_TRY(); @@ -4404,15 +4396,11 @@ postgresAnalyzeForeignTable(Relation relation, if (PQntuples(res) != 1 || PQnfields(res) != 1) elog(ERROR, "unexpected result from deparseAnalyzeSizeSql query"); *totalpages = strtoul(PQgetvalue(res, 0, 0), NULL, 10); - - PQclear(res); - res = NULL; } - PG_CATCH(); + PG_FINALLY(); { if (res) PQclear(res); - PG_RE_THROW(); } PG_END_TRY(); @@ -4925,16 +4913,11 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) commands = lappend(commands, pstrdup(buf.data)); } - - /* Clean up */ - PQclear(res); - res = NULL; } - PG_CATCH(); + PG_FINALLY(); { if (res) PQclear(res); - PG_RE_THROW(); } PG_END_TRY(); diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c index 992c70e8a0..49f32ac4d3 100644 --- a/contrib/sepgsql/hooks.c +++ b/contrib/sepgsql/hooks.c @@ -372,13 +372,11 @@ 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 d2505f7f34..d8a1d129d2 100644 --- a/contrib/sepgsql/label.c +++ b/contrib/sepgsql/label.c @@ -465,14 +465,11 @@ 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; } @@ -600,13 +597,11 @@ 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)); } @@ -640,13 +635,11 @@ 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)); } @@ -851,13 +844,11 @@ 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, @@ -937,14 +928,11 @@ 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 192aabea0b..b7c489cc33 100644 --- a/contrib/sepgsql/selinux.c +++ b/contrib/sepgsql/selinux.c @@ -871,13 +871,11 @@ 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 8ce0bc631b..f5279cc9b6 100644 --- a/contrib/sepgsql/uavc.c +++ b/contrib/sepgsql/uavc.c @@ -181,14 +181,11 @@ 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 78896da391..7ab6d7d983 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3446,14 +3446,12 @@ 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, 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 @@ -3673,14 +3671,12 @@ reindex_relation(Oid relid, int flags, int options) i++; } } - PG_CATCH(); + PG_FINALLY(); { /* Make sure list gets cleared on error exit */ ResetReindexPending(); - PG_RE_THROW(); } PG_END_TRY(); - ResetReindexPending(); /* * Close rel, but continue to hold the lock. diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index d0649d2e3e..a3209d076b 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -2028,22 +2028,15 @@ asyncQueueReadAllNotifications(void) snapshot); } while (!reachedStop); } - PG_CATCH(); + PG_FINALLY(); { /* Update shared state */ LWLockAcquire(AsyncQueueLock, LW_SHARED); QUEUE_BACKEND_POS(MyBackendId) = pos; LWLockRelease(AsyncQueueLock); - - PG_RE_THROW(); } PG_END_TRY(); - /* Update shared state */ - LWLockAcquire(AsyncQueueLock, LW_SHARED); - QUEUE_BACKEND_POS(MyBackendId) = pos; - LWLockRelease(AsyncQueueLock); - /* Done with snapshot */ UnregisterSnapshot(snapshot); } diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 3aeef30b28..e17d8c760f 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1916,13 +1916,11 @@ 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 f7ee9838f7..0301ae1ddd 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -934,13 +934,11 @@ 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); @@ -1007,17 +1005,13 @@ 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 f7202cc9e7..a04b0c9e57 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -942,17 +942,13 @@ 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/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 2e67a5889e..1419195766 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -493,16 +493,11 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel) slotname))); } } - PG_CATCH(); + PG_FINALLY(); { - /* Close the connection in case of failure. */ walrcv_disconnect(wrconn); - PG_RE_THROW(); } PG_END_TRY(); - - /* And we are done with the remote side. */ - walrcv_disconnect(wrconn); } else ereport(WARNING, @@ -1023,16 +1018,12 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) walrcv_clear_result(res); } - PG_CATCH(); + PG_FINALLY(); { - /* Close the connection in case of failure */ walrcv_disconnect(wrconn); - PG_RE_THROW(); } PG_END_TRY(); - walrcv_disconnect(wrconn); - pfree(cmd.data); table_close(rel, NoLock); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 7ba859d446..0b84de5943 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2431,13 +2431,11 @@ 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 4b67b40b28..da1da23400 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -430,17 +430,13 @@ vacuum(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 b0ece7ec25..1ee96c0b9f 100644 --- a/src/backend/libpq/be-fsstubs.c +++ b/src/backend/libpq/be-fsstubs.c @@ -503,13 +503,11 @@ 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 c6faa6619d..f2269ad35c 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1514,13 +1514,11 @@ 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: @@ -1716,16 +1714,12 @@ 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 0280c2625c..c397461ad5 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -1193,13 +1193,11 @@ xml_pstrdup_and_free(xmlChar *str) { result = pstrdup((char *) str); } - PG_CATCH(); + PG_FINALLY(); { xmlFree(str); - PG_RE_THROW(); } PG_END_TRY(); - xmlFree(str); } else result = NULL; @@ -3866,19 +3864,14 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt) result = xmlBuffer_to_xmltype(buf); } - PG_CATCH(); + PG_FINALLY() { if (nodefree) nodefree(cur_copy); if (buf) xmlBufferFree(buf); - PG_RE_THROW(); } PG_END_TRY(); - - if (nodefree) - nodefree(cur_copy); - xmlBufferFree(buf); } else { @@ -3893,13 +3886,11 @@ 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; @@ -4734,16 +4725,13 @@ XmlTableGetValue(TableFuncScanState *state, int colnum, state->typioparams[colnum], typmod); } - PG_CATCH(); + PG_FINALLY(); { if (xpathobj != NULL) xmlXPathFreeObject(xpathobj); - PG_RE_THROW(); } PG_END_TRY(); - xmlXPathFreeObject(xpathobj); - return result; #else NO_XML_SUPPORT(); diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index c480999c51..f0fb308552 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1862,20 +1862,15 @@ 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; } @@ -1958,22 +1953,15 @@ 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; PG_RETURN_VOID(); diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c index e92deb32ca..1b592c8a52 100644 --- a/src/pl/plpgsql/src/pl_handler.c +++ b/src/pl/plpgsql/src/pl_handler.c @@ -264,19 +264,14 @@ plpgsql_call_handler(PG_FUNCTION_ARGS) else retval = plpgsql_exec_function(func, fcinfo, NULL, !nonatomic); } - PG_CATCH(); + PG_FINALLY(); { - /* Decrement use-count, restore cur_estate, and propagate error */ + /* 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 e4d543a4d4..b44ce7e225 100644 --- a/src/pl/plpython/plpy_cursorobject.c +++ b/src/pl/plpython/plpy_cursorobject.c @@ -228,13 +228,11 @@ 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 25930f99d7..15cc444af8 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,8 @@ 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 920322e912..6994d7c10b 100644 --- a/src/pl/plpython/plpy_exec.c +++ b/src/pl/plpython/plpy_exec.c @@ -403,18 +403,13 @@ 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; } @@ -1052,15 +1047,12 @@ 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) PLy_elog(ERROR, NULL); diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c index 2fe435d42b..ed2eee0603 100644 --- a/src/pl/plpython/plpy_spi.c +++ b/src/pl/plpython/plpy_spi.c @@ -249,13 +249,11 @@ 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 371e534fd2..589c76e7a7 100644 --- a/src/pl/plpython/plpy_typeio.c +++ b/src/pl/plpython/plpy_typeio.c @@ -925,15 +925,12 @@ 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 8277d1ea85..fccd22b4f5 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,20 +776,9 @@ 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; } base-commit: 61ecea45e50bcd3b87d4e905719e63e41d6321ce -- 2.23.0