recordDependencyOnOwner(RelationRelationId, relid, ownerid);
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
if (reloftypeid)
{
collowner);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new collation */
InvokeObjectAccessHook(OAT_POST_CREATE,
conowner);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new conversion */
InvokeObjectAccessHook(OAT_POST_CREATE,
*
* This must be called during creation of any user-definable object type
* that could be a member of an extension.
+ *
+ * If isReplace is true, the object already existed (or might have already
+ * existed), so we must check for a pre-existing extension membership entry.
+ * Passing false is a guarantee that the object is newly created, and so
+ * could not already be a member of any extension.
*/
void
-recordDependencyOnCurrentExtension(const ObjectAddress *object)
+recordDependencyOnCurrentExtension(const ObjectAddress *object,
+ bool isReplace)
{
+ /* Only whole objects can be extension members */
+ Assert(object->objectSubId == 0);
+
if (creating_extension)
{
ObjectAddress extension;
+ /* Only need to check for existing membership if isReplace */
+ if (isReplace)
+ {
+ Oid oldext;
+
+ oldext = getExtensionOfObject(object->classId, object->objectId);
+ if (OidIsValid(oldext))
+ {
+ /* If already a member of this extension, nothing to do */
+ if (oldext == CurrentExtensionObject)
+ return;
+ /* Already a member of some other extension, so reject */
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("%s is already a member of extension \"%s\"",
+ getObjectDescription(object),
+ get_extension_name(oldext))));
+ }
+ }
+
+ /* OK, record it as a member of CurrentExtensionObject */
extension.classId = ExtensionRelationId;
extension.objectId = CurrentExtensionObject;
extension.objectSubId = 0;
recordDependencyOnOwner(NamespaceRelationId, nspoid, ownerId);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new schema */
InvokeObjectAccessHook(OAT_POST_CREATE, NamespaceRelationId, nspoid, 0);
oper->oprowner);
/* Dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, true);
}
* Create dependencies for the new function. If we are updating an
* existing function, first delete any existing pg_depend entries.
* (However, since we are not changing ownership or permissions, the
- * shared dependencies do *not* need to change, and we leave them alone.
- * We also don't change any pre-existing extension-membership dependency.)
+ * shared dependencies do *not* need to change, and we leave them alone.)
*/
if (is_update)
deleteDependencyRecordsFor(ProcedureRelationId, retval, true);
}
/* dependency on extension */
- if (!is_update)
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, is_update);
heap_freetuple(tup);
*
* If rebuild is true, we remove existing dependencies and rebuild them
* from scratch. This is needed for ALTER TYPE, and also when replacing
- * a shell type. We don't remove/rebuild extension dependencies, though.
+ * a shell type.
*/
void
GenerateTypeDependencies(Oid typeNamespace,
* For a relation rowtype (that's not a composite type), we should skip
* these because we'll depend on them indirectly through the pg_class
* entry. Likewise, skip for implicit arrays since we'll depend on them
- * through the element type. The same goes for extension membership.
+ * through the element type.
*/
if ((!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE) &&
!isImplicitArray)
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
recordDependencyOnOwner(TypeRelationId, typeObjectId, owner);
-
- /* dependency on extension */
- if (!rebuild)
- recordDependencyOnCurrentExtension(&myself);
}
+ /* dependency on extension */
+ recordDependencyOnCurrentExtension(&myself, rebuild);
+
/* Normal dependencies on the I/O functions */
if (OidIsValid(inputProcedure))
{
recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new foreign data wrapper */
InvokeObjectAccessHook(OAT_POST_CREATE,
recordDependencyOnOwner(ForeignServerRelationId, srvId, ownerId);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new foreign server */
InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0);
}
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new user mapping */
InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0);
char sourcetyptype;
char targettyptype;
Oid funcid;
+ Oid castid;
int nargs;
char castcontext;
char castmethod;
tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
- simple_heap_insert(relation, tuple);
+ castid = simple_heap_insert(relation, tuple);
CatalogUpdateIndexes(relation, tuple);
/* make dependency entries */
myself.classId = CastRelationId;
- myself.objectId = HeapTupleGetOid(tuple);
+ myself.objectId = castid;
myself.objectSubId = 0;
/* dependency on source type */
}
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new cast */
- InvokeObjectAccessHook(OAT_POST_CREATE,
- CastRelationId, myself.objectId, 0);
+ InvokeObjectAccessHook(OAT_POST_CREATE, CastRelationId, castid, 0);
heap_freetuple(tuple);
recordDependencyOnOwner(OperatorFamilyRelationId, opfamilyoid, GetUserId());
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new operator family */
InvokeObjectAccessHook(OAT_POST_CREATE,
recordDependencyOnOwner(OperatorClassRelationId, opclassoid, GetUserId());
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* Post creation hook for new operator class */
InvokeObjectAccessHook(OAT_POST_CREATE,
* Create dependencies for the new language. If we are updating an
* existing language, first delete any existing pg_depend entries.
* (However, since we are not changing ownership or permissions, the
- * shared dependencies do *not* need to change, and we leave them alone.
- * We also don't change any pre-existing extension-membership dependency.)
+ * shared dependencies do *not* need to change, and we leave them alone.)
*/
myself.classId = LanguageRelationId;
myself.objectId = HeapTupleGetOid(tup);
languageOwner);
/* dependency on extension */
- if (!is_update)
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, is_update);
/* dependency on the PL handler function */
referenced.classId = ProcedureRelationId;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* dependencies on functions */
referenced.classId = ProcedureRelationId;
recordDependencyOnOwner(myself.classId, myself.objectId, dict->dictowner);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* dependency on template */
referenced.classId = TSTemplateRelationId;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on extension */
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, false);
/* dependencies on functions */
referenced.classId = ProcedureRelationId;
recordDependencyOnOwner(myself.classId, myself.objectId, cfg->cfgowner);
/* dependency on extension */
- if (!removeOld)
- recordDependencyOnCurrentExtension(&myself);
+ recordDependencyOnCurrentExtension(&myself, removeOld);
/* dependency on parser */
referenced.classId = TSParserRelationId;
int nreferenced,
DependencyType behavior);
-extern void recordDependencyOnCurrentExtension(const ObjectAddress *object);
+extern void recordDependencyOnCurrentExtension(const ObjectAddress *object,
+ bool isReplace);
extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
bool skipExtensionDeps);