1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-13 18:28:01 +03:00

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 table we ignore it.

Fixes bug #17056

Backpatch to release 11,

Reviewed by: Andres Freund, Álvaro Herrera and Tom Lane
This commit is contained in:
Andrew Dunstan
2021-06-18 07:44:58 -04:00
parent ba529a6ff4
commit 306c318043
5 changed files with 63 additions and 5 deletions

View File

@@ -2065,6 +2065,13 @@ SetAttrMissing(Oid relid, char *attname, char *value)
/* lock the table the attribute belongs to */
tablerel = heap_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 = heap_open(AttributeRelationId, RowExclusiveLock);
atttup = SearchSysCacheAttName(relid, attname);
@@ -2198,7 +2205,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
if (add_column_mode)
if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode)
{
expr2 = expression_planner(expr2);
estate = CreateExecutorState();

View File

@@ -10315,10 +10315,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
/*
* Here we go --- change the recorded column type and collation. (Note
* heapTup is a copy of the syscache entry, so okay to scribble on.)
* First fix up the missing value if any.
* heapTup is a copy of the syscache entry, so okay to scribble on.) First
* fix up the missing value if any. There shouldn't be any missing values
* for anything except plain tables, but if there are, ignore them.
*/
if (attTup->atthasmissing)
if (rel->rd_rel->relkind == RELKIND_RELATION && attTup->atthasmissing)
{
Datum missingval;
bool missingNull;

View File

@@ -546,6 +546,7 @@ RelationBuildTupleDesc(Relation relation)
{
Form_pg_attribute attp;
int attnum;
bool atthasmissing;
attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
@@ -559,6 +560,22 @@ RelationBuildTupleDesc(Relation relation)
attp,
ATTRIBUTE_FIXED_PART_SIZE);
/*
* Fix atthasmissing flag - it's only for plain tables. Others
* should not have missing values set, but there may be some left from
* before when we placed that check, so this code defensively ignores
* such values.
*/
atthasmissing = attp->atthasmissing;
if (relation->rd_rel->relkind != RELKIND_RELATION && atthasmissing)
{
Form_pg_attribute nattp;
atthasmissing = false;
nattp = TupleDescAttr(relation->rd_att, attnum - 1);
nattp->atthasmissing = false;
}
/* Update constraint/default info */
if (attp->attnotnull)
constr->has_not_null = true;
@@ -578,7 +595,7 @@ RelationBuildTupleDesc(Relation relation)
}
/* Likewise for a missing value */
if (attp->atthasmissing)
if (atthasmissing)
{
Datum missingval;
bool missingNull;