Add tuple deformation test for virtual generated columns

Add coverage for a virtual generated NOT NULL column followed by a
physically stored NOT NULL column.  This exercises the tuple deformation
case fixed by 89eafad297, where TupleDescFinalize() could incorrectly
treat a virtual generated column as part of the guaranteed physical column
prefix and compute cached offsets past it.

Without that fix, deforming the following column could read from the wrong
tuple offset.

Author: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/A4BC563C-0CA3-4EF3-952A-EA41F9E5BF1E%40gmail.com
This commit is contained in:
David Rowley
2026-06-17 16:57:16 +12:00
parent ab3023ad1e
commit 1f7dfe8c8e
4 changed files with 26 additions and 0 deletions
@@ -721,6 +721,11 @@ ERROR: null value in column "b" of relation "gtest21b" violates not-null constr
DETAIL: Failing row contains (null, null).
ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL;
INSERT INTO gtest21b (a) VALUES (0); -- ok now
-- virtual generated columns are not physically stored, even when not null
--CREATE TABLE gtest21c (a int NOT NULL, b int GENERATED ALWAYS AS (a * 2) VIRTUAL NOT NULL, c int NOT NULL);
--INSERT INTO gtest21c (a, c) VALUES (10, 42);
--SELECT a, b, c FROM gtest21c;
--DROP TABLE gtest21c;
-- not-null constraint with partitioned table
CREATE TABLE gtestnn_parent (
f1 int,
@@ -727,6 +727,16 @@ ERROR: null value in column "b" of relation "gtest21b" violates not-null constr
DETAIL: Failing row contains (null, virtual).
ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL;
INSERT INTO gtest21b (a) VALUES (0); -- ok now
-- virtual generated columns are not physically stored, even when not null
CREATE TABLE gtest21c (a int NOT NULL, b int GENERATED ALWAYS AS (a * 2) VIRTUAL NOT NULL, c int NOT NULL);
INSERT INTO gtest21c (a, c) VALUES (10, 42);
SELECT a, b, c FROM gtest21c;
a | b | c
----+----+----
10 | 20 | 42
(1 row)
DROP TABLE gtest21c;
-- not-null constraint with partitioned table
CREATE TABLE gtestnn_parent (
f1 int,
@@ -368,6 +368,11 @@ INSERT INTO gtest21b (a) VALUES (NULL); -- error
ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL;
INSERT INTO gtest21b (a) VALUES (0); -- ok now
-- virtual generated columns are not physically stored, even when not null
--CREATE TABLE gtest21c (a int NOT NULL, b int GENERATED ALWAYS AS (a * 2) VIRTUAL NOT NULL, c int NOT NULL);
--INSERT INTO gtest21c (a, c) VALUES (10, 42);
--SELECT a, b, c FROM gtest21c;
--DROP TABLE gtest21c;
-- not-null constraint with partitioned table
CREATE TABLE gtestnn_parent (
f1 int,
@@ -374,6 +374,12 @@ INSERT INTO gtest21b (a) VALUES (NULL); -- error
ALTER TABLE gtest21b ALTER COLUMN b DROP NOT NULL;
INSERT INTO gtest21b (a) VALUES (0); -- ok now
-- virtual generated columns are not physically stored, even when not null
CREATE TABLE gtest21c (a int NOT NULL, b int GENERATED ALWAYS AS (a * 2) VIRTUAL NOT NULL, c int NOT NULL);
INSERT INTO gtest21c (a, c) VALUES (10, 42);
SELECT a, b, c FROM gtest21c;
DROP TABLE gtest21c;
-- not-null constraint with partitioned table
CREATE TABLE gtestnn_parent (
f1 int,