Attached are some new functions that extend the libpq api to make
calling the parameterized interfaces easier, especially when making
binary calls. IMO, this fills one of the two big missing parts of the
libpq api when making binary database calls, the other being client
side handling of complex structures (arrays, etc).
The code covers two major areas of functionality and isolated for
separate inclusion:
* PGparam (param.c)
* get/set functions for the pgresult (result_ext.c)
We are happy with both pieces but they can be adopted separately or not at all.
The attached code is basically a cleaned up version of wrappers put in
place in our own applications, plus a functional test. The major
ideas were:
* introduce a new opaque structure, PGparam, that handles some of the
more difficult aspects of memory management associated with binary
calls.
* remove the requirement of client side code having to do byte swapping
* make binary calls as efficient as possible, with a minimal amount of
memory allocations
* introduce, as much as possible, no additional portability issues or
additional dependencies to the libpq api.
Here are the interesting and/or possibly controversial pieces:
* For portability purposes, we had the 64 bit integer put function
take a pointer where the other putters take value types. We couldn't
think of any other way to do it because there is not 64 bit portable
integer type in libpq.
* The synchronous execution functions (for example PQparamExec), takes
a pointer to a result and return error status, which is _not_ how the
other flavors of Exec operate, but is very convenient however. If you
pass in NULL the result is discarded for you. We are stuck on this
approach, but we like it.
* The getters check the returned type oid to make sure it is sane.
For this reason, we have to include catalog/pg_type.h and postgres.h
to get to the OID defines (these are not exposed to the interface
however). I don't see a reason why this is not ok.
The 64 bit integer is handled as a pointer in the get/set functions
because as far as we can tell there is no 64 bit integer type we can
count on without introducing compatibility issues.
We considered putting the PGparam struct into the PGconn structure.
In this case, a PGconn pointer would be passed to the PQparamXXX
functions instead of a PGparam, and would lazy allocate the structure
and free it on PQfinish. We are curious for opinions on this.
Writing credits to myself and Andrew Chernow. If this proposal is
accepted, we will write all the documentation and make suitable
changes necessary for inclusion, presumably for the 8.4 release. To
compile the changes see the attached makefile.
What we would really like is to use the backend input and output
functions for data types, rather than reimplementing this within the
client ... ie pqformat.c and similar files. For this reason, we did
not re-implement get/put functions for the geometric types (we thought
about it), etc. Merging the client and the server marshaling may
require some abstraction of the server so formatting functions can be
called from the client api.
Hopefully this will open up the binary interfaces to more developers.
For certain types of queries, binary calls can be a huge win in terms
of efficiency.
merlin