dont-change-extension-membership-in-ALTER-TYPE.patch
text/x-diff
Filename: dont-change-extension-membership-in-ALTER-TYPE.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/pg_depend.c | 7 | 0 |
| src/backend/catalog/pg_type.c | 16 | 8 |
| src/backend/commands/typecmds.c | 2 | 0 |
| src/include/catalog/pg_type.h | 1 | 0 |
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 10f3119670..07bcdc463a 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -179,6 +179,13 @@ recordMultipleDependencies(const ObjectAddress *depender,
* 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.
+ *
+ * Note: isReplace = true is typically used when updating a object in
+ * CREATE OR REPLACE and similar commands. The net effect is that if an
+ * extension script uses such a command on a pre-existing free-standing
+ * object, the object will be absorbed into the extension. If the object
+ * is already a member of some other extension, the command will fail.
+ * This behavior is desirable for cases such as replacing a shell type.
*/
void
recordDependencyOnCurrentExtension(const ObjectAddress *object,
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 6f9b5471da..cdce22f394 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -167,6 +167,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
0,
false,
false,
+ true, /* make extension dependency */
false);
/* Post creation hook for new shell type */
@@ -504,6 +505,7 @@ TypeCreate(Oid newTypeOid,
relationKind,
isImplicitArray,
isDependentType,
+ true, /* make extension dependency */
rebuildDeps);
/* Post creation hook for new type */
@@ -537,13 +539,17 @@ TypeCreate(Oid newTypeOid,
* isDependentType is true if this is an implicit array or relation rowtype;
* that means it doesn't need its own dependencies on owner etc.
*
- * 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 an existing extension dependency, though.
- * (That means an extension can't absorb a shell type created in another
- * extension, nor ALTER a type created by another extension. Also, if it
- * replaces a free-standing shell type or ALTERs a free-standing type,
- * that type will become a member of the extension.)
+ * We make an extension-membership dependency if we're in an extension
+ * script and makeExtensionDep is true (and isDependentType isn't true).
+ * makeExtensionDep should be true when creating a new type or replacing a
+ * shell type, but not for ALTER TYPE on an existing type. Passing false
+ * causes the type's extension membership to be left alone.
+ *
+ * rebuild should be true if this is a pre-existing type. We will 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 any
+ * existing extension dependency, though (hence, if makeExtensionDep is also
+ * true and the type belongs to some other extension, an error will occur).
*/
void
GenerateTypeDependencies(HeapTuple typeTuple,
@@ -553,6 +559,7 @@ GenerateTypeDependencies(HeapTuple typeTuple,
char relationKind, /* only for relation rowtypes */
bool isImplicitArray,
bool isDependentType,
+ bool makeExtensionDep,
bool rebuild)
{
Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
@@ -611,7 +618,8 @@ GenerateTypeDependencies(HeapTuple typeTuple,
recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
typeForm->typowner, typacl);
- recordDependencyOnCurrentExtension(&myself, rebuild);
+ if (makeExtensionDep)
+ recordDependencyOnCurrentExtension(&myself, rebuild);
}
/* Normal dependencies on the I/O and support functions */
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 93eeff950b..6bdb1a1660 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2675,6 +2675,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
0, /* relation kind is n/a */
false, /* a domain isn't an implicit array */
false, /* nor is it any kind of dependent type */
+ false, /* don't touch extension membership */
true); /* We do need to rebuild dependencies */
InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
@@ -4415,6 +4416,7 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
0, /* we rejected composite types above */
isImplicitArray, /* it might be an array */
isImplicitArray, /* dependent iff it's array */
+ false, /* don't touch extension membership */
true);
InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index b05db9641a..e568e21dee 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -386,6 +386,7 @@ extern void GenerateTypeDependencies(HeapTuple typeTuple,
* rowtypes */
bool isImplicitArray,
bool isDependentType,
+ bool makeExtensionDep,
bool rebuild);
extern void RenameTypeInternal(Oid typeOid, const char *newTypeName,