On Sat, Feb 23, 2019 at 12:29 AM Michael Paquier <mich...@paquier.xyz> wrote:
> On Fri, Feb 22, 2019 at 09:45:42AM -0500, Tom Lane wrote: > > +1 ... maybe "(dropped)", because we tend to use parens for this sort > > of thing, I think. > > +1. Using "dropped" sounds good to me in this context. Perhaps we > could have something more fancy like what's used for dropped columns? > It would be nice to get a reference to a schema, like say "dropped > temporary schema". > I think that's unnecessary given the context: 2019-02-23 15:43:56.375 CET [17250] LOG: autovacuum: dropping orphan temp table "postgres.(dropped).bar" That said, it just moves the crash. Turns out the problem goes a lot deeper than just the logging, it's basically the cleanup of orphaned temp tables that's completely broken if you drop the namespace. TRAP: FailedAssertion("!(relation->rd_backend != (-1))", File: "relcache.c", Line: 1085) 2019-02-23 15:43:56.378 CET [17146] LOG: server process (PID 17250) was terminated by signal 6: Aborted #2 0x0000563e0fe4bc83 in ExceptionalCondition (conditionName=conditionName@entry=0x563e10035fb0 "!(relation->rd_backend != (-1))", errorType=errorType@entry=0x563e0fe9bf9d "FailedAssertion", fileName=fileName@entry=0x563e100357dc "relcache.c", lineNumber=lineNumber@entry=1085) at assert.c:54 #3 0x0000563e0fe40e18 in RelationBuildDesc (targetRelId=24580, insertIt=insertIt@entry=true) at relcache.c:1085 #4 0x0000563e0fe41a86 in RelationIdGetRelation (relationId=<optimized out>, relationId@entry=24580) at relcache.c:1894 #5 0x0000563e0fa24b4c in relation_open (relationId=relationId@entry=24580, lockmode=lockmode@entry=8) at relation.c:59 #6 0x0000563e0fadcfea in heap_drop_with_catalog (relid=24580) at heap.c:1856 #7 0x0000563e0fad9145 in doDeletion (flags=21, object=<optimized out>) at dependency.c:1329 #8 deleteOneObject (flags=21, depRel=0x7ffd80db4808, object=<optimized out>) at dependency.c:1231 #9 deleteObjectsInList (targetObjects=targetObjects@entry=0x563e10640110, depRel=depRel@entry=0x7ffd80db4808, flags=flags@entry=21) at dependency.c:271 #10 0x0000563e0fad91f0 in performDeletion (object=object@entry=0x7ffd80db4944, behavior=behavior@entry=DROP_CASCADE, flags=flags@entry=21) at dependency.c:352 #11 0x0000563e0fa13532 in do_autovacuum () at autovacuum.c:2269 So basically I think it's the wrong approach to try to fix this error message. We need to fix the underlying problem. Which is the ability to drop the temp table schemas and then create temp tables which ahve no schemas. We could try to recreate the namespace if dropped. But a quick fix around that just moved coredumps around to a lot of other dependent places. I think we're better off just peventing the explicit drop of a temp schema. See attached? We'd also want to block things like: ALTER SCHEMA pg_temp_3 RENAME TO foobar; DROP SCHEMA foobar; Are there any more things beyond RENAME we need to block? -- Magnus Hagander Me: https://www.hagander.net/ <http://www.hagander.net/> Work: https://www.redpill-linpro.com/ <http://www.redpill-linpro.com/>
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index f26a2f4779..c9841e2dc2 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -101,6 +101,23 @@ RemoveObjects(DropStmt *stmt) errhint("Use DROP AGGREGATE to drop aggregate functions."))); } + /* + * Don't allow dropping of temp namespaces, since there can still be + * references to the oids all over. + * We have to look at the name of the schema, since the checks for isTempNamespace() + * only checks if it's *our* temp one,gi + */ + if (stmt->removeType == OBJECT_SCHEMA) + { + char *name = get_namespace_name(address.objectId); + if (name && (strncmp(name, "pg_temp_", 8) == 0 || strncmp(name, "pg_toast_temp_", 14) == 0)) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot drop temporary schema \"%s\"", + get_namespace_name(address.objectId)), + errhint("temporary schemas are dropped automatically when the session ends."))); + } + /* Check permissions. */ namespaceId = get_object_namespace(&address); if (!OidIsValid(namespaceId) ||