PG_FINALLY
authorPeter Eisentraut <[email protected]>
Fri, 1 Nov 2019 10:09:52 +0000 (11:09 +0100)
committerPeter Eisentraut <[email protected]>
Fri, 1 Nov 2019 10:18:03 +0000 (11:18 +0100)
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

32 files changed:
contrib/auto_explain/auto_explain.c
contrib/dblink/dblink.c
contrib/hstore_plpython/hstore_plpython.c
contrib/jsonb_plpython/jsonb_plpython.c
contrib/pg_stat_statements/pg_stat_statements.c
contrib/pg_trgm/trgm_regexp.c
contrib/postgres_fdw/connection.c
contrib/postgres_fdw/postgres_fdw.c
contrib/sepgsql/hooks.c
contrib/sepgsql/label.c
contrib/sepgsql/selinux.c
contrib/sepgsql/uavc.c
src/backend/catalog/index.c
src/backend/commands/async.c
src/backend/commands/copy.c
src/backend/commands/event_trigger.c
src/backend/commands/extension.c
src/backend/commands/subscriptioncmds.c
src/backend/commands/trigger.c
src/backend/commands/vacuum.c
src/backend/libpq/be-fsstubs.c
src/backend/tcop/utility.c
src/backend/utils/adt/xml.c
src/include/utils/elog.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_handler.c
src/pl/plpython/plpy_cursorobject.c
src/pl/plpython/plpy_elog.c
src/pl/plpython/plpy_exec.c
src/pl/plpython/plpy_spi.c
src/pl/plpython/plpy_typeio.c
src/pl/tcl/pltcl.c

index a9536c2de053ebad9c657b58108f17064bf1171c..f118dbaedd7df889442884b432fe5e7b6b741b11 100644 (file)
@@ -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();
 }
index 54b7bf952f3b2c10fb97405cc6be5bbdb09803f5..7e225589a9b33621e1af8d0b82dd563a555fa2cf 100644 (file)
@@ -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);
 }
 
index 4dee56974039695567f32f8118b4003fd1b0cdd1..39bad5580232117cb4d813e2f50017d1dd4ba8dd 100644 (file)
@@ -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);
 }
index ecaa4c6f92b3009dae26a8b22b20c617efc865d8..b41c738ad62f5371570ed188a46145950378ab8c 100644 (file)
@@ -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;
 }
 
index 221b47298ce55d8f7cdd8b4cbee00aedbc8e228f..63b5888ebbc8e72a08116adfea72e31a274f611f 100644 (file)
@@ -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();
 
index 7965a29c9f963c312b247fdb5b062218117f5d02..e65e6838230f4aa0497f37afaa21ee0f7b013e84 100644 (file)
@@ -555,15 +555,12 @@ createTrgmNFA(text *text_re, Oid collation,
        {
                trg = createTrgmNFAInternal(&regex, graph, rcontext);
        }
-       PG_CATCH();
+       PG_FINALLY();
        {
                pg_regfree(&regex);
-               PG_RE_THROW();
        }
        PG_END_TRY();
 
-       pg_regfree(&regex);
-
        /* Clean up all the cruft we created */
        MemoryContextSwitchTo(oldcontext);
        MemoryContextDelete(tmpcontext);
index 12f9dd35be85354d98861c231e2b9e01e72e6c88..7cd69cc70916d485e5d2967756e3803af461973b 100644 (file)
@@ -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);
 }
 
 /*
index 32366641a3eb2df370bd578c34f02c51b4cfc681..fa142960eb55d245e36b86d45935fd40a909992d 100644 (file)
@@ -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();
 
index 992c70e8a062b77d31bf1a270d3f176230a7e438..49f32ac4d3334e28bf3d7b895902b69930853f06 100644 (file)
@@ -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;
 }
 
 /*
index d2505f7f34353854afff66588345ea3852f4d55b..d8a1d129d29b447dab72a052c2c46dbff63564db 100644 (file)
@@ -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);
 }
index 192aabea0b3411d4ed420c60983b7f6fe5c2681f..b7c489cc33625c036a1585971958be2b31ef4b35 100644 (file)
@@ -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;
 }
index 8ce0bc631b7fa0626b1fa17ccd6f168c50a5d44c..f5279cc9b6e22af551fb4cd83a11b742d5d92147 100644 (file)
@@ -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;
 }
index f6c31ccd7660f6e37a5dfc938d212d536ceb223c..7c34509696dfe9699510ce16d3e0b9d7387a9514 100644 (file)
@@ -3449,14 +3449,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
@@ -3676,14 +3674,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.
index d0649d2e3ef17a8552e67f4a6ee75c288819d11f..a3209d076b3ac6279c88758044b7c5ab0db46cd8 100644 (file)
@@ -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);
 }
index 3aeef30b281546e0ef6a2baf4b46f2775217160d..e17d8c760f73c380d6eef39688af4798e010c48b 100644 (file)
@@ -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 */
index f7ee9838f7f6b06b5193577eaefc0c9cc61c7175..0301ae1ddd9027c4a83f3f0f0eb73474a0e26b39 100644 (file)
@@ -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);
 
index f7202cc9e7dc5ef51821bcb855d0c93db96c803c..a04b0c9e5795c0d89afcdd2e57ae380670e8ba2c 100644 (file)
@@ -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.
         */
index 2e67a5889e581d5f89d3bf2a20b44802b81b3244..14191957665781c6c197243c48db3dfe093b9c13 100644 (file)
@@ -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);
index 7ba859d446d6c459bd7a551d8bb08dfbebc64006..0b84de59437e75b1f55286f492c4ce2ce37687ed 100644 (file)
@@ -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);
 
index 4b67b40b2858320567d50c9969b288730d62c2de..da1da234000081711ecb86555d841f5f3fc64930 100644 (file)
@@ -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.
         */
index b0ece7ec25752a124d3e75ed31f057e8cd6543a2..1ee96c0b9fc69a977002a991324ed8c4b66a97e3 100644 (file)
@@ -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(),
index c6faa6619d2fc2b7d87347ceba97e5c6b8909c22..f2269ad35ca4e718eea232183ca6e5021c91a53e 100644 (file)
@@ -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();
 }
 
 /*
index 0280c2625c65f21e8de4b5536b4f609170d4e6da..c397461ad5de1daf5da19b843d4fdb17f1d42bf9 100644 (file)
@@ -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();
index ba0b7f6f79cd9ba0288c1580468d87a144314792..853c2e0709ed92f92c02937db118c9ff6be1ad14 100644 (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)
 
 /*
index c480999c51d9d5dbe349af231bb07c72c081efa2..f0fb3085523ae87f50874ce41a9f796593d2c4a4 100644 (file)
@@ -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();
index e92deb32ca4de385055853cac8b1a53415d93365..1b592c8a5250b6c47a8389879aef61e2254723e2 100644 (file)
@@ -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
         */
index e4d543a4d4614d9a6432acd374f6c29c82870e01..b44ce7e225f010fcebd317d79c050d15085eae3f 100644 (file)
@@ -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,
index 25930f99d78574b9935a9456cee58048b8c8e695..15cc444af8eb236dbaa8b39d0354a296ca517048 100644 (file)
@@ -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);
 }
 
 /*
index 920322e912b326ba8e4d01df600aca5beb7ee16d..6994d7c10b946d19a16b42dd07444590c51f47d6 100644 (file)
@@ -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);
index 2fe435d42b0321784283111a0396ab844a56e027..ed2eee0603ae91c458f48bf5119c6af4dc0f7d2f 100644 (file)
@@ -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,
index 371e534fd2252d2a2829207c31265c5b8ef770d0..589c76e7a76ae1460235d49da8784983afb69f4a 100644 (file)
@@ -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;
 }
 
index 8277d1ea8576a69efcb3f9561ec3dc7978735d1f..fccd22b4f5152b79f048de739d830cbf6a85d712 100644 (file)
@@ -765,9 +765,10 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted)
                        retval = pltcl_func_handler(fcinfo, &current_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;
 }