]> granicus.if.org Git - postgresql/commitdiff
Disallow deletion of CurrentExtensionObject while running extension script.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 29 Nov 2011 00:12:17 +0000 (19:12 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 29 Nov 2011 00:12:41 +0000 (19:12 -0500)
While the deletion in itself wouldn't break things, any further creation
of objects in the script would result in dangling pg_depend entries being
added by recordDependencyOnCurrentExtension().  An example from Phil
Sorber convinced me that this is just barely likely enough to be worth
expending a couple lines of code to defend against.  The resulting error
message might be confusing, but it's better than leaving corrupted catalog
contents for the user to deal with.

src/backend/commands/extension.c

index 024d4c8a009e10e9e8004915271540b6a0bc0dc7..63b3ffa4ef0290bc3adb6df068a7945148653456 100644 (file)
@@ -1642,6 +1642,23 @@ RemoveExtensionById(Oid extId)
        HeapTuple       tuple;
        ScanKeyData entry[1];
 
+       /*
+        * Disallow deletion of any extension that's currently open for insertion;
+        * else subsequent executions of recordDependencyOnCurrentExtension()
+        * could create dangling pg_depend records that refer to a no-longer-valid
+        * pg_extension OID.  This is needed not so much because we think people
+        * might write "DROP EXTENSION foo" in foo's own script files, as because
+        * errors in dependency management in extension script files could give
+        * rise to cases where an extension is dropped as a result of recursing
+        * from some contained object.  Because of that, we must test for the case
+        * here, not at some higher level of the DROP EXTENSION command.
+        */
+       if (extId == CurrentExtensionObject)
+               ereport(ERROR,
+                               (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+                                errmsg("cannot drop extension \"%s\" because it is being modified",
+                                               get_extension_name(extId))));
+
        rel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
        ScanKeyInit(&entry[0],