We have put up a new version of our extensions to the libpq api, here:


Four functions are getting dropped and will be replaced with a generic
version taking a va_list. Also, in some functions result format is
being moved to the end in order to be more compatible with existing

These functions are getting dropped:
PQexecParamsf (conn, resfmt, query, ...)
PQexecPreparedf(conn, resfmt, stmt, typespec, ...)

PQsendQueryParamsf(conn, resfmt, query, ...)
PQsendQueryPreparedf(conn, resfmt, stmt, typespec, ...)

The goal of the 'f' functions was to be able to execute a
parameterized query in one line. They had some downsides:
*) four functions added to API that did essentially the same thing
*) awkward to wrap, doesn't take a va_list (most large projects will
wrap PQ functions for error handling, etc)
*) prevents some low hanging efficiency fruit, by not allowing the
PGparam to be reused
*) taking the above, didn't meet the main goal (easiness).

In the end, they were not useful enough to justify their inclusion
into the api (we determined this from practical use).

And 'PQputvf' is being added;
int PQputvf(
PGparam *param,
char *stmtBuf, /* If not NULL, replaces %int4 with $1 syntax */
size_t stmtBufLen, /* If stmtbuf is too small, this errors out */
const char *spec, /* specifier string, with ir without SQL */
va_list ap);

This function, while low level, is designed to be used with high level
wrappers since it takes a va_list...after some reflection, we thought
it better to provide the basic tools for writing high level wrappers
rather than trying to make them all. Consider the following user-land
wrapper...connection and error handling can be handled to the
requirements of the application, and the query can be executed with
the method of choice (exec/send). PQputvf stacks the param object
from arguments passed through the va_list and optionally rewrites
(%int4->$1) the query passed into 'buf' which can be NULL.

/* User application wrapper */
PGresult *myexec(PGconn *conn, const char *cmdSpec, ...)
int n;
PGresult *res;
va_list ap;
static char stmt[8192]; /* app specific buffer size */
static PQparam *param = NULL; /* param reused */

if(!param) param = PQparamCreate(conn);

va_start(ap, stmt);
n = PQputvf(param, stmt, sizeof(stmt), cmdSpec, ap);

/* put failed... (error is in param object) */
if(!n) return NULL;

/* always return binary */
res = PQparamExec(conn, param, stmt, 1);
return res;

/* usage, puts two int4 and executes "SELECT $1 + $2" */
PGresult *res = myexec(conn, "SELECT %int4 + %int4", 1234, 5678);

In our applications, we often push error handling and connection
management into a wrapper function like the above...to do this
properly required a va_list style put function. The f versions were
too abstracted to do these kinds of things.

Merlin & Andrew

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppgsql-hackers @
postedJan 11, '08 at 6:48p
activeJan 11, '08 at 6:48p

1 user in discussion

Merlin Moncure: 1 post



site design / logo © 2022 Grokbase