Disallow changing/dropping default expression of a SERIAL column
authorBruce Momjian
Tue, 27 Jun 2006 03:21:55 +0000 (03:21 +0000)
committerBruce Momjian
Tue, 27 Jun 2006 03:21:55 +0000 (03:21 +0000)
Dhanaraj M

src/backend/catalog/dependency.c
src/backend/catalog/heap.c
src/backend/commands/tablecmds.c
src/include/catalog/dependency.h
src/include/catalog/heap.h

index 3543ac2280b59e7d7271b453569b52c6b8ddcac1..bf39e8d1e1dbdd229ac2735c78453e1a7b6a7d4a 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.54 2006/05/28 02:27:08 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.55 2006/06/27 03:21:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1927,3 +1927,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);   
+
+}
index a3e629307452ab6fff7b49f5436e8c86d69b5a72..79898aa473ef47223dbdc41478fa76ca75fa16ac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.299 2006/05/10 23:18:39 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.300 2006/06/27 03:21:54 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -2133,3 +2133,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);
+
+}
index 2d80f6c536b8dd7f82cb4564fd3f71f681c33db0..825245ae8d78b063e89db46faaeb4e664ee6280f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.185 2006/06/16 18:42:21 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.186 2006/06/27 03:21:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3365,6 +3365,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)
index 1276ef0cacc7d13004dc264b0ba66353ad7f03ec..dd35ddc8011ee2aa7e584d82c312a0a594f6e85c 100644 (file)
@@ -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.23 2006/04/30 01:08:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.24 2006/06/27 03:21:55 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 */
index 4d17a054235f71bd90e55c41fe0068a83ae7a8e7..8489f88ebc7fc9e3c230f6e4047ddf742efb434f 100644 (file)
@@ -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.80 2006/04/30 01:08:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.81 2006/06/27 03:21:55 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 */