diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/prepare.c | 1 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 1 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 1 | ||||
-rw-r--r-- | src/backend/nodes/params.c | 54 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 1 | ||||
-rw-r--r-- | src/backend/utils/adt/datum.c | 16 |
6 files changed, 63 insertions, 11 deletions
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index fb33d305af..0d4aa69d82 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -392,6 +392,7 @@ EvaluateParams(PreparedStatement *pstmt, List *params, paramLI->parserSetup = NULL; paramLI->parserSetupArg = NULL; paramLI->numParams = num_params; + paramLI->paramMask = NULL; i = 0; foreach(l, exprstates) diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 812a610d02..0919c046e5 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -910,6 +910,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache, paramLI->parserSetup = NULL; paramLI->parserSetupArg = NULL; paramLI->numParams = nargs; + paramLI->paramMask = NULL; fcache->paramLI = paramLI; } else diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 300401e01f..13ddb8fc25 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -2330,6 +2330,7 @@ _SPI_convert_params(int nargs, Oid *argtypes, paramLI->parserSetup = NULL; paramLI->parserSetupArg = NULL; paramLI->numParams = nargs; + paramLI->paramMask = NULL; for (i = 0; i < nargs; i++) { diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c index d093263589..0351774921 100644 --- a/src/backend/nodes/params.c +++ b/src/backend/nodes/params.c @@ -15,6 +15,7 @@ #include "postgres.h" +#include "nodes/bitmapset.h" #include "nodes/params.h" #include "storage/shmem.h" #include "utils/datum.h" @@ -50,6 +51,7 @@ copyParamList(ParamListInfo from) retval->parserSetup = NULL; retval->parserSetupArg = NULL; retval->numParams = from->numParams; + retval->paramMask = NULL; for (i = 0; i < from->numParams; i++) { @@ -58,6 +60,17 @@ copyParamList(ParamListInfo from) int16 typLen; bool typByVal; + /* Ignore parameters we don't need, to save cycles and space. */ + if (retval->paramMask != NULL && + !bms_is_member(i, retval->paramMask)) + { + nprm->value = (Datum) 0; + nprm->isnull = true; + nprm->pflags = 0; + nprm->ptype = InvalidOid; + continue; + } + /* give hook a chance in case parameter is dynamic */ if (!OidIsValid(oprm->ptype) && from->paramFetch != NULL) (*from->paramFetch) (from, i + 1); @@ -90,19 +103,28 @@ EstimateParamListSpace(ParamListInfo paramLI) for (i = 0; i < paramLI->numParams; i++) { ParamExternData *prm = ¶mLI->params[i]; + Oid typeOid; 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); + /* Ignore parameters we don't need, to save cycles and space. */ + if (paramLI->paramMask != NULL && + !bms_is_member(i, paramLI->paramMask)) + typeOid = InvalidOid; + else + { + /* give hook a chance in case parameter is dynamic */ + if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL) + (*paramLI->paramFetch) (paramLI, i + 1); + typeOid = prm->ptype; + } 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); + if (OidIsValid(typeOid)) + get_typlenbyval(typeOid, &typLen, &typByVal); else { /* If no type OID, assume by-value, like copyParamList does. */ @@ -150,15 +172,24 @@ SerializeParamList(ParamListInfo paramLI, char **start_address) for (i = 0; i < nparams; i++) { ParamExternData *prm = ¶mLI->params[i]; + Oid typeOid; 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); + /* Ignore parameters we don't need, to save cycles and space. */ + if (paramLI->paramMask != NULL && + !bms_is_member(i, paramLI->paramMask)) + typeOid = InvalidOid; + else + { + /* give hook a chance in case parameter is dynamic */ + if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL) + (*paramLI->paramFetch) (paramLI, i + 1); + typeOid = prm->ptype; + } /* Write type OID. */ - memcpy(*start_address, &prm->ptype, sizeof(Oid)); + memcpy(*start_address, &typeOid, sizeof(Oid)); *start_address += sizeof(Oid); /* Write flags. */ @@ -166,8 +197,8 @@ SerializeParamList(ParamListInfo paramLI, char **start_address) *start_address += sizeof(uint16); /* Write datum/isnull. */ - if (OidIsValid(prm->ptype)) - get_typlenbyval(prm->ptype, &typLen, &typByVal); + if (OidIsValid(typeOid)) + get_typlenbyval(typeOid, &typLen, &typByVal); else { /* If no type OID, assume by-value, like copyParamList does. */ @@ -209,6 +240,7 @@ RestoreParamList(char **start_address) paramLI->parserSetup = NULL; paramLI->parserSetupArg = NULL; paramLI->numParams = nparams; + paramLI->paramMask = NULL; for (i = 0; i < nparams; i++) { diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index cb580dc0a7..1dc2eb0fcc 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -1629,6 +1629,7 @@ exec_bind_message(StringInfo input_message) params->parserSetup = NULL; params->parserSetupArg = NULL; params->numParams = numParams; + params->paramMask = NULL; for (paramno = 0; paramno < numParams; paramno++) { diff --git a/src/backend/utils/adt/datum.c b/src/backend/utils/adt/datum.c index 3d9e35442d..0d61950455 100644 --- a/src/backend/utils/adt/datum.c +++ b/src/backend/utils/adt/datum.c @@ -264,6 +264,11 @@ datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen) /* no need to use add_size, can't overflow */ if (typByVal) sz += sizeof(Datum); + else if (VARATT_IS_EXTERNAL_EXPANDED(value)) + { + ExpandedObjectHeader *eoh = DatumGetEOHP(value); + sz += EOH_get_flat_size(eoh); + } else sz += datumGetSize(value, typByVal, typLen); } @@ -292,6 +297,7 @@ void datumSerialize(Datum value, bool isnull, bool typByVal, int typLen, char **start_address) { + ExpandedObjectHeader *eoh = NULL; int header; /* Write header word. */ @@ -299,6 +305,11 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen, header = -2; else if (typByVal) header = -1; + else if (VARATT_IS_EXTERNAL_EXPANDED(value)) + { + eoh = DatumGetEOHP(value); + header = EOH_get_flat_size(eoh); + } else header = datumGetSize(value, typByVal, typLen); memcpy(*start_address, &header, sizeof(int)); @@ -312,6 +323,11 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen, memcpy(*start_address, &value, sizeof(Datum)); *start_address += sizeof(Datum); } + else if (eoh) + { + EOH_flatten_into(eoh, (void *) *start_address, header); + *start_address += header; + } else { memcpy(*start_address, DatumGetPointer(value), header); |