Change postgres_fdw to show casts as casts, not underlying function calls.

On reflection this method seems to be exposing an unreasonable amount of
implementation detail.  It wouldn't matter when talking to a remote server
of the identical Postgres version, but it seems likely to make things worse
not better if the remote is a different version with different casting
infrastructure.  Instead adopt ruleutils.c's policy of regurgitating the
cast as it was originally specified; including not showing it at all, if
it was implicit to start with.  (We must do that because for some datatypes
explicit and implicit casts have different semantics.)
This commit is contained in:
Tom Lane 2013-02-22 07:30:21 -05:00
parent 5fd386bb31
commit 211e157a51
2 changed files with 47 additions and 19 deletions

View file

@ -855,10 +855,6 @@ deparseArrayRef(StringInfo buf, ArrayRef *node, PlannerInfo *root)
/* /*
* Deparse given node which represents a function call into buf. * Deparse given node which represents a function call into buf.
*
* Here not only explicit function calls and explicit casts but also implicit
* casts are deparsed to avoid problems caused by different cast settings
* between local and remote.
*/ */
static void static void
deparseFuncExpr(StringInfo buf, FuncExpr *node, PlannerInfo *root) deparseFuncExpr(StringInfo buf, FuncExpr *node, PlannerInfo *root)
@ -870,6 +866,37 @@ deparseFuncExpr(StringInfo buf, FuncExpr *node, PlannerInfo *root)
bool first; bool first;
ListCell *arg; ListCell *arg;
/*
* If the function call came from an implicit coercion, then just show the
* first argument.
*/
if (node->funcformat == COERCE_IMPLICIT_CAST)
{
deparseExpr(buf, (Expr *) linitial(node->args), root);
return;
}
/*
* If the function call came from a cast, then show the first argument
* plus an explicit cast operation.
*/
if (node->funcformat == COERCE_EXPLICIT_CAST)
{
Oid rettype = node->funcresulttype;
int32 coercedTypmod;
/* Get the typmod if this is a length-coercion function */
(void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
deparseExpr(buf, (Expr *) linitial(node->args), root);
appendStringInfo(buf, "::%s",
format_type_with_typemod(rettype, coercedTypmod));
return;
}
/*
* Normal function: display as proname(args).
*/
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(node->funcid)); proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(node->funcid));
if (!HeapTupleIsValid(proctup)) if (!HeapTupleIsValid(proctup))
elog(ERROR, "cache lookup failed for function %u", node->funcid); elog(ERROR, "cache lookup failed for function %u", node->funcid);
@ -1062,9 +1089,10 @@ static void
deparseRelabelType(StringInfo buf, RelabelType *node, PlannerInfo *root) deparseRelabelType(StringInfo buf, RelabelType *node, PlannerInfo *root)
{ {
deparseExpr(buf, node->arg, root); deparseExpr(buf, node->arg, root);
appendStringInfo(buf, "::%s", if (node->relabelformat != COERCE_IMPLICIT_CAST)
format_type_with_typemod(node->resulttype, appendStringInfo(buf, "::%s",
node->resulttypmod)); format_type_with_typemod(node->resulttype,
node->resulttypmod));
} }
/* /*

View file

@ -188,11 +188,11 @@ SELECT * FROM ft1 WHERE false;
-- with WHERE clause -- with WHERE clause
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.ft1 t1 Foreign Scan on public.ft1 t1
Output: c1, c2, c3, c4, c5, c6, c7, c8 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 ((c7 >= '1'::bpchar)) AND (("C 1" = 101)) AND ((c6::text = '1'::text)) Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c7 >= '1'::bpchar)) AND (("C 1" = 101)) AND ((c6 = '1'::text))
(3 rows) (3 rows)
SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
@ -353,11 +353,11 @@ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL; --
(3 rows) (3 rows)
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------
Foreign Scan on public.ft1 t1 Foreign Scan on public.ft1 t1
Output: c1, c2, c3, c4, c5, c6, c7, c8 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 ((round("numeric"(abs("C 1")), 0) = 1::numeric)) Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((round(abs("C 1"), 0) = 1::numeric))
(3 rows) (3 rows)
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l) EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l)
@ -369,11 +369,11 @@ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c1 = -c1; --
(3 rows) (3 rows)
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE 1 = c1!; -- OpExpr(r) EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE 1 = c1!; -- OpExpr(r)
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------
Foreign Scan on public.ft1 t1 Foreign Scan on public.ft1 t1
Output: c1, c2, c3, c4, c5, c6, c7, c8 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 ((1::numeric = (int8("C 1") !))) Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((1::numeric = ("C 1" !)))
(3 rows) (3 rows)
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
@ -401,11 +401,11 @@ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[
(3 rows) (3 rows)
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------
Foreign Scan on public.ft1 t1 Foreign Scan on public.ft1 t1
Output: c1, c2, c3, c4, c5, c6, c7, c8 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 ((c6::text = E'foo''s\\bar'::text)) Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c6 = E'foo''s\\bar'::text))
(3 rows) (3 rows)
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote