diff options
author | Robert Haas <rhaas@postgresql.org> | 2015-09-28 21:55:57 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2015-09-28 21:55:57 -0400 |
commit | d1b7c1ffe72e86932b5395f29e006c3f503bc53d (patch) | |
tree | 9758eda06ae19401beef3c74373ecb076e9f9238 /src/backend/nodes/params.c | |
parent | 0557dc276f1022965f72dc8bcfc820dfd83a7dc2 (diff) | |
download | postgresql-d1b7c1ffe72e86932b5395f29e006c3f503bc53d.tar.gz postgresql-d1b7c1ffe72e86932b5395f29e006c3f503bc53d.zip |
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
Diffstat (limited to 'src/backend/nodes/params.c')
-rw-r--r-- | src/backend/nodes/params.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c index fb803f8ee8b..d093263589c 100644 --- a/src/backend/nodes/params.c +++ b/src/backend/nodes/params.c @@ -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; +} |