Re: libpq type system 0.9a - Mailing list pgsql-patches

From Andrew Chernow
Subject Re: libpq type system 0.9a
Date
Msg-id 47CF3709.7030901@esilo.com
Whole thread Raw
In response to Re: libpq type system 0.9a  ("Merlin Moncure" <mmoncure@gmail.com>)
List pgsql-patches
Merlin Moncure wrote:
> On Wed, Mar 5, 2008 at 5:47 PM, Florian G. Pflug <fgp@phlo.org> wrote:
>> Merlin Moncure wrote:
>>  > Yesterday, we notified -hackers of the latest version of the libpq
>>  > type system.  Just to be sure the right people are getting notified,
>>  > we are posting the latest patch here as well.  Would love to get some
>>  > feedback on this.
>>  Sorry if this has been discussed before, but why is it necessary
>>  to specify the type when calling PQgetf on a result? It seems that this
>>  formatting string *always* has to match the type list of your select
>>  statement, no?
>
> yes...it always has to match.  the format string requirements could in
> theory be relaxed (for 'get') but this would break symmetry with 'put'
> and you would lose a sanity check...getf like scanf writes directly
> into application memory so the double-specifying (directly in the
> format string and indirectly in the query) isn't necessarily a bad
> thing.  imagine if your application was 'select * from table' and one
> of the field types changed...disaster.
>
> merlin
>
>

A few other reasons....

 >>why is it necessary to specify the type when calling PQgetf on a result

Unlike PQgetvalue, all values returned by PQgetf are either native C types or
structures ... not C strings.  When you call getf you must tell it what types to
read out of the result object.  Like scanf, they must be the correctly sized
data types.

PGdate date;
int i4;
PQgetf(result, tup_num, "%date %int4", 0, &date, 1, &i4);

Specifying anything other than a %date or %int4 in the above example is a
programming error.  You would be asking to fetch a value of the wrong type.
Without the formatting string, libpq would have to va_arg(ASSUME_T) your value.

// no specifier
int i;
PQgetf(result, tup, field, &i);

In the above, libpq would have to use PQftype to determine what the native C
type is of your variable argument.  If PQftype returned INT8OID, you begin to
clobber your application's memory space ... va_arg(ap, long long) on a 32-bit
value.  This problem is solved by telling libpq what data type you want from a
field.

Also, the libpq type system enforces strict type checking when performing getf
calls.  This protects from mis-matches "programming errors" on types:

For example:

-- create table t (a int8);
PQresult *result = PQexec(conn, "SELECT a FROM t");
char *val = PQgetvalue(result, ...);
int a = atoi(val); // assumed its an int4

In the above example, the libpq user thinks the 'a' column of the 't' table is
an int4 when in fact its an int8.  The above may work most of the time but will
eventually truncate the value and nip you in the butt.  With PQgetf, you would
get an error saying the server returned an int8 and you are asking for an int4.
  Thus, the programming bug would be squashed immediately.

Also, user-defined types are not known to libpq so PQftype would not really
work.  They could if the libpq type system referenced data types by OID, but
this is not portable to other servers.  It is more portable to use the type
name.  For example, a company with 15 postgresql servers that use the same
collection of company-specific user-defined data types.  The type names would be
the same across the 15 servers but there is no guarentee the OIDs would be.

Composites and arrays caused a few issues as well.

We also tried to provide as much protection as possible ... in the spirit of the
backend.

--
Andrew Chernow
eSilo, LLC
every bit counts
http://www.esilo.com/

pgsql-patches by date:

Previous
From: "Merlin Moncure"
Date:
Subject: Re: libpq type system 0.9a
Next
From: Robert Lor
Date:
Subject: Re: DTrace probe patch for OS X Leopard