Code review for recent patch to allow ALTER TABLE ADD COLUMN when

a child table already has a matching column.  Acquire appropriate
lock on child table; do the right thing with any CHECK constraints
attached to the new parent column.
This commit is contained in:
Tom Lane 2002-11-02 22:02:08 +00:00
parent e02d1abee6
commit 2a01b05936
1 changed files with 32 additions and 15 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.50 2002/10/21 22:06:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.51 2002/11/02 22:02:08 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1649,6 +1649,7 @@ AlterTableAddColumn(Oid myrelid,
*children; *children;
ColumnDef *colDefChild = copyObject(colDef); ColumnDef *colDefChild = copyObject(colDef);
/* Child should see column as singly inherited */
colDefChild->inhcount = 1; colDefChild->inhcount = 1;
colDefChild->is_local = false; colDefChild->is_local = false;
@ -1665,37 +1666,53 @@ AlterTableAddColumn(Oid myrelid,
if (childrelid == myrelid) if (childrelid == myrelid)
continue; continue;
childrel = heap_open(childrelid, AccessExclusiveLock);
/* Does child already have a column by this name? */
attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock); attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopyAttName(childrelid, colDef->colname); tuple = SearchSysCacheCopyAttName(childrelid, colDef->colname);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
/* No, recurse to add it normally */
heap_close(attrdesc, RowExclusiveLock); heap_close(attrdesc, RowExclusiveLock);
heap_close(childrel, NoLock);
AlterTableAddColumn(childrelid, true, colDefChild); AlterTableAddColumn(childrelid, true, colDefChild);
continue; continue;
} }
childatt = (Form_pg_attribute) GETSTRUCT(tuple); childatt = (Form_pg_attribute) GETSTRUCT(tuple);
typeTuple = typenameType(colDef->typename); /* Okay if child matches by type */
if (typenameTypeId(colDef->typename) != childatt->atttypid ||
colDef->typename->typmod != childatt->atttypmod)
elog(ERROR, "ALTER TABLE: child table \"%s\" has different type for column \"%s\"",
get_rel_name(childrelid), colDef->colname);
if (HeapTupleGetOid(typeTuple) != childatt->atttypid || /*
colDef->typename->typmod != childatt->atttypmod) * XXX if we supported NOT NULL or defaults, would need to do
elog(ERROR, "ALTER TABLE: child table %u has different " * more work here to verify child matches
"type for column \"%s\"", */
childrelid, colDef->colname);
elog(NOTICE, "ALTER TABLE: merging definition of column \"%s\" for child %s",
colDef->colname, get_rel_name(childrelid));
/* Bump the existing child att's inhcount */
childatt->attinhcount++; childatt->attinhcount++;
simple_heap_update(attrdesc, &tuple->t_self, tuple); simple_heap_update(attrdesc, &tuple->t_self, tuple);
CatalogUpdateIndexes(attrdesc, tuple); CatalogUpdateIndexes(attrdesc, tuple);
childrel = RelationIdGetRelation(childrelid);
elog(NOTICE, "ALTER TABLE: merging definition of column "
"\"%s\" for child %s", colDef->colname,
RelationGetRelationName(childrel));
RelationClose(childrel);
heap_close(attrdesc, RowExclusiveLock); /*
* Propagate any new CHECK constraints into the child table
* and its descendants
*/
if (colDef->constraints != NIL)
{
CommandCounterIncrement();
AlterTableAddConstraint(childrelid, true, colDef->constraints);
}
heap_freetuple(tuple); heap_freetuple(tuple);
ReleaseSysCache(typeTuple); heap_close(attrdesc, RowExclusiveLock);
heap_close(childrel, NoLock);
} }
} }
else else