Re: BUG #17800: ON CONFLICT DO UPDATE fails to detect incompatible fields that leads to a server crash - Mailing list pgsql-bugs

From Tom Lane
Subject Re: BUG #17800: ON CONFLICT DO UPDATE fails to detect incompatible fields that leads to a server crash
Date
Msg-id 3974447.1677000474@sss.pgh.pa.us
Whole thread Raw
In response to Re: BUG #17800: ON CONFLICT DO UPDATE fails to detect incompatible fields that leads to a server crash  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: BUG #17800: ON CONFLICT DO UPDATE fails to detect incompatible fields that leads to a server crash  (Andres Freund <andres@anarazel.de>)
List pgsql-bugs
I wrote:
> Bisecting produced some interesting results: the "wrong type"
> failure has existed for a pretty long time on HEAD.  The reason
> I don't see it on v13 etc is that commits 3f7323cbb et al fixed
> it in those branches.  That's probably accidental, but I'm too
> tired to poke at it more tonight.

Sigh ... no, it's not accidental: this is exactly the same problem
3f7323cbb fixed, but popping up in two new places.

In the first place, the test cases we had that led to 3f7323cbb
were using traditionally-inherited tables, in which an update
of this sort leads to a plan like

regression=# create table ti (a int, b text);
CREATE TABLE
regression=# create table tichild() inherits(ti);
CREATE TABLE
regression=# explain (verbose, costs off) UPDATE ti SET (a, b) = (SELECT ti.a, ti.b || '+');
                                QUERY PLAN
---------------------------------------------------------------------------
 Update on public.ti
   Update on public.ti ti_1
   Update on public.tichild ti_2
   ->  Result
         Output: $2, $3, (SubPlan 1 (returns $2,$3)), ti.tableoid, ti.ctid
         ->  Append
               ->  Seq Scan on public.ti ti_1
                     Output: ti_1.a, ti_1.b, ti_1.tableoid, ti_1.ctid
               ->  Seq Scan on public.tichild ti_2
                     Output: ti_2.a, ti_2.b, ti_2.tableoid, ti_2.ctid
         SubPlan 1 (returns $2,$3)
           ->  Result
                 Output: ti.a, (ti.b || '+'::text)
(13 rows)

But if the target is a partitioned table, as in Alexander's example:

regression=# explain (verbose, costs off) UPDATE t SET (a, b) = (SELECT t.a, t.b || '+');
                                    QUERY PLAN
-----------------------------------------------------------------------------------
 Update on public.t
   Update on public.tp1 t_1
   Update on public.tp2 t_2
   ->  Append
         ->  Seq Scan on public.tp1 t_1
               Output: $2, $3, (SubPlan 1 (returns $2,$3)), t_1.tableoid, t_1.ctid
               SubPlan 1 (returns $2,$3)
                 ->  Result
                       Output: t_1.a, (t_1.b || '+'::text)
         ->  Seq Scan on public.tp2 t_2
               Output: $2, $3, (SubPlan 1 (returns $2,$3)), t_2.tableoid, t_2.ctid
(11 rows)

I'm not real sure why this discrepancy exists, or whether it's a good
idea.  But at any rate, the reason why I thought 3f7323cbb would only
be needed in the back branches is that I thought we had eliminated all
cases of making multiple clones of an UPDATE's target list when we
nuked inheritance_planner.  But here we have multiple clones of a
MULTIEXPR_SUBLINK SubPlan, and they're all sharing the same output
parameters ($2 and $3, here), and so the confusion about which args list
has to be executed during a recomputation comes right back.

If that were the only problem then I'd seriously think about fixing it
by disallowing this sort of push-down of the UPDATE targetlist when
MULTIEXPR_SUBLINKs are present.  However, the reason we're seeing a
comparable problem in ON CONFLICT is that ExecInitPartitionInfo *also*
makes clones of an UPDATE targetlist, and it is far too naive to fix
this problem.

Not sure about a good fix.  We could imagine porting v13's
SS_make_multiexprs_unique logic forward into the newer branches,
but that depends on a lot of planner infrastructure that won't
be available when ExecInitPartitionInfo runs.  I think in the
back branches we might be forced into disallowing MULTIEXPR_SUBLINKs
in ON CONFLICT targetlists, because supporting them properly is
looking like a mess.

At this point I'm seriously regretting the entire MULTIEXPR_SUBLINK
design, and am wondering if we could find a different solution for
that.  That couldn't lead to a back-patchable fix, obviously.

Another angle is that having ExecInitPartitionInfo doing this sort
of work is a big misallocation of responsibility.  If these tlists
were getting built in the planner it'd be far easier to fix.

            regards, tom lane



pgsql-bugs by date:

Previous
From: Dean Rasheed
Date:
Subject: Re: BUG #17803: Rule "ALSO INSERT ... SELECT ..." fails to substitute default values
Next
From: Tom Lane
Date:
Subject: Re: BUG #17803: Rule "ALSO INSERT ... SELECT ..." fails to substitute default values