Re: PGparam proposal

From: Andrew Chernow <ac(at)esilo(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org, Merlin Moncure <mmoncure(at)gmail(dot)com>
Subject: Re: PGparam proposal
Date: 2007-12-11 15:31:46
Message-ID: 475EAD62.305@esilo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

For starters, if binary results is a feature you wish you could uninvent
then we are probably dead in the water for that reason. This goes to
the core of our concept. If there is no desire to synch client & server
in regards to type handling, than this a waste of time. I think all of
this would make libpq more powerful. With that said, my follow up:

> I think a printf-style API is fundamentally a bad idea in this
> context. printf only works well when the set of concepts (datatypes,
> format specifiers, etc) is small and fixed;

As of now, including numbers and alpha chars, there are 62 classes of
which we used 11 (a class is the first char). That leaves 51 classes
with 62 types per class. Where I would agree with you, is that over
time things can become cryptic.

There are only several ways to do this.

1. Use Oids - doesn't work because they are not publically exposed by libpq.

2. Create a function for each type. This idea was rejected because it
bloated the API (I'll buy this).

3. Type aliasing schema - naturally, printf-style comes to mind but may
become cryptic.

I should mention that we were only trying to support built-in pgtypes in
libpq. If you are looking to support all external types, then we
propose the below:

For #3, maybe it would be better to abandon %c or %cc type encoding and
move into something more verbose. We could just spell out the type:
%int4, %point, etc... Maybe for built-in types you could prepend 'pg':
%pgint4, %pgpoint. This opens up the namespace and removes scalability
and cryptic issues.

Expanding on %pgint4 idea, 3rd party types can supply their own %typname
handlers (a more moduler approach). You can install them at runtime,
PQinstallTypeHandler(typname, etc..), or something like that. When a
3rd party %typname is encountered, the appropriate handler would be
used. Standard pgtypes would be installed by default.

PQinstallTypeHandler(... "gisbox2d" ...);
PQputf(... "%gisbox2d %pgpolygon %pgint4" ...);
//PQgetf would use the same %typname

The only thing libpq should support by default, is the built-in pgtypes.
A handler can expand on this.

> I find the idea of embedding state like that into the PGconn to be
> pretty horrid, as well. It makes the design non-reentrant
>
> You can't just randomly change the behavior of existing API functions.

Okay. We initially had the PGparam as a public opaque, but changed it.
We will stop piggy backing off the existing parameterized functions.
Instead, we will supply a PGparam exec/send functions.

typedef struct pg_param PGparam;//opaque

param = PQparamCreate(conn);
PQputf(param, "%pgint4 %pgtimestamptz", 62, &tstz);
res = PQparamExec(conn, param, "command", resfmt);
//PQparamExec will always PQparamClear(param), whether it failed or not
//That means after an exec/send, the param object is ready for puts
PQparamFinish(param); // free it

// This causes the below sequence of function calls:
// PQparamCreate, PQputf, PQexecParams("... VALUES ($1)"), PQparamFinish
res = PQparamExecf(conn, resfmt, "INSERT INTO t VALUES (%pgint)", 62);

> * the 8.2-to-8.3 change in the width of type money

We have code comments throughout the patches, as well as documented in
the release notes. At this point, we solved getf by checking
PGgetlength. If its 4, read4 otherwise read8. For putf, we would have
to check the server version.

> * the likely future change to type timestamptz to store original
> timezone explicitly

We would have to change how timestamptz handles the binary format from
that version forward, looks like a switch on sversion for back+forwards
compatibility.

> * the likely future change to type text to store encoding/collation
> info explicitly

Would the server do text conversion and then pass the converted text
back to the client? Or, would it choose a common encoding like UTF-8
and return the text with encoding and let the client convert. How does
this affect text format?

In the end, some of these changes would change the text format right?
That would push these changes into the API users lap, to parse and fuss
with. I just think it is cleaner to synch the binary and/or text
formats with the server. If you are looking for ways to change the
binary/text format of types w/o having to make the most recent clients
aware of this, then I think we have lost this battle.

Another solution is revamping utils/adt so that it is a shared API for
client & server. If you upgrade a client, you would automatically get
the latest formatting functions. Just like libpq checks protocol
version in several places, conn->sversion would have to be checked, or
maybe have a typefmt_api_version.

andrew & merlin

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Simon Riggs 2007-12-11 15:35:33 Re: WORM and Read Only Tables (v0.1)
Previous Message Simon Riggs 2007-12-11 15:31:36 Re: WORM and Read Only Tables (v0.1)