mirror of
https://github.com/postgres/postgres.git
synced 2025-06-26 12:21:12 +03:00
Parallel executor support.
This code provides infrastructure for a parallel leader to start up parallel workers to execute subtrees of the plan tree being executed in the master. User-supplied parameters from ParamListInfo are passed down, but PARAM_EXEC parameters are not. Various other constructs, such as initplans, subplans, and CTEs, are also not currently shared. Nevertheless, there's enough here to support a basic implementation of parallel query, and we can lift some of the current restrictions as needed. Amit Kapila and Robert Haas
This commit is contained in:
@ -112,6 +112,7 @@ CopyPlanFields(const Plan *from, Plan *newnode)
|
||||
COPY_SCALAR_FIELD(total_cost);
|
||||
COPY_SCALAR_FIELD(plan_rows);
|
||||
COPY_SCALAR_FIELD(plan_width);
|
||||
COPY_SCALAR_FIELD(plan_node_id);
|
||||
COPY_NODE_FIELD(targetlist);
|
||||
COPY_NODE_FIELD(qual);
|
||||
COPY_NODE_FIELD(lefttree);
|
||||
|
@ -271,6 +271,7 @@ _outPlanInfo(StringInfo str, const Plan *node)
|
||||
WRITE_FLOAT_FIELD(total_cost, "%.2f");
|
||||
WRITE_FLOAT_FIELD(plan_rows, "%.0f");
|
||||
WRITE_INT_FIELD(plan_width);
|
||||
WRITE_INT_FIELD(plan_node_id);
|
||||
WRITE_NODE_FIELD(targetlist);
|
||||
WRITE_NODE_FIELD(qual);
|
||||
WRITE_NODE_FIELD(lefttree);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "nodes/params.h"
|
||||
#include "storage/shmem.h"
|
||||
#include "utils/datum.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
@ -73,3 +74,157 @@ copyParamList(ParamListInfo from)
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimate the amount of space required to serialize a ParamListInfo.
|
||||
*/
|
||||
Size
|
||||
EstimateParamListSpace(ParamListInfo paramLI)
|
||||
{
|
||||
int i;
|
||||
Size sz = sizeof(int);
|
||||
|
||||
if (paramLI == NULL || paramLI->numParams <= 0)
|
||||
return sz;
|
||||
|
||||
for (i = 0; i < paramLI->numParams; i++)
|
||||
{
|
||||
ParamExternData *prm = ¶mLI->params[i];
|
||||
int16 typLen;
|
||||
bool typByVal;
|
||||
|
||||
/* give hook a chance in case parameter is dynamic */
|
||||
if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL)
|
||||
(*paramLI->paramFetch) (paramLI, i + 1);
|
||||
|
||||
sz = add_size(sz, sizeof(Oid)); /* space for type OID */
|
||||
sz = add_size(sz, sizeof(uint16)); /* space for pflags */
|
||||
|
||||
/* space for datum/isnull */
|
||||
if (OidIsValid(prm->ptype))
|
||||
get_typlenbyval(prm->ptype, &typLen, &typByVal);
|
||||
else
|
||||
{
|
||||
/* If no type OID, assume by-value, like copyParamList does. */
|
||||
typLen = sizeof(Datum);
|
||||
typByVal = true;
|
||||
}
|
||||
sz = add_size(sz,
|
||||
datumEstimateSpace(prm->value, prm->isnull, typByVal, typLen));
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize a paramListInfo structure into caller-provided storage.
|
||||
*
|
||||
* We write the number of parameters first, as a 4-byte integer, and then
|
||||
* write details for each parameter in turn. The details for each parameter
|
||||
* consist of a 4-byte type OID, 2 bytes of flags, and then the datum as
|
||||
* serialized by datumSerialize(). The caller is responsible for ensuring
|
||||
* that there is enough storage to store the number of bytes that will be
|
||||
* written; use EstimateParamListSpace to find out how many will be needed.
|
||||
* *start_address is updated to point to the byte immediately following those
|
||||
* written.
|
||||
*
|
||||
* RestoreParamList can be used to recreate a ParamListInfo based on the
|
||||
* serialized representation; this will be a static, self-contained copy
|
||||
* just as copyParamList would create.
|
||||
*/
|
||||
void
|
||||
SerializeParamList(ParamListInfo paramLI, char **start_address)
|
||||
{
|
||||
int nparams;
|
||||
int i;
|
||||
|
||||
/* Write number of parameters. */
|
||||
if (paramLI == NULL || paramLI->numParams <= 0)
|
||||
nparams = 0;
|
||||
else
|
||||
nparams = paramLI->numParams;
|
||||
memcpy(*start_address, &nparams, sizeof(int));
|
||||
*start_address += sizeof(int);
|
||||
|
||||
/* Write each parameter in turn. */
|
||||
for (i = 0; i < nparams; i++)
|
||||
{
|
||||
ParamExternData *prm = ¶mLI->params[i];
|
||||
int16 typLen;
|
||||
bool typByVal;
|
||||
|
||||
/* give hook a chance in case parameter is dynamic */
|
||||
if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL)
|
||||
(*paramLI->paramFetch) (paramLI, i + 1);
|
||||
|
||||
/* Write type OID. */
|
||||
memcpy(*start_address, &prm->ptype, sizeof(Oid));
|
||||
*start_address += sizeof(Oid);
|
||||
|
||||
/* Write flags. */
|
||||
memcpy(*start_address, &prm->pflags, sizeof(uint16));
|
||||
*start_address += sizeof(uint16);
|
||||
|
||||
/* Write datum/isnull. */
|
||||
if (OidIsValid(prm->ptype))
|
||||
get_typlenbyval(prm->ptype, &typLen, &typByVal);
|
||||
else
|
||||
{
|
||||
/* If no type OID, assume by-value, like copyParamList does. */
|
||||
typLen = sizeof(Datum);
|
||||
typByVal = true;
|
||||
}
|
||||
datumSerialize(prm->value, prm->isnull, typByVal, typLen,
|
||||
start_address);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a ParamListInfo structure.
|
||||
*
|
||||
* The result is allocated in CurrentMemoryContext.
|
||||
*
|
||||
* Note: the intent of this function is to make a static, self-contained
|
||||
* set of parameter values. If dynamic parameter hooks are present, we
|
||||
* intentionally do not copy them into the result. Rather, we forcibly
|
||||
* instantiate all available parameter values and copy the datum values.
|
||||
*/
|
||||
ParamListInfo
|
||||
RestoreParamList(char **start_address)
|
||||
{
|
||||
ParamListInfo paramLI;
|
||||
Size size;
|
||||
int i;
|
||||
int nparams;
|
||||
|
||||
memcpy(&nparams, *start_address, sizeof(int));
|
||||
*start_address += sizeof(int);
|
||||
|
||||
size = offsetof(ParamListInfoData, params) +
|
||||
nparams * sizeof(ParamExternData);
|
||||
|
||||
paramLI = (ParamListInfo) palloc(size);
|
||||
paramLI->paramFetch = NULL;
|
||||
paramLI->paramFetchArg = NULL;
|
||||
paramLI->parserSetup = NULL;
|
||||
paramLI->parserSetupArg = NULL;
|
||||
paramLI->numParams = nparams;
|
||||
|
||||
for (i = 0; i < nparams; i++)
|
||||
{
|
||||
ParamExternData *prm = ¶mLI->params[i];
|
||||
|
||||
/* Read type OID. */
|
||||
memcpy(&prm->ptype, *start_address, sizeof(Oid));
|
||||
*start_address += sizeof(Oid);
|
||||
|
||||
/* Read flags. */
|
||||
memcpy(&prm->pflags, *start_address, sizeof(uint16));
|
||||
*start_address += sizeof(uint16);
|
||||
|
||||
/* Read datum/isnull. */
|
||||
prm->value = datumRestore(start_address, &prm->isnull);
|
||||
}
|
||||
|
||||
return paramLI;
|
||||
}
|
||||
|
@ -1413,6 +1413,7 @@ ReadCommonPlan(Plan *local_node)
|
||||
READ_FLOAT_FIELD(total_cost);
|
||||
READ_FLOAT_FIELD(plan_rows);
|
||||
READ_INT_FIELD(plan_width);
|
||||
READ_INT_FIELD(plan_node_id);
|
||||
READ_NODE_FIELD(targetlist);
|
||||
READ_NODE_FIELD(qual);
|
||||
READ_NODE_FIELD(lefttree);
|
||||
|
Reference in New Issue
Block a user