]> granicus.if.org Git - postgresql/commitdiff
Fix a couple of contrib/dblink bugs.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 4 Apr 2012 00:43:30 +0000 (20:43 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 4 Apr 2012 00:43:30 +0000 (20:43 -0400)
dblink_exec leaked temporary database connections if any error occurred
after connection setup, for example
SELECT dblink_exec('...connect string...', 'select 1/0');
Add a PG_TRY block to ensure PQfinish gets done when it is needed.
(dblink_record_internal is on the hairy edge of needing similar treatment,
but seems not to be actively broken at the moment.)

Also, in 9.0 and up, only one of the three functions using tuplestore
return mode was properly checking that the query context would allow
a tuplestore result.

Noted while reviewing dblink patch.  Back-patch to all supported branches.

contrib/dblink/dblink.c

index c8f91a72fb38e1a6bfd857264af81c38caaa49fe..cc8714dae62a0ff13dbaa2bde510eed05172f138 100644 (file)
@@ -1127,20 +1127,23 @@ PG_FUNCTION_INFO_V1(dblink_exec);
 Datum
 dblink_exec(PG_FUNCTION_ARGS)
 {
+       text       *volatile sql_cmd_status = NULL;
+       PGconn     *volatile conn = NULL;
+       volatile bool freeconn = false;
+
+       DBLINK_INIT;
+
+       PG_TRY();
+       {
        char       *msg;
        PGresult   *res = NULL;
-       text       *sql_cmd_status = NULL;
        TupleDesc       tupdesc = NULL;
-       PGconn     *conn = NULL;
        char       *connstr = NULL;
        char       *sql = NULL;
        char       *conname = NULL;
        remoteConn *rconn = NULL;
-       bool            freeconn = false;
        bool            fail = true;    /* default to backward compatible behavior */
 
-       DBLINK_INIT;
-
        if (PG_NARGS() == 3)
        {
                /* must be text,text,bool */
@@ -1215,8 +1218,17 @@ dblink_exec(PG_FUNCTION_ARGS)
                                (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
                                 errmsg("statement returning results not allowed")));
        }
+       }
+       PG_CATCH();
+       {
+               /* 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 and cleanup */
+       /* if needed, close the connection to the database */
        if (freeconn)
                PQfinish(conn);