Classify DROP operations by whether or not they are user-initiated.
authorRobert Haas <rhaas@postgresql.org>
Thu, 26 Jan 2012 14:24:54 +0000 (09:24 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 26 Jan 2012 14:30:27 +0000 (09:30 -0500)
This doesn't do anything useful just yet, but is intended as supporting
infrastructure for allowing sepgsql to sensibly check DROP permissions.

KaiGai Kohei and Robert Haas

14 files changed:
src/backend/catalog/aclchk.c
src/backend/catalog/dependency.c
src/backend/catalog/heap.c
src/backend/catalog/pg_shdepend.c
src/backend/commands/cluster.c
src/backend/commands/dropcmds.c
src/backend/commands/foreigncmds.c
src/backend/commands/opclasscmds.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/postmaster/autovacuum.c
src/backend/storage/large_object/inv_api.c
src/include/catalog/dependency.h
src/include/catalog/heap.h

index f5e6a3f061980e20d7dfddebce6667ea18d98c91..9315e79c991d81dcc35881d4ae24fcb71ea30804 100644 (file)
@@ -1211,7 +1211,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
            myself.objectId = HeapTupleGetOid(tuple);
            myself.objectSubId = 0;
 
-           performDeletion(&myself, DROP_RESTRICT);
+           performDeletion(&myself, DROP_RESTRICT, 0);
        }
    }
    else
index 0b3d489ae006d15e916a23ba885afc75f4c9fa46..db86262b4f06ec5b78f834eb10fbae45a1e77033 100644 (file)
@@ -171,7 +171,8 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
                       DropBehavior behavior,
                       int msglevel,
                       const ObjectAddress *origObject);
-static void deleteOneObject(const ObjectAddress *object, Relation depRel);
+static void deleteOneObject(const ObjectAddress *object,
+                           Relation depRel, int32 flags);
 static void doDeletion(const ObjectAddress *object);
 static void AcquireDeletionLock(const ObjectAddress *object);
 static void ReleaseDeletionLock(const ObjectAddress *object);
@@ -205,10 +206,17 @@ static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
  * that can participate in dependencies.  Note that the next two routines
  * are variants on the same theme; if you change anything here you'll likely
  * need to fix them too.
+ *
+ * flags should include PERFORM_DELETION_INTERNAL when the drop operation is
+ * not the direct result of a user-initiated action.  For example, when a
+ * temporary schema is cleaned out so that a new backend can use it, or when
+ * a column default is dropped as an intermediate step while adding a new one,
+ * that's an internal operation.  On the other hand, when the we drop something
+ * because the user issued a DROP statement against it, that's not internal.
  */
 void
 performDeletion(const ObjectAddress *object,
-               DropBehavior behavior)
+               DropBehavior behavior, int flags)
 {
    Relation    depRel;
    ObjectAddresses *targetObjects;
@@ -254,7 +262,7 @@ performDeletion(const ObjectAddress *object,
    {
        ObjectAddress *thisobj = targetObjects->refs + i;
 
-       deleteOneObject(thisobj, depRel);
+       deleteOneObject(thisobj, depRel, flags);
    }
 
    /* And clean up */
@@ -274,7 +282,7 @@ performDeletion(const ObjectAddress *object,
  */
 void
 performMultipleDeletions(const ObjectAddresses *objects,
-                        DropBehavior behavior)
+                        DropBehavior behavior, int flags)
 {
    Relation    depRel;
    ObjectAddresses *targetObjects;
@@ -336,7 +344,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
    {
        ObjectAddress *thisobj = targetObjects->refs + i;
 
-       deleteOneObject(thisobj, depRel);
+       deleteOneObject(thisobj, depRel, flags);
    }
 
    /* And clean up */
@@ -407,7 +415,14 @@ deleteWhatDependsOn(const ObjectAddress *object,
        if (thisextra->flags & DEPFLAG_ORIGINAL)
            continue;
 
-       deleteOneObject(thisobj, depRel);
+       /*
+        * Since this function is currently only used to clean out temporary
+        * schemas, we pass PERFORM_DELETION_INTERNAL here, indicating that
+        * the operation is an automatic system operation rather than a user
+        * action.  If, in the future, this function is used for other
+        * purposes, we might need to revisit this.
+        */
+       deleteOneObject(thisobj, depRel, PERFORM_DELETION_INTERNAL);
    }
 
    /* And clean up */
@@ -950,7 +965,7 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
  * depRel is the already-open pg_depend relation.
  */
 static void
-deleteOneObject(const ObjectAddress *object, Relation depRel)
+deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
 {
    ScanKeyData key[3];
    int         nkeys;
index 204236f550eb096fa5ea850835f89b515ee5bc83..aef410ae9b2156e94ee06b12ffcfd2897d83b461 100644 (file)
@@ -1528,7 +1528,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
  */
 void
 RemoveAttrDefault(Oid relid, AttrNumber attnum,
-                 DropBehavior behavior, bool complain)
+                 DropBehavior behavior, bool complain, bool internal)
 {
    Relation    attrdef_rel;
    ScanKeyData scankeys[2];
@@ -1559,7 +1559,8 @@ RemoveAttrDefault(Oid relid, AttrNumber attnum,
        object.objectId = HeapTupleGetOid(tuple);
        object.objectSubId = 0;
 
-       performDeletion(&object, behavior);
+       performDeletion(&object, behavior,
+                       internal ? PERFORM_DELETION_INTERNAL : 0);
 
        found = true;
    }
index c3e55ab6a7afacd7f240b4d910c848d962d68b37..11cb9883a762a30bb86eb1a23437459fcc26fd8c 100644 (file)
@@ -1240,7 +1240,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
    }
 
    /* the dependency mechanism does the actual work */
-   performMultipleDeletions(deleteobjs, behavior);
+   performMultipleDeletions(deleteobjs, behavior, 0);
 
    heap_close(sdepRel, RowExclusiveLock);
 
index 9408f259a611f45d0bb2777cd597f80317ec774b..349d13034e32975356c755e76533ac76d704abd2 100644 (file)
@@ -1443,7 +1443,7 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
     * The new relation is local to our transaction and we know nothing
     * depends on it, so DROP_RESTRICT should be OK.
     */
-   performDeletion(&object, DROP_RESTRICT);
+   performDeletion(&object, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
 
    /* performDeletion does CommandCounterIncrement at end */
 
index 9eeba041cffd840e71ddbd229b197aeb683877ef..298940c7c42ba15f966b285c5b4ed86526ac90e7 100644 (file)
@@ -119,7 +119,7 @@ RemoveObjects(DropStmt *stmt)
    }
 
    /* Here we really delete them. */
-   performMultipleDeletions(objects, stmt->behavior);
+   performMultipleDeletions(objects, stmt->behavior, 0);
 
    free_object_addresses(objects);
 }
index a9ec904c357afbb68f78e1f270aca7a66cdf2e9f..4135e268575f46bc8afe43179b0beed19f74e7c1 100644 (file)
@@ -1286,7 +1286,7 @@ RemoveUserMapping(DropUserMappingStmt *stmt)
    object.objectId = umId;
    object.objectSubId = 0;
 
-   performDeletion(&object, DROP_CASCADE);
+   performDeletion(&object, DROP_CASCADE, 0);
 }
 
 
index 5dca0222fdf28a63e4beca5b40d5d95fa234b2a7..5dc131a50e2221d01804ee2a57cf6de68e86bdfd 100644 (file)
@@ -1519,7 +1519,7 @@ dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid,
        object.objectId = amopid;
        object.objectSubId = 0;
 
-       performDeletion(&object, DROP_RESTRICT);
+       performDeletion(&object, DROP_RESTRICT, 0);
    }
 }
 
@@ -1559,7 +1559,7 @@ dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid,
        object.objectId = amprocid;
        object.objectSubId = 0;
 
-       performDeletion(&object, DROP_RESTRICT);
+       performDeletion(&object, DROP_RESTRICT, 0);
    }
 }
 
index cb8ac67812ab9ba9c9fab1135f623b82acc62fa6..9172d999310e76b7153ea70b410e7c6a738864ef 100644 (file)
@@ -816,7 +816,7 @@ RemoveRelations(DropStmt *drop)
        add_exact_object_address(&obj, objects);
    }
 
-   performMultipleDeletions(objects, drop->behavior);
+   performMultipleDeletions(objects, drop->behavior, 0);
 
    free_object_addresses(objects);
 }
@@ -4803,8 +4803,13 @@ ATExecColumnDefault(Relation rel, const char *colName,
     * Remove any old default for the column.  We use RESTRICT here for
     * safety, but at present we do not expect anything to depend on the
     * default.
+    *
+    * We treat removing the existing default as an internal operation when
+    * it is preparatory to adding a new default, but as a user-initiated
+    * operation when the user asked for a drop.
     */
-   RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false);
+   RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false,
+                     newDefault == NULL ? false : true);
 
    if (newDefault)
    {
@@ -5217,7 +5222,7 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
    object.objectId = RelationGetRelid(rel);
    object.objectSubId = attnum;
 
-   performDeletion(&object, behavior);
+   performDeletion(&object, behavior, 0);
 
    /*
     * If we dropped the OID column, must adjust pg_class.relhasoids and tell
@@ -6731,7 +6736,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
        conobj.objectId = HeapTupleGetOid(tuple);
        conobj.objectSubId = 0;
 
-       performDeletion(&conobj, behavior);
+       performDeletion(&conobj, behavior, 0);
 
        found = true;
 
@@ -7453,7 +7458,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
         * We use RESTRICT here for safety, but at present we do not expect
         * anything to depend on the default.
         */
-       RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true);
+       RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true,
+                         true);
 
        StoreAttrDefault(rel, attnum, defaultexpr);
    }
@@ -7598,7 +7604,7 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
        obj.classId = ConstraintRelationId;
        obj.objectId = lfirst_oid(oid_item);
        obj.objectSubId = 0;
-       performDeletion(&obj, DROP_RESTRICT);
+       performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
    }
 
    foreach(oid_item, tab->changedIndexOids)
@@ -7606,7 +7612,7 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
        obj.classId = RelationRelationId;
        obj.objectId = lfirst_oid(oid_item);
        obj.objectSubId = 0;
-       performDeletion(&obj, DROP_RESTRICT);
+       performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
    }
 
    /*
@@ -9764,7 +9770,14 @@ PreCommit_on_commit_actions(void)
                    object.classId = RelationRelationId;
                    object.objectId = oc->relid;
                    object.objectSubId = 0;
-                   performDeletion(&object, DROP_CASCADE);
+
+                   /*
+                    * Since this is an automatic drop, rather than one
+                    * directly initiated by the user, we pass the
+                    * PERFORM_DELETION_INTERNAL flag.
+                    */
+                   performDeletion(&object,
+                                   DROP_CASCADE, PERFORM_DELETION_INTERNAL);
 
                    /*
                     * Note that table deletion will call
index 0043bf1fee29ec66829951199ebf55f82838b63a..03918486a15fba64d7c49d2da8574020d14af69c 100644 (file)
@@ -2318,7 +2318,7 @@ AlterDomainDropConstraint(List *names, const char *constrName,
            conobj.objectId = HeapTupleGetOid(contup);
            conobj.objectSubId = 0;
 
-           performDeletion(&conobj, behavior);
+           performDeletion(&conobj, behavior, 0);
            found = true;
        }
    }
index e84e21c62cd83bb26bd495bcb2568b9dbac62dda..49c15c32616c385a55fe00929793be5a1189d4f0 100644 (file)
@@ -2044,7 +2044,7 @@ do_autovacuum(void)
                    object.classId = RelationRelationId;
                    object.objectId = relid;
                    object.objectSubId = 0;
-                   performDeletion(&object, DROP_CASCADE);
+                   performDeletion(&object, DROP_CASCADE, PERFORM_DELETION_INTERNAL);
                }
                else
                {
index afa572b3b1cd5781025e2a0f4a91639bc4c98830..a14ce442c1c35d3ab2d5e297060491206cc1dd84 100644 (file)
@@ -307,7 +307,7 @@ inv_drop(Oid lobjId)
    object.classId = LargeObjectRelationId;
    object.objectId = lobjId;
    object.objectSubId = 0;
-   performDeletion(&object, DROP_CASCADE);
+   performDeletion(&object, DROP_CASCADE, 0);
 
    /*
     * Advance command counter so that tuple removal will be seen by later
index 087341e5768371bb31fb0bc59ccc56d90ed62937..28e68c5ab59d63fb37a2e4d1976643e751423697 100644 (file)
@@ -152,11 +152,13 @@ typedef enum ObjectClass
 
 /* in dependency.c */
 
+#define PERFORM_DELETION_INTERNAL          0x0001
+
 extern void performDeletion(const ObjectAddress *object,
-               DropBehavior behavior);
+               DropBehavior behavior, int flags);
 
 extern void performMultipleDeletions(const ObjectAddresses *objects,
-                        DropBehavior behavior);
+                        DropBehavior behavior, int flags);
 
 extern void deleteWhatDependsOn(const ObjectAddress *object,
                    bool showNotices);
index 46bee44b5cf4f5d44243454efe09809dae646231..205538209689e9209f70b20e1697b6da0d1edf8b 100644 (file)
@@ -107,7 +107,7 @@ extern void DeleteRelationTuple(Oid relid);
 extern void DeleteAttributeTuples(Oid relid);
 extern void RemoveAttributeById(Oid relid, AttrNumber attnum);
 extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
-                 DropBehavior behavior, bool complain);
+                 DropBehavior behavior, bool complain, bool internal);
 extern void RemoveAttrDefaultById(Oid attrdefId);
 extern void RemoveStatistics(Oid relid, AttrNumber attnum);