From a0a0512182cdca33d41485a5399573e6e380c229 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 29 Apr 2006 16:43:54 +0000 Subject: [PATCH] Disallow changing DEFAULT expression of a SERIAL column. Dhanaraj M --- src/backend/catalog/dependency.c | 88 +++++++++++++++++++++++++++++++- src/backend/catalog/heap.c | 49 +++++++++++++++++- src/backend/commands/tablecmds.c | 7 ++- src/include/catalog/dependency.h | 5 +- src/include/catalog/heap.h | 5 +- 5 files changed, 149 insertions(+), 5 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 160647aed7..3e50d27e38 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.51 2006/03/16 00:31:54 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.52 2006/04/29 16:43:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1931,3 +1931,89 @@ getRelationDescription(StringInfo buffer, Oid relid) ReleaseSysCache(relTup); } + +/* Recursively travel and search for the default sequence. Finally detach it */ + +void performSequenceDefaultDeletion(const ObjectAddress *object, + DropBehavior behavior, int deleteFlag) +{ + + ScanKeyData key[3]; + int nkeys; + SysScanDesc scan; + HeapTuple tup; + ObjectAddress otherObject; + Relation depRel; + + depRel = heap_open(DependRelationId, RowExclusiveLock); + + ScanKeyInit(&key[0], + Anum_pg_depend_classid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->classId)); + ScanKeyInit(&key[1], + Anum_pg_depend_objid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); + if (object->objectSubId != 0) + { + ScanKeyInit(&key[2], + Anum_pg_depend_objsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(object->objectSubId)); + nkeys = 3; + } + else + nkeys = 2; + + scan = systable_beginscan(depRel, DependDependerIndexId, true, + SnapshotNow, nkeys, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + + Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup); + + otherObject.classId = foundDep->refclassid; + otherObject.objectId = foundDep->refobjid; + otherObject.objectSubId = foundDep->refobjsubid; + + /* Detach the default sequence from the relation */ + if(deleteFlag == 1) + { + simple_heap_delete(depRel, &tup->t_self); + break; + } + + switch (foundDep->deptype) + { + case DEPENDENCY_NORMAL: + { + + if(getObjectClass(&otherObject) == OCLASS_CLASS) + { + /* Dont allow to change the default sequence */ + if(deleteFlag == 2) + { + systable_endscan(scan); + heap_close(depRel, RowExclusiveLock); + elog(ERROR, "%s is a SERIAL sequence. Can't alter the relation", getObjectDescription(&otherObject)); + return; + } + else /* Detach the default sequence from the relation */ + { + performSequenceDefaultDeletion(&otherObject, behavior, 1); + systable_endscan(scan); + heap_close(depRel, RowExclusiveLock); + return; + } + } + } + + } + } + + systable_endscan(scan); + heap_close(depRel, RowExclusiveLock); + +} diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 962a382b79..9803720a83 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.296 2006/04/24 01:40:48 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.297 2006/04/29 16:43:54 momjian Exp $ * * * INTERFACE ROUTINES @@ -2136,3 +2136,50 @@ heap_truncate_find_FKs(List *relationIds) return result; } + + +/* Detach the default sequence and the relation */ + +void +RemoveSequenceDefault(Oid relid, AttrNumber attnum, + DropBehavior behavior, bool flag) +{ + Relation attrdef_rel; + ScanKeyData scankeys[2]; + SysScanDesc scan; + HeapTuple tuple; + + attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock); + + ScanKeyInit(&scankeys[0], + Anum_pg_attrdef_adrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + ScanKeyInit(&scankeys[1], + Anum_pg_attrdef_adnum, + BTEqualStrategyNumber, F_INT2EQ, + Int16GetDatum(attnum)); + + scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true, + SnapshotNow, 2, scankeys); + + /* There should be at most one matching tuple, but we loop anyway */ + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + ObjectAddress object; + + object.classId = AttrDefaultRelationId; + object.objectId = HeapTupleGetOid(tuple); + object.objectSubId = 0; + + if(flag == true) /* Detach the sequence */ + performSequenceDefaultDeletion(&object, behavior, 0); + else /* Don't allow to change the default sequence */ + performSequenceDefaultDeletion(&object, behavior, 2); + + } + + systable_endscan(scan); + heap_close(attrdef_rel, RowExclusiveLock); + +} diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 6483578e80..1ed5fa9bbb 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.181 2006/03/14 22:48:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.182 2006/04/29 16:43:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -3362,6 +3362,11 @@ ATExecColumnDefault(Relation rel, const char *colName, * safety, but at present we do not expect anything to depend on the * default. */ + if (newDefault) + RemoveSequenceDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false); + else + RemoveSequenceDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true); + RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false); if (newDefault) diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 8e61515b60..4915c8dfd7 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.21 2006/03/05 15:58:54 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.22 2006/04/29 16:43:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -207,4 +207,7 @@ extern void shdepDropOwned(List *relids, DropBehavior behavior); extern void shdepReassignOwned(List *relids, Oid newrole); +extern void performSequenceDefaultDeletion(const ObjectAddress *object, + DropBehavior behavior, int deleteFlag); + #endif /* DEPENDENCY_H */ diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index fc50930f73..f503589f18 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.78 2006/03/05 15:58:54 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.79 2006/04/29 16:43:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -97,4 +97,7 @@ extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind); extern void CheckAttributeType(const char *attname, Oid atttypid); +extern void RemoveSequenceDefault(Oid relid, AttrNumber attnum, + DropBehavior behavior, bool flag); + #endif /* HEAP_H */