diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/common/printtup.c | 18 | ||||
-rw-r--r-- | src/backend/bootstrap/bootstrap.c | 25 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 45 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 23 | ||||
-rw-r--r-- | src/backend/executor/nodeAgg.c | 8 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 11 | ||||
-rw-r--r-- | src/backend/nodes/print.c | 5 | ||||
-rw-r--r-- | src/backend/parser/parse_coerce.c | 35 | ||||
-rw-r--r-- | src/backend/parser/parse_type.c | 11 | ||||
-rw-r--r-- | src/backend/tcop/fastpath.c | 89 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 128 | ||||
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 26 | ||||
-rw-r--r-- | src/backend/utils/adt/rowtypes.c | 91 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 5 | ||||
-rw-r--r-- | src/backend/utils/adt/varlena.c | 5 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 8 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 168 |
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 |