OSDN Git Service

Disallow changing DEFAULT expression of a SERIAL column.
authorBruce Momjian <bruce@momjian.us>
Sat, 29 Apr 2006 16:43:54 +0000 (16:43 +0000)
committerBruce Momjian <bruce@momjian.us>
Sat, 29 Apr 2006 16:43:54 +0000 (16:43 +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 160647a..3e50d27 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.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);   
+
+}
index 962a382..9803720 100644 (file)
@@ -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);
+
+}
index 6483578..1ed5fa9 100644 (file)
@@ -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)
index 8e61515..4915c8d 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.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 */
index fc50930..f503589 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.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 */