Forbid DROP SCHEMA on temporary namespaces
authorMichael Paquier <[email protected]>
Fri, 27 Dec 2019 08:59:39 +0000 (17:59 +0900)
committerMichael Paquier <[email protected]>
Fri, 27 Dec 2019 08:59:39 +0000 (17:59 +0900)
This operation was possible for the owner of the schema or a superuser.
Down to 9.4, doing this operation would cause inconsistencies in a
session whose temporary schema was dropped, particularly if trying to
create new temporary objects after the drop.  A more annoying
consequence is a crash of autovacuum on an assertion failure when
logging information about an orphaned temp table dropped.  Note that
because of 246a6c8 (present in v11~), which has made the removal of
orphaned temporary tables more aggressive, the failure could be
triggered more easily, but it is possible to reproduce down to 9.4.

Reported-by: Mahendra Singh, Prabhat Sahu
Author: Michael Paquier
Reviewed-by: Kyotaro Horiguchi, Mahendra Singh
Discussion: https://postgr.es/m/CAKYtNAr9Zq=1-ww4etHo-VCC-k120YxZy5OS01VkaLPaDbv2tg@mail.gmail.com
Backpatch-through: 9.4

src/backend/commands/dropcmds.c

index e64ad8027e22f9455063b6b9b87b74edee9109ba..cb0227661deef58b48f1a4e2b49844b64e3c7323 100644 (file)
@@ -26,6 +26,7 @@
 #include "nodes/makefuncs.h"
 #include "parser/parse_type.h"
 #include "utils/builtins.h"
+#include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
 
@@ -116,6 +117,21 @@ RemoveObjects(DropStmt *stmt)
            ReleaseSysCache(tup);
        }
 
+       /*
+        * Prevent the drop of a temporary schema, be it owned by the current
+        * session or another backend as this would mess up with the callback
+        * registered to clean up temporary objects at the end of a session.
+        * Note also that the creation of any follow-up temporary object would
+        * result in inconsistencies within the session whose temporary schema
+        * has been dropped.
+        */
+       if (stmt->removeType == OBJECT_SCHEMA &&
+           isAnyTempNamespace(address.objectId))
+           ereport(ERROR,
+                   (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                    errmsg("cannot drop temporary schema \"%s\"",
+                           get_namespace_name(address.objectId))));
+
        /* Check permissions. */
        namespaceId = get_object_namespace(&address);
        if (!OidIsValid(namespaceId) ||