Fix postgresql_fdw to use PQsendQueryParams() to execute foreign query.
authorShigeru Hanada <[email protected]>
Tue, 15 Mar 2011 02:18:54 +0000 (11:18 +0900)
committerShigeru Hanada <[email protected]>
Tue, 15 Mar 2011 02:18:54 +0000 (11:18 +0900)
contrib/postgresql_fdw/postgresql_fdw.c

index 39bd1be49f9aa63a097ec0873e12fdea25a1cc48..3f030b91ac7f0655540ae98c273a8e09a12c4e02 100644 (file)
@@ -503,11 +503,11 @@ pgBeginForeignScan(ForeignScanState *node, int eflags)
    FdwPlan        *fdwplan;
    const char     *sql;
    PGconn         *conn;
-   PGresult       *res;
    ParamListInfo   params = node->ss.ps.state->es_param_list_info;
    int         numParams = params ? params->numParams : 0;
    Oid        *types = NULL;
    const char **values = NULL;
+   int             ret;
 
    elog(DEBUG3, "%s() called", __FUNCTION__);
 
@@ -562,34 +562,32 @@ pgBeginForeignScan(ForeignScanState *node, int eflags)
     */
    fdwplan = ((ForeignScan *) node->ss.ps.plan)->fdwplan;
    sql = strVal(list_nth(fdwplan->fdw_private, 0));
-   res = PQexecParams(conn, sql, numParams, types, values, NULL, NULL, 0);
+   ret = PQsendQueryParams(conn, sql, numParams, types, values, NULL, NULL, 0);
+
+   /* Free parameters */
    if (numParams > 0)
    {
-       int i;
+       int     i;
+
        pfree(types);
        for (i = 0; i < numParams; i++)
            pfree((char *) values[i]);
        pfree(values);
    }
 
-   /*
-    * If the query has failed, reporting details is enough here.
-    * Connections which are used by this query (including other scans) will
-    * be cleaned up by the foreign connection manager.
-    */
-   if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+   if (ret != 1)
    {
        char *msg;
 
        msg = pstrdup(PQerrorMessage(conn));
-       PQclear(res);
        ereport(ERROR,
-               (errmsg("could not execute foreign query"),
+               (errmsg("could not send foreign query"),
                 errdetail("%s", msg),
                 errhint("%s", sql)));
    }
 
-   festate->res = res;
+   /* The result has not been retrieved yet. */
+   festate->res = NULL;
    festate->nextrow = 0;
 
    node->fdw_state = (void *) festate;
@@ -612,6 +610,40 @@ pgIterateForeignScan(ForeignScanState *node)
 
    elog(DEBUG3, "%s() called", __FUNCTION__);
 
+   /*
+    * If this was the first call for this foreign query, retrieve the results.
+    */
+   if (festate->res == NULL)
+   {
+       PGresult       *res;
+
+       res = PQgetResult(festate->conn);
+
+       /*
+        * If the query has failed, reporting details is enough here.
+        * Connections which are used by this query (including other scans) will
+        * be cleaned up by the foreign connection manager.
+        */
+       if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+       {
+           FdwPlan    *fdwplan;
+           char       *sql;
+           char       *msg;
+
+           fdwplan = ((ForeignScan *) node->ss.ps.plan)->fdwplan;
+           sql = strVal(list_nth(fdwplan->fdw_private, 0));
+
+           msg = pstrdup(PQerrorMessage(festate->conn));
+           PQclear(res);
+           ereport(ERROR,
+                   (errmsg("could not execute foreign query"),
+                    errdetail("%s", msg),
+                    errhint("%s", sql)));
+       }
+
+       festate->res = res;
+   }
+
    if (festate->nextrow == PQntuples(festate->res))
        ExecClearTuple(slot);
    else