aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-07-25 22:16:18 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-07-25 22:16:18 +0000
commit82eed4dba254b8fda71d429b29d222ffb4e93fca (patch)
treeeb84bdb8b70e931a08c23c07bc5c83d305bf19b3 /src/backend
parentfdb5b69e9c8f7186fe43c21580ac2ba45db1740f (diff)
downloadpostgresql-82eed4dba254b8fda71d429b29d222ffb4e93fca.tar.gz
postgresql-82eed4dba254b8fda71d429b29d222ffb4e93fca.zip
Arrange to put TOAST tables belonging to temporary tables into special schemas
named pg_toast_temp_nnn, alongside the pg_temp_nnn schemas used for the temp tables themselves. This allows low-level code such as the relcache to recognize that these tables are indeed temporary, which enables various optimizations such as not WAL-logging changes and using local rather than shared buffers for access. Aside from obvious performance benefits, this provides a solution to bug #3483, in which other backends unexpectedly held open file references to temporary tables. The scheme preserves the property that TOAST tables are not in any schema that's normally in the search path, so they don't conflict with user table names. initdb forced because of changes in system view definitions.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/catalog.c13
-rw-r--r--src/backend/catalog/namespace.c80
-rw-r--r--src/backend/catalog/system_views.sql32
-rw-r--r--src/backend/catalog/toasting.c22
-rw-r--r--src/backend/storage/lmgr/lmgr.c4
-rw-r--r--src/backend/utils/cache/relcache.c6
6 files changed, 121 insertions, 36 deletions
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index 049d216a787..acd107958ff 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.70 2007/03/25 19:45:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.71 2007/07/25 22:16:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,7 @@
#include "access/transam.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
+#include "catalog/namespace.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
@@ -196,15 +197,17 @@ IsSystemNamespace(Oid namespaceId)
/*
* IsToastNamespace
- * True iff namespace is pg_toast.
+ * True iff namespace is pg_toast or my temporary-toast-table namespace.
*
- * NOTE: the reason this isn't a macro is to avoid having to include
- * catalog/pg_namespace.h in a lot of places.
+ * Note: this will return false for temporary-toast-table namespaces belonging
+ * to other backends. Those are treated the same as other backends' regular
+ * temp table namespaces, and access is prevented where appropriate.
*/
bool
IsToastNamespace(Oid namespaceId)
{
- return namespaceId == PG_TOAST_NAMESPACE;
+ return (namespaceId == PG_TOAST_NAMESPACE) ||
+ isTempToastNamespace(namespaceId);
}
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 55379b66f65..2f8753bd2e0 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.96 2007/04/20 02:37:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.97 2007/07/25 22:16:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -152,6 +152,9 @@ static List *overrideStack = NIL;
* in a particular backend session (this happens when a CREATE TEMP TABLE
* command is first executed). Thereafter it's the OID of the temp namespace.
*
+ * myTempToastNamespace is the OID of the namespace for my temp tables' toast
+ * tables. It is set when myTempNamespace is, and is InvalidOid before that.
+ *
* myTempNamespaceSubID shows whether we've created the TEMP namespace in the
* current subtransaction. The flag propagates up the subtransaction tree,
* so the main transaction will correctly recognize the flag if all
@@ -161,6 +164,8 @@ static List *overrideStack = NIL;
*/
static Oid myTempNamespace = InvalidOid;
+static Oid myTempToastNamespace = InvalidOid;
+
static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
/*
@@ -1600,8 +1605,34 @@ isTempNamespace(Oid namespaceId)
}
/*
+ * isTempToastNamespace - is the given namespace my temporary-toast-table
+ * namespace?
+ */
+bool
+isTempToastNamespace(Oid namespaceId)
+{
+ if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
+ return true;
+ return false;
+}
+
+/*
+ * isTempOrToastNamespace - is the given namespace my temporary-table
+ * namespace or my temporary-toast-table namespace?
+ */
+bool
+isTempOrToastNamespace(Oid namespaceId)
+{
+ if (OidIsValid(myTempNamespace) &&
+ (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
+ return true;
+ return false;
+}
+
+/*
* isAnyTempNamespace - is the given namespace a temporary-table namespace
- * (either my own, or another backend's)?
+ * (either my own, or another backend's)? Temporary-toast-table namespaces
+ * are included, too.
*/
bool
isAnyTempNamespace(Oid namespaceId)
@@ -1609,29 +1640,42 @@ isAnyTempNamespace(Oid namespaceId)
bool result;
char *nspname;
- /* If the namespace name starts with "pg_temp_", say "true" */
+ /* True if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
nspname = get_namespace_name(namespaceId);
if (!nspname)
return false; /* no such namespace? */
- result = (strncmp(nspname, "pg_temp_", 8) == 0);
+ result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
+ (strncmp(nspname, "pg_toast_temp_", 14) == 0);
pfree(nspname);
return result;
}
/*
* isOtherTempNamespace - is the given namespace some other backend's
- * temporary-table namespace?
+ * temporary-table namespace (including temporary-toast-table namespaces)?
*/
bool
isOtherTempNamespace(Oid namespaceId)
{
/* If it's my own temp namespace, say "false" */
- if (isTempNamespace(namespaceId))
+ if (isTempOrToastNamespace(namespaceId))
return false;
- /* Else, if the namespace name starts with "pg_temp_", say "true" */
+ /* Else, if it's any temp namespace, say "true" */
return isAnyTempNamespace(namespaceId);
}
+/*
+ * GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
+ * which must already be assigned. (This is only used when creating a toast
+ * table for a temp table, so we must have already done InitTempTableNamespace)
+ */
+Oid
+GetTempToastNamespace(void)
+{
+ Assert(OidIsValid(myTempToastNamespace));
+ return myTempToastNamespace;
+}
+
/*
* GetOverrideSearchPath - fetch current search path definition in form
@@ -2006,6 +2050,7 @@ InitTempTableNamespace(void)
{
char namespaceName[NAMEDATALEN];
Oid namespaceId;
+ Oid toastspaceId;
Assert(!OidIsValid(myTempNamespace));
@@ -2055,11 +2100,30 @@ InitTempTableNamespace(void)
}
/*
+ * If the corresponding temp-table namespace doesn't exist yet, create it.
+ * (We assume there is no need to clean it out if it does exist, since
+ * dropping a parent table should make its toast table go away.)
+ */
+ snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
+ MyBackendId);
+
+ toastspaceId = GetSysCacheOid(NAMESPACENAME,
+ CStringGetDatum(namespaceName),
+ 0, 0, 0);
+ if (!OidIsValid(toastspaceId))
+ {
+ toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID);
+ /* Advance command counter to make namespace visible */
+ CommandCounterIncrement();
+ }
+
+ /*
* Okay, we've prepared the temp namespace ... but it's not committed yet,
* so all our work could be undone by transaction rollback. Set flag for
* AtEOXact_Namespace to know what to do.
*/
myTempNamespace = namespaceId;
+ myTempToastNamespace = toastspaceId;
/* It should not be done already. */
AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
@@ -2089,6 +2153,7 @@ AtEOXact_Namespace(bool isCommit)
else
{
myTempNamespace = InvalidOid;
+ myTempToastNamespace = InvalidOid;
baseSearchPathValid = false; /* need to rebuild list */
}
myTempNamespaceSubID = InvalidSubTransactionId;
@@ -2140,6 +2205,7 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
myTempNamespaceSubID = InvalidSubTransactionId;
/* TEMP namespace creation failed, so reset state */
myTempNamespace = InvalidOid;
+ myTempToastNamespace = InvalidOid;
baseSearchPathValid = false; /* need to rebuild list */
}
}
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index c5f8810d0af..c091c855708 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -3,7 +3,7 @@
*
* Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.38 2007/06/28 00:02:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.39 2007/07/25 22:16:18 tgl Exp $
*/
CREATE VIEW pg_roles AS
@@ -221,11 +221,13 @@ CREATE VIEW pg_stat_all_tables AS
CREATE VIEW pg_stat_sys_tables AS
SELECT * FROM pg_stat_all_tables
- WHERE schemaname IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
CREATE VIEW pg_stat_user_tables AS
SELECT * FROM pg_stat_all_tables
- WHERE schemaname NOT IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
CREATE VIEW pg_statio_all_tables AS
SELECT
@@ -254,11 +256,13 @@ CREATE VIEW pg_statio_all_tables AS
CREATE VIEW pg_statio_sys_tables AS
SELECT * FROM pg_statio_all_tables
- WHERE schemaname IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
CREATE VIEW pg_statio_user_tables AS
SELECT * FROM pg_statio_all_tables
- WHERE schemaname NOT IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
CREATE VIEW pg_stat_all_indexes AS
SELECT
@@ -278,11 +282,13 @@ CREATE VIEW pg_stat_all_indexes AS
CREATE VIEW pg_stat_sys_indexes AS
SELECT * FROM pg_stat_all_indexes
- WHERE schemaname IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
CREATE VIEW pg_stat_user_indexes AS
SELECT * FROM pg_stat_all_indexes
- WHERE schemaname NOT IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
CREATE VIEW pg_statio_all_indexes AS
SELECT
@@ -302,11 +308,13 @@ CREATE VIEW pg_statio_all_indexes AS
CREATE VIEW pg_statio_sys_indexes AS
SELECT * FROM pg_statio_all_indexes
- WHERE schemaname IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
CREATE VIEW pg_statio_user_indexes AS
SELECT * FROM pg_statio_all_indexes
- WHERE schemaname NOT IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
CREATE VIEW pg_statio_all_sequences AS
SELECT
@@ -322,11 +330,13 @@ CREATE VIEW pg_statio_all_sequences AS
CREATE VIEW pg_statio_sys_sequences AS
SELECT * FROM pg_statio_all_sequences
- WHERE schemaname IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname IN ('pg_catalog', 'information_schema') OR
+ schemaname ~ '^pg_toast';
CREATE VIEW pg_statio_user_sequences AS
SELECT * FROM pg_statio_all_sequences
- WHERE schemaname NOT IN ('pg_catalog', 'pg_toast', 'information_schema');
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema') AND
+ schemaname !~ '^pg_toast';
CREATE VIEW pg_stat_activity AS
SELECT
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 463f038c0f7..2fe44f59f8c 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.6 2007/04/06 04:21:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.7 2007/07/25 22:16:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
+#include "catalog/namespace.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_type.h"
@@ -108,6 +109,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
Relation class_rel;
Oid toast_relid;
Oid toast_idxid;
+ Oid namespaceid;
char toast_relname[NAMEDATALEN];
char toast_idxname[NAMEDATALEN];
IndexInfo *indexInfo;
@@ -173,16 +175,20 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
tupdesc->attrs[2]->attstorage = 'p';
/*
- * Note: the toast relation is placed in the regular pg_toast namespace
- * even if its master relation is a temp table. There cannot be any
- * naming collision, and the toast rel will be destroyed when its master
- * is, so there's no need to handle the toast rel as temp.
- *
+ * Toast tables for regular relations go in pg_toast; those for temp
+ * relations go into the per-backend temp-toast-table namespace.
+ */
+ if (rel->rd_istemp)
+ namespaceid = GetTempToastNamespace();
+ else
+ namespaceid = PG_TOAST_NAMESPACE;
+
+ /*
* XXX would it make sense to apply the master's reloptions to the toast
- * table?
+ * table? Or maybe some toast-specific reloptions?
*/
toast_relid = heap_create_with_catalog(toast_relname,
- PG_TOAST_NAMESPACE,
+ namespaceid,
rel->rd_rel->reltablespace,
toastOid,
rel->rd_rel->relowner,
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 6f6c609f53d..1c5db363203 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.91 2007/06/19 20:13:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.92 2007/07/25 22:16:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -619,7 +619,7 @@ LockTagIsTemp(const LOCKTAG *tag)
/* field1 is dboid, field2 is reloid for all of these */
if ((Oid) tag->locktag_field1 == InvalidOid)
return false; /* shared, so not temp */
- if (isTempNamespace(get_rel_namespace((Oid) tag->locktag_field2)))
+ if (isTempOrToastNamespace(get_rel_namespace((Oid) tag->locktag_field2)))
return true;
break;
case LOCKTAG_TRANSACTION:
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 45cb103adee..f69fb0c9362 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.261 2007/05/27 03:50:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.262 2007/07/25 22:16:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -838,7 +838,7 @@ RelationBuildDesc(Oid targetRelId, Relation oldrelation)
relation->rd_isnailed = false;
relation->rd_createSubid = InvalidSubTransactionId;
relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
- relation->rd_istemp = isTempNamespace(relation->rd_rel->relnamespace);
+ relation->rd_istemp = isTempOrToastNamespace(relation->rd_rel->relnamespace);
/*
* initialize the tuple descriptor (relation->rd_att).
@@ -2315,7 +2315,7 @@ RelationBuildLocalRelation(const char *relname,
need_eoxact_work = true;
/* is it a temporary relation? */
- rel->rd_istemp = isTempNamespace(relnamespace);
+ rel->rd_istemp = isTempOrToastNamespace(relnamespace);
/*
* create a new tuple descriptor from the one passed in. We do this