mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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:
		@@ -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 "
 | 
								 * Propagate any new CHECK constraints into the child table
 | 
				
			||||||
					"\"%s\" for child %s", colDef->colname,
 | 
								 * and its descendants
 | 
				
			||||||
					RelationGetRelationName(childrel));
 | 
								 */
 | 
				
			||||||
			RelationClose(childrel);
 | 
								if (colDef->constraints != NIL)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									CommandCounterIncrement();
 | 
				
			||||||
 | 
									AlterTableAddConstraint(childrelid, true, colDef->constraints);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			heap_close(attrdesc, RowExclusiveLock);
 | 
					 | 
				
			||||||
			heap_freetuple(tuple);
 | 
								heap_freetuple(tuple);
 | 
				
			||||||
			ReleaseSysCache(typeTuple);
 | 
								heap_close(attrdesc, RowExclusiveLock);
 | 
				
			||||||
 | 
								heap_close(childrel, NoLock);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user