aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tablecmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r--src/backend/commands/tablecmds.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c79cd1f9edd..7b2bab71c34 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.42 2002/09/22 00:37:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.43 2002/09/22 19:42:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -609,6 +609,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
attributeName,
TypeNameToString(def->typename),
format_type_be(attribute->atttypid));
+ def->inhcount++;
/* Merge of NOT NULL constraints = OR 'em together */
def->is_not_null |= attribute->attnotnull;
/* Default and other constraints are handled below */
@@ -625,7 +626,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
typename->typeid = attribute->atttypid;
typename->typmod = attribute->atttypmod;
def->typename = typename;
- def->is_inherited = true;
+ def->inhcount = 1;
+ def->is_local = false;
def->is_not_null = attribute->attnotnull;
def->raw_default = NULL;
def->cooked_default = NULL;
@@ -758,6 +760,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
attributeName,
TypeNameToString(def->typename),
TypeNameToString(newdef->typename));
+ /* Mark the column as locally defined */
+ def->is_local = true;
/* Merge of NOT NULL constraints = OR 'em together */
def->is_not_null |= newdef->is_not_null;
/* If new def has a default, override previous default */
@@ -1155,7 +1159,7 @@ renameatt(Oid myrelid,
* if the attribute is inherited, forbid the renaming, unless we are
* already inside a recursive rename.
*/
- if (attform->attisinherited && !recursing)
+ if (attform->attinhcount > 0 && !recursing)
elog(ERROR, "renameatt: inherited attribute \"%s\" may not be renamed",
oldattname);
@@ -1628,7 +1632,8 @@ AlterTableAddColumn(Oid myrelid,
*children;
ColumnDef *colDefChild = copyObject(colDef);
- colDefChild->is_inherited = true;
+ colDefChild->inhcount = 1;
+ colDefChild->is_local = false;
/* this routine is actually in the planner */
children = find_all_inheritors(myrelid);
@@ -1742,7 +1747,8 @@ AlterTableAddColumn(Oid myrelid,
attribute->atthasdef = (colDef->raw_default != NULL ||
colDef->cooked_default != NULL);
attribute->attisdropped = false;
- attribute->attisinherited = colDef->is_inherited;
+ attribute->attislocal = colDef->is_local;
+ attribute->attinhcount = colDef->inhcount;
ReleaseSysCache(typeTuple);
@@ -2373,13 +2379,14 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
RelationGetRelationName(rel));
/* Don't drop inherited columns */
- if (tupleDesc->attrs[attnum - 1]->attisinherited && !recursing)
+ if (tupleDesc->attrs[attnum - 1]->attinhcount > 0 && !recursing)
elog(ERROR, "ALTER TABLE: Cannot drop inherited column \"%s\"",
colName);
/*
* If we are asked to drop ONLY in this table (no recursion), we need
- * to mark the inheritors' attribute as non-inherited.
+ * to mark the inheritors' attribute as locally defined rather than
+ * inherited.
*/
if (!recurse && !recursing)
{
@@ -2396,6 +2403,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
Oid childrelid = lfirsti(child);
Relation childrel;
HeapTuple tuple;
+ Form_pg_attribute childatt;
childrel = heap_open(childrelid, AccessExclusiveLock);
@@ -2403,43 +2411,84 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "ALTER TABLE: relation %u has no column \"%s\"",
childrelid, colName);
+ childatt = (Form_pg_attribute) GETSTRUCT(tuple);
- ((Form_pg_attribute) GETSTRUCT(tuple))->attisinherited = false;
+ if (childatt->attinhcount <= 0)
+ elog(ERROR, "ALTER TABLE: relation %u has non-inherited column \"%s\"",
+ childrelid, colName);
+ childatt->attinhcount--;
+ childatt->attislocal = true;
simple_heap_update(attr_rel, &tuple->t_self, tuple);
/* keep the system catalog indexes current */
CatalogUpdateIndexes(attr_rel, tuple);
+ heap_freetuple(tuple);
+
heap_close(childrel, NoLock);
}
heap_close(attr_rel, RowExclusiveLock);
}
/*
- * Propagate to children if desired
+ * Propagate to children if desired. Unlike most other ALTER routines,
+ * we have to do this one level of recursion at a time; we can't use
+ * find_all_inheritors to do it in one pass.
*/
if (recurse)
{
+ Relation attr_rel;
List *child,
*children;
- /* this routine is actually in the planner */
- children = find_all_inheritors(myrelid);
+ /* We only want direct inheritors in this case */
+ children = find_inheritance_children(myrelid);
- /*
- * find_all_inheritors does the recursive search of the
- * inheritance hierarchy, so all we have to do is process all of
- * the relids in the list that it returns.
- */
+ attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
foreach(child, children)
{
Oid childrelid = lfirsti(child);
+ Relation childrel;
+ HeapTuple tuple;
+ Form_pg_attribute childatt;
if (childrelid == myrelid)
continue;
- AlterTableDropColumn(childrelid, false, true, colName, behavior);
+
+ childrel = heap_open(childrelid, AccessExclusiveLock);
+
+ tuple = SearchSysCacheCopyAttName(childrelid, colName);
+ if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
+ elog(ERROR, "ALTER TABLE: relation %u has no column \"%s\"",
+ childrelid, colName);
+ childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ if (childatt->attinhcount <= 0)
+ elog(ERROR, "ALTER TABLE: relation %u has non-inherited column \"%s\"",
+ childrelid, colName);
+
+ if (childatt->attinhcount == 1 && !childatt->attislocal)
+ {
+ /* Time to delete this child column, too */
+ AlterTableDropColumn(childrelid, true, true, colName, behavior);
+ }
+ else
+ {
+ /* Child column must survive my deletion */
+ childatt->attinhcount--;
+
+ simple_heap_update(attr_rel, &tuple->t_self, tuple);
+
+ /* keep the system catalog indexes current */
+ CatalogUpdateIndexes(attr_rel, tuple);
+ }
+
+ heap_freetuple(tuple);
+
+ heap_close(childrel, NoLock);
}
+ heap_close(attr_rel, RowExclusiveLock);
}
/*