From bf6ae654768063f95e381145e9cf44969138c5dd Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 2 Jun 2020 16:47:26 -0700 Subject: [PATCH v3 07/10] wip: make send calls in printtup.c cheaper Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/access/common/printtup.c | 40 +++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index 8a4953ea033..b4c031f67e7 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -49,6 +49,15 @@ typedef struct bool typisvarlena; /* is it varlena (ie possibly toastable)? */ int16 format; /* format code for this column */ FmgrInfo finfo; /* Precomputed call info for output fn */ + + /* use union with FunctionCallInfoBaseData to guarantee alignment */ + union + { + FunctionCallInfoBaseData fcinfo; + /* ensure enough space for nargs args is available */ + char fcinfo_data[SizeForFunctionCallInfo(1)]; + } fcinfo_data; + } PrinttupAttrInfo; typedef struct @@ -278,6 +287,9 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) &thisState->typoutput, &thisState->typisvarlena); fmgr_info(thisState->typoutput, &thisState->finfo); + InitFunctionCallInfoData(thisState->fcinfo_data.fcinfo, + &thisState->finfo, 1, InvalidOid, + NULL, NULL); } else if (format == 1) { @@ -285,6 +297,9 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) &thisState->typsend, &thisState->typisvarlena); fmgr_info(thisState->typsend, &thisState->finfo); + InitFunctionCallInfoData(thisState->fcinfo_data.fcinfo, + &thisState->finfo, 1, InvalidOid, + NULL, NULL); } else ereport(ERROR, @@ -361,11 +376,28 @@ printtup(TupleTableSlot *slot, DestReceiver *self) { /* Binary output */ bytea *outputbytes; + int outputlen; + Datum result; + FunctionCallInfo fcinfo = &thisState->fcinfo_data.fcinfo; - outputbytes = SendFunctionCall(&thisState->finfo, attr); - pq_sendint32(buf, VARSIZE(outputbytes) - VARHDRSZ); - pq_sendbytes(buf, VARDATA(outputbytes), - VARSIZE(outputbytes) - VARHDRSZ); + fcinfo->args[0].value = attr; + fcinfo->args[0].isnull = false; + result = FunctionCallInvoke(fcinfo); + + /* + * Check for null result, since caller is clearly not expecting + * one + */ + if (unlikely(fcinfo->isnull)) + elog(ERROR, "send function return null"); + + outputbytes = DatumGetByteaP(result); + outputlen = VARSIZE(outputbytes) - VARHDRSZ; + + Assert(outputlen > 0); + + pq_sendint32(buf, outputlen); + pq_sendbytes(buf, VARDATA(outputbytes), outputlen); } } -- 2.38.0