Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/common/printtup.c18
-rw-r--r--src/backend/bootstrap/bootstrap.c25
-rw-r--r--src/backend/commands/copy.c45
-rw-r--r--src/backend/executor/execTuples.c23
-rw-r--r--src/backend/executor/nodeAgg.c8
-rw-r--r--src/backend/executor/spi.c11
-rw-r--r--src/backend/nodes/print.c5
-rw-r--r--src/backend/parser/parse_coerce.c35
-rw-r--r--src/backend/parser/parse_type.c11
-rw-r--r--src/backend/tcop/fastpath.c89
-rw-r--r--src/backend/tcop/postgres.c128
-rw-r--r--src/backend/utils/adt/arrayfuncs.c26
-rw-r--r--src/backend/utils/adt/rowtypes.c91
-rw-r--r--src/backend/utils/adt/ruleutils.c5
-rw-r--r--src/backend/utils/adt/varlena.c5
-rw-r--r--src/backend/utils/cache/lsyscache.c8
-rw-r--r--src/backend/utils/fmgr/fmgr.c168
17 files changed, 427 insertions, 274 deletions
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 3ba606dfaf1..ba5793b0e7e 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.94 2006/03/05 15:58:20 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.95 2006/04/04 19:35:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -331,8 +331,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
/* Text output */
char *outputstr;
- outputstr = DatumGetCString(FunctionCall1(&thisState->finfo,
- attr));
+ outputstr = OutputFunctionCall(&thisState->finfo, attr);
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
pfree(outputstr);
}
@@ -341,9 +340,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
/* Binary output */
bytea *outputbytes;
- outputbytes = DatumGetByteaP(FunctionCall1(&thisState->finfo,
- attr));
- /* We assume the result will not have been toasted */
+ outputbytes = SendFunctionCall(&thisState->finfo, attr);
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
pq_sendbytes(&buf, VARDATA(outputbytes),
VARSIZE(outputbytes) - VARHDRSZ);
@@ -429,8 +426,7 @@ printtup_20(TupleTableSlot *slot, DestReceiver *self)
else
attr = origattr;
- outputstr = DatumGetCString(FunctionCall1(&thisState->finfo,
- attr));
+ outputstr = OutputFunctionCall(&thisState->finfo, attr);
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
pfree(outputstr);
@@ -542,8 +538,7 @@ debugtup(TupleTableSlot *slot, DestReceiver *self)
else
attr = origattr;
- value = DatumGetCString(OidFunctionCall1(typoutput,
- attr));
+ value = OidOutputFunctionCall(typoutput, attr);
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
@@ -632,8 +627,7 @@ printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
else
attr = origattr;
- outputbytes = DatumGetByteaP(FunctionCall1(&thisState->finfo,
- attr));
+ outputbytes = SendFunctionCall(&thisState->finfo, attr);
/* We assume the result will not have been toasted */
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
pq_sendbytes(&buf, VARDATA(outputbytes),
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 1d48fc44e18..c1d16b0e8fc 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.213 2006/03/07 01:03:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.214 2006/04/04 19:35:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -826,11 +826,11 @@ InsertOneValue(char *value, int i)
if (ap == NULL)
elog(ERROR, "could not find atttypid %u in Typ list", typoid);
- /* XXX this should match getTypeIOParam() */
- if (ap->am_typ.typtype == 'c')
- typioparam = typoid;
- else
+ /* XXX this logic should match getTypeIOParam() */
+ if (OidIsValid(ap->am_typ.typelem))
typioparam = ap->am_typ.typelem;
+ else
+ typioparam = typoid;
typinput = ap->am_typ.typinput;
typoutput = ap->am_typ.typoutput;
@@ -850,19 +850,18 @@ InsertOneValue(char *value, int i)
elog(ERROR, "type oid %u not found", typoid);
elog(DEBUG5, "Typ == NULL, typeindex = %u", typeindex);
- /* XXX there are no composite types in TypInfo */
- typioparam = TypInfo[typeindex].elem;
+ /* XXX this logic should match getTypeIOParam() */
+ if (OidIsValid(TypInfo[typeindex].elem))
+ typioparam = TypInfo[typeindex].elem;
+ else
+ typioparam = typoid;
typinput = TypInfo[typeindex].inproc;
typoutput = TypInfo[typeindex].outproc;
}
- values[i] = OidFunctionCall3(typinput,
- CStringGetDatum(value),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
- prt = DatumGetCString(OidFunctionCall1(typoutput,
- values[i]));
+ values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
+ prt = OidOutputFunctionCall(typoutput, values[i]);
elog(DEBUG4, "inserted -> %s", prt);
pfree(prt);
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 23c057af8e0..af21d565f17 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.261 2006/03/23 00:19:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.262 2006/04/04 19:35:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1382,8 +1382,8 @@ CopyTo(CopyState cstate)
{
if (!cstate->binary)
{
- string = DatumGetCString(FunctionCall1(&out_functions[attnum - 1],
- value));
+ string = OutputFunctionCall(&out_functions[attnum - 1],
+ value);
if (cstate->csv_mode)
CopyAttributeOutCSV(cstate, string,
force_quote[attnum - 1],
@@ -1395,9 +1395,8 @@ CopyTo(CopyState cstate)
{
bytea *outputbytes;
- outputbytes = DatumGetByteaP(FunctionCall1(&out_functions[attnum - 1],
- value));
- /* We assume the result will not have been toasted */
+ outputbytes = SendFunctionCall(&out_functions[attnum - 1],
+ value);
CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ);
CopySendData(cstate, VARDATA(outputbytes),
VARSIZE(outputbytes) - VARHDRSZ);
@@ -1459,6 +1458,13 @@ copy_in_error_callback(void *arg)
cstate->cur_attname, attval);
pfree(attval);
}
+ else if (cstate->cur_attname)
+ {
+ /* error is relevant to a particular column, value is NULL */
+ errcontext("COPY %s, line %d, column %s: NULL input",
+ cstate->cur_relname, cstate->cur_lineno,
+ cstate->cur_attname);
+ }
else
{
/* error is relevant to a particular line */
@@ -1854,19 +1860,16 @@ CopyFrom(CopyState cstate)
string = cstate->null_print;
}
- /* If we read an SQL NULL, no need to do anything */
+ cstate->cur_attname = NameStr(attr[m]->attname);
+ cstate->cur_attval = string;
+ values[m] = InputFunctionCall(&in_functions[m],
+ string,
+ typioparams[m],
+ attr[m]->atttypmod);
if (string != NULL)
- {
- cstate->cur_attname = NameStr(attr[m]->attname);
- cstate->cur_attval = string;
- values[m] = FunctionCall3(&in_functions[m],
- CStringGetDatum(string),
- ObjectIdGetDatum(typioparams[m]),
- Int32GetDatum(attr[m]->atttypmod));
nulls[m] = ' ';
- cstate->cur_attname = NULL;
- cstate->cur_attval = NULL;
- }
+ cstate->cur_attname = NULL;
+ cstate->cur_attval = NULL;
}
Assert(fieldno == nfields);
@@ -2900,7 +2903,7 @@ CopyReadBinaryAttribute(CopyState cstate,
if (fld_size == -1)
{
*isnull = true;
- return (Datum) 0;
+ return ReceiveFunctionCall(flinfo, NULL, typioparam, typmod);
}
if (fld_size < 0)
ereport(ERROR,
@@ -2924,10 +2927,8 @@ CopyReadBinaryAttribute(CopyState cstate,
cstate->attribute_buf.data[fld_size] = '\0';
/* Call the column type's binary input converter */
- result = FunctionCall3(flinfo,
- PointerGetDatum(&cstate->attribute_buf),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(typmod));
+ result = ReceiveFunctionCall(flinfo, &cstate->attribute_buf,
+ typioparam, typmod);
/* Trouble if it didn't eat the whole buffer */
if (cstate->attribute_buf.cursor != cstate->attribute_buf.len)
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index bd50027f776..81f589fd44b 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.92 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.93 2006/04/04 19:35:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -928,6 +928,7 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
/*
* BuildTupleFromCStrings - build a HeapTuple given user data in C string form.
* values is an array of C strings, one for each attribute of the return tuple.
+ * A NULL string pointer indicates we want to create a NULL field.
*/
HeapTuple
BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
@@ -937,35 +938,25 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Datum *dvalues;
char *nulls;
int i;
- Oid attioparam;
- int32 atttypmod;
HeapTuple tuple;
dvalues = (Datum *) palloc(natts * sizeof(Datum));
nulls = (char *) palloc(natts * sizeof(char));
- /* Call the "in" function for each non-null, non-dropped attribute */
+ /* Call the "in" function for each non-dropped attribute */
for (i = 0; i < natts; i++)
{
if (!tupdesc->attrs[i]->attisdropped)
{
/* Non-dropped attributes */
+ dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i],
+ values[i],
+ attinmeta->attioparams[i],
+ attinmeta->atttypmods[i]);
if (values[i] != NULL)
- {
- attioparam = attinmeta->attioparams[i];
- atttypmod = attinmeta->atttypmods[i];
-
- dvalues[i] = FunctionCall3(&attinmeta->attinfuncs[i],
- CStringGetDatum(values[i]),
- ObjectIdGetDatum(attioparam),
- Int32GetDatum(atttypmod));
nulls[i] = ' ';
- }
else
- {
- dvalues[i] = (Datum) 0;
nulls[i] = 'n';
- }
}
else
{
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 5b48545aac9..a242d53968e 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -61,7 +61,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.138 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.139 2006/04/04 19:35:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1407,10 +1407,8 @@ GetAggInitVal(Datum textInitVal, Oid transtype)
getTypeInputInfo(transtype, &typinput, &typioparam);
strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
- initVal = OidFunctionCall3(typinput,
- CStringGetDatum(strInitVal),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
+ initVal = OidInputFunctionCall(typinput, strInitVal,
+ typioparam, -1);
pfree(strInitVal);
return initVal;
}
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 183bc89b020..3563ba23d3a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.149 2006/03/14 22:48:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.150 2006/04/04 19:35:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -629,9 +629,9 @@ SPI_fname(TupleDesc tupdesc, int fnumber)
char *
SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
{
+ char *result;
Datum origval,
- val,
- result;
+ val;
bool isnull;
Oid typoid,
foutoid;
@@ -666,14 +666,13 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
else
val = origval;
- result = OidFunctionCall1(foutoid,
- val);
+ result = OidOutputFunctionCall(foutoid, val);
/* Clean up detoasted copy, if any */
if (val != origval)
pfree(DatumGetPointer(val));
- return DatumGetCString(result);
+ return result;
}
Datum
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index 18b7535cd06..c3fbdf242d0 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.78 2006/03/05 15:58:28 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.79 2006/04/04 19:35:34 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -357,8 +357,7 @@ print_expr(Node *expr, List *rtable)
getTypeOutputInfo(c->consttype,
&typoutput, &typIsVarlena);
- outputstr = DatumGetCString(OidFunctionCall1(typoutput,
- c->constvalue));
+ outputstr = OidOutputFunctionCall(typoutput, c->constvalue);
printf("%s", outputstr);
pfree(outputstr);
}
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index bcb8e0016df..5a343e768dd 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.135 2006/03/05 15:58:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.136 2006/04/04 19:35:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -166,26 +166,21 @@ coerce_type(ParseState *pstate, Node *node,
newcon->constbyval = typeByVal(targetType);
newcon->constisnull = con->constisnull;
+ /*
+ * We pass typmod -1 to the input routine, primarily because
+ * existing input routines follow implicit-coercion semantics for
+ * length checks, which is not always what we want here. Any
+ * length constraint will be applied later by our caller.
+ *
+ * We assume here that UNKNOWN's internal representation is the
+ * same as CSTRING.
+ */
if (!con->constisnull)
- {
- /*
- * We assume here that UNKNOWN's internal representation is the
- * same as CSTRING
- */
- char *val = DatumGetCString(con->constvalue);
-
- /*
- * We pass typmod -1 to the input routine, primarily because
- * existing input routines follow implicit-coercion semantics for
- * length checks, which is not always what we want here. Any
- * length constraint will be applied later by our caller.
- *
- * Note that we call stringTypeDatum using the domain's pg_type
- * row, if it's a domain. This works because the domain row has
- * the same typinput and typelem as the base type --- ugly...
- */
- newcon->constvalue = stringTypeDatum(targetType, val, -1);
- }
+ newcon->constvalue = stringTypeDatum(targetType,
+ DatumGetCString(con->constvalue),
+ -1);
+ else
+ newcon->constvalue = stringTypeDatum(targetType, NULL, -1);
result = (Node *) newcon;
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index e88e6c37c1e..fec4552c9c4 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.79 2006/03/14 22:48:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.80 2006/04/04 19:35:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -326,7 +326,8 @@ typeTypeRelid(Type typ)
/*
* Given a type structure and a string, returns the internal representation
- * of that string
+ * of that string. The "string" can be NULL to perform conversion of a NULL
+ * (which might result in failure, if the input function rejects NULLs).
*/
Datum
stringTypeDatum(Type tp, char *string, int32 atttypmod)
@@ -336,10 +337,8 @@ stringTypeDatum(Type tp, char *string, int32 atttypmod)
typinput = ((Form_pg_type) GETSTRUCT(tp))->typinput;
typioparam = getTypeIOParam(tp);
- return OidFunctionCall3(typinput,
- CStringGetDatum(string),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(atttypmod));
+ return OidInputFunctionCall(typinput, string,
+ typioparam, atttypmod);
}
/* given a typeid, return the type's typrelid (associated relation, if any) */
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index f9a5d7116b1..c9fa715600f 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.85 2006/03/05 15:58:40 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.86 2006/04/04 19:35:35 tgl Exp $
*
* NOTES
* This cruft is the server side of PQfn.
@@ -154,8 +154,7 @@ SendFunctionResult(Datum retval, bool isnull, Oid rettype, int16 format)
char *outputstr;
getTypeOutputInfo(rettype, &typoutput, &typisvarlena);
- outputstr = DatumGetCString(OidFunctionCall1(typoutput,
- retval));
+ outputstr = OidOutputFunctionCall(typoutput, retval);
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
pfree(outputstr);
}
@@ -166,9 +165,7 @@ SendFunctionResult(Datum retval, bool isnull, Oid rettype, int16 format)
bytea *outputbytes;
getTypeBinaryOutputInfo(rettype, &typsend, &typisvarlena);
- outputbytes = DatumGetByteaP(OidFunctionCall1(typsend,
- retval));
- /* We assume the result will not have been toasted */
+ outputbytes = OidSendFunctionCall(typsend, retval);
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
pq_sendbytes(&buf, VARDATA(outputbytes),
VARSIZE(outputbytes) - VARHDRSZ);
@@ -433,23 +430,25 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info * fip,
if (argsize == -1)
{
fcinfo->argnull[i] = true;
- continue;
}
- fcinfo->argnull[i] = false;
- if (argsize < 0)
- ereport(ERROR,
- (errcode(ERRCODE_PROTOCOL_VIOLATION),
- errmsg("invalid argument size %d in function call message",
- argsize)));
-
- /* Reset abuf to empty, and insert raw data into it */
- abuf.len = 0;
- abuf.data[0] = '\0';
- abuf.cursor = 0;
-
- appendBinaryStringInfo(&abuf,
- pq_getmsgbytes(msgBuf, argsize),
- argsize);
+ else
+ {
+ fcinfo->argnull[i] = false;
+ if (argsize < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROTOCOL_VIOLATION),
+ errmsg("invalid argument size %d in function call message",
+ argsize)));
+
+ /* Reset abuf to empty, and insert raw data into it */
+ abuf.len = 0;
+ abuf.data[0] = '\0';
+ abuf.cursor = 0;
+
+ appendBinaryStringInfo(&abuf,
+ pq_getmsgbytes(msgBuf, argsize),
+ argsize);
+ }
if (numAFormats > 1)
aformat = aformats[i];
@@ -472,31 +471,36 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info * fip,
* have to do encoding conversion before calling the typinput
* routine, though.
*/
- pstring = pg_client_to_server(abuf.data, argsize);
- fcinfo->arg[i] =
- OidFunctionCall3(typinput,
- CStringGetDatum(pstring),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
+ if (argsize == -1)
+ pstring = NULL;
+ else
+ pstring = pg_client_to_server(abuf.data, argsize);
+
+ fcinfo->arg[i] = OidInputFunctionCall(typinput, pstring,
+ typioparam, -1);
/* Free result of encoding conversion, if any */
- if (pstring != abuf.data)
+ if (pstring && pstring != abuf.data)
pfree(pstring);
}
else if (aformat == 1)
{
Oid typreceive;
Oid typioparam;
+ StringInfo bufptr;
/* Call the argument type's binary input converter */
getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
- fcinfo->arg[i] = OidFunctionCall3(typreceive,
- PointerGetDatum(&abuf),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
+ if (argsize == -1)
+ bufptr = NULL;
+ else
+ bufptr = &abuf;
+
+ fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, bufptr,
+ typioparam, -1);
/* Trouble if it didn't eat the whole buffer */
- if (abuf.cursor != abuf.len)
+ if (argsize != -1 && abuf.cursor != abuf.len)
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("incorrect binary data format in function argument %d",
@@ -552,18 +556,22 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info * fip,
Oid typreceive;
Oid typioparam;
+ getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
+
argsize = pq_getmsgint(msgBuf, 4);
if (argsize == -1)
{
fcinfo->argnull[i] = true;
+ fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, NULL,
+ typioparam, -1);
continue;
}
fcinfo->argnull[i] = false;
if (argsize < 0)
ereport(ERROR,
(errcode(ERRCODE_PROTOCOL_VIOLATION),
- errmsg("invalid argument size %d in function call message",
- argsize)));
+ errmsg("invalid argument size %d in function call message",
+ argsize)));
/* Reset abuf to empty, and insert raw data into it */
abuf.len = 0;
@@ -574,13 +582,8 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info * fip,
pq_getmsgbytes(msgBuf, argsize),
argsize);
- /* Call the argument type's binary input converter */
- getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
-
- fcinfo->arg[i] = OidFunctionCall3(typreceive,
- PointerGetDatum(&abuf),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
+ fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, &abuf,
+ typioparam, -1);
/* Trouble if it didn't eat the whole buffer */
if (abuf.cursor != abuf.len)
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 78cb8c3f811..df9ef8983a0 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.482 2006/03/14 22:48:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.483 2006/04/04 19:35:35 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -1486,6 +1486,9 @@ exec_bind_message(StringInfo input_message)
Oid ptype = lfirst_oid(l);
int32 plength;
bool isNull;
+ StringInfoData pbuf;
+ char csave;
+ int16 pformat;
plength = pq_getmsgint(input_message, 4);
isNull = (plength == -1);
@@ -1493,16 +1496,6 @@ exec_bind_message(StringInfo input_message)
if (!isNull)
{
const char *pvalue = pq_getmsgbytes(input_message, plength);
- int16 pformat;
- StringInfoData pbuf;
- char csave;
-
- if (numPFormats > 1)
- pformat = pformats[i];
- else if (numPFormats > 0)
- pformat = pformats[0];
- else
- pformat = 0; /* default = text */
/*
* Rather than copying data around, we just set up a phony
@@ -1519,63 +1512,80 @@ exec_bind_message(StringInfo input_message)
csave = pbuf.data[plength];
pbuf.data[plength] = '\0';
+ }
+ else
+ {
+ pbuf.data = NULL; /* keep compiler quiet */
+ csave = 0;
+ }
- if (pformat == 0)
- {
- Oid typinput;
- Oid typioparam;
- char *pstring;
+ if (numPFormats > 1)
+ pformat = pformats[i];
+ else if (numPFormats > 0)
+ pformat = pformats[0];
+ else
+ pformat = 0; /* default = text */
- getTypeInputInfo(ptype, &typinput, &typioparam);
+ if (pformat == 0)
+ {
+ Oid typinput;
+ Oid typioparam;
+ char *pstring;
- /*
- * We have to do encoding conversion before calling the
- * typinput routine.
- */
+ getTypeInputInfo(ptype, &typinput, &typioparam);
+
+ /*
+ * We have to do encoding conversion before calling the
+ * typinput routine.
+ */
+ if (isNull)
+ pstring = NULL;
+ else
pstring = pg_client_to_server(pbuf.data, plength);
- params[i].value =
- OidFunctionCall3(typinput,
- CStringGetDatum(pstring),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
- /* Free result of encoding conversion, if any */
- if (pstring != pbuf.data)
- pfree(pstring);
- }
- else if (pformat == 1)
- {
- Oid typreceive;
- Oid typioparam;
- /*
- * Call the parameter type's binary input converter
- */
- getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
-
- params[i].value =
- OidFunctionCall3(typreceive,
- PointerGetDatum(&pbuf),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(-1));
-
- /* Trouble if it didn't eat the whole buffer */
- if (pbuf.cursor != pbuf.len)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
- errmsg("incorrect binary data format in bind parameter %d",
- i + 1)));
- }
+ params[i].value = OidInputFunctionCall(typinput, pstring,
+ typioparam, -1);
+ /* Free result of encoding conversion, if any */
+ if (pstring && pstring != pbuf.data)
+ pfree(pstring);
+ }
+ else if (pformat == 1)
+ {
+ Oid typreceive;
+ Oid typioparam;
+ StringInfo bufptr;
+
+ /*
+ * Call the parameter type's binary input converter
+ */
+ getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
+
+ if (isNull)
+ bufptr = NULL;
else
- {
+ bufptr = &pbuf;
+
+ params[i].value = OidReceiveFunctionCall(typreceive, bufptr,
+ typioparam, -1);
+
+ /* Trouble if it didn't eat the whole buffer */
+ if (!isNull && pbuf.cursor != pbuf.len)
ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unsupported format code: %d",
- pformat)));
- }
+ (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+ errmsg("incorrect binary data format in bind parameter %d",
+ i + 1)));
+ }
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unsupported format code: %d",
+ pformat)));
+ }
- /* Restore message buffer contents */
+ /* Restore message buffer contents */
+ if (!isNull)
pbuf.data[plength] = csave;
- }
params[i].kind = PARAM_NUM;
params[i].id = i + 1;
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 1de3ff13a7d..dba7353ba58 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.127 2006/03/05 15:58:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.128 2006/04/04 19:35:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -787,14 +787,14 @@ ReadArrayStr(char *arrayStr,
pg_strcasecmp(itemstart, "NULL") == 0)
{
/* it's a NULL item */
+ values[i] = InputFunctionCall(inputproc, NULL,
+ typioparam, typmod);
nulls[i] = true;
}
else
{
- values[i] = FunctionCall3(inputproc,
- CStringGetDatum(itemstart),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(typmod));
+ values[i] = InputFunctionCall(inputproc, itemstart,
+ typioparam, typmod);
nulls[i] = false;
}
}
@@ -1018,8 +1018,7 @@ array_out(PG_FUNCTION_ARGS)
Datum itemvalue;
itemvalue = fetch_att(p, typbyval, typlen);
- values[i] = DatumGetCString(FunctionCall1(&my_extra->proc,
- itemvalue));
+ values[i] = OutputFunctionCall(&my_extra->proc, itemvalue);
p = att_addlength(p, typlen, PointerGetDatum(p));
p = (char *) att_align(p, typalign);
@@ -1357,6 +1356,8 @@ ReadArrayBinary(StringInfo buf,
if (itemlen == -1)
{
/* -1 length means NULL */
+ values[i] = ReceiveFunctionCall(receiveproc, NULL,
+ typioparam, typmod);
nulls[i] = true;
continue;
}
@@ -1378,10 +1379,8 @@ ReadArrayBinary(StringInfo buf,
buf->data[buf->cursor] = '\0';
/* Now call the element's receiveproc */
- values[i] = FunctionCall3(receiveproc,
- PointerGetDatum(&elem_buf),
- ObjectIdGetDatum(typioparam),
- Int32GetDatum(typmod));
+ values[i] = ReceiveFunctionCall(receiveproc, &elem_buf,
+ typioparam, typmod);
nulls[i] = false;
/* Trouble if it didn't eat the whole buffer */
@@ -1515,10 +1514,7 @@ array_send(PG_FUNCTION_ARGS)
bytea *outputbytes;
itemvalue = fetch_att(p, typbyval, typlen);
-
- outputbytes = DatumGetByteaP(FunctionCall1(&my_extra->proc,
- itemvalue));
- /* We assume the result will not have been toasted */
+ outputbytes = SendFunctionCall(&my_extra->proc, itemvalue);
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
pq_sendbytes(&buf, VARDATA(outputbytes),
VARSIZE(outputbytes) - VARHDRSZ);
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 9d7fcaa413a..bb61dc29568 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.14 2006/03/05 15:58:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.15 2006/04/04 19:35:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,6 +136,7 @@ record_in(PG_FUNCTION_ARGS)
{
ColumnIOData *column_info = &my_extra->columns[i];
Oid column_type = tupdesc->attrs[i]->atttypid;
+ char *column_data;
/* Ignore dropped columns in datatype, but fill with nulls */
if (tupdesc->attrs[i]->attisdropped)
@@ -161,7 +162,7 @@ record_in(PG_FUNCTION_ARGS)
/* Check for null: completely empty input means null */
if (*ptr == ',' || *ptr == ')')
{
- values[i] = (Datum) 0;
+ column_data = NULL;
nulls[i] = 'n';
}
else
@@ -207,27 +208,29 @@ record_in(PG_FUNCTION_ARGS)
appendStringInfoChar(&buf, ch);
}
- /*
- * Convert the column value
- */
- if (column_info->column_type != column_type)
- {
- getTypeInputInfo(column_type,
- &column_info->typiofunc,
- &column_info->typioparam);
- fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
- fcinfo->flinfo->fn_mcxt);
- column_info->column_type = column_type;
- }
-
- values[i] = FunctionCall3(&column_info->proc,
- CStringGetDatum(buf.data),
- ObjectIdGetDatum(column_info->typioparam),
- Int32GetDatum(tupdesc->attrs[i]->atttypmod));
+ column_data = buf.data;
nulls[i] = ' ';
}
/*
+ * Convert the column value
+ */
+ if (column_info->column_type != column_type)
+ {
+ getTypeInputInfo(column_type,
+ &column_info->typiofunc,
+ &column_info->typioparam);
+ fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
+ fcinfo->flinfo->fn_mcxt);
+ column_info->column_type = column_type;
+ }
+
+ values[i] = InputFunctionCall(&column_info->proc,
+ column_data,
+ column_info->typioparam,
+ tupdesc->attrs[i]->atttypmod);
+
+ /*
* Prep for next column
*/
needComma = true;
@@ -372,8 +375,7 @@ record_out(PG_FUNCTION_ARGS)
column_info->column_type = column_type;
}
- value = DatumGetCString(FunctionCall1(&column_info->proc,
- values[i]));
+ value = OutputFunctionCall(&column_info->proc, values[i]);
/* Detect whether we need double quotes for this value */
nq = (value[0] == '\0'); /* force quotes for empty string */
@@ -505,6 +507,9 @@ record_recv(PG_FUNCTION_ARGS)
Oid column_type = tupdesc->attrs[i]->atttypid;
Oid coltypoid;
int itemlen;
+ StringInfoData item_buf;
+ StringInfo bufptr;
+ char csave;
/* Ignore dropped columns in datatype, but fill with nulls */
if (tupdesc->attrs[i]->attisdropped)
@@ -532,8 +537,9 @@ record_recv(PG_FUNCTION_ARGS)
if (itemlen == -1)
{
/* -1 length means NULL */
- values[i] = (Datum) 0;
+ bufptr = NULL;
nulls[i] = 'n';
+ csave = 0; /* keep compiler quiet */
}
else
{
@@ -543,9 +549,6 @@ record_recv(PG_FUNCTION_ARGS)
* We assume we can scribble on the input buffer so as to maintain
* the convention that StringInfos have a trailing null.
*/
- StringInfoData item_buf;
- char csave;
-
item_buf.data = &buf->data[buf->cursor];
item_buf.maxlen = itemlen + 1;
item_buf.len = itemlen;
@@ -556,23 +559,28 @@ record_recv(PG_FUNCTION_ARGS)
csave = buf->data[buf->cursor];
buf->data[buf->cursor] = '\0';
- /* Now call the column's receiveproc */
- if (column_info->column_type != column_type)
- {
- getTypeBinaryInputInfo(column_type,
- &column_info->typiofunc,
- &column_info->typioparam);
- fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
- fcinfo->flinfo->fn_mcxt);
- column_info->column_type = column_type;
- }
-
- values[i] = FunctionCall3(&column_info->proc,
- PointerGetDatum(&item_buf),
- ObjectIdGetDatum(column_info->typioparam),
- Int32GetDatum(tupdesc->attrs[i]->atttypmod));
+ bufptr = &item_buf;
nulls[i] = ' ';
+ }
+ /* Now call the column's receiveproc */
+ if (column_info->column_type != column_type)
+ {
+ getTypeBinaryInputInfo(column_type,
+ &column_info->typiofunc,
+ &column_info->typioparam);
+ fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
+ fcinfo->flinfo->fn_mcxt);
+ column_info->column_type = column_type;
+ }
+
+ values[i] = ReceiveFunctionCall(&column_info->proc,
+ bufptr,
+ column_info->typioparam,
+ tupdesc->attrs[i]->atttypmod);
+
+ if (bufptr)
+ {
/* Trouble if it didn't eat the whole buffer */
if (item_buf.cursor != itemlen)
ereport(ERROR,
@@ -712,8 +720,7 @@ record_send(PG_FUNCTION_ARGS)
column_info->column_type = column_type;
}
- outputbytes = DatumGetByteaP(FunctionCall1(&column_info->proc,
- values[i]));
+ outputbytes = SendFunctionCall(&column_info->proc, values[i]);
/* We assume the result will not have been toasted */
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 714140e0617..f8daab6eeaf 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.217 2006/03/16 00:31:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.218 2006/04/04 19:35:36 tgl Exp $
**********************************************************************/
#include "postgres.h"
@@ -3921,8 +3921,7 @@ get_const_expr(Const *constval, deparse_context *context)
getTypeOutputInfo(constval->consttype,
&typoutput, &typIsVarlena);
- extval = DatumGetCString(OidFunctionCall1(typoutput,
- constval->constvalue));
+ extval = OidOutputFunctionCall(typoutput, constval->constvalue);
switch (constval->consttype)
{
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index b936b8219dd..79dc0178a80 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.145 2006/03/05 15:58:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.146 2006/04/04 19:35:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2580,8 +2580,7 @@ array_to_text(PG_FUNCTION_ARGS)
{
itemvalue = fetch_att(p, typbyval, typlen);
- value = DatumGetCString(FunctionCall1(&my_extra->proc,
- itemvalue));
+ value = OutputFunctionCall(&my_extra->proc, itemvalue);
if (printed)
appendStringInfo(&buf, "%s%s", fldsep, value);
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 6eb6ea802bf..fb24cc62366 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.132 2006/03/05 15:58:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.133 2006/04/04 19:35:36 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -1554,10 +1554,8 @@ get_typdefault(Oid typid)
strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
datum));
/* Convert C string to a value of the given type */
- datum = OidFunctionCall3(type->typinput,
- CStringGetDatum(strDefaultVal),
- ObjectIdGetDatum(getTypeIOParam(typeTuple)),
- Int32GetDatum(-1));
+ datum = OidInputFunctionCall(type->typinput, strDefaultVal,
+ getTypeIOParam(typeTuple), -1);
/* Build a Const node containing the value */
expr = (Node *) makeConst(typid,
type->typlen,
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index e64ede6f566..4a663135dcb 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.99 2006/03/05 15:58:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.100 2006/04/04 19:35:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1683,6 +1683,172 @@ OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
/*
+ * Special cases for convenient invocation of datatype I/O functions.
+ */
+
+/*
+ * Call a previously-looked-up datatype input function.
+ *
+ * "str" may be NULL to indicate we are reading a NULL. In this case
+ * the caller should assume the result is NULL, but we'll call the input
+ * function anyway if it's not strict. So this is almost but not quite
+ * the same as FunctionCall3.
+ */
+Datum
+InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ if (str == NULL && flinfo->fn_strict)
+ return (Datum) 0; /* just return null result */
+
+ InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);
+
+ fcinfo.arg[0] = CStringGetDatum(str);
+ fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
+ fcinfo.arg[2] = Int32GetDatum(typmod);
+ fcinfo.argnull[0] = (str == NULL);
+ fcinfo.argnull[1] = false;
+ fcinfo.argnull[2] = false;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Should get null result if and only if str is NULL */
+ if (str == NULL)
+ {
+ if (!fcinfo.isnull)
+ elog(ERROR, "input function %u returned non-NULL",
+ fcinfo.flinfo->fn_oid);
+ }
+ else
+ {
+ if (fcinfo.isnull)
+ elog(ERROR, "input function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+ }
+
+ return result;
+}
+
+/*
+ * Call a previously-looked-up datatype output function.
+ *
+ * Do not call this on NULL datums.
+ *
+ * This is mere window dressing for FunctionCall1, but its use is recommended
+ * anyway so that code invoking output functions can be identified easily.
+ */
+char *
+OutputFunctionCall(FmgrInfo *flinfo, Datum val)
+{
+ return DatumGetCString(FunctionCall1(flinfo, val));
+}
+
+/*
+ * Call a previously-looked-up datatype binary-input function.
+ *
+ * "buf" may be NULL to indicate we are reading a NULL. In this case
+ * the caller should assume the result is NULL, but we'll call the receive
+ * function anyway if it's not strict. So this is almost but not quite
+ * the same as FunctionCall3.
+ */
+Datum
+ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
+ Oid typioparam, int32 typmod)
+{
+ FunctionCallInfoData fcinfo;
+ Datum result;
+
+ if (buf == NULL && flinfo->fn_strict)
+ return (Datum) 0; /* just return null result */
+
+ InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL);
+
+ fcinfo.arg[0] = PointerGetDatum(buf);
+ fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
+ fcinfo.arg[2] = Int32GetDatum(typmod);
+ fcinfo.argnull[0] = (buf == NULL);
+ fcinfo.argnull[1] = false;
+ fcinfo.argnull[2] = false;
+
+ result = FunctionCallInvoke(&fcinfo);
+
+ /* Should get null result if and only if buf is NULL */
+ if (buf == NULL)
+ {
+ if (!fcinfo.isnull)
+ elog(ERROR, "receive function %u returned non-NULL",
+ fcinfo.flinfo->fn_oid);
+ }
+ else
+ {
+ if (fcinfo.isnull)
+ elog(ERROR, "receive function %u returned NULL",
+ fcinfo.flinfo->fn_oid);
+ }
+
+ return result;
+}
+
+/*
+ * Call a previously-looked-up datatype binary-output function.
+ *
+ * Do not call this on NULL datums.
+ *
+ * This is little more than window dressing for FunctionCall1, but its use is
+ * recommended anyway so that code invoking output functions can be identified
+ * easily. Note however that it does guarantee a non-toasted result.
+ */
+bytea *
+SendFunctionCall(FmgrInfo *flinfo, Datum val)
+{
+ return DatumGetByteaP(FunctionCall1(flinfo, val));
+}
+
+/*
+ * As above, for I/O functions identified by OID. These are only to be used
+ * in seldom-executed code paths. They are not only slow but leak memory.
+ */
+Datum
+OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
+{
+ FmgrInfo flinfo;
+
+ fmgr_info(functionId, &flinfo);
+ return InputFunctionCall(&flinfo, str, typioparam, typmod);
+}
+
+char *
+OidOutputFunctionCall(Oid functionId, Datum val)
+{
+ FmgrInfo flinfo;
+
+ fmgr_info(functionId, &flinfo);
+ return OutputFunctionCall(&flinfo, val);
+}
+
+Datum
+OidReceiveFunctionCall(Oid functionId, StringInfo buf,
+ Oid typioparam, int32 typmod)
+{
+ FmgrInfo flinfo;
+
+ fmgr_info(functionId, &flinfo);
+ return ReceiveFunctionCall(&flinfo, buf, typioparam, typmod);
+}
+
+bytea *
+OidSendFunctionCall(Oid functionId, Datum val)
+{
+ FmgrInfo flinfo;
+
+ fmgr_info(functionId, &flinfo);
+ return SendFunctionCall(&flinfo, val);
+}
+
+
+/*
* !!! OLD INTERFACE !!!
*
* fmgr() is the only remaining vestige of the old-style caller support