mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Improve the situation for parallel query versus temp relations.
Transmit the leader's temp-namespace state to workers. This is important because without it, the workers do not really have the same search path as the leader. For example, there is no good reason (and no extant code either) to prevent a worker from executing a temp function that the leader created previously; but as things stood it would fail to find the temp function, and then either fail or execute the wrong function entirely. We still prohibit a worker from creating a temp namespace on its own. In effect, a worker can only see the session's temp namespace if the leader had created it before starting the worker, which seems like the right semantics. Also, transmit the leader's BackendId to workers, and arrange for workers to use that when determining the physical file path of a temp relation belonging to their session. While the original intent was to prevent such accesses entirely, there were a number of holes in that, notably in places like dbsize.c which assume they can safely access temp rels of other sessions anyway. We might as well get this right, as a small down payment on someday allowing workers to access the leader's temp tables. (With this change, directly using "MyBackendId" as a relation or buffer backend ID is deprecated; you should use BackendIdForTempRelations() instead. I left a couple of such uses alone though, as they're not going to be reachable in parallel workers until we do something about localbuf.c.) Move the thou-shalt-not-access-thy-leader's-temp-tables prohibition down into localbuf.c, which is where it actually matters, instead of having it in relation_open(). This amounts to recognizing that access to temp tables' catalog entries is perfectly safe in a worker, it's only the data in local buffers that is problematic. Having done all that, we can get rid of the test in has_parallel_hazard() that says that use of a temp table's rowtype is unsafe in parallel workers. That test was unduly expensive, and if we really did need such a prohibition, that was not even close to being a bulletproof guard for it. (For example, any user-defined function executed in a parallel worker might have attempted such access.)
This commit is contained in:
@ -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);
|
||||
@ -1409,49 +1408,6 @@ has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
|
||||
return has_parallel_hazard_walker((Node *) rinfo->clause, 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
|
||||
@ -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
|
||||
*****************************************************************************/
|
||||
|
Reference in New Issue
Block a user