From b02832719ce9926fe5a1c9b7e03cebf3dbf6a653 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 12 May 2003 16:48:17 +0000 Subject: [PATCH] Avoid unnecessary copying of parameter values in BIND. This allows efficient insertion of large bytea values through the BIND interface. --- src/backend/tcop/postgres.c | 46 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index f444302e96..a37ed5a9b6 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.342 2003/05/09 18:08:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.343 2003/05/12 16:48:17 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1265,13 +1265,9 @@ exec_bind_message(StringInfo input_message) if (numParams > 0) { bool isaborted = IsAbortedTransactionBlockState(); - StringInfoData pbuf; List *l; MemoryContext oldContext; - /* Note that the string buffer lives in MessageContext */ - initStringInfo(&pbuf); - oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); params = (ParamListInfo) @@ -1289,14 +1285,7 @@ exec_bind_message(StringInfo input_message) if (!isNull) { - /* Reset pbuf to empty, and insert raw data into it */ - pbuf.len = 0; - pbuf.data[0] = '\0'; - pbuf.cursor = 0; - - appendBinaryStringInfo(&pbuf, - pq_getmsgbytes(input_message, plength), - plength); + const char *pvalue = pq_getmsgbytes(input_message, plength); if (isaborted) { @@ -1306,6 +1295,8 @@ exec_bind_message(StringInfo input_message) else { int16 pformat; + StringInfoData pbuf; + char csave; if (numPFormats > 1) pformat = pformats[i]; @@ -1314,6 +1305,23 @@ exec_bind_message(StringInfo input_message) else pformat = 0; /* default = text */ + /* + * Rather than copying data around, we just set up a phony + * StringInfo pointing to the correct portion of the + * message buffer. We assume we can scribble on the + * message buffer so as to maintain the convention that + * StringInfos have a trailing null. This is grotty but + * is a big win when dealing with very large parameter + * strings. + */ + pbuf.data = (char *) pvalue; + pbuf.maxlen = plength + 1; + pbuf.len = plength; + pbuf.cursor = 0; + + csave = pbuf.data[plength]; + pbuf.data[plength] = '\0'; + if (pformat == 0) { Oid typInput; @@ -1322,11 +1330,8 @@ exec_bind_message(StringInfo input_message) getTypeInputInfo(ptype, &typInput, &typElem); /* - * Since stringinfo.c keeps a trailing null in - * place even for binary data, the contents of - * pbuf are a valid C string. We have to do - * encoding conversion before calling the typinput - * routine, though. + * We have to do encoding conversion before calling + * the typinput routine. */ pstring = (char *) pg_client_to_server((unsigned char *) pbuf.data, @@ -1362,6 +1367,9 @@ exec_bind_message(StringInfo input_message) { elog(ERROR, "Invalid format code %d", pformat); } + + /* Restore message buffer contents */ + pbuf.data[plength] = csave; } } @@ -2524,7 +2532,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.342 $ $Date: 2003/05/09 18:08:48 $\n"); + puts("$Revision: 1.343 $ $Date: 2003/05/12 16:48:17 $\n"); } /* -- 2.11.0