* Create cursor for node's query with current parameter values. */
| 3714 | * Create cursor for node's query with current parameter values. |
| 3715 | */ |
| 3716 | static void |
| 3717 | create_cursor(ForeignScanState *node) |
| 3718 | { |
| 3719 | PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state; |
| 3720 | ExprContext *econtext = node->ss.ps.ps_ExprContext; |
| 3721 | int numParams = fsstate->numParams; |
| 3722 | const char **values = fsstate->param_values; |
| 3723 | PGconn *conn = fsstate->conn; |
| 3724 | StringInfoData buf; |
| 3725 | PGresult *res; |
| 3726 | |
| 3727 | /* First, process a pending asynchronous request, if any. */ |
| 3728 | if (fsstate->conn_state->pendingAreq) |
| 3729 | process_pending_request(fsstate->conn_state->pendingAreq); |
| 3730 | |
| 3731 | /* |
| 3732 | * Construct array of query parameter values in text format. We do the |
| 3733 | * conversions in the short-lived per-tuple context, so as not to cause a |
| 3734 | * memory leak over repeated scans. |
| 3735 | */ |
| 3736 | if (numParams > 0) |
| 3737 | { |
| 3738 | MemoryContext oldcontext; |
| 3739 | |
| 3740 | oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); |
| 3741 | |
| 3742 | process_query_params(econtext, |
| 3743 | fsstate->param_flinfo, |
| 3744 | fsstate->param_exprs, |
| 3745 | values); |
| 3746 | |
| 3747 | MemoryContextSwitchTo(oldcontext); |
| 3748 | } |
| 3749 | |
| 3750 | /* Construct the DECLARE CURSOR command */ |
| 3751 | initStringInfo(&buf); |
| 3752 | appendStringInfo(&buf, "DECLARE c%u CURSOR FOR\n%s", |
| 3753 | fsstate->cursor_number, fsstate->query); |
| 3754 | |
| 3755 | /* |
| 3756 | * Notice that we pass NULL for paramTypes, thus forcing the remote server |
| 3757 | * to infer types for all parameters. Since we explicitly cast every |
| 3758 | * parameter (see deparse.c), the "inference" is trivial and will produce |
| 3759 | * the desired result. This allows us to avoid assuming that the remote |
| 3760 | * server has the same OIDs we do for the parameters' types. |
| 3761 | */ |
| 3762 | if (!PQsendQueryParams(conn, buf.data, numParams, |
| 3763 | NULL, values, NULL, NULL, 0)) |
| 3764 | pgfdw_report_error(ERROR, NULL, conn, false, buf.data); |
| 3765 | |
| 3766 | /* |
| 3767 | * Get the result, and check for success. |
| 3768 | * |
| 3769 | * We don't use a PG_TRY block here, so be careful not to throw error |
| 3770 | * without releasing the PGresult. |
| 3771 | */ |
| 3772 | res = pgfdw_get_result(conn, buf.data); |
| 3773 | if (PQresultStatus(res) != PGRES_COMMAND_OK) |
no test coverage detected