Skip to content

Commit

Permalink
Don't set a fast default for anything but a plain table
Browse files Browse the repository at this point in the history
The fast default code added in Release 11 omitted to check that the
table a fast default was being added to was a plain table. Thus one
could be added to a foreign table, which predicably blows up. Here we
perform that check.

In addition, on the back branches, since some of these might have
escaped into the wild, if we encounter a missing value for
an attribute of something other than a plain table we ignore it.

Fixes bug #17056

Backpatch to release 11,

Reviewed by: Andres Freund, Álvaro Herrera and Tom Lane
  • Loading branch information
adunstan committed Jun 18, 2021
1 parent 981524d commit 0a4efdc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/backend/catalog/heap.c
Expand Up @@ -2161,6 +2161,13 @@ SetAttrMissing(Oid relid, char *attname, char *value)
/* lock the table the attribute belongs to */
tablerel = table_open(relid, AccessExclusiveLock);

/* Don't do anything unless it's a plain table */
if (tablerel->rd_rel->relkind != RELKIND_RELATION)
{
table_close(tablerel, AccessExclusiveLock);
return;
}

/* Lock the attribute row and get the data */
attrrel = table_open(AttributeRelationId, RowExclusiveLock);
atttup = SearchSysCacheAttName(relid, attname);
Expand Down Expand Up @@ -2287,7 +2294,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;

if (add_column_mode && !attgenerated)
if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode &&
!attgenerated)
{
expr2 = expression_planner(expr2);
estate = CreateExecutorState();
Expand Down
19 changes: 19 additions & 0 deletions src/test/regress/expected/fast_default.out
Expand Up @@ -797,7 +797,26 @@ SELECT * FROM t WHERE a IS NULL;
(1 row)

ROLLBACK;
-- verify that a default set on a non-plain table doesn't set a missing
-- value on the attribute
CREATE FOREIGN DATA WRAPPER dummy;
CREATE SERVER s0 FOREIGN DATA WRAPPER dummy;
CREATE FOREIGN TABLE ft1 (c1 integer NOT NULL) SERVER s0;
ALTER FOREIGN TABLE ft1 ADD COLUMN c8 integer DEFAULT 0;
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10);
SELECT count(*)
FROM pg_attribute
WHERE attrelid = 'ft1'::regclass AND
(attmissingval IS NOT NULL OR atthasmissing);
count
-------
0
(1 row)

-- cleanup
DROP FOREIGN TABLE ft1;
DROP SERVER s0;
DROP FOREIGN DATA WRAPPER dummy;
DROP TABLE vtype;
DROP TABLE vtype2;
DROP TABLE follower;
Expand Down
14 changes: 14 additions & 0 deletions src/test/regress/sql/fast_default.sql
Expand Up @@ -524,8 +524,22 @@ SET LOCAL enable_seqscan = false;
SELECT * FROM t WHERE a IS NULL;
ROLLBACK;

-- verify that a default set on a non-plain table doesn't set a missing
-- value on the attribute
CREATE FOREIGN DATA WRAPPER dummy;
CREATE SERVER s0 FOREIGN DATA WRAPPER dummy;
CREATE FOREIGN TABLE ft1 (c1 integer NOT NULL) SERVER s0;
ALTER FOREIGN TABLE ft1 ADD COLUMN c8 integer DEFAULT 0;
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10);
SELECT count(*)
FROM pg_attribute
WHERE attrelid = 'ft1'::regclass AND
(attmissingval IS NOT NULL OR atthasmissing);

-- cleanup
DROP FOREIGN TABLE ft1;
DROP SERVER s0;
DROP FOREIGN DATA WRAPPER dummy;
DROP TABLE vtype;
DROP TABLE vtype2;
DROP TABLE follower;
Expand Down

0 comments on commit 0a4efdc

Please sign in to comment.