Disallow VACUUM, ANALYZE, TRUNCATE on temp tables belonging to other
authorTom Lane
Mon, 23 Sep 2002 20:43:41 +0000 (20:43 +0000)
committerTom Lane
Mon, 23 Sep 2002 20:43:41 +0000 (20:43 +0000)
backends.  Given that temp tables now store data locally in the local
buffer manager, these things are not going to work safely.

src/backend/catalog/namespace.c
src/backend/commands/analyze.c
src/backend/commands/tablecmds.c
src/backend/commands/vacuum.c
src/include/catalog/namespace.h

index 182d9016e974667d3bb407ac1f714935854aaeae..c5a5c70ebc7b898877a6077c6b7d82be89bf7282 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.35 2002/09/04 20:31:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.36 2002/09/23 20:43:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1217,6 +1217,28 @@ isTempNamespace(Oid namespaceId)
    return false;
 }
 
+/*
+ * isOtherTempNamespace - is the given namespace some other backend's
+ * temporary-table namespace?
+ */
+bool
+isOtherTempNamespace(Oid namespaceId)
+{
+   bool        result;
+   char       *nspname;
+
+   /* If it's my own temp namespace, say "false" */
+   if (isTempNamespace(namespaceId))
+       return false;
+   /* Else, if the namespace name starts with "pg_temp_", say "true" */
+   nspname = get_namespace_name(namespaceId);
+   if (!nspname)
+       return false;           /* no such namespace? */
+   result = (strncmp(nspname, "pg_temp_", 8) == 0);
+   pfree(nspname);
+   return result;
+}
+
 /*
  * PushSpecialNamespace - push a "special" namespace onto the front of the
  * search path.
index 5c20b05447e3529158c131080ea93fb935ecf6bd..4c06a28621a93c64ba5ce77c02a87bcd52235876 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.46 2002/09/04 20:31:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.47 2002/09/23 20:43:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_statistic.h"
 #include "catalog/pg_type.h"
@@ -215,6 +216,19 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
        return;
    }
 
+   /*
+    * Silently ignore tables that are temp tables of other backends ---
+    * trying to analyze these is rather pointless, since their
+    * contents are probably not up-to-date on disk.  (We don't throw a
+    * warning here; it would just lead to chatter during a database-wide
+    * ANALYZE.)
+    */
+   if (isOtherTempNamespace(RelationGetNamespace(onerel)))
+   {
+       relation_close(onerel, AccessShareLock);
+       return;
+   }
+
    /*
     * We can ANALYZE any table except pg_statistic. See update_attstats
     */
index 7b2bab71c34d1e0dc4a0d2878f559799c41d8b95..0934a274c7ad3d76d8707ac48af1b0fea0a84111 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.43 2002/09/22 19:42:50 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.44 2002/09/23 20:43:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -367,6 +367,7 @@ TruncateRelation(const RangeVar *relation)
             RelationGetRelationName(rel));
    }
 
+   /* Permissions checks */
    if (!allowSystemTableMods && IsSystemRelation(rel))
        elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
             RelationGetRelationName(rel));
@@ -374,6 +375,13 @@ TruncateRelation(const RangeVar *relation)
    if (!pg_class_ownercheck(relid, GetUserId()))
        aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
 
+   /*
+    * Don't allow truncate on temp tables of other backends ... their
+    * local buffer manager is not going to cope.
+    */
+   if (isOtherTempNamespace(RelationGetNamespace(rel)))
+       elog(ERROR, "TRUNCATE cannot be used on temp tables of other processes");
+
    /*
     * Don't allow truncate on tables which are referenced by foreign keys
     */
index 42172ac07b49922be6d70135eefddbb4808723bf..04c13be4e074a8380034305727288be9b547493d 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.239 2002/09/23 00:42:48 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.240 2002/09/23 20:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -775,6 +775,20 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
        return;
    }
 
+   /*
+    * Silently ignore tables that are temp tables of other backends ---
+    * trying to vacuum these will lead to great unhappiness, since their
+    * contents are probably not up-to-date on disk.  (We don't throw a
+    * warning here; it would just lead to chatter during a database-wide
+    * VACUUM.)
+    */
+   if (isOtherTempNamespace(RelationGetNamespace(onerel)))
+   {
+       relation_close(onerel, lmode);
+       CommitTransactionCommand(true);
+       return;
+   }
+
    /*
     * Get a session-level lock too. This will protect our access to the
     * relation across multiple transactions, so that we can vacuum the
index 3369f678095ad8ef8b899a6f4bc78c1f1f5c7295..531afac1453f7a2144972107713a7a32f02b7b64 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: namespace.h,v 1.20 2002/09/04 20:31:37 momjian Exp $
+ * $Id: namespace.h,v 1.21 2002/09/23 20:43:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,6 +76,7 @@ extern RangeVar *makeRangeVarFromNameList(List *names);
 extern char *NameListToString(List *names);
 
 extern bool isTempNamespace(Oid namespaceId);
+extern bool isOtherTempNamespace(Oid namespaceId);
 
 extern void PushSpecialNamespace(Oid namespaceId);
 extern void PopSpecialNamespace(Oid namespaceId);