summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/commands/prepare.c1
-rw-r--r--src/backend/executor/functions.c1
-rw-r--r--src/backend/executor/spi.c1
-rw-r--r--src/backend/nodes/params.c54
-rw-r--r--src/backend/tcop/postgres.c1
-rw-r--r--src/backend/utils/adt/datum.c16
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 = &paramLI->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 = &paramLI->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);