Re: PGparam proposal - Mailing list pgsql-hackers

From Andrew Chernow
Subject Re: PGparam proposal
Date
Msg-id 475ED265.8070009@esilo.com
Whole thread Raw
In response to Re: PGparam proposal  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: PGparam proposal  (Andrew Chernow <ac@esilo.com>)
List pgsql-hackers
>library users would have no idea whether> the values they provide are being sent as text or binary.

The putf interface currently abstracts how it actually sends it. 
Although, you do put a C type rather than a string.  There is a putstr 
"%pqtypstr", which puts the string representation of a type.
> providing an easier-to-use> API for PQexecParams and friends, and what parts are actually> interested in binary data
transmission(and why)
 

There are two things happening here and two things we are trying to solve:

1. putf and PGparam - simpler interface for executing queries using 
parameterized functions.

2. getf - doesn't use PGparam at all.  You pass it a PGresult.  The goal 
of this is to translate either text or binary results into a uniform C 
type or structure.  For instance, we expose the below structure for inet.

/* This struct works with CIDR as well. */
typedef struct
{  /* convenience, value the same as first 2 bytes of sa_buf */  unsigned short sa_family;
  /* mask, ie. /24 */  int mask;  int is_cidr;
  /* Cast to: sockaddr, sockaddr_in, sockaddr_in6, sockaddr_stroage */  int sa_len;  char sa_buf[128]; /* avoid
referencingsockaddr structs */
 
} PGinet;

// "res" could be text or binary results, but PGinet remains the same.
PGinet inet;
PGgetf(res, tup_num, "%pginet", field_num &inet);
connect(sock,  (const struct sockaddr *)inet.sa_buf,  (socklen_t)inet.sa_len);

The above is simpler than examining "10.0.0.1/32" and converting it to a 
struct sockaddr.  The same struct is used when putting a type as a "C 
type" rather than as a string.  You can use getf without ever using 
putf+PGparam, and vise-versa.
> your proposal completely glossed over the> issue of exactly what data structure would be exposed to clients for>
anythingmore complex than an integer
 

Complex types require a receiving structure on the client side, thus the 
types we added to libpq-fe.h: PGinet, PGpolygon, PGarray, PGtimestamp, 
etc...  But keep in mind that these structs are the result of libpq 
extracting the data from text/binary formats and assigning data to 
struct members.  It does not expose raw format, the API user can already 
get that via PQgetvalue().
> If we could have libpq insulate client apps from these kinds> of changes, that would be one thing;

This is the goal of getf.  The API user interfaces through PGinet, not 
through the output of PQgetvalue().  We propose that its libpq's job 
internally to handle changes to text or binary formats and expose 
consistent types/structures.
> type NUMERIC (say, as a bignum integer plus> exponent instead of the current BCD-ish format)

This is what we want to hide inside libpq's getf.  Just expose a 
PGnumeric that has been translated into c types.  We never expose the 
wire format, only the C translated version of it.
> without any reliance on binary data transmission whatsoever.

Yes this is possible, but at a performance & ease-of-use cost.  Our 
performance tests didn't show much gain with strings or ints, but 
complex types were 10 times faster (putting/getting arrays, polygons, 
paths, etc...).  So, the trade-off is a little more maintainence 
overhead on libpq.

BTW, previously we mentioned a 3rd party handler api concept.  This is 
not needed to get libpq up and going with built-in types (which is all 
we feel it should be responsible for).  the handler API can always be 
added later w/o changing existing functions ... have to add a couple though.

andrew & merlin




pgsql-hackers by date:

Previous
From: Peter Eisentraut
Date:
Subject: Re: archive_command failures report confusing exit status
Next
From: Guillaume Lelarge
Date:
Subject: psql \dFp's behavior