aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c12
-rw-r--r--src/backend/access/transam/parallel.c12
-rw-r--r--src/backend/catalog/catalog.c2
-rw-r--r--src/backend/catalog/namespace.c45
-rw-r--r--src/backend/catalog/storage.c2
-rw-r--r--src/backend/optimizer/util/clauses.c55
-rw-r--r--src/backend/storage/buffer/localbuf.c14
-rw-r--r--src/backend/utils/adt/dbsize.c2
-rw-r--r--src/backend/utils/cache/relcache.c4
-rw-r--r--src/backend/utils/init/globals.c2
-rw-r--r--src/include/catalog/namespace.h4
-rw-r--r--src/include/storage/backendid.h10
12 files changed, 92 insertions, 72 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 6db62410979..0b3332ecf5d 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -1131,13 +1131,7 @@ relation_open(Oid relationId, LOCKMODE lockmode)
/* Make note that we've accessed a temporary relation */
if (RelationUsesLocalBuffers(r))
- {
- if (IsParallelWorker())
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
- errmsg("cannot access temporary tables during a parallel operation")));
MyXactAccessedTempRel = true;
- }
pgstat_initstats(r);
@@ -1183,13 +1177,7 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
/* Make note that we've accessed a temporary relation */
if (RelationUsesLocalBuffers(r))
- {
- if (IsParallelWorker())
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
- errmsg("cannot access temporary tables during a parallel operation")));
MyXactAccessedTempRel = true;
- }
pgstat_initstats(r);
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 74a483e0fd9..ab5ef2573cf 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -17,6 +17,7 @@
#include "access/xact.h"
#include "access/xlog.h"
#include "access/parallel.h"
+#include "catalog/namespace.h"
#include "commands/async.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
@@ -67,6 +68,8 @@ typedef struct FixedParallelState
Oid database_id;
Oid authenticated_user_id;
Oid current_user_id;
+ Oid temp_namespace_id;
+ Oid temp_toast_namespace_id;
int sec_context;
PGPROC *parallel_master_pgproc;
pid_t parallel_master_pid;
@@ -288,6 +291,8 @@ InitializeParallelDSM(ParallelContext *pcxt)
fps->database_id = MyDatabaseId;
fps->authenticated_user_id = GetAuthenticatedUserId();
GetUserIdAndSecContext(&fps->current_user_id, &fps->sec_context);
+ GetTempNamespaceState(&fps->temp_namespace_id,
+ &fps->temp_toast_namespace_id);
fps->parallel_master_pgproc = MyProc;
fps->parallel_master_pid = MyProcPid;
fps->parallel_master_backend_id = MyBackendId;
@@ -1019,6 +1024,13 @@ ParallelWorkerMain(Datum main_arg)
/* Restore user ID and security context. */
SetUserIdAndSecContext(fps->current_user_id, fps->sec_context);
+ /* Restore temp-namespace state to ensure search path matches leader's. */
+ SetTempNamespaceState(fps->temp_namespace_id,
+ fps->temp_toast_namespace_id);
+
+ /* Set ParallelMasterBackendId so we know how to address temp relations. */
+ ParallelMasterBackendId = fps->parallel_master_backend_id;
+
/*
* We've initialized all of our state now; nothing should change
* hereafter.
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index d1cf45bef47..1baaa0bb898 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -390,7 +390,7 @@ GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
switch (relpersistence)
{
case RELPERSISTENCE_TEMP:
- backend = MyBackendId;
+ backend = BackendIdForTempRelations();
break;
case RELPERSISTENCE_UNLOGGED:
case RELPERSISTENCE_PERMANENT:
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index a1aba8ee556..8fd4c3136bc 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -3074,6 +3074,51 @@ GetTempToastNamespace(void)
/*
+ * GetTempNamespaceState - fetch status of session's temporary namespace
+ *
+ * This is used for conveying state to a parallel worker, and is not meant
+ * for general-purpose access.
+ */
+void
+GetTempNamespaceState(Oid *tempNamespaceId, Oid *tempToastNamespaceId)
+{
+ /* Return namespace OIDs, or 0 if session has not created temp namespace */
+ *tempNamespaceId = myTempNamespace;
+ *tempToastNamespaceId = myTempToastNamespace;
+}
+
+/*
+ * SetTempNamespaceState - set status of session's temporary namespace
+ *
+ * This is used for conveying state to a parallel worker, and is not meant for
+ * general-purpose access. By transferring these namespace OIDs to workers,
+ * we ensure they will have the same notion of the search path as their leader
+ * does.
+ */
+void
+SetTempNamespaceState(Oid tempNamespaceId, Oid tempToastNamespaceId)
+{
+ /* Worker should not have created its own namespaces ... */
+ Assert(myTempNamespace == InvalidOid);
+ Assert(myTempToastNamespace == InvalidOid);
+ Assert(myTempNamespaceSubID == InvalidSubTransactionId);
+
+ /* Assign same namespace OIDs that leader has */
+ myTempNamespace = tempNamespaceId;
+ myTempToastNamespace = tempToastNamespaceId;
+
+ /*
+ * It's fine to leave myTempNamespaceSubID == InvalidSubTransactionId.
+ * Even if the namespace is new so far as the leader is concerned, it's
+ * not new to the worker, and we certainly wouldn't want the worker trying
+ * to destroy it.
+ */
+
+ baseSearchPathValid = false; /* may need to rebuild list */
+}
+
+
+/*
* GetOverrideSearchPath - fetch current search path definition in form
* used by PushOverrideSearchPath.
*
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index fe68c998e8d..67f19063264 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -85,7 +85,7 @@ RelationCreateStorage(RelFileNode rnode, char relpersistence)
switch (relpersistence)
{
case RELPERSISTENCE_TEMP:
- backend = MyBackendId;
+ backend = BackendIdForTempRelations();
needs_wal = false;
break;
case RELPERSISTENCE_UNLOGGED:
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index e7909eb5d59..dc814a2b3ac 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -115,7 +115,6 @@ static bool has_parallel_hazard_walker(Node *node,
has_parallel_hazard_arg *context);
static bool parallel_too_dangerous(char proparallel,
has_parallel_hazard_arg *context);
-static bool typeid_is_temp(Oid typeid);
static bool contain_nonstrict_functions_walker(Node *node, void *context);
static bool contain_leaked_vars_walker(Node *node, void *context);
static Relids find_nonnullable_rels_walker(Node *node, bool top_level);
@@ -1410,49 +1409,6 @@ has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
}
/*
- * It is an error for a parallel worker to touch a temporary table in any
- * way, so we can't handle nodes whose type is the rowtype of such a
- * table.
- */
- if (!context->allow_restricted)
- {
- switch (nodeTag(node))
- {
- case T_Var:
- case T_Const:
- case T_Param:
- case T_Aggref:
- case T_WindowFunc:
- case T_ArrayRef:
- case T_FuncExpr:
- case T_NamedArgExpr:
- case T_OpExpr:
- case T_DistinctExpr:
- case T_NullIfExpr:
- case T_FieldSelect:
- case T_FieldStore:
- case T_RelabelType:
- case T_CoerceViaIO:
- case T_ArrayCoerceExpr:
- case T_ConvertRowtypeExpr:
- case T_CaseExpr:
- case T_CaseTestExpr:
- case T_ArrayExpr:
- case T_RowExpr:
- case T_CoalesceExpr:
- case T_MinMaxExpr:
- case T_CoerceToDomain:
- case T_CoerceToDomainValue:
- case T_SetToDefault:
- if (typeid_is_temp(exprType(node)))
- return true;
- break;
- default:
- break;
- }
- }
-
- /*
* For each node that might potentially call a function, we need to
* examine the pg_proc.proparallel marking for that function to see
* whether it's safe enough for the current value of allow_restricted.
@@ -1558,17 +1514,6 @@ parallel_too_dangerous(char proparallel, has_parallel_hazard_arg *context)
return proparallel != PROPARALLEL_SAFE;
}
-static bool
-typeid_is_temp(Oid typeid)
-{
- Oid relid = get_typ_typrelid(typeid);
-
- if (!OidIsValid(relid))
- return false;
-
- return (get_rel_persistence(relid) == RELPERSISTENCE_TEMP);
-}
-
/*****************************************************************************
* Check clauses for nonstrict functions
*****************************************************************************/
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 201ce2668fd..53981794b98 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -15,6 +15,7 @@
*/
#include "postgres.h"
+#include "access/parallel.h"
#include "catalog/catalog.h"
#include "executor/instrument.h"
#include "storage/buf_internals.h"
@@ -412,6 +413,19 @@ InitLocalBuffers(void)
HASHCTL info;
int i;
+ /*
+ * Parallel workers can't access data in temporary tables, because they
+ * have no visibility into the local buffers of their leader. This is a
+ * convenient, low-cost place to provide a backstop check for that. Note
+ * that we don't wish to prevent a parallel worker from accessing catalog
+ * metadata about a temp table, so checks at higher levels would be
+ * inappropriate.
+ */
+ if (IsParallelWorker())
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
+ errmsg("cannot access temporary tables during a parallel operation")));
+
/* Allocate and zero buffer headers and auxiliary arrays */
LocalBufferDescriptors = (BufferDesc *) calloc(nbufs, sizeof(BufferDesc));
LocalBufferBlockPointers = (Block *) calloc(nbufs, sizeof(Block));
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 4ec2fed2b35..0776f3bf6cf 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -1004,7 +1004,7 @@ pg_relation_filepath(PG_FUNCTION_ARGS)
break;
case RELPERSISTENCE_TEMP:
if (isTempOrTempToastNamespace(relform->relnamespace))
- backend = MyBackendId;
+ backend = BackendIdForTempRelations();
else
{
/* Do it the hard way. */
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index afb6c8772da..70a651a8fc3 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -993,7 +993,7 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
case RELPERSISTENCE_TEMP:
if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
{
- relation->rd_backend = MyBackendId;
+ relation->rd_backend = BackendIdForTempRelations();
relation->rd_islocaltemp = true;
}
else
@@ -2970,7 +2970,7 @@ RelationBuildLocalRelation(const char *relname,
break;
case RELPERSISTENCE_TEMP:
Assert(isTempOrTempToastNamespace(relnamespace));
- rel->rd_backend = MyBackendId;
+ rel->rd_backend = BackendIdForTempRelations();
rel->rd_islocaltemp = true;
break;
default:
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 5a7783b981e..f23208353c3 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -71,6 +71,8 @@ char postgres_exec_path[MAXPGPATH]; /* full path to backend */
BackendId MyBackendId = InvalidBackendId;
+BackendId ParallelMasterBackendId = InvalidBackendId;
+
Oid MyDatabaseId = InvalidOid;
Oid MyDatabaseTableSpace = InvalidOid;
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 2ccb3a7a03a..eee94d86226 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -125,6 +125,10 @@ extern bool isAnyTempNamespace(Oid namespaceId);
extern bool isOtherTempNamespace(Oid namespaceId);
extern int GetTempNamespaceBackendId(Oid namespaceId);
extern Oid GetTempToastNamespace(void);
+extern void GetTempNamespaceState(Oid *tempNamespaceId,
+ Oid *tempToastNamespaceId);
+extern void SetTempNamespaceState(Oid tempNamespaceId,
+ Oid tempToastNamespaceId);
extern void ResetTempTableNamespace(void);
extern OverrideSearchPath *GetOverrideSearchPath(MemoryContext context);
diff --git a/src/include/storage/backendid.h b/src/include/storage/backendid.h
index 7d9676f5348..dec8a972715 100644
--- a/src/include/storage/backendid.h
+++ b/src/include/storage/backendid.h
@@ -24,4 +24,14 @@ typedef int BackendId; /* unique currently active backend identifier */
extern PGDLLIMPORT BackendId MyBackendId; /* backend id of this backend */
+/* backend id of our parallel session leader, or InvalidBackendId if none */
+extern PGDLLIMPORT BackendId ParallelMasterBackendId;
+
+/*
+ * The BackendId to use for our session's temp relations is normally our own,
+ * but parallel workers should use their leader's ID.
+ */
+#define BackendIdForTempRelations() \
+ (ParallelMasterBackendId == InvalidBackendId ? MyBackendId : ParallelMasterBackendId)
+
#endif /* BACKENDID_H */