diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-09-02 14:54:40 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-09-02 14:54:40 -0400 |
commit | df92bc115ec8712cfdd0c7a26ef20b11914ab0a2 (patch) | |
tree | 6d9e7276b6ed8ba5867d673b26408b357b319440 /src/backend/optimizer/plan/subselect.c | |
parent | f249f1026f71bd8f2e820f1895b745d59fab041e (diff) | |
download | postgresql-df92bc115ec8712cfdd0c7a26ef20b11914ab0a2.tar.gz postgresql-df92bc115ec8712cfdd0c7a26ef20b11914ab0a2.zip |
Fix oversight in recent MULTIEXPR_SUBLINK fix.
Commits 3f7323cbb et al missed the possibility that the Params
they are looking for could be buried under implicit coercions,
as well as other stuff that processIndirection() could add to
the original targetlist entry. Copy the code in ruleutils.c
that deals with such cases. (I thought about refactoring so
that there's just one copy; but seeing that we only need this
in old back branches, it seems not worth the trouble.)
Per off-list report from Andre Lin. As before, only v10-v13
need the patch.
Discussion: https://postgr.es/m/17596-c5357f61427a81dc@postgresql.org
Diffstat (limited to 'src/backend/optimizer/plan/subselect.c')
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 4c6f84a6755..cde52114a7d 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -914,20 +914,54 @@ SS_make_multiexprs_unique(PlannerInfo *root, PlannerInfo *subroot) /* * Now we must find the Param nodes that reference the MULTIEXPR outputs * and update their sublink IDs so they'll reference the new outputs. - * Fortunately, those too must be at top level of the cloned targetlist. + * Fortunately, those too must be in the cloned targetlist, but they could + * be buried under FieldStores and SubscriptingRefs and CoerceToDomains + * (cf processIndirection()), and underneath those there could be an + * implicit type coercion. */ offset = list_length(root->multiexpr_params); foreach(lc, subroot->parse->targetList) { TargetEntry *tent = (TargetEntry *) lfirst(lc); + Node *expr; Param *p; int subqueryid; int colno; - if (!IsA(tent->expr, Param)) + expr = (Node *) tent->expr; + while (expr) + { + if (IsA(expr, FieldStore)) + { + FieldStore *fstore = (FieldStore *) expr; + + expr = (Node *) linitial(fstore->newvals); + } + else if (IsA(expr, SubscriptingRef)) + { + SubscriptingRef *sbsref = (SubscriptingRef *) expr; + + if (sbsref->refassgnexpr == NULL) + break; + + expr = (Node *) sbsref->refassgnexpr; + } + else if (IsA(expr, CoerceToDomain)) + { + CoerceToDomain *cdomain = (CoerceToDomain *) expr; + + if (cdomain->coercionformat != COERCE_IMPLICIT_CAST) + break; + expr = (Node *) cdomain->arg; + } + else + break; + } + expr = strip_implicit_coercions(expr); + if (expr == NULL || !IsA(expr, Param)) continue; - p = (Param *) tent->expr; + p = (Param *) expr; if (p->paramkind != PARAM_MULTIEXPR) continue; subqueryid = p->paramid >> 16; |