8000 Don't set a fast default for anything but a plain table · postgrespro/postgres@306c318 · GitHub
[go: up one dir, main page]

Skip to content

Commit 306c318

Browse files
committed
Don't set a fast default for anything but a plain table
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 8000 table we ignore it. Fixes bug #17056 Backpatch to release 11, Reviewed by: Andres Freund, Álvaro Herrera and Tom Lane
1 parent ba529a6 commit 306c318

File tree

5 files changed

+63
-5
lines changed

5 files changed

+63
-5
lines changed

src/backend/catalog/heap.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,13 @@ SetAttrMissing(Oid relid, char *attname, char *value)
20652065
/* lock the table the attribute belongs to */
20662066
tablerel = heap_open(relid, AccessExclusiveLock);
20672067

2068+
/* Don't do anything unless it's a plain table */
2069+
if (tablerel->rd_rel->relkind != RELKIND_RELATION)
2070+
{
2071+
table_close(tablerel, AccessExclusiveLock);
2072+
return;
2073+
}
2074+
20682075
/* Lock the attribute row and get the data */
20692076
attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
20702077
atttup = SearchSysCacheAttName(relid, attname);
@@ -2198,7 +2205,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
21982205
valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
21992206
replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
22002207

2201-
if (add_column_mode)
2208+
if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode)
22022209
{
22032210
expr2 = expression_planner(expr2);
22042211
estate = CreateExecutorState();

src/backend/commands/tablecmds.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10315,10 +10315,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
1031510315

1031610316
/*
1031710317
* Here we go --- change the recorded column type and collation. (Note
10318-
* heapTup is a copy of the syscache entry, so okay to scribble on.)
10319-
* First fix up the missing value if any.
10318+
* heapTup is a copy of the syscache entry, so okay to scribble on.) First
10319+
* fix up the missing value if any. There shouldn't be any missing values
10320+
* for anything except plain tables, but if there are, ignore them.
1032010321
*/
10321-
if (attTup->atthasmissing)
10322+
if (rel->rd_rel->relkind == RELKIND_RELATION && attTup->atthasmissing)
1032210323
{
1032310324
Datum missingval;
1032410325
bool missingNull;

src/backend/utils/cache/relcache.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ RelationBuildTupleDesc(Relation relation)
546546
{
547547
Form_pg_attribute attp;
548548
int attnum;
549+
bool atthasmissing;
549550

550551
attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
551552

@@ -559,6 +560,22 @@ RelationBuildTupleDesc(Relation relation)
559560
attp,
560561
ATTRIBUTE_FIXED_PART_SIZE);
561562

563+
/*
564+
* Fix atthasmissing flag - it's only for plain tables. Others
565+
* should not have missing values set, but there may be some left from
566+
* before when we placed that check, so this code defensively ignores
567+
* such values.
568+
*/
569+
atthasmissing = attp->atthasmissing;
570+
if (relation->rd_rel->relkind != RELKIND_RELATION && atthasmissing)
571+
{
572+
Form_pg_attribute nattp;
573+
574+
atthasmissing = false;
575+
nattp = TupleDescAttr(relation->rd_att, attnum - 1);
576+
nattp->atthasmissing = false;
577+
}
578+
562579
/* Update constraint/default info */
563580
if (attp->attnotnull)
564581
constr->has_not_null = true;
@@ -578,7 +595,7 @@ RelationBuildTupleDesc(Relation relation)
578595
}
579596

580597
/* Likewise for a missing value */
581-
if (attp->atthasmissing)
598+
if (atthasmissing)
582599
{
583600
Datum missingval;
584601
bool missingNull;

src/test/regress/expected/fast_default.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,26 @@ SELECT * FROM t WHERE a IS NULL;
797797
(1 row)
798798

799799
ROLLBACK;
800+
-- verify that a default set on a non-plain table doesn't set a missing
801+
-- value on the attribute
802+
CREATE FOREIGN DATA WRAPPER dummy;
803+
CREATE SERVER s0 FOREIGN DATA WRAPPER dummy;
804+
CREATE FOREIGN TABLE ft1 (c1 integer NOT NULL) SERVER s0;
805+
ALTER FOREIGN TABLE ft1 ADD COLUMN c8 integer DEFAULT 0;
806+
ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE char(10);
807+
SELECT count(*)
808+
FROM pg_attribute
809+
WHERE attrelid = 'ft1'::regclass AND
810+
(attmissingval IS NOT NULL OR atthasmissing);
811+
count
812+
-------
813+
0
814+
(1 row)
815+
800816
-- cleanup
817+
DROP FOREIGN TABLE ft1;
818+
DROP SERVER s0;
819+
DROP FOREIGN DATA WRAPPER dummy;
801820
DROP TABLE vtype;
802821
DROP TABLE vtype2;
803822
DROP TABLE follower;

src/test/regress/sql/fast_default.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,22 @@ SET LOCAL enable_seqscan = false;
524524
SELECT * FROM t WHERE a IS NULL;
525525
ROLLBACK;
526526

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

528539
-- cleanup
540+
DROP FOREIGN TABLE ft1;
541+
DROP SERVER s0;
542+
DROP FOREIGN DATA WRAPPER dummy;
529543
DROP TABLE vtype;
530544
DROP TABLE vtype2;
531545
DROP TABLE follower;

0 commit comments

Comments
 (0)
0