diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 97ae019d10a..3ad983c7fa5 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -1254,7 +1254,17 @@ slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, * to implement a tail-call optimization */ *offp = off; - slot_getmissingattrs(slot, attnum, reqnatts); + + Assert(HeapTupleHeaderGetNatts(tup) <= attnum); + + /* + * Fetch all missing attributes. We pass natts rather than attnum as + * if we're deforming attributes after having already deformed some + * missing attributes, then the call to populate_isnull_array() may + * have overwritten the previous tts_isnull values from what was + * stored in the previous call to slot_getmissingattrs(). + */ + slot_getmissingattrs(slot, HeapTupleHeaderGetNatts(tup), reqnatts); return; } done: diff --git a/src/test/regress/expected/fast_default.out b/src/test/regress/expected/fast_default.out index 49485f5ec6a..20356467655 100644 --- a/src/test/regress/expected/fast_default.out +++ b/src/test/regress/expected/fast_default.out @@ -944,6 +944,21 @@ SELECT * FROM t ORDER BY id; (3 rows) DROP TABLE t; +-- Ensure defaults are correctly applied during tuple deformation for whole +-- row vars when the defaults are deformed incrementally. +CREATE TABLE t_missing_wholerow (a int NOT NULL, b int); +INSERT INTO t_missing_wholerow (a, b) VALUES (1, null); -- with NULL bitmap +INSERT INTO t_missing_wholerow (a, b) VALUES (2, 3); -- without NULL bitmap +ALTER TABLE t_missing_wholerow ADD COLUMN c int NOT NULL DEFAULT 15; +ALTER TABLE t_missing_wholerow ADD COLUMN d bigint NOT NULL DEFAULT 25; +SELECT a, b, c, t FROM t_missing_wholerow t; + a | b | c | t +---+---+----+------------- + 1 | | 15 | (1,,15,25) + 2 | 3 | 15 | (2,3,15,25) +(2 rows) + +DROP TABLE t_missing_wholerow; -- cleanup DROP FOREIGN TABLE ft1; DROP SERVER s0; diff --git a/src/test/regress/sql/fast_default.sql b/src/test/regress/sql/fast_default.sql index ccd138c4efc..36f81a184f0 100644 --- a/src/test/regress/sql/fast_default.sql +++ b/src/test/regress/sql/fast_default.sql @@ -618,6 +618,16 @@ REPACK t; SELECT * FROM t ORDER BY id; DROP TABLE t; +-- Ensure defaults are correctly applied during tuple deformation for whole +-- row vars when the defaults are deformed incrementally. +CREATE TABLE t_missing_wholerow (a int NOT NULL, b int); +INSERT INTO t_missing_wholerow (a, b) VALUES (1, null); -- with NULL bitmap +INSERT INTO t_missing_wholerow (a, b) VALUES (2, 3); -- without NULL bitmap +ALTER TABLE t_missing_wholerow ADD COLUMN c int NOT NULL DEFAULT 15; +ALTER TABLE t_missing_wholerow ADD COLUMN d bigint NOT NULL DEFAULT 25; +SELECT a, b, c, t FROM t_missing_wholerow t; +DROP TABLE t_missing_wholerow; + -- cleanup DROP FOREIGN TABLE ft1; DROP SERVER s0;