On 2018-12-14 16:49, Tom Lane wrote:
I don't especially like the MACRO({...}) proposal, because it looks way
too much like gcc's special syntax for "statement expressions". If we
have to go this way, I'd rather see if MACRO((...)) can be made to work.
But I question your assumption that we have to have two physical copies
of the "finally" code. There's nothing wrong with implementing this
sort of infrastructure with some goto's, or whatever else we have to
have to make it work. Also, it'd look more natural as an extension
to the existing PG_TRY infrastructure if the source code were like
PG_TRY();
{
...
}
PG_FINALLY();
{
...
}
PG_END_TRY();
Here is a new implementation that works just like that.
--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From be2246f8e239e57498928d55eb7813e59d2df719 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
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