In INSERT/UPDATE, use the table's real tuple descriptor as target.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 8 Nov 2020 18:08:36 +0000 (13:08 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 8 Nov 2020 18:08:36 +0000 (13:08 -0500)
This back-patches commit 20d3fe900 into the v12 and v13 branches.
At the time I thought that commit was not fixing any observable
bug, but Bertrand Drouvot showed otherwise: adding a dropped column
to the previously-considered scenario crashes v12 and v13, unless the
dropped column happens to be an integer.  That is, of course, because
the tupdesc we derive from the plan output tlist fails to describe
the dropped column accurately, so that we'll do the wrong thing with
a tuple in which that column isn't NULL.

There is no bug in pre-v12 branches because they already did use
the table's real tuple descriptor for any trigger-returned tuple.
It seems that this set of bugs can be blamed on the changes that
removed es_trig_tuple_slot, though I've not attempted to pin that
down precisely.

Although there's no code change needed in HEAD, update the test case
to include a dropped column there too.

Discussion: https://postgr.es/m/db5d97c8-f48a-51e2-7b08-b73d5434d425@amazon.com
Discussion: https://postgr.es/m/16644-5da7ef98a7ac4545@postgresql.org

src/test/regress/expected/triggers.out
src/test/regress/sql/triggers.sql

index 027494bc76f9d98ccc3c129f45b123f3f5cc6edc..0f058d2d1e76594ef99001b308fea2f8f1d040ad 100644 (file)
@@ -216,34 +216,56 @@ select * from trigtest;
 
 drop table trigtest;
 -- Check behavior with an implicit column default, too (bug #16644)
-create table trigtest (a integer);
+create table trigtest (
+  a integer,
+  b bool default true not null,
+  c text default 'xyzzy' not null);
 create trigger trigger_return_old
    before insert or delete or update on trigtest
    for each row execute procedure trigger_return_old();
 insert into trigtest values(1);
 select * from trigtest;
- a 
----
- 1
+ a | b |   c   
+---+---+-------
+ 1 | t | xyzzy
+(1 row)
+
+alter table trigtest add column d integer default 42 not null;
+select * from trigtest;
+ a | b |   c   | d  
+---+---+-------+----
+ 1 | t | xyzzy | 42
+(1 row)
+
+update trigtest set a = 2 where a = 1 returning *;
+ a | b |   c   | d  
+---+---+-------+----
+ 1 | t | xyzzy | 42
+(1 row)
+
+select * from trigtest;
+ a | b |   c   | d  
+---+---+-------+----
+ 1 | t | xyzzy | 42
 (1 row)
 
-alter table trigtest add column b integer default 42 not null;
+alter table trigtest drop column b;
 select * from trigtest;
- a | b  
----+----
- 1 | 42
+ a |   c   | d  
+---+-------+----
+ 1 | xyzzy | 42
 (1 row)
 
 update trigtest set a = 2 where a = 1 returning *;
- a | b  
----+----
- 1 | 42
+ a |   c   | d  
+---+-------+----
+ 1 | xyzzy | 42
 (1 row)
 
 select * from trigtest;
- a | b  
----+----
- 1 | 42
+ a |   c   | d  
+---+-------+----
+ 1 | xyzzy | 42
 (1 row)
 
 drop table trigtest;
index 212b4f1f959fd5507e8f8759ccd2391db8fe6d0b..1d122af14edffdaab7f74d2012eefb49886ab943 100644 (file)
@@ -155,7 +155,10 @@ select * from trigtest;
 drop table trigtest;
 
 -- Check behavior with an implicit column default, too (bug #16644)
-create table trigtest (a integer);
+create table trigtest (
+  a integer,
+  b bool default true not null,
+  c text default 'xyzzy' not null);
 
 create trigger trigger_return_old
    before insert or delete or update on trigtest
@@ -164,7 +167,13 @@ create trigger trigger_return_old
 insert into trigtest values(1);
 select * from trigtest;
 
-alter table trigtest add column b integer default 42 not null;
+alter table trigtest add column d integer default 42 not null;
+
+select * from trigtest;
+update trigtest set a = 2 where a = 1 returning *;
+select * from trigtest;
+
+alter table trigtest drop column b;
 
 select * from trigtest;
 update trigtest set a = 2 where a = 1 returning *;