mirror of
https://github.com/postgres/postgres.git
synced 2025-05-12 16:21:30 +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:
parent
ba529a6ff4
commit
306c318043
@ -2065,6 +2065,13 @@ SetAttrMissing(Oid relid, char *attname, char *value)
|
|||||||
/* lock the table the attribute belongs to */
|
/* lock the table the attribute belongs to */
|
||||||
tablerel = heap_open(relid, AccessExclusiveLock);
|
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 */
|
/* Lock the attribute row and get the data */
|
||||||
attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
|
attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
|
||||||
atttup = SearchSysCacheAttName(relid, attname);
|
atttup = SearchSysCacheAttName(relid, attname);
|
||||||
@ -2198,7 +2205,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
|
|||||||
valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
|
valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
|
||||||
replacesAtt[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);
|
expr2 = expression_planner(expr2);
|
||||||
estate = CreateExecutorState();
|
estate = CreateExecutorState();
|
||||||
|
@ -10315,10 +10315,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Here we go --- change the recorded column type and collation. (Note
|
* Here we go --- change the recorded column type and collation. (Note
|
||||||
* heapTup is a copy of the syscache entry, so okay to scribble on.)
|
* heapTup is a copy of the syscache entry, so okay to scribble on.) First
|
||||||
* First fix up the missing value if any.
|
* 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;
|
Datum missingval;
|
||||||
bool missingNull;
|
bool missingNull;
|
||||||
|
19
src/backend/utils/cache/relcache.c
vendored
19
src/backend/utils/cache/relcache.c
vendored
@ -546,6 +546,7 @@ RelationBuildTupleDesc(Relation relation)
|
|||||||
{
|
{
|
||||||
Form_pg_attribute attp;
|
Form_pg_attribute attp;
|
||||||
int attnum;
|
int attnum;
|
||||||
|
bool atthasmissing;
|
||||||
|
|
||||||
attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
|
attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
|
||||||
|
|
||||||
@ -559,6 +560,22 @@ RelationBuildTupleDesc(Relation relation)
|
|||||||
attp,
|
attp,
|
||||||
ATTRIBUTE_FIXED_PART_SIZE);
|
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 */
|
/* Update constraint/default info */
|
||||||
if (attp->attnotnull)
|
if (attp->attnotnull)
|
||||||
constr->has_not_null = true;
|
constr->has_not_null = true;
|
||||||
@ -578,7 +595,7 @@ RelationBuildTupleDesc(Relation relation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Likewise for a missing value */
|
/* Likewise for a missing value */
|
||||||
if (attp->atthasmissing)
|
if (atthasmissing)
|
||||||
{
|
{
|
||||||
Datum missingval;
|
Datum missingval;
|
||||||
bool missingNull;
|
bool missingNull;
|
||||||
|
@ -797,7 +797,26 @@ SELECT * FROM t WHERE a IS NULL;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ROLLBACK;
|
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
|
-- cleanup
|
||||||
|
DROP FOREIGN TABLE ft1;
|
||||||
|
DROP SERVER s0;
|
||||||
|
DROP FOREIGN DATA WRAPPER dummy;
|
||||||
DROP TABLE vtype;
|
DROP TABLE vtype;
|
||||||
DROP TABLE vtype2;
|
DROP TABLE vtype2;
|
||||||
DROP TABLE follower;
|
DROP TABLE follower;
|
||||||
|
@ -524,8 +524,22 @@ SET LOCAL enable_seqscan = false;
|
|||||||
SELECT * FROM t WHERE a IS NULL;
|
SELECT * FROM t WHERE a IS NULL;
|
||||||
ROLLBACK;
|
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
|
-- cleanup
|
||||||
|
DROP FOREIGN TABLE ft1;
|
||||||
|
DROP SERVER s0;
|
||||||
|
DROP FOREIGN DATA WRAPPER dummy;
|
||||||
DROP TABLE vtype;
|
DROP TABLE vtype;
|
||||||
DROP TABLE vtype2;
|
DROP TABLE vtype2;
|
||||||
DROP TABLE follower;
|
DROP TABLE follower;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user