diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 927d6a43bd..a873d72b3a 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; diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index 6e134d53f6..ed99bdde7f 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1717,49 +1717,49 @@ reset enable_bitmapscan; -- -- Check handling of MULTIEXPR SubPlans in inherited updates -- -create table inhpar(f1 int, f2 name); +create table inhpar(f1 int, f2 text[]); insert into inhpar select generate_series(1,10); create table inhcld() inherits(inhpar); insert into inhcld select generate_series(11,10000); vacuum analyze inhcld; vacuum analyze inhpar; explain (verbose, costs off) -update inhpar set (f1, f2) = (select p2.unique2, p2.stringu1 - from int4_tbl limit 1) +update inhpar set (f1, f2[1]) = (select p2.unique2, p2.stringu1 + from int4_tbl limit 1) from onek p2 where inhpar.f1 = p2.unique1; - QUERY PLAN ------------------------------------------------------------------------------ + QUERY PLAN +----------------------------------------------------------------------------------------------- Update on public.inhpar Update on public.inhpar Update on public.inhcld inhpar_1 -> Merge Join - Output: $4, $5, (SubPlan 1 (returns $2,$3)), inhpar.ctid, p2.ctid + Output: $4, inhpar.f2[1] := $5, (SubPlan 1 (returns $2,$3)), inhpar.ctid, p2.ctid Merge Cond: (p2.unique1 = inhpar.f1) -> Index Scan using onek_unique1 on public.onek p2 Output: p2.unique2, p2.stringu1, p2.ctid, p2.unique1 -> Sort - Output: inhpar.ctid, inhpar.f1 + Output: inhpar.f2, inhpar.ctid, inhpar.f1 Sort Key: inhpar.f1 -> Seq Scan on public.inhpar - Output: inhpar.ctid, inhpar.f1 + Output: inhpar.f2, inhpar.ctid, inhpar.f1 SubPlan 1 (returns $2,$3) -> Limit Output: (p2.unique2), (p2.stringu1) -> Seq Scan on public.int4_tbl Output: p2.unique2, p2.stringu1 -> Hash Join - Output: $6, $7, (SubPlan 1 (returns $2,$3)), inhpar_1.ctid, p2.ctid + Output: $6, inhpar_1.f2[1] := $7, (SubPlan 1 (returns $2,$3)), inhpar_1.ctid, p2.ctid Hash Cond: (inhpar_1.f1 = p2.unique1) -> Seq Scan on public.inhcld inhpar_1 - Output: inhpar_1.ctid, inhpar_1.f1 + Output: inhpar_1.f2, inhpar_1.ctid, inhpar_1.f1 -> Hash Output: p2.unique2, p2.stringu1, p2.ctid, p2.unique1 -> Seq Scan on public.onek p2 Output: p2.unique2, p2.stringu1, p2.ctid, p2.unique1 (27 rows) -update inhpar set (f1, f2) = (select p2.unique2, p2.stringu1 - from int4_tbl limit 1) +update inhpar set (f1, f2[1]) = (select p2.unique2, p2.stringu1 + from int4_tbl limit 1) from onek p2 where inhpar.f1 = p2.unique1; drop table inhpar cascade; NOTICE: drop cascades to table inhcld diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index fd4f252c29..7d3813704e 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -632,7 +632,7 @@ reset enable_bitmapscan; -- -- Check handling of MULTIEXPR SubPlans in inherited updates -- -create table inhpar(f1 int, f2 name); +create table inhpar(f1 int, f2 text[]); insert into inhpar select generate_series(1,10); create table inhcld() inherits(inhpar); insert into inhcld select generate_series(11,10000); @@ -640,11 +640,11 @@ vacuum analyze inhcld; vacuum analyze inhpar; explain (verbose, costs off) -update inhpar set (f1, f2) = (select p2.unique2, p2.stringu1 - from int4_tbl limit 1) +update inhpar set (f1, f2[1]) = (select p2.unique2, p2.stringu1 + from int4_tbl limit 1) from onek p2 where inhpar.f1 = p2.unique1; -update inhpar set (f1, f2) = (select p2.unique2, p2.stringu1 - from int4_tbl limit 1) +update inhpar set (f1, f2[1]) = (select p2.unique2, p2.stringu1 + from int4_tbl limit 1) from onek p2 where inhpar.f1 = p2.unique1; drop table inhpar cascade;