Hi,

On 2025-05-20 10:59:22 -0400, Andres Freund wrote:
> On 2025-05-18 19:31:33 -0400, Tom Lane wrote:
> > While chasing down Valgrind leakage reports, I was disturbed
> > to realize that some of them arise from a case where the
> > executor scribbles on the plan tree it's given, which it is
> > absolutely not supposed to do:
> >
> >         /*
> >          * Initialize result tuple slot and assign its rowtype using the 
> > first
> >          * RETURNING list.  We assume the rest will look the same.
> >          */
> >         mtstate->ps.plan->targetlist = (List *) linitial(returningLists);
> >
> > A bit of git archaeology fingers Andres' commit 4717fdb14, which we
> > can't easily revert since he later got rid of ExecAssignResultType
> > altogether.  But I think we need to do something about it --- it's
> > purest luck that this doesn't cause serious problems in some cases.
>
> I have no idea what I was smoking at that time, this clearly is wrong.
>
> I think the reason it doesn't cause problems is that we're just using the
> first child's targetlist every time and we're just assigning the same value
> back every time.
>
>
> What's even more absurd is: Why do we even need to assign the result type at
> all? Before & after 4717fdb14. The planner ought to have already figured this
> out, no?
>
> It seems that if not, we'd have a problem anyway, who says the "calling" nodes
> (say a wCTE) can cope with whatever output we come up with?
>
> Except of course, there is exactly one case in our tests where the tupledescs
> aren't equal :(

That's a harmless difference, as it turns out. The varnos / varattnos differ,
but that's fine, because we don't actually build the projection with that
tlist, we just use to allocate the slot, and that doesn't care about the
tlist. The building of the projection uses the specific child's returning
list.

Afaict the mtstate->ps.plan->targetlist assignment, and the ExecTypeFromTL(),
ExecAssignResultTypeFromTL() before that, are completely superfluous.  Am I
missing something?


Wonder if the targetlist assignment is superfluous made me wonder if we would
detect mismatches - and afaict we largely wouldn't. There's basically no
verification in ExecBuildProjectionInfo().  And indeed, adding something very
basic shows:

--- /home/andres/src/postgresql/src/test/regress/expected/merge.out     
2025-04-06 22:54:14.078394968 -0400
+++ 
/srv/dev/build/postgres/m-dev-assert/testrun/regress/regress/results/merge.out  
    2025-05-20 11:51:51.549525728 -0400
@@ -2653,20 +2653,95 @@
 MERGE into measurement m
  USING new_measurement nm ON
       (m.city_id = nm.city_id and m.logdate=nm.logdate)
 WHEN MATCHED AND nm.peaktemp IS NULL THEN DELETE
 WHEN MATCHED THEN UPDATE
      SET peaktemp = greatest(m.peaktemp, nm.peaktemp),
         unitsales = m.unitsales + coalesce(nm.unitsales, 0)
 WHEN NOT MATCHED THEN INSERT
      (city_id, logdate, peaktemp, unitsales)
    VALUES (city_id, logdate, peaktemp, unitsales);
+WARNING:  type mismatch: resno 1: slot type 0 vs expr type 23
+WARNING:  TargetEntry:
+DETAIL:     {TARGETENTRY
+   :expr
+      {VAR
+      :varno -1
+      :varattno 3
+      :vartype 23
+      :vartypmod -1
+      :varcollid 0
+      :varnullingrels (b)
+      :varlevelsup 0
+      :varreturningtype 0
+      :varnosyn 2
+      :varattnosyn 1
+      :location 384
+      }
+   :resno 1
+   :resname city_id
+   :ressortgroupref 0
+   :resorigtbl 0
+   :resorigcol 0
+   :resjunk false
+   }
+
+WARNING:  type mismatch: resno 2: slot type 23 vs expr type 1082
+WARNING:  TargetEntry:
+DETAIL:     {TARGETENTRY
+   :expr
+      {VAR
+      :varno -1
+      :varattno 4
+      :vartype 1082
+      :vartypmod -1
+      :varcollid 0
+      :varnullingrels (b)
+      :varlevelsup 0
+      :varreturningtype 0
+      :varnosyn 2
+      :varattnosyn 2
+      :location 393
+      }
+   :resno 2
+   :resname logdate
+   :ressortgroupref 0
+   :resorigtbl 0
+   :resorigcol 0
+   :resjunk false
+   }
+
+WARNING:  type mismatch: resno 3: slot type 1082 vs expr type 23
+WARNING:  TargetEntry:
+DETAIL:     {TARGETENTRY
+   :expr
+      {VAR
+      :varno -1
+      :varattno 1
+      :vartype 23
+      :vartypmod -1
+      :varcollid 0
+      :varnullingrels (b)
+      :varlevelsup 0
+      :varreturningtype 0
+      :varnosyn 2
+      :varattnosyn 3
+      :location 402
+      }
+   :resno 3
...


Greetings,

Andres Freund


Reply via email to