Hi
I send the appropriate patch for bug #2073. This fix disallows to change the
default sequence.
I ran the regression test and passed. The bug details are given below.
I am awaiting to answer for any further clarifications.
===================================================================
Bug reference: 2073
Logged by: Aaron Dummer
Email address: aaron ( at ) dummer ( dot ) info
PostgreSQL version: 8.0.3
Operating system: Debian Linux
Description: Can't drop sequence when created via SERIAL column
Details:
If I create a table named foo with a column named bar, column type SERIAL,
it auto-generates a sequence named foo_bar_seq. Now if I manually create a
new sequence called custom_seq, and change the default value of foo.bar to
reference the new sequence, I still can't delete the old sequence
(foo_bar_seq).
In other words, from a user's point of view, the foo table is no longer
dependent on the foo_bar_seq, yet the system still sees it as dependent.
I brought this topic up on the #postgresql IRC channel and the behavior was
confirmed by AndrewSN, scampbell_, and mastermind.
Right. We have this TODO item:
* %Disallow changing default expression of a SERIAL column?
which would prevent you from changing the default expression for a
SERIAL column. So the answer is, don't do that, and in the future, we
might prevent it.
--
Bruce Momjian
==================================================================
*** ./src/backend/catalog/dependency.c.orig Wed Apr 26 10:54:40 2006
--- ./src/backend/catalog/dependency.c Wed Apr 26 12:09:01 2006
***************
*** 1931,1933 ****
--- 1931,2019 ----
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);
+
+ }
*** ./src/backend/catalog/heap.c.orig Wed Apr 26 10:59:18 2006
--- ./src/backend/catalog/heap.c Wed Apr 26 12:03:49 2006
***************
*** 2136,2138 ****
--- 2136,2185 ----
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);
+
+ }
*** ./src/backend/commands/tablecmds.c.orig Wed Apr 26 11:00:14 2006
--- ./src/backend/commands/tablecmds.c Wed Apr 26 11:57:43 2006
***************
*** 3362,3367 ****
--- 3362,3372 ----
* 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)
*** ./src/include/catalog/dependency.h.orig Wed Apr 26 11:05:28 2006
--- ./src/include/catalog/dependency.h Wed Apr 26 11:06:13 2006
***************
*** 207,210 ****
--- 207,213 ----
extern void shdepReassignOwned(List *relids, Oid newrole);
+ extern void performSequenceDefaultDeletion(const ObjectAddress *object,
+ DropBehavior behavior, int deleteFlag);
+
#endif /* DEPENDENCY_H */
*** ./src/include/catalog/heap.h.orig Wed Apr 26 11:04:59 2006
--- ./src/include/catalog/heap.h Wed Apr 26 11:57:56 2006
***************
*** 97,100 ****
--- 97,103 ----
extern void CheckAttributeType(const char *attname, Oid atttypid);
+ extern void RemoveSequenceDefault(Oid relid, AttrNumber attnum,
+ DropBehavior behavior, bool flag);
+
#endif /* HEAP_H */
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings