1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-11 20:28:21 +03:00

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
This commit is contained in:
Tom Lane
2020-01-26 14:31:08 -05:00
parent 38a957316d
commit 215824f918
3 changed files with 67 additions and 0 deletions

View File

@ -390,6 +390,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.
*/