proposed libpq type system changes 0.9 - Mailing list pgsql-hackers

From Merlin Moncure
Subject proposed libpq type system changes 0.9
Date
Msg-id b42b73150801111048i3858f868lba190c271415e9be@mail.gmail.com
Whole thread Raw
List pgsql-hackers
We have put up a new version of our extensions to the libpq api, here:

http://www.esilo.com/projects/postgresql/libpq/typesys-beta-0.9.tar.gz

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
functions.

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,  /*
Ifstmtbuf 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); va_end(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
eSilo


pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: [BUGS] BUG #3852: Could not create complex aggregate
Next
From: Gavin Sherry
Date:
Subject: Re: Dynamic Partitioning using Segment Visibility Maps