aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/postgres_fdw/deparse.c18
-rw-r--r--contrib/postgres_fdw/expected/postgres_fdw.out12
-rw-r--r--contrib/postgres_fdw/postgres_fdw.c15
3 files changed, 32 insertions, 13 deletions
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index f005e0f26fb..1f4b2449be7 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -331,12 +331,10 @@ foreign_expr_walker(Node *node, foreign_expr_cxt *context)
* function or type defined in the information_schema.
*
* Our constraints for dealing with types are tighter than they are for
- * functions or operators: we want to accept only types that are in pg_catalog
- * (else format_type might incorrectly fail to schema-qualify their names),
- * and we want to be sure that the remote server will use the same OID as
- * we do (since we must transmit a numeric type OID when passing a value of
- * the type as a query parameter). Both of these are reasons to reject
- * objects created post-bootstrap.
+ * functions or operators: we want to accept only types that are in pg_catalog,
+ * else format_type might incorrectly fail to schema-qualify their names.
+ * (This could be fixed with some changes to format_type, but for now there's
+ * no need.) Thus we must exclude information_schema types.
*
* XXX there is a problem with this, which is that the set of built-in
* objects expands over time. Something that is built-in to us might not
@@ -794,12 +792,20 @@ deparseConst(StringInfo buf, Const *node, PlannerInfo *root)
* We don't need to renumber the parameter ID, because the executor functions
* in postgres_fdw.c preserve the numbering of PARAM_EXTERN Params.
* (This might change soon.)
+ *
+ * Note: we label the Param's type explicitly rather than relying on
+ * transmitting a numeric type OID in PQexecParams(). This allows us to
+ * avoid assuming that types have the same OIDs on the remote side as they
+ * do locally --- they need only have the same names.
*/
static void
deparseParam(StringInfo buf, Param *node, PlannerInfo *root)
{
Assert(node->paramkind == PARAM_EXTERN);
appendStringInfo(buf, "$%d", node->paramid);
+ appendStringInfo(buf, "::%s",
+ format_type_with_typemod(node->paramtype,
+ node->paramtypmod));
}
/*
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index b81a3086738..9a2c8e83cc4 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -558,11 +558,11 @@ EXPLAIN (VERBOSE, COSTS false) EXECUTE st4(1);
-- once we try it enough times, should switch to generic plan
EXPLAIN (VERBOSE, COSTS false) EXECUTE st4(1);
- QUERY PLAN
-----------------------------------------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------------------------------------------------------------------------
Foreign Scan on public.ft1 t1
Output: c1, c2, c3, c4, c5, c6, c7, c8
- Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1))
+ Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
(3 rows)
-- value of $1 should not be sent to remote
@@ -613,12 +613,12 @@ EXPLAIN (VERBOSE, COSTS false) EXECUTE st5('foo', 1);
(4 rows)
EXPLAIN (VERBOSE, COSTS false) EXECUTE st5('foo', 1);
- QUERY PLAN
-----------------------------------------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------------------------------------------------------------------------
Foreign Scan on public.ft1 t1
Output: c1, c2, c3, c4, c5, c6, c7, c8
Filter: (t1.c8 = $1)
- Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $2))
+ Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $2::integer))
(4 rows)
EXECUTE st5('foo', 1);
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 0aef00b738d..a3256179f2b 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -902,10 +902,23 @@ create_cursor(ForeignScanState *node)
params->paramFetch(params, paramno);
/*
+ * Force the remote server to infer a type for this parameter.
+ * Since we explicitly cast every parameter (see deparse.c), the
+ * "inference" is trivial and will produce the desired result.
+ * This allows us to avoid assuming that the remote server has the
+ * same OIDs we do for the parameters' types.
+ *
+ * We'd not need to pass a type array to PQexecParams at all,
+ * except that there may be unused holes in the array, which
+ * will have to be filled with something or the remote server will
+ * complain. We arbitrarily set them to INT4OID earlier.
+ */
+ types[paramno - 1] = InvalidOid;
+
+ /*
* Get string representation of each parameter value by invoking
* type-specific output function, unless the value is null.
*/
- types[paramno - 1] = prm->ptype;
if (prm->isnull)
values[paramno - 1] = NULL;
else