summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-09-02 14:54:41 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-09-02 14:54:41 -0400
commit42d0d46f9825f7c3977e874380b093bb42a7e8ac (patch)
tree6c9dc0752534b0cf69eae4886b0dfea2d725866f
parent258b0411b243856aa02d955dc8f9ccfa631c500f (diff)
downloadpostgresql-42d0d46f9825f7c3977e874380b093bb42a7e8ac.tar.gz
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
-rw-r--r--src/backend/optimizer/plan/subselect.c40
-rw-r--r--src/test/regress/expected/inherit.out24
-rw-r--r--src/test/regress/sql/inherit.sql10
3 files changed, 54 insertions, 20 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 7640e98a8d..bb42047600 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -915,20 +915,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 ArrayRefs 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, ArrayRef))
+ {
+ ArrayRef *aref = (ArrayRef *) expr;
+
+ if (aref->refassgnexpr == NULL)
+ break;
+
+ expr = (Node *) aref->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 2ac33facd3..2bf465542b 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1699,49 +1699,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
-> 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)), inhcld.ctid, p2.ctid
+ Output: $6, inhcld.f2[1] := $7, (SubPlan 1 (returns $2,$3)), inhcld.ctid, p2.ctid
Hash Cond: (inhcld.f1 = p2.unique1)
-> Seq Scan on public.inhcld
- Output: inhcld.ctid, inhcld.f1
+ Output: inhcld.f2, inhcld.ctid, inhcld.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 9a8c52a3eb..f750d9251b 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -622,7 +622,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);
@@ -630,11 +630,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;