Classify DROP operations by whether or not they are user-initiated.

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
This commit is contained in:
Robert Haas 2012-01-26 09:24:54 -05:00
parent bc3347484a
commit 0e549697d1
14 changed files with 61 additions and 30 deletions

View 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

View 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;

View 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;
}

View 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);

View 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 */

View 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);
}

View File

@ -1286,7 +1286,7 @@ RemoveUserMapping(DropUserMappingStmt *stmt)
object.objectId = umId;
object.objectSubId = 0;
performDeletion(&object, DROP_CASCADE);
performDeletion(&object, DROP_CASCADE, 0);
}

View 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);
}
}

View 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

View 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;
}
}

View 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
{

View 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

View 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);

View 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);