diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-01-26 14:31:08 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-01-26 14:31:08 -0500 |
commit | 7294f99a0b2043cf9b34a9a59ecb3dfbfae94f85 (patch) | |
tree | 60f69389330151f28089c0c3e040d7b142d1b07b /contrib/postgres_fdw/deparse.c | |
parent | c4c76d198e3db48ac390a46eab66bcaf1d734a2c (diff) | |
download | postgresql-7294f99a0b2043cf9b34a9a59ecb3dfbfae94f85.tar.gz postgresql-7294f99a0b2043cf9b34a9a59ecb3dfbfae94f85.zip |
In postgres_fdw, don't try to ship MULTIEXPR updates to remote server.
In a statement like "UPDATE remote_tab SET (x,y) = (SELECT ...)",
we'd conclude that the statement could be directly executed remotely,
because the sub-SELECT is in a resjunk tlist item that's not examined
for shippability. Currently that ends up crashing if the sub-SELECT
contains any remote Vars. Prevent the crash by deeming MULTIEXEC
Params to be unshippable.
This is a bit of a brute-force solution, since if the sub-SELECT
*doesn't* contain any remote Vars, the current execution technology
would work; but that's not a terribly common use-case for this syntax,
I think. In any case, we generally don't try to ship sub-SELECTs, so
it won't surprise anybody that this doesn't end up as a remote direct
update. I'd be inclined to see if that general limitation can be fixed
before worrying about this case further.
Per report from Lukáš Sobotka.
Back-patch to 9.6. 9.5 had MULTIEXPR, but we didn't try to perform
remote direct updates then, so the case didn't arise anyway.
Discussion: https://postgr.es/m/CAJif3k+iA_ekBB5Zw2hDBaE1wtiQa4LH4_JUXrrMGwTrH0J01Q@mail.gmail.com
Diffstat (limited to 'contrib/postgres_fdw/deparse.c')
-rw-r--r-- | contrib/postgres_fdw/deparse.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 6da4c834bf8..613c8e1319c 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -393,6 +393,22 @@ foreign_expr_walker(Node *node, Param *p = (Param *) node; /* + * If it's a MULTIEXPR Param, punt. We can't tell from here + * whether the referenced sublink/subplan contains any remote + * Vars; if it does, handling that is too complicated to + * consider supporting at present. Fortunately, MULTIEXPR + * Params are not reduced to plain PARAM_EXEC until the end of + * planning, so we can easily detect this case. (Normal + * PARAM_EXEC Params are safe to ship because their values + * come from somewhere else in the plan tree; but a MULTIEXPR + * references a sub-select elsewhere in the same targetlist, + * so we'd be on the hook to evaluate it somehow if we wanted + * to handle such cases as direct foreign updates.) + */ + if (p->paramkind == PARAM_MULTIEXPR) + return false; + + /* * Collation rule is same as for Consts and non-foreign Vars. */ collation = p->paramcollid; |