Thread: Re: [PATCHES] libpq type system 0.9a

Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
I know there has been lots of versions and technical feedback related to
this proposed feature.  However, I have talked to Tom and neither of us
see sufficient user request for this capability to add this code into
the core server.  I recommend you place it on pgfoundry and see if you
can get a sufficient user-base there.  If you need something exposed by
libpq that is not there already, please let us know.

One interesting idea would be if ecpg could use this functionality in
place of its own type-specific functions --- if that were the case, we
could reconsider adding this to core because it would be required by
ecpg.

Sorry for the bad news.  I think we all hoped that enough interest would
be generated for this to be accepted.

---------------------------------------------------------------------------

Andrew Chernow wrote:
> Andrew Chernow wrote:
> > Joe Conway wrote:
> >> Alvaro Herrera wrote:
> >>> Merlin Moncure escribi?:
> >>>> 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.
> >>>
> >>> I had a look at this patch some days ago, and the first question in my
> >>> mind was: why is it explicitely on libpq?  Why not have it as a separate
> >>> library (say libpqtypes)?  That way, applications not using it would not
> >>> need to link to it.  Applications interested in using it would just need
> >>> to add another -l switch to their link line.
> >>>
> >>
> >> +1
> >>
> >> Joe
> >>
> >>
> > 
> > What is gained by having a separate library?  Our changes don't bloat 
> > the library size so I'm curious what the benefits are to not linking 
> > with it?  If someone doesn't want to use, they don't have to.  Similar 
> > to the backend, there is stuff in there I personally don't use (like geo 
> > types), but I'm not sure that justifies a link option -lgeotypes.
> > 
> > The changes we made are closely tied to libpq's functionality.  Adding 
> > PQputf to simplify the parameterized API, adding PQgetf to compliment 
> > PQgetvalue and added the ability to register user-defined type handlers 
> > (used by putf and getf). PQgetf makes extensive use of PGresult's 
> > internal API, especially for arrays and composites.  Breaking this into 
> > a separate library would require an external library to access the 
> > private internals of libpq.
> > 
> > Personally, I am not really in favor of this idea because it breaks 
> > apart code that is very related.  Although, it is doable.
> > 
> 
> I poked around to see how this would work.  There are some problems.
> 
> 1. members were added to PGconn so connection-based type handler information can 
> be copied to PGparam and PGresult objects.
> 
> 2. members were added to PGresult, referenced in #1.  To properly getf values, 
> the connection-based type handler information must be available to PGresult. 
> Otherwise, PQgetf would require an additional argument, a PGconn, which may have 
> been closed already.
> 
> 3. PQfinish calls pqClearTypeHandler to free type info assigned to the PGconn.
> 
> 4. PQclear also calls pqClearTypeHandlers
> 
> It would also remove some of the simplicity.  Creating a connection would no 
> longer initialized type info, which gets copied to PGparam and PGresult.  Type 
> info includes a list of built-in handlers and backend config, like 
> integer_datetimes, server-version, etc...  That means an additional function 
> must be called after PQconnectdb.  But where would the type info be stored?  It 
> wouldn't exist in PGconn anymore?  Also, this would require double frees.  You 
> have to free the result as well as the type info since they are no longer one 
> object.  Same holds true for a pgconn.
> 
> There is something elegant about not requiring additional API calls to perform a 
> putf or getf.  It'll just work if you want to use it.  You can use PQgetf on a 
> result returned by PQexec and you can use PQputf, PQparamExec followed by 
> PQgetvalue.
> 
> -- 
> Andrew Chernow
> eSilo, LLC
> every bit counts
> http://www.esilo.com/
> 
> -- 
> Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-patches

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Bruce Momjian wrote:
> I know there has been lots of versions and technical feedback related to
> this proposed feature.  However, I have talked to Tom and neither of us
> see sufficient user request for this capability to add this code into
> the core server.  I recommend you place it on pgfoundry and see if you
> can get a sufficient user-base there.  If you need something exposed by
> libpq that is not there already, please let us know.
>
> One interesting idea would be if ecpg could use this functionality in
> place of its own type-specific functions --- if that were the case, we
> could reconsider adding this to core because it would be required by
> ecpg.
>
> Sorry for the bad news.  I think we all hoped that enough interest would
> be generated for this to be accepted.
>
>   

I think you should conduct a wider survey before you make that decision. 
In particular, I'd like to hear from driver writers like Greg Sabino 
Mullane and Jeff Davis, as well as regular libpq users.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Andrew Dunstan wrote:
> 
> 
> Bruce Momjian wrote:
> > I know there has been lots of versions and technical feedback related to
> > this proposed feature.  However, I have talked to Tom and neither of us
> > see sufficient user request for this capability to add this code into
> > the core server.  I recommend you place it on pgfoundry and see if you
> > can get a sufficient user-base there.  If you need something exposed by
> > libpq that is not there already, please let us know.
> >
> > One interesting idea would be if ecpg could use this functionality in
> > place of its own type-specific functions --- if that were the case, we
> > could reconsider adding this to core because it would be required by
> > ecpg.
> >
> > Sorry for the bad news.  I think we all hoped that enough interest would
> > be generated for this to be accepted.
> >
> >   
> 
> I think you should conduct a wider survey before you make that decision. 
> In particular, I'd like to hear from driver writers like Greg Sabino 
> Mullane and Jeff Davis, as well as regular libpq users.

Well, they are welcome to chime in but the patch has been out the for a
while and they haven't spoken yet.  We have to base our decisions on
people who do chime in.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> I think you should conduct a wider survey before you make that decision. 
> In particular, I'd like to hear from driver writers like Greg Sabino 
> Mullane and Jeff Davis, as well as regular libpq users.

Well, the survey's already been taken, pretty much: there's been just
about no positive feedback in all the time that this proposal's been
discussed.  I haven't noticed anyone except Andrew and Merlin saying
that they wanted this or would use it.

Currently there's about 400K of C source code in libpq.  The patch as-is
adds more than 100K, and it would surely get larger if we actively
pursued this line of development.  (For one thing, the density of
comments in the submitted patch is well below what I'd find acceptable;
by the time it was commented to a level comparable to the existing libpq
code, it'd be a lot more than 100K.)  That's a pretty big increment for
a facility that it appears would be used only by a small minority of
users.  I think that at minimum we'd have to insist on it being
refactored as a separate library, and then the case for it being in core
rather than on pgfoundry seems kinda weak.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
"Greg Sabino Mullane"
Date:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160


> I think you should conduct a wider survey before you make that decision.
> In particular, I'd like to hear from driver writers like Greg Sabino
> Mullane and Jeff Davis, as well as regular libpq users.

I can state that there would be almost zero chance this would ever be
used by DBD::Pg, as it would seem to add overhead with no additional
functionality over what we already have. Unless I'm misreading what it
does and someone can make the case why I should use it.

- --
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200804081349
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8

-----BEGIN PGP SIGNATURE-----

iEYEAREDAAYFAkf7sGkACgkQvJuQZxSWSsi8FgCgkGUGh2ieOAtvNlXX6orjO8oc
0bIAoPF7ojxM1c38kw7+L4Ar7FRZmdrn
=U2BM
-----END PGP SIGNATURE-----




Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 12:59 PM, Bruce Momjian <bruce@momjian.us> wrote:
>  Sorry for the bad news.  I think we all hoped that enough interest would
>  be generated for this to be accepted.

I think that's really unfortunate.  Personally, I think that anyone
who did any amount of C coding against libpq at all would never have
any reason to code in the traditional fashion (PQexec, etc).  Anyone
who would claim otherwise IMO does not code vs. libpq or does not
completely understand what we are trying to do.

In particular, I think that the decision to so quickly shut the door
on the ability to support arrays and composites in binary on the
client side.  Contrary to what is stated there have been considerable
requests for this on the various lists.

I am dismayed that throughout this process there has been no
substantive discussion (save for Tom) on what we were trying to do,
only to be informed about rejection based on an internal discussion.
What issues were raised were opaque and sans reasoning or
justification of how that would improve the patch or the functionality
(move to separate library for example -- how would this improve
things?).  Our follow ups were not followed up.  We would have been
delighted to take suggestions.

I attributed the silence to general lack of interest and anticipated
this response.  However I think that those involved should step back
and take a look at what they are walking away from here.

merlin


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 1:51 PM, Greg Sabino Mullane <greg@turnstep.com> wrote:
>  > I think you should conduct a wider survey before you make that decision.
>  > In particular, I'd like to hear from driver writers like Greg Sabino
>  > Mullane and Jeff Davis, as well as regular libpq users.
>
>  I can state that there would be almost zero chance this would ever be
>  used by DBD::Pg, as it would seem to add overhead with no additional
>  functionality over what we already have. Unless I'm misreading what it
>  does and someone can make the case why I should use it.

does DBD::pg move arrays in and out of the server? do you parse them
yourself?  if you answer yes to either question you should take a
second look.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Alvaro Herrera
Date:
Merlin Moncure escribió:

> I attributed the silence to general lack of interest and anticipated
> this response.  However I think that those involved should step back
> and take a look at what they are walking away from here.

I suggest you take a survey on a more widely read forum, like
pgsql-general or even pgsql-announce.  Keep in mind that many of the
most active people in pgsql-hackers is not actually writing libpq
programs (I know I am not.)

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Greg Sabino Mullane wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: RIPEMD160
> 
> 
>> I think you should conduct a wider survey before you make that decision.
>> In particular, I'd like to hear from driver writers like Greg Sabino
>> Mullane and Jeff Davis, as well as regular libpq users.
> 
> I can state that there would be almost zero chance this would ever be
> used by DBD::Pg, as it would seem to add overhead with no additional
> functionality over what we already have. Unless I'm misreading what it
> does and someone can make the case why I should use it.
> 
> - --
> Greg Sabino Mullane greg@turnstep.com
> PGP Key: 0x14964AC8 200804081349
> http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
> 
> -----BEGIN PGP SIGNATURE-----
> 
> iEYEAREDAAYFAkf7sGkACgkQvJuQZxSWSsi8FgCgkGUGh2ieOAtvNlXX6orjO8oc
> 0bIAoPF7ojxM1c38kw7+L4Ar7FRZmdrn
> =U2BM
> -----END PGP SIGNATURE-----
> 
> 
> 

This idea is for the libpq user, although driver writers could find it 
handy as well.  Really, anyone who uses libpq directly.  That's the real 
audience.

I don't know what overhead greg is referring to.  How is DBD::pg 
handling arrays of composites?  Are you parsing text output?  Wouldn't 
it be less overhead to avoid text parsing and transmit binary data?
>>no additional functionality over what we already have
What about user-defined type registration, sub-classing user or built-in  type handlers, handling of all data types in
binary. There is a lot 
 
of new functionality added by this patch to the existing libpq.

I don't think the appropriate audience got a look at this, maybe posting 
on general or libpq lists.  From my perspective as a long time C coder, 
this made my application code cleaner, easier to maintain and faster in 
many cases.  It removed a lot of code that is now handled by this patch.

I am not sure why Tom is worried about source code size, normally the 
concern is linked size.  Code comments were never finished, as the 
library was changing so much to meet some requests.  Instead, we focused 
on providing API documentation and the overall idea (over 1000 lines). 
This changed much less than the implementation.

I think the real issue is simply the wrong audience.  Its the coder in 
the field making heavy use of libpq that would find this appealing, not 
really backend hackers.

It is disappointing because I was excited to here ideas from others, 
which never happened.

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
"Merlin Moncure" <mmoncure@gmail.com> writes:
> On Tue, Apr 8, 2008 at 1:51 PM, Greg Sabino Mullane <greg@turnstep.com> wrote:
>> I can state that there would be almost zero chance this would ever be
>> used by DBD::Pg, as it would seem to add overhead with no additional
>> functionality over what we already have. Unless I'm misreading what it
>> does and someone can make the case why I should use it.

> does DBD::pg move arrays in and out of the server? do you parse them
> yourself?  if you answer yes to either question you should take a
> second look.

Better support for arrays and composites is certainly something that
people might want, but the problem with this design is that it forces
them to buy into a number of other decisions that they don't necessarily
want.

I could see adding four functions to libpq that create and parse
the textual representations of arrays and records.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
"Joshua D. Drake"
Date:
On Tue, 08 Apr 2008 14:34:51 -0400
Andrew Chernow <ac@esilo.com> wrote:

> I am not sure why Tom is worried about source code size, normally the 
> concern is linked size.  Code comments were never finished, as the 

Every byte added is a byte maintained (or not).

Joshua D. Drake
-- 
The PostgreSQL Company since 1997: http://www.commandprompt.com/ 
PostgreSQL Community Conference: http://www.postgresqlconference.org/
United States PostgreSQL Association: http://www.postgresql.us/
Donate to the PostgreSQL Project: http://www.postgresql.org/about/donate




Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Better support for arrays and composites is certainly something that
> people might want, but the problem with this design is that it forces
> them to buy into a number of other decisions that they don't necessarily
> want.
>
> I could see adding four functions to libpq that create and parse
> the textual representations of arrays and records.
>
>             
>   

Well, that was the part that interested me, so let me now speak up in 
favor of better array/record support in libpq.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 2:49 PM, Andrew Dunstan <andrew@dunslane.net> wrote:
> > Better support for arrays and composites is certainly something that
> > people might want, but the problem with this design is that it forces
> > them to buy into a number of other decisions that they don't necessarily
> > want.
> >
> > I could see adding four functions to libpq that create and parse
> > the textual representations of arrays and records.

>  Well, that was the part that interested me, so let me now speak up in favor
> of better array/record support in libpq.

by the way, we handle both text and binary array results...and getting
things in binary is _much_ faster.  not to mention text is
destructive.  for example, composite types in text do not return the
oid of composite member fields.

with our patch, since you can 'pop' a result of a returned composite,
or array of composite, you have access to all that information in the
result api.  so I would argue that allowing text only parsing only
recovers a portion of the provided functionality.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> 
> Better support for arrays and composites is certainly something that
> people might want, but the problem with this design is that it forces
> them to buy into a number of other decisions that they don't necessarily
> want.
> 
> 
>             regards, tom lane
> 


What decisions are we forcing upon the libpq user?

Well, most of the functionality is handled by about 3 functions (putf, 
getf, and paramexec).  The difference is, our patch is not limited to 
only handling text arrays and composites.  It can do it all, which we 
thought would of been a requirement to get approved.

There is a performance boost to handling arrays and composites in 
binary, which we use a lot because there are no stored procedures (note, 
not trying to take a jab about stored procedures, just giving an example 
of how we use and abuse arrays and composites).

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
"Joshua D. Drake" <jd@commandprompt.com> writes:
> On Tue, 08 Apr 2008 14:34:51 -0400
> Andrew Chernow <ac@esilo.com> wrote:
>> I am not sure why Tom is worried about source code size, normally the 
>> concern is linked size.  Code comments were never finished, as the 

> Every byte added is a byte maintained (or not).

Actually I was thinking more about disk footprint.  Andrew's comment is
correct if you work with statically linked code where the compiler pulls
out only the needed .o files from a .a library, but that's pretty out of
fashion these days.  Most people are dealing with a monolithic libpq.so
and might carp a bit if it gets 25% or 50% bigger for stuff that doesn't
interest them.

Perhaps I'm overly sensitive to this because I'm tuned into Red Hat's
constant struggles to fit a Linux distribution onto a reasonable number
of CDs ...
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Merlin Moncure wrote:
> I attributed the silence to general lack of interest and anticipated
> this response.  However I think that those involved should step back
> and take a look at what they are walking away from here.

Agreed.  There are technical issues, but they can be addressed with
work. The more fundamental issue is whether we want this functionality
in libpq vs pgfoundry, and with a lack of interest, as you stated,
having it on pgfoundry seems the only logical direction.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Tom Lane wrote:
> "Joshua D. Drake" <jd@commandprompt.com> writes:
> > On Tue, 08 Apr 2008 14:34:51 -0400
> > Andrew Chernow <ac@esilo.com> wrote:
> >> I am not sure why Tom is worried about source code size, normally the 
> >> concern is linked size.  Code comments were never finished, as the 
> 
> > Every byte added is a byte maintained (or not).
> 
> Actually I was thinking more about disk footprint.  Andrew's comment is
> correct if you work with statically linked code where the compiler pulls
> out only the needed .o files from a .a library, but that's pretty out of
> fashion these days.  Most people are dealing with a monolithic libpq.so
> and might carp a bit if it gets 25% or 50% bigger for stuff that doesn't
> interest them.
> 
> Perhaps I'm overly sensitive to this because I'm tuned into Red Hat's
> constant struggles to fit a Linux distribution onto a reasonable number
> of CDs ...

Also, if we add to libpq we have to document this new functionality.  It
doesn't make sense to add to the API unless there is a significant
number of people who will use it.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> Tom Lane wrote:
>> Better support for arrays and composites is certainly something that
>> people might want, but the problem with this design is that it forces
>> them to buy into a number of other decisions that they don't necessarily
>> want.

> What decisions are we forcing upon the libpq user?

Well, for starters, using binary format.  It is undeniable that that
creates more portability risks (cross-architecture and cross-PG-version
issues) than text format.  Not everyone wants to take those risks for
benefits that may not be meaningful for their apps.

The other forced decision is the whole PQputf/PQgetf notation, which
people may or may not find natural --- it still seems a pretty poor
choice to me for this specific problem.  PQputf, in the form where
you're generating a SQL command string along with some parameters,
isn't too unreasonable, but unless you've already bought into binary
parameter handling it's not gaining all that much either.  And
PQgetf is just weird.  The format of a PGresult is generally well
known by the app; trying to force it into the model of string
scanning is a poor fit.  For instance there's no mapping at all
for what to do with constant parts of the format string.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 3:10 PM, Bruce Momjian <bruce@momjian.us> wrote:
>  > Actually I was thinking more about disk footprint.  Andrew's comment is
>  > correct if you work with statically linked code where the compiler pulls
>  > out only the needed .o files from a .a library, but that's pretty out of
>  > fashion these days.  Most people are dealing with a monolithic libpq.so
>  > and might carp a bit if it gets 25% or 50% bigger for stuff that doesn't
>  > interest them.

on my box, the .so went from 118k to 175k. while this is significant
in percentage terms, I don't think redhat is going to complain about
57k (correct me if I'm wrong here).

>  Also, if we add to libpq we have to document this new functionality.  It
>  doesn't make sense to add to the API unless there is a significant
>  number of people who will use it.

We are prepared to write the formal documentation if necessary (and
whatever else, code comments and a proper regression test for
example).  I'll address the 'who will want to use it' in response to
Tom's mail.

merlin


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 3:22 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Andrew Chernow <ac@esilo.com> writes:
>  > Tom Lane wrote:
>  >> Better support for arrays and composites is certainly something that
>  >> people might want, but the problem with this design is that it forces
>  >> them to buy into a number of other decisions that they don't necessarily
>  >> want.

> > What decisions are we forcing upon the libpq user?
>
>  Well, for starters, using binary format.  It is undeniable that that
>  creates more portability risks (cross-architecture and cross-PG-version
>  issues) than text format.  Not everyone wants to take those risks for
>  benefits that may not be meaningful for their apps.

personally, I think these claims of portability are a bit
overblown...they are trivially checked by regressions tests.  the
version question is more interesting and solutions range from the easy
(force version match to access binary types) to the complex.

>  The other forced decision is the whole PQputf/PQgetf notation, which
>  people may or may not find natural --- it still seems a pretty poor
>  choice to me for this specific problem.  PQputf, in the form where
>  you're generating a SQL command string along with some parameters,
>  isn't too unreasonable, but unless you've already bought into binary
>  parameter handling it's not gaining all that much either.  And
>  PQgetf is just weird.  The format of a PGresult is generally well
>  known by the app; trying to force it into the model of string
>  scanning is a poor fit.  For instance there's no mapping at all
>  for what to do with constant parts of the format string.

We chose to do the PQgetf function that way as a compromise of many
different requirements (we went through several alternative
implementations before settling on the final one).  At minimum, you
have to supply at least _some_ type information because getf writes
into application memory, and aside from the obvious safety issues,
there are user defined types to consider.

Since you can register additional type into the handler system at
runtime (including 'automagic' discovery of composite types by name),
there has to be some way of directing the library to the proper
handler.  Since everything is driven by typename, it all comes down to
how you want to do this.  We like the varargs style since it provides
some symmetry with putf and feels 'right' in coding.

The only other approach to getf that meets all the requirements would
be like this:
PQgetf(result, tup_num, "date", 0, &date); // not varargs

where the typestring is fixed to one type...you could only pull out
one parameter at a time (no variable argument list). We considered
this carefully, and we opted for the submitted approach as the best
solution.  One other benefit to doing things this way is we get to
alter the 'format escape character, (%)', to # when lookup by name as
opposed to column position is desired.

The constant part of the format string in getf are ignored, they have
no meaning in that context.  Same with putf.  Although, there is
PQputvf which will take something like this: "select %int4 + %int4"
and turn it into "select $1 + $2".  In PQputvf, everything surrounding
the type modifier is still ignored.  So, the API is symmetrical in
terms of type string, except that for query execution there is an
extra stage where the query string is mapped.  What you find to be
weird here I think is rather elegant :-).

>>PQputf/PQgetf notation, which
>  people may or may not find natural --- it still seems a pretty poor
>  choice to me for this specific problem
We reference types by there name (can include schema as well).  There
is no better mnemonic than that ... is there?  For example, if I have
some funky type 'foo' defined on the server, what is more natural than
pulling that type with %foo (which can be optionally schema
qualified)?

By the way, we ended up with the current implementation based on your
concerns with previous attempts (using two letter format codes, or
exported static type handlers)...(we really like how things turned out
though...using schema qualified type names as the 'typespec' really
makes the libpq code look 'pretty'.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Martijn van Oosterhout
Date:
On Tue, Apr 08, 2008 at 02:34:51PM -0400, Andrew Chernow wrote:
> This idea is for the libpq user, although driver writers could find it
> handy as well.  Really, anyone who uses libpq directly.  That's the real
> audience.

Quite, I'm writing array parsing code right now and this would make my
life much easier too. However, my question is:

> I am not sure why Tom is worried about source code size, normally the
> concern is linked size.

How tight is the link to libpq? Could it exist as a seperate library:
libpqbin or something? Still in core, just only used by the people who
want it.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Please line up in a tree and maintain the heap invariant while
> boarding. Thank you for flying nlogn airlines.

Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Martijn van Oosterhout wrote:
-- Start of PGP signed section.
> On Tue, Apr 08, 2008 at 02:34:51PM -0400, Andrew Chernow wrote:
> > This idea is for the libpq user, although driver writers could find it 
> > handy as well.  Really, anyone who uses libpq directly.  That's the real 
> > audience.
> 
> Quite, I'm writing array parsing code right now and this would make my
> life much easier too. However, my question is:
> 
> > I am not sure why Tom is worried about source code size, normally the 
> > concern is linked size. 
> 
> How tight is the link to libpq? Could it exist as a seperate library:
> libpqbin or something? Still in core, just only used by the people who
> want it.

The idea of pgfoundry was that it would be an independent library and
could be used by people who need it.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Martijn van Oosterhout wrote:
> How tight is the link to libpq? Could it exist as a seperate library:
> libpqbin or something? Still in core, just only used by the people who
> want it.
> 

I gave this a lot of thought and I do think we could abstract this.  The 
idea is to complie it in or out.

Add a --with-typesys to configure, which could enable "#ifdef 
LIBPQ_ENABLE_TYPESYS" everywhere.  If you don't specify --with-typesys, 
the API calls would still be there but would return ENOSYS, assign an 
error string or something.  This preserves link capatability.

This would trim out the 50k everyone is worried about :)  I'm sure there 
are other ways to acocmplish this, but this one seems easiest and keeps 
it all centralized.  Just like --with-openssl, except that loads 
libcrypto.so.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> Martijn van Oosterhout wrote:
>> How tight is the link to libpq? Could it exist as a seperate library:
>> libpqbin or something? Still in core, just only used by the people who
>> want it.
>>
> 
> I gave this a lot of thought and I do think we could abstract this.  The 
> idea is to complie it in or out.
> 
> Add a --with-typesys to configure, which could enable "#ifdef 
> LIBPQ_ENABLE_TYPESYS" everywhere.  If you don't specify --with-typesys, 
> the API calls would still be there but would return ENOSYS, assign an 
> error string or something.  This preserves link capatability.
> 
> This would trim out the 50k everyone is worried about :)  I'm sure there 
> are other ways to acocmplish this, but this one seems easiest and keeps 
> it all centralized.  Just like --with-openssl, except that loads 
> libcrypto.so.
> 

Forgot to say: There is stuff in PGconn, PGresult, PQclear, PQfinish 
(maybe a couple other places).

A separate library would remove the ability to call PQexec followed by 
PQgetf because the result object is no longer aware of the typesys.  You 
would need the separate library to wrap the result object or something:

typesysResult = TypeSysGetResult(PQexec());

Or, you need to wrap the libpq API calls, typesysResult = TypeSysExec();.

Both are doable but not nearly as slick as: res = PQexec; PQgetf(res, 
..); PQclear(res);


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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
"Merlin Moncure" <mmoncure@gmail.com> writes:
>>> Actually I was thinking more about disk footprint.  Andrew's comment is
>>> correct if you work with statically linked code where the compiler pulls
>>> out only the needed .o files from a .a library, but that's pretty out of
>>> fashion these days.  Most people are dealing with a monolithic libpq.so
>>> and might carp a bit if it gets 25% or 50% bigger for stuff that doesn't
>>> interest them.

> on my box, the .so went from 118k to 175k. while this is significant
> in percentage terms, I don't think redhat is going to complain about
> 57k (correct me if I'm wrong here).

Yipes, 48% growth in the binary already?  That's much higher than
I'd expected from my quick source-code count, even with the scarcity of
comments.  What happens by the time the feature actually becomes mature?

Yes, I could see Red Hat complaining about that.  I'd rather have libpq
(as it currently stands) included in core RHEL, and "libpqtypes" as an
optional extra, than have a monolithic library get booted out to extras
altogether.  It could happen.  Don't think they don't see us as a
secondary objective ... mysql still has a lot more mindshare.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
>> I gave this a lot of thought and I do think we could abstract this.  The 
>> idea is to complie it in or out.

[shrug...] So the packagers will compile it out, and you're still hosed,
or at least any users who'd like to use it are.

> Forgot to say: There is stuff in PGconn, PGresult, PQclear, PQfinish 
> (maybe a couple other places).

I didn't see anything there that seemed that it *had* to be inside
libpq, and certainly not anything that couldn't be handled with a
small hook or two.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Alvaro Herrera
Date:
Bruce Momjian wrote:
> Martijn van Oosterhout wrote:

> > How tight is the link to libpq? Could it exist as a seperate library:
> > libpqbin or something? Still in core, just only used by the people who
> > want it.
> 
> The idea of pgfoundry was that it would be an independent library and
> could be used by people who need it.

I don't think phasing it out to pgfoundry is a good idea, because it has
some dependency on the OIDs of datatypes.  Besides, it is likely that it
could be used by ecpg instead of it having its own PGTYPES stuff.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> Andrew Chernow <ac@esilo.com> writes:
>>> I gave this a lot of thought and I do think we could abstract this.  The 
>>> idea is to complie it in or out.
> 
> [shrug...] So the packagers will compile it out, and you're still hosed,
> or at least any users who'd like to use it are.
> 
>> Forgot to say: There is stuff in PGconn, PGresult, PQclear, PQfinish 
>> (maybe a couple other places).
> 
> I didn't see anything there that seemed that it *had* to be inside
> libpq, and certainly not anything that couldn't be handled with a
> small hook or two.
> 
>             regards, tom lane
> 

How about using dlopen and dlsym?

Sseparate the library as many are suggesting.  But leave the functions, the 
tid-bits in PGconn, PGresult, etc... in there (2 or 3 typedefs would be needed 
but all data-type typedefs "PGtimestamp" can be removed).  You need something 
inside the PGconn and PGresult, even if just a function pointer that gets called 
if not NULL.

Yank pqtypes function bodies, and related helper functions, and replace them 
with something like below:

int PQputf(...)
{
#ifdef HAVE_DLOPEN  if(pqtypes->putf)    return pqtypes->putf(...);  return 1; /* failed, PGparam error = "not enabled"
*/
#else  return 1; /* failed, PGparam error = "cannot load dynamically" */
#endif
}

Then add a PQtypesEnable(bool), which would dlopen(libpqtypes) and dlsym the 10 
functions or so we need.  Any typedefs you need would be in libpqtypes.h rather 
than libpq-fe.h.  You could disable it as well, which would unload libpqtypes. 
The default would obviously be disabled.

The entire patch would be one small file with a couple 1 line changes to PGconn 
and PGresult.  This would remove all overhead, at least 95% of it.
>>couldn't be handled with a small hook or two.
Maybe, have not thought of that.  The problem, is that I am trying to make avoid 
having to keep track of two different APIs.  The goal is the libpq user is 
coding to the libpq API, not some other API like PGTypesExec.

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


Re: [PATCHES] libpq type system 0.9a

From
Alvaro Herrera
Date:
Andrew Chernow wrote:

> Forgot to say: There is stuff in PGconn, PGresult, PQclear, PQfinish  
> (maybe a couple other places).

Maybe there's a way we can have libpqtypes adding calls into some
hypothetical libpq hooks.  So libpqtypes registers its hooks in _init()
or some such, and it gets picked up automatically by any app that links
to it.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Alvaro Herrera wrote:
> Andrew Chernow wrote:
> 
>> Forgot to say: There is stuff in PGconn, PGresult, PQclear, PQfinish  
>> (maybe a couple other places).
> 
> Maybe there's a way we can have libpqtypes adding calls into some
> hypothetical libpq hooks.  So libpqtypes registers its hooks in _init()
> or some such, and it gets picked up automatically by any app that links
> to it.
> 

Kinda what my last suggestion was.  Some tid-bits need to be reside in libpq, 
but very little.  I was thinking PQtypesEnable(bool) which would dlopen 
libpqtypes and map all functions needed.  This would leave the function bodies 
of PQputf, PQgetf, PQparamExec, etc... as simple proxy functions to the 
dynamically loaded functions.  This removes any bloat that people don't like 
right now but still allows one to use libpq as the primary interface, rather 
than having to fiddle with libpq and some other API.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Andrew Chernow wrote:
> Alvaro Herrera wrote:
>> Andrew Chernow wrote:
>>
>>> Forgot to say: There is stuff in PGconn, PGresult, PQclear, 
>>> PQfinish  (maybe a couple other places).
>>
>> Maybe there's a way we can have libpqtypes adding calls into some
>> hypothetical libpq hooks.  So libpqtypes registers its hooks in _init()
>> or some such, and it gets picked up automatically by any app that links
>> to it.
>>
>
> Kinda what my last suggestion was.  Some tid-bits need to be reside in 
> libpq, but very little.  I was thinking PQtypesEnable(bool) which 
> would dlopen libpqtypes and map all functions needed.  This would 
> leave the function bodies of PQputf, PQgetf, PQparamExec, etc... as 
> simple proxy functions to the dynamically loaded functions.  This 
> removes any bloat that people don't like right now but still allows 
> one to use libpq as the primary interface, rather than having to 
> fiddle with libpq and some other API.

Please make sure that any scheme you have along these lines will work on 
Windows DLLs too.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Dunstan wrote:

> 
> Please make sure that any scheme you have along these lines will work on 
> Windows DLLs too.
> 
> 

Ofcourse: LoadLibrary(), GetProcAddress(), __declspec(dllexport).

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


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 6:09 PM, Alvaro Herrera
<alvherre@commandprompt.com> wrote:
> Andrew Chernow wrote:
>
>  > Forgot to say: There is stuff in PGconn, PGresult, PQclear, PQfinish
>  > (maybe a couple other places).
>
>  Maybe there's a way we can have libpqtypes adding calls into some
>  hypothetical libpq hooks.  So libpqtypes registers its hooks in _init()
>  or some such, and it gets picked up automatically by any app that links
>  to it.

I've been having some thoughts along those lines as well.  As
currently written there is a already a de facto 'init' as the various
static type handlers are assembled into the type handlers for the
built in types.

About 50% of the patch as written is libpq plumbing which extends the
API, defines the structures, and various things like that.  IMO, there
is very little point to abstracting that out into a separate library.
The 50% is the type handlers and various assorted conversion
functions.  This half will only increase as we introduce new types and
other conversions.  I think, if there is some reasonable case for
separation, it is here (the type handlers)...and I think this might
present a reasonable approach for dealing with version compatibility
issues.  One thought I had was that a 8.4 libpq would be able to load
the 8.3 types when dealing with a 8.3 server for example.  Maybe this
is a non-starter, but it's one case where splitting things out might
have some other advantages.

If this works the way I'm thinking about it, it would probably better
than a compile time flag...I don't think that satisfies anyway since
hardly anyone compiles their own libpq any more (presumably everyone
would just compile it in, making the check moot).  Anyone with an
appreciation for irony and a long memory will recall me griping about
the odbc driver compiling openssl in, because it required me to
package in a bunch of extra dlls on windows :-).

In terms of moving the code to pgfoundry, I think this is absolutely
the wrong thing to do, except in terms of deciding the patch
unsuitable for inclusion into core (or deferring that decision).
People that used it would naturally expect changes to happen in
concert with the server.  Better just to come to a consensus...in, or
out  :-)

merlin


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Alvaro Herrera <alvherre@commandprompt.com> writes:
> Bruce Momjian wrote:
>> The idea of pgfoundry was that it would be an independent library and
>> could be used by people who need it.

> I don't think phasing it out to pgfoundry is a good idea, because it has
> some dependency on the OIDs of datatypes.

Well, if you'll remind me of the last time we changed the OID of a
standard datatype, I'd put some credence in that argument.

> Besides, it is likely that it
> could be used by ecpg instead of it having its own PGTYPES stuff.

Yeah, Bruce and I were talking about that, but on reflection I'm not
sure that there's much potential commonality.  The thing that's most
problematic about ecpg is that it wants to offer client-side equivalents
of some server datatype-manipulation functions; and I don't actually see
much of any of that in the proposed patch.  All that's really here is
format conversion stuff, so there's no hope of unifying that code
unless this patch adopts ecpg's choices of client-side representation
(which I believe are mostly Informix legacy choices, so I'm not sure we
want that).
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> Kinda what my last suggestion was.  Some tid-bits need to be reside in libpq, 
> but very little.  I was thinking PQtypesEnable(bool) which would dlopen 
> libpqtypes and map all functions needed.  This would leave the function bodies 
> of PQputf, PQgetf, PQparamExec, etc... as simple proxy functions to the 
> dynamically loaded functions.  This removes any bloat that people don't like 
> right now but still allows one to use libpq as the primary interface, rather 
> than having to fiddle with libpq and some other API.

This is still 100% backwards.  My idea of a libpq hook is something that
could be used by libpgtypes *and other things*.  What you are proposing
is something where the entire API of the supposed add-on is hard-wired
into libpq.  That's just bad design, especially when the adequacy of
the proposed API is itself in question.

When I say I'd accept some hooks into libpq, I mean some hooks that
could be used by either libpgtypes or something that would like to do
something roughly similar but with a different API offered to clients.
The particular hook that you seem to mostly need is the ability to
allocate some private memory associated with a particular PGconn object,
and maybe also with individual PGresults, and then to be able to free
that at PQclear or PQfinish.  Try designing it like that.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> Andrew Chernow <ac@esilo.com> writes:
>> Kinda what my last suggestion was.  Some tid-bits need to be reside in libpq, 
>> but very little.  I was thinking PQtypesEnable(bool) which would dlopen 
>> libpqtypes and map all functions needed.  This would leave the function bodies 
>> of PQputf, PQgetf, PQparamExec, etc... as simple proxy functions to the 
>> dynamically loaded functions.  This removes any bloat that people don't like 
>> right now but still allows one to use libpq as the primary interface, rather 
>> than having to fiddle with libpq and some other API.
> 
> This is still 100% backwards.  My idea of a libpq hook is something that
> could be used by libpgtypes *and other things*.  What you are proposing
> is something where the entire API of the supposed add-on is hard-wired
> into libpq.  That's just bad design, especially when the adequacy of
> the proposed API is itself in question.
> 
> When I say I'd accept some hooks into libpq, I mean some hooks that
> could be used by either libpgtypes or something that would like to do
> something roughly similar but with a different API offered to clients.
> The particular hook that you seem to mostly need is the ability to
> allocate some private memory associated with a particular PGconn object,
> and maybe also with individual PGresults, and then to be able to free
> that at PQclear or PQfinish.  Try designing it like that.
> 
>             regards, tom lane
> 

My idea was not a response to your hook idea.  It was different 
altogether.

My idea is trying to create one interface where some parts need to be 
enabled (nothing wrong with that design, this is a plugin-like model).

Your idea creates two interfaces where one of them can hook into the 
other.  These are two different concepts.

the question is, are you asking for two different interfaces or are you 
just looking to minimize overhead.  I thought it was the latter which is 
why I proposed a plugin-like model.  It removes bloat as well as 
maintains a single interface.  Nothing wrong with the design unless it 
doesn't meet your requirements.

Andrew



Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Tom Lane wrote:
> This is still 100% backwards.  My idea of a libpq hook is something that
> could be used by libpgtypes *and other things*.  What you are proposing
> is something where the entire API of the supposed add-on is hard-wired
> into libpq.  That's just bad design, especially when the adequacy of
> the proposed API is itself in question.
> 
> When I say I'd accept some hooks into libpq, I mean some hooks that
> could be used by either libpgtypes or something that would like to do
> something roughly similar but with a different API offered to clients.
> The particular hook that you seem to mostly need is the ability to
> allocate some private memory associated with a particular PGconn object,
> and maybe also with individual PGresults, and then to be able to free
> that at PQclear or PQfinish.  Try designing it like that.

Agreed.  A minimal change to libpq has a much better chance of being
accepted.  Let me remind people that the community is not required to
accept any patch --- it is accepted based on community feedback.  If we
accepted everything our API would be a mess and Postgres would be much
harder to use.

I think a wise thing would be for the patch submitters to give a _basic_
outline of what PQparam is trying to accomplish --- I mean like 10-20
lines with a code snippet, or code snippet with/withouth PQparam.  Right
now there are too many people trying to guess.  Of course, this should
have been done at the start.  I found this posting from August, 2007 but
it isn't short/clear enough:
http://archives.postgresql.org/pgsql-hackers/2007-08/msg00630.php

I feel this API is foreign enough from what people expect from a typical
database interface library that it should be a separate library with its
own documentation, whether the library is a separate directory in core
or in pgfoundry.

FYI, it might be interesting to extend it to cover what ecpg wants ---
we have been looking for a way to get the database-dependent parts of
ecpg out of the ecpg directory and this might be a solution, _even_ if
it makes your library larger.

Again, I don't think we have trouble with another library, assuming it
does something that many people want to do and it is so tied to the
backend that it needs to be in core. (However, Tom's mention that the
OIDs don't change weakens the logic that is should be in core.)

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Andrew Chernow wrote:
> My idea was not a response to your hook idea.  It was different 
> altogether.
> 
> My idea is trying to create one interface where some parts need to be 
> enabled (nothing wrong with that design, this is a plugin-like model).
> 
> Your idea creates two interfaces where one of them can hook into the 
> other.  These are two different concepts.
> 
> the question is, are you asking for two different interfaces or are you 
> just looking to minimize overhead.  I thought it was the latter which is 
> why I proposed a plugin-like model.  It removes bloat as well as 
> maintains a single interface.  Nothing wrong with the design unless it 
> doesn't meet your requirements.

The idea is that the hooks you need in libpq would be available always,
for your interface and for others.  This would allow your library to use
native libpq on any >=8.4 platform.  People who want to use your library
would have to link in your library and call your additional functions.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
>>
>> When I say I'd accept some hooks into libpq, I mean some hooks that
>> could be used by either libpgtypes or something that would like to do
>> something roughly similar but with a different API offered to clients.
>> The particular hook that you seem to mostly need is the ability to
>> allocate some private memory associated with a particular PGconn object,
>> and maybe also with individual PGresults, and then to be able to free
>> that at PQclear or PQfinish.  Try designing it like that.
>>
>>             regards, tom lane

Your method would work as well.  The only issue is you still have the 
same issue of binary distributed libpqs.  Would redhat distribute a 
binary linked with libpqtypes?  If not, you have the same issue of the 
end-user having to compile libpq ... passing -lpqtypes to the linker. 
If redhat did link it, you run into the disk space complaint all over again.

My suggestion was trying to work around this by dynamically loading the 
library, PQtypesEnable(TRUE).  In this model, redhat doesn't even have 
to distribute libpqtypes.so (considering the disk space issue).  It 
could be easily be an additional download.  All you need are some proxy 
functions inside libpq, PQputf calling a dynamically loaded function. 
This passes the disk space complaints and doesn't require a re-compile 
if an end-user wants to use it.

Andrew



Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Andrew Chernow wrote:
> Andrew Chernow wrote:
>>>
>>> When I say I'd accept some hooks into libpq, I mean some hooks that
>>> could be used by either libpgtypes or something that would like to do
>>> something roughly similar but with a different API offered to clients.
>>> The particular hook that you seem to mostly need is the ability to
>>> allocate some private memory associated with a particular PGconn 
>>> object,
>>> and maybe also with individual PGresults, and then to be able to free
>>> that at PQclear or PQfinish.  Try designing it like that.
>>>
>>>             regards, tom lane
>
> Your method would work as well.  The only issue is you still have the 
> same issue of binary distributed libpqs.  Would redhat distribute a 
> binary linked with libpqtypes?  If not, you have the same issue of the 
> end-user having to compile libpq ... passing -lpqtypes to the linker. 
> If redhat did link it, you run into the disk space complaint all over 
> again.
>
> My suggestion was trying to work around this by dynamically loading 
> the library, PQtypesEnable(TRUE).  In this model, redhat doesn't even 
> have to distribute libpqtypes.so (considering the disk space issue).  
> It could be easily be an additional download.  All you need are some 
> proxy functions inside libpq, PQputf calling a dynamically loaded 
> function. This passes the disk space complaints and doesn't require a 
> re-compile if an end-user wants to use it.
>
>

Why would RedHat need to know anything at all about libpqtypes? AIUI Tom 
is suggesting an API that in libpq that libpqtypes or some other library 
could use, but not that libpq would be linked against libpqtypes at all.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Andrew Chernow wrote:
> Your method would work as well.  The only issue is you still have the 
> same issue of binary distributed libpqs.  Would redhat distribute a 
> binary linked with libpqtypes?  If not, you have the same issue of the 
> end-user having to compile libpq ... passing -lpqtypes to the linker. 
> If redhat did link it, you run into the disk space complaint all over again.
> 
> My suggestion was trying to work around this by dynamically loading the 
> library, PQtypesEnable(TRUE).  In this model, redhat doesn't even have 
> to distribute libpqtypes.so (considering the disk space issue).  It 
> could be easily be an additional download.  All you need are some proxy 
> functions inside libpq, PQputf calling a dynamically loaded function. 
> This passes the disk space complaints and doesn't require a re-compile 
> if an end-user wants to use it.

I don't see requiring users to add -lpqtypes to use these functions as a
problem.  The idea is that the default libpq would have enough hooks
that you could use it without modification.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
"Greg Sabino Mullane"
Date:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160


Andrew states:
> What about user-defined type registration, sub-classing user or built-in
> type handlers, handling of all data types in binary.  There is a lot
> of new functionality added by this patch to the existing libpq.

All of which may be useful, and may not. Right now DBD::Pg is trying to
move further from libpq, rather than binding closer to it, mainly because
it's a huge dependency burden and it takes forever to add new features.
For example, if this got accepted and put into 8.4, the very earliest DBD::Pg
could take advantage of the code would be mid 2009 (assuming an optimistic
release schedule). Even then, only once 8.4 was widely in use (2010?) would the
average DBD::Pg be compiled against it. And that means lots more forking to handle
the old version until then. But don't take my non-use personally: as you say, this
may be more helpful towards C programmers. I only weighed in because I was asked
to specifically.

> I don't think the appropriate audience got a look at this, maybe posting
> on general or libpq lists.  From my perspective as a long time C coder,
> this made my application code cleaner, easier to maintain and faster in
> many cases.  It removed a lot of code that is now handled by this patch.

Did you even post on -interfaces? I would think that would be the first place
to post, certainly before -patches.

Merlin asks:
> does DBD::pg move arrays in and out of the server? do you parse them
> yourself?  if you answer yes to either question you should take a
> second look.

Yes, we move them into and out of the server, and into and out of Perl arrays
in the process. I'd be happy to give the new way a try however: have you
any sample code and documentation? Emphasis on the latter.

- --
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200804082025
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
-----BEGIN PGP SIGNATURE-----

iEYEAREDAAYFAkf8DcIACgkQvJuQZxSWSshk/QCfS8Ocsoqo6U/LPNhnz9OH9Bm4
83MAoOvsSWkKuyE+LA1UhLpyX0bICQbZ
=2XsW
-----END PGP SIGNATURE-----           



Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Bruce Momjian wrote:

> 
> I don't see requiring users to add -lpqtypes to use these functions as a
> problem.  The idea is that the default libpq would have enough hooks
> that you could use it without modification.
> 

You are correct, brain fart on my part.  Not sure where my mind was at 
but I scratch those commit about redhat linking in libpqtypes.  Sorry 
about that.

I think the hook idea would work.  Have to look at composites and 
arrays, they create their own result objects from scratch.

Andrew



Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
>> I think a wise thing would be for the patch submitters to give a _basic_> outline of what PQparam is trying to
accomplish--- I mean like 10-20> lines with a code snippet, or code snippet with/withouth PQparam.>I found this posting
fromAugust, 2007 but> it isn't short/clear enough:>
 

That is very old.  There are tons of examples if you download the patch 
and look at some of the documentation .txt files.
>> FYI, it might be interesting to extend it to cover what ecpg wants ---> we have been looking for a way to get the
database-dependentparts of> ecpg out of the ecpg directory and this might be a solution, _even_ if> it makes your
librarylarger.>
 

I am not all to familiar with ecpg.  Our idea is nothing more than data 
type converters, there are no type operators.

Our goal is to leverage the binary parameterized API and offer the 
ability to get C types from an enhanced PQgetvalue, PQgetf.  PQgetf 
understands the external binary format of the backend, so it can convert 
that to C types.  It also understand how to convert text output from the 
backend.  This allows existing applications using text results to drop 
in PQgetf here and there.  You don't have to use PGparam or PQputf at 
all to use PQgetf.

PQputf, allows one to pack parameters into a PQparam object that can be 
executed at another time.  It knows how to take C types and convert them 
to the backend's external binary format.  The patch always sends data in 
binary format, but can get results in text or binary.

Along the way, we devised a way for user-defined types to be used.  This 
introduced PQregisterTypeHandler.  This function can allow one to 
sub-class existing type handlers, like extending "%timestamp" and making 
"%epoch".  It allows registering user-defined types.  the type will be 
looked up in the backend and resolved properly.  It also allows one to 
create aliases .. simple domains.  Let's say you have a C type, typedef 
int user_id;.  You could register an alias where "user_id=int4".  Now 
you can putf and getf "%user_id".  this abstracts code from possible 
integer width changes, you just change your typedef and registration 
code to "user_id=int8".

Take a peak at the documentation files in the patch, root of tar *.txt 
files.  they are very verbose and have loads of examples.  The 
regression-test.c file has lots of use cases.

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

To sum it up, the main concepts are PQputf, PQgetf and 
PQregisterTypeHandler.  The other functions maintain a PGparam or 
exec/send one.

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


Re: [PATCHES] libpq type system 0.9a

From
Jeff Davis
Date:
On Tue, 2008-04-08 at 13:08 -0400, Andrew Dunstan wrote:
> I think you should conduct a wider survey before you make that decision. 
> In particular, I'd like to hear from driver writers like Greg Sabino 
> Mullane and Jeff Davis, as well as regular libpq users.
> 

I looked into this today.
* Arrays and composites

Better ability in libpq to parse and construct arrays and composites
would be helpful. I think this is worthwhile to consider, and I would
expose the functionality (at least for arrays) in ruby-pg if available.
* Binary formatting

The exclusive use of binary formats is worrisome to me. This circumvents
one level of indirection that we have (i.e. that everything moves
through in/out functions), and will impose a backwards-compatibility
requirement on the internal representation of data types, including
user-defined data types. As far as I know, we currently have no such
requirement, even for built-in types.
* Type conversion callbacks

The type conversion hooks make some sense, but I have reservations about
that policy as well. The data types in PostgreSQL will never match
perfectly the data types in a host language -- NULL in particular
doesn't have a direct counterpart.

If there were a perfect mapping of types, it would seem like a much
better idea. The problem is that we don't want to have some types that
are perfectly mapped (e.g. int, bytea), some that are imperfectly mapped
(e.g. dates, numeric), and some types that have no conversion defined
and fall back to something else. In this case, the result format is
always binary, so we can't even fall back to text.

In my experience trying to implicitly map to types doesn't save a lot of
time for the developer. You end up spending time referencing the
documentation (or some other part of the code) to figure out how the
edge cases are being handled rather than just handling them explicitly
in the code. For instance, wrapping a value you expect to be a date in
Date.parse() is more readable in most cases.

Regards,Jeff Davis



Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
This patch has an identity crisis.  We initially called it PGparam (possibly 
mispelled several times as PQparam) and then changed it to libpq type system 
(typesys).

Several on patches started to call it libpqtypes, even I did.  Any objections to 
fixing the name to libpqtypes?

Any thoughts on the hooking suggested by Tom?  It sounds like it should be 
generic enough so more than just libpqtypes can make use of it.  I think 
something of this nature should have input before I do anything.

Possible Hook points: (at least ones needed by libpqtypes)
conn_create
conn_reset
conn_destroy
result_create
result_destroy

I guess libpqtypes would have to maintain a map of conns and results?  Right now 
it can associate type info because we added members to conn and result.  When 
conn_create(conn) is called, libpqtypes would need to map this by pointer 
address (as it is all it has as an identifier).  Still feels like maybe there 
should be a void* in a conn and result used for per-connection/result based info 
(libpqtypes or not).

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


Re: [PATCHES] libpq type system 0.9a

From
Jeff Davis
Date:
On Tue, 2008-04-08 at 12:59 -0400, Bruce Momjian wrote:
> If you need something exposed by
> libpq that is not there already, please let us know.

The things that I found missing in libpq so far are:
* The ability to choose some result columns to be binary-formatted and
others to be text-formatted. I haven't thought of a reasonable API for
this yet, particularly since we already have so many ways of executing a
statement.
* an "escapeIdent" function.
* PQescapeBytea escapes for both inclusion in a SQL statement and also
the escaping for the input function for bytea. This means that, if you
are passing a binary value as a text-format parameter, using
PQescapeBytea is incorrect, and you need to write your own octal escape
routine. This is obviously a minor complaint, and may not even be worth
polluting the namespace. I only mention it because it seems like an easy
mistake to make.

I don't have a proposal ready for any of these yet, but this is what
I've found to be awkward or limiting during my work on ruby-pg. If I
have a more complete proposal I'll start a new thread.

Regards,Jeff Davis



Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 8:06 PM, Bruce Momjian <bruce@momjian.us> wrote:
>  I think a wise thing would be for the patch submitters to give a _basic_
>  outline of what PQparam is trying to accomplish --- I mean like 10-20
>  lines with a code snippet, or code snippet with/withouth PQparam.  Right
>  now there are too many people trying to guess.  Of course, this should
>  have been done at the start.  I found this posting from August, 2007 but
>  it isn't short/clear enough:

see [dated jan 8]:
http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg102719.html

merlin


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 9:28 PM, Jeff Davis <pgsql@j-davis.com> wrote:

with proposed changes, (I think) all your suggestions are addressed/moot. see:

>   * The ability to choose some result columns to be binary-formatted and
>  others to be text-formatted. I haven't thought of a reasonable API for
>  this yet, particularly since we already have so many ways of executing a
>  statement.

with PQgetf, you are abstracted from resultformat.  The library
converts your data for you into consistent types (in practice, the
result format is always binary)...without the 'negatives' of dealing
with binary data.

>   * an "escapeIdent" function.

not sure what this is...

>   * PQescapeBytea escapes for both inclusion in a SQL statement and also
>  the escaping for the input function for bytea. This means that, if you
>  are passing a binary value as a text-format parameter, using
>  PQescapeBytea is incorrect, and you need to write your own octal escape
>  routine. This is obviously a minor complaint, and may not even be worth
>  polluting the namespace. I only mention it because it seems like an easy
>  mistake to make.

PQescapeBytea is unnecessary with proposed patch...input parameters
are moved to proper format by the library.  You simply %bytea the
parameter and let the library handle the rest.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Jeff Davis
Date:
On Tue, 2008-04-08 at 15:22 -0400, Tom Lane wrote:
> Well, for starters, using binary format.  It is undeniable that that
> creates more portability risks (cross-architecture and cross-PG-version
> issues) than text format.  Not everyone wants to take those risks for
> benefits that may not be meaningful for their apps.

What are the cross-architecture risks involved?

Regards,Jeff Davis



Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Jeff Davis wrote:
> On Tue, 2008-04-08 at 15:22 -0400, Tom Lane wrote:
>> Well, for starters, using binary format.  It is undeniable that that
>> creates more portability risks (cross-architecture and cross-PG-version
>> issues) than text format.  Not everyone wants to take those risks for
>> benefits that may not be meaningful for their apps.
> 
> What are the cross-architecture risks involved?
> 
> Regards,
>     Jeff Davis
> 
> 
>>> What are the cross-architecture risks involved?
We didn't run into any issues here.  close attention was paid to byte 
ordering, the rest was handled by libpq's cross-platform handling.

cross-PG-version is a different story.  the patch already uses server 
version to toggle (like use int4 for money pre-8.3).  If we make this a 
separate library, it would be easy to plug in a newer or older one. 
Merlin had some ideas here ... Merlin?

Andrew


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 9:21 PM, Jeff Davis <pgsql@j-davis.com> wrote:
>  I looked into this today.
>
>   * Arrays and composites
>
>  Better ability in libpq to parse and construct arrays and composites
>  would be helpful. I think this is worthwhile to consider, and I would
>  expose the functionality (at least for arrays) in ruby-pg if available.

Right..that was the principle objective.  In our particular case we
move a lot of data in and out via arrays, and in certain case moving
data in and out via binary is a huge performance win.

>   * Binary formatting
>
>  The exclusive use of binary formats is worrisome to me. This circumvents
>  one level of indirection that we have (i.e. that everything moves
>  through in/out functions), and will impose a backwards-compatibility
>  requirement on the internal representation of data types, including
>  user-defined data types. As far as I know, we currently have no such
>  requirement, even for built-in types.

This is a valid concern. That said, the in/out functions don't change
_that_ much, and even if they did..there are solutions to this
problem.  Forwards compatibility is the worst case (8.4 libpq
connecting to 8.5 server).  If this problem was reasonably addressed
though, would it alleviate your concerns?

>   * Type conversion callbacks
>
>  The type conversion hooks make some sense, but I have reservations about
>  that policy as well. The data types in PostgreSQL will never match
>  perfectly the data types in a host language -- NULL in particular
>  doesn't have a direct counterpart.

>  If there were a perfect mapping of types, it would seem like a much
>  better idea. The problem is that we don't want to have some types that
>  are perfectly mapped (e.g. int, bytea), some that are imperfectly mapped
>  (e.g. dates, numeric), and some types that have no conversion defined
>  and fall back to something else. In this case, the result format is
>  always binary, so we can't even fall back to text.

We introduced types for which there were no native
counterparts...PGtime for example,   This choice of which types map
and which don't is fairly arbitrary, but not terrible from libpq
perspective.  We could for example typedef int to PGint, or PGint4 to
make things more consistent, I suppose.

I would suggest that if you want text from the database, cast it as
such in the query and pull it with %text.

>  In my experience trying to implicitly map to types doesn't save a lot of
>  time for the developer. You end up spending time referencing the
>  documentation (or some other part of the code) to figure out how the
>  edge cases are being handled rather than just handling them explicitly
>  in the code. For instance, wrapping a value you expect to be a date in
>  Date.parse() is more readable in most cases.

There are many types where this is not the case.  Consider the
geometric types for example.  There is little reason to pull these in
text and farily large performance benefits to retrieving in binary.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Jeff Davis <pgsql@j-davis.com> writes:
> On Tue, 2008-04-08 at 15:22 -0400, Tom Lane wrote:
>> Well, for starters, using binary format.  It is undeniable that that
>> creates more portability risks (cross-architecture and cross-PG-version
>> issues) than text format.  Not everyone wants to take those risks for
>> benefits that may not be meaningful for their apps.

> What are the cross-architecture risks involved?

The biggie is floating-point format.  IEEE standard is not quite
universal ... and even for platforms that fully adhere to that standard,
it's not entirely clear that we get the endianness issues correct.
There used to be platforms where FP and integer endianness were
different; is anyone sure that's no longer the case?

But I'll agree that cross-version hazards are a much more clear and
present danger.  We've already broken binary compatibility at least once
since the current binary-I/O system was instituted (intervals now have
three fields not two) and there are obvious candidates for future
breakage, such as text locale/encoding support.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Tue, Apr 8, 2008 at 10:15 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>  The biggie is floating-point format.  IEEE standard is not quite
>  universal ... and even for platforms that fully adhere to that standard,
>  it's not entirely clear that we get the endianness issues correct.
>  There used to be platforms where FP and integer endianness were
>  different; is anyone sure that's no longer the case?

If somebody can provide a machine to test this, we will code for
this...and hope to catch any other cases with the regression test.  As
it happens, we have a fairly large array of old hardware to test on,
pa-risc, power, mips, etc. We are still setting them up to test some
of our own stuff, but we will put things through the ringer, no doubt
(we will also put some machines on the buildfarm).

>  But I'll agree that cross-version hazards are a much more clear and
>  present danger.  We've already broken binary compatibility at least once
>  since the current binary-I/O system was instituted (intervals now have
>  three fields not two) and there are obvious candidates for future
>  breakage, such as text locale/encoding support.

There are other cases, for example money getting promoted to 64 bit.
Here is an even better example.  When looking at the array_send/recv
functions, I noticed that a good candidate for wire format
optimization would be to trim out the length columns for arrays where
the type is fixed length and has no nulls (great win for arrays of
ints and such).  This change would involve modifying some of the most
complicated parts of the proposed patch...these things are going to
happen..

So, this problem has to be dealt with, so lets look at some ways of handling it:
*) only allow direct binary mapping between client/server between same
version, or 'trusted' version. (lame, but easy).

*) as above, but break it down to type level. similar to catalog bump
for types. basically, if the client is not the same version as the
server, there is a negotiation so that the client and server agree
which types if any are unsafe to send.  Better, and still fairly easy,
since we are still sidestepping backwards compatibility, but in a more
fine-grained way.

*) as above, but start (from here on in), building in logical to grok
older versions of binary formats, to a certain suitable time frame.
This is the biggest headache in terms of long term maintenance, since
it puts lots of checks into the code, but is the only way of
completely isolating clients from the issue.  We have already chosen
this path for a couple of times (money for example), as things evolved
over the 8.3 cycle.

While format changes do happen, this is a farily uncommon thing.  I
suspect that on average there about 3-5 format changes per major
release...this would ad up to about 20 or so version specific checks
in the in/out procedures should we go down the compatibility road.
Not great, but not completely terrible either.  In terms of everything
else we had to do, this was a minor nuisance at worst.  We are
completely open to how this particular issue should be tackled. We
didn't feel particularly rushed, since the biggest problems wouldn't
manifest until 8.5 at the earliest...

Another issue that you have not addressed, is that (rightly or
wrongly), we are adding another non-trivial step in terms of
introducing new built in types.  It's already a fairly large checklist
as it is (enums acquired send/recv almost too late for the 8.3 cycle).One of my least favorite things about the
proposalis the amount code
 
duplication in libpq and the server...I think that this can be fixed
in the long run, eliminating this 'extra' step by consolidating the
client and server in/out routines into a consolidated library.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> 
> Any thoughts on the hooking suggested by Tom?  It sounds like it should 
> be generic enough so more than just libpqtypes can make use of it.  I 
> think something of this nature should have input before I do anything.
> 
> Possible Hook points: (at least ones needed by libpqtypes)
> conn_create
> conn_reset
> conn_destroy
> result_create
> result_destroy
> 
> I guess libpqtypes would have to maintain a map of conns and results?  
> Right now it can associate type info because we added members to conn 
> and result.  When conn_create(conn) is called, libpqtypes would need to 
> map this by pointer address (as it is all it has as an identifier).  
> Still feels like maybe there should be a void* in a conn and result used 
> for per-connection/result based info (libpqtypes or not).
> 

Well, I can get it working with a very small patch.  We actually don't need very 
much in libpq.  Although, making it somehow generic enough to be useful to other 
extensions is a bit tricky.  Please, suggestions would be helpful.

Below is a raw shell of an idea that will work for libpqtypes.  Start by 
removing our entire patch and then add the below:

// libpqtypes only needs the below.  could add op_reset,
// op_linkerror, etc...
enum
{  HOOK_OP_CREATE,  HOOK_OP_DESTROY
};

struct pg_conn
{  // everything currently in a pg_conn  // ...
  // libpqtypes needs HOOK_OP_DESTROY, a ptr to hookData  // is always used in case the hooklib needs to allocate  //
orreallocate the hookData.  void *hookData;  int (*connHook)(PGconn *conn, int op, void **hookData);
 
}

struct pg_result
{  // everything currently in a pg_result  .....
  // libpqtypes needs create & destroy  // conn is NULL for destroy  void *hookData;  int (*resultHook)(PGconn *conn,
PGresult*result,    int op, void **hookData);
 
}

freePGconn(PGconn *conn)
{  // ...  if(conn->connHook)    conn->connHook(conn, HOOK_OP_DESTROY, &conn->hookdata);  // ...
}

PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
{  // ... (result allocated here)  if(result->resultHook)    result->resultHook(conn, result,      HOOK_OP_CREATE,
&result->hookData); // ...
 
}

PQclear(PGresult *result)
{  // ...  if(result->resultHook)    result->resultHook(NULL, result,      HOOK_OP_DESTROY, &result->hookdata);  //
...
}

// library wide
int PQregisterHooks(connHook, resultHook);

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
> 
> Well, I can get it working with a very small patch.  We actually don't 
> need very much in libpq.  Although, making it somehow generic enough to 
> be useful to other extensions is a bit tricky.  Please, suggestions 
> would be helpful.
> 
> Below is a raw shell of an idea that will work for libpqtypes.  Start by 
> removing our entire patch and then add the below:
> 
> // libpqtypes only needs the below.  could add op_reset,
> // op_linkerror, etc...
> enum
> {
>   HOOK_OP_CREATE,
>   HOOK_OP_DESTROY
> };
> 
> struct pg_conn
> {
>   // everything currently in a pg_conn
>   // ...
> 
>   // libpqtypes needs HOOK_OP_DESTROY, a ptr to hookData
>   // is always used in case the hooklib needs to allocate
>   // or reallocate the hookData.
>   void *hookData;
>   int (*connHook)(PGconn *conn, int op, void **hookData);
> }
> 
> struct pg_result
> {
>   // everything currently in a pg_result
>   .....
> 
>   // libpqtypes needs create & destroy
>   // conn is NULL for destroy
>   void *hookData;
>   int (*resultHook)(PGconn *conn, PGresult *result,
>     int op, void **hookData);
> }
> 

There is no need to pass hookData to the hook function.  libpqtypes already 
accesses PGconn and PGresult directly so it can just access the hookData member.

int (*connHook)(PGconn *conn, int op);
int (*resultHook)(PGconn *conn, PGresult *result, in top);

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


Re: [PATCHES] libpq type system 0.9a

From
Jeff Davis
Date:
On Tue, 2008-04-08 at 22:15 -0400, Tom Lane wrote:
> The biggie is floating-point format.  IEEE standard is not quite
> universal ... and even for platforms that fully adhere to that standard,
> it's not entirely clear that we get the endianness issues correct.
> There used to be platforms where FP and integer endianness were
> different; is anyone sure that's no longer the case?
> 

These seem solvable with platform-specific code in the send/recv for the
applicable types. I don't have such machines to test on, however.

> But I'll agree that cross-version hazards are a much more clear and
> present danger.  We've already broken binary compatibility at least once
> since the current binary-I/O system was instituted (intervals now have
> three fields not two) and there are obvious candidates for future
> breakage, such as text locale/encoding support.

Is there a lower standard for maintaining compatibility for external
binary representations than external text representations? 

It seems that there would have to be more flexibility in changing the
external binary representation if a type between versions in order to
"be cheap to convert to internal form" as the docs say here:
http://www.postgresql.org/docs/8.3/static/sql-createtype.html

Regards,Jeff Davis



Re: [PATCHES] libpq type system 0.9a

From
Jeff Davis
Date:
On Tue, 2008-04-08 at 22:06 -0400, Merlin Moncure wrote:
> This is a valid concern. That said, the in/out functions don't change
> _that_ much, and even if they did..there are solutions to this
> problem.  Forwards compatibility is the worst case (8.4 libpq
> connecting to 8.5 server).  If this problem was reasonably addressed
> though, would it alleviate your concerns?
> 

You're starting to convince me on this point, but the instability of
external binary representations between versions is still worrisome.

> We introduced types for which there were no native
> counterparts...PGtime for example,   This choice of which types map
> and which don't is fairly arbitrary, but not terrible from libpq
> perspective.  We could for example typedef int to PGint, or PGint4 to
> make things more consistent, I suppose.
> 
> I would suggest that if you want text from the database, cast it as
> such in the query and pull it with %text.

There are many cases that are fairly hard to get a perfect mapping. If
you use PGtime, for instance, there are no C operators for it, so
you're basically just getting the data in binary format. That can be a
benefit in many applications, but that's an argument for allowing
binary-format results, not for implicitly casting from one type to
another.

If you try to use the C time type instead, you will have many more
operators available, but will lose precision. That's OK for many
applications, but not a general solution.

And I think NULL is still particularly tricky. If you have to check
each field explicitly anyway, it doesn't seem to save a lot of effort
to implicitly cast the value. In ruby-pg, I return nil for a NULL, and
I think that works fairly well because almost any operator will
immediately fail on nil (in Ruby), so mistakes are caught quickly. If
we're casting NULL to 0, and then have to check to see that it's NULL,
that seems as error-prone as libpq is currently.

I think the heart of this problem is that the mapping works great
except where the types don't quite match up. To remember what types fit
and how well they fit, you have to refer back to other code or docs. To
really make the types match up well would be a huge effort.

> >  In my experience trying to implicitly map to types doesn't save a lot of
> >  time for the developer. You end up spending time referencing the
> >  documentation (or some other part of the code) to figure out how the
> >  edge cases are being handled rather than just handling them explicitly
> >  in the code. For instance, wrapping a value you expect to be a date in
> >  Date.parse() is more readable in most cases.
> 
> There are many types where this is not the case.  Consider the
> geometric types for example.  There is little reason to pull these in
> text and farily large performance benefits to retrieving in binary.
> 

Agreed. Again though, that's an argument for allowing binary-format
results.

Regards,Jeff Davis



Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
>>There are many cases that are fairly hard to get a perfect mapping. If>>you use PGtime, for instance, there are no C
operatorsfor it
 
> 
> 

Yeah, our patch is designed to allow one to interface with libpq using C data 
types, rather than strings (most common) or for the brave external binary format.
>>If you try to use the C time type instead, you will>>have many more operators available, but will lose precision.
That is why we didn't use something like struct tm.  Instead, we have PGtime, 
PGdate and PGtimestamp.  PGtimestamp has a PGtime and PGdate in it.  See 
libpq-fe.h inside our patch.

/* Below is a PGtime. */
typedef struct
{  /* The number of hours past midnight, in the range 0 to 23. */  int hour;
  /* The number of minutes after the hour, in the range 0 to 59. */  int min;
  /* The number of seconds after the minute, in the range 0 to 59. */  int sec;
  /* The number of microseconds after the second, in the   * range of 0 to 999999.   */  int usec;
  /*   * When non-zero, this is a TIME WITH TIME ZONE.  Otherwise,   * it is a TIME WITHOUT TIME ZONE.   */  int
withtz;
  /* A value of 1 indicates daylight savings time.  A value of 0 indicates   * standard time.  A value of -1 means
unknownor could not determine.   */  int isdst;
 
  /* Seconds east of UTC. This value is not always available. It is   * set to 0 if it cannot be determined.   */  int
gmtoff;
  /* Timezone abbreviation: such as EST, GMT, PDT, etc. This value is   * not always available.  It is set to an empty
stringif it cannot be   * determined.  It can also be in ISO 8601 GMT+/-hhmmss format.   */  char tzname[16];
 
} PGtime;

Our patch was not designed to operate on these data types, although it could 
with a little work.  It sounds like people would like this functionality, some 
referring to ecpg.

Numeric is a the odd ball in our patch.  We saw no benefit to supplying a struct 
for it so we always expose numerics as strings (put or get).  Internally, we 
convert the string to binary format for puts.  On binary gets, we convert the 
external format to a numeric string.  We left it to the libpq user to strtod or 
use a Big Number library.
>>And I think NULL is still particularly tricky
PQgetisnull is used by our code.  It doesn't error out, but after zeroing the 
provided user memory, it just returns.  The libpq user should check isnull where 
they care about it.

Almost all of the types that required a PGstruct, are very solid mappings.  For 
instance, geo types are straight forward, not much to a PGpoint.  Geo type 
structs were kept very close to the backend.

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


Re: [PATCHES] libpq type system 0.9a

From
Gregory Stark
Date:
"Jeff Davis" <pgsql@j-davis.com> writes:

>  * Binary formatting
>
> The exclusive use of binary formats is worrisome to me. This circumvents
> one level of indirection that we have (i.e. that everything moves
> through in/out functions), and will impose a backwards-compatibility
> requirement on the internal representation of data types, including
> user-defined data types. As far as I know, we currently have no such
> requirement, even for built-in types.

This is actually incorrect. Binary I/O still goes through a function call, the
send/recv functions instead of the in/out functions. In theory these are also
supposed to be cross-platform.

In practice they are, uhm, less cross-platform. For example they send floats
as raw (presumably) IEEE floats. There have also been fewer clients using
binary mode, so you're more likely to run into bugs.

But the reason fewer clients use binary mode is because they would have to
implement all this type-specific knowledge. It doesn't make sense to do it for
every driver or application but if you're implementing it once in a library it
does start to make more sense.

Note however that not every data type will necessarily provide a binary
send/recv function. The built-in data types do, but only as a matter of
policy. It's not an error to create a type with no binary i/o functions. 
So I think you have to support using text mode as an option.

--  Gregory Stark EnterpriseDB          http://www.enterprisedb.com Ask me about EnterpriseDB's RemoteDBA services!


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Wed, Apr 9, 2008 at 6:13 AM, Gregory Stark <stark@enterprisedb.com> wrote:
>  > The exclusive use of binary formats is worrisome to me. This circumvents
>  > one level of indirection that we have (i.e. that everything moves
>  > through in/out functions), and will impose a backwards-compatibility
>  > requirement on the internal representation of data types, including
>  > user-defined data types. As far as I know, we currently have no such
>  > requirement, even for built-in types.
>
>  This is actually incorrect. Binary I/O still goes through a function call, the
>  send/recv functions instead of the in/out functions. In theory these are also
>  supposed to be cross-platform.
>
>  In practice they are, uhm, less cross-platform. For example they send floats
>  as raw (presumably) IEEE floats. There have also been fewer clients using
>  binary mode, so you're more likely to run into bugs.

small correction: you _were_ more likely to run into bugs.  in the
process of developing this patch during the 8.3 cycle, we caught,
fixed, and submitted a number of binary format related issues,
including some wacky things that are not possible through the text
parser (a polygon with zero points for example).  we used regression
testing heavily in development.

>  But the reason fewer clients use binary mode is because they would have to
>  implement all this type-specific knowledge. It doesn't make sense to do it for
>  every driver or application but if you're implementing it once in a library it
>  does start to make more sense.
>
>  Note however that not every data type will necessarily provide a binary
>  send/recv function. The built-in data types do, but only as a matter of
>  policy. It's not an error to create a type with no binary i/o functions.
>  So I think you have to support using text mode as an option.

You have this option. there is nothing keeping you from using getvalue
vs. getf.  However, due to libpq limitations, if any datatype must
return text the entire result must be text (resultFormat)...this is
also interestingly true for functions that return 'void'.  So, at
present, to use PQgetf, you result set must be binary.

In some of the early versions of the patch we introduced parsing code
to compute text results in addition to binary results (so for
getf('%int), the library does the atoi for you, checking range and
such).  We ended up dropping this because we were getting nervous
about the size of the patch at that point.

In any event, I think a better solution would be to change
resultformat to mean 'give me binary format if it's available' on a
per column basis...libpq already has a method to check field format of
the result and getf can just raise a run-time error if you try to pass
a native type in when it's not available.  This would be a pretty
amazing sequence of events...only likely to occur when developing new
types for example.  Is this (mixed text/binary results) possible with
the v3 protocol?

merlin


Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Merlin Moncure wrote:
> However, due to libpq limitations, if any datatype must
> return text the entire result must be text (resultFormat)...this is
> also interestingly true for functions that return 'void'.  So, at
> present, to use PQgetf, you result set must be binary.
>
>
>   

I'm surprised you didn't try to address that limitation.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Wed, Apr 9, 2008 at 8:04 AM, Andrew Dunstan <andrew@dunslane.net> wrote:
\>  Merlin Moncure wrote:
>
> > However, due to libpq limitations, if any datatype must
> > return text the entire result must be text (resultFormat)...this is
> > also interestingly true for functions that return 'void'.  So, at
> > present, to use PQgetf, you result set must be binary.
>
>  I'm surprised you didn't try to address that limitation.


whoops! we did...thinko on my part.  Text results are fully supported
save for composites and arrays.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Dunstan wrote:
> 
> 
> Merlin Moncure wrote:
>> However, due to libpq limitations, if any datatype must
>> return text the entire result must be text (resultFormat)...this is 
> 
> I'm surprised you didn't try to address that limitation.
> 
> 

That would change the existing behavior of resultFormat, although not terribly.  Currently, the server will spit back
anerror if you use binary results but 
 
some type hasn't implemented a send/recv.  Instead of an error, the server could 
"fallback" to the type's in/out routines and mark the column as text format.

I think the "fallback" approach is more intelligent behavior but such a change 
could break libpq clients.  They might be blindly ASSuming if the exec worked 
with resultFormat=1, that everything returned by PQgetvalue will be binary (I'm 
guilty of this one, prior to libpqtypes).

Our patch would work with no changes because it supports text and binary 
results.  So, each type handler already toggles itself based on PQfformat.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Andrew Chernow wrote:
> Andrew Dunstan wrote:
>>
>>
>> Merlin Moncure wrote:
>>> However, due to libpq limitations, if any datatype must
>>> return text the entire result must be text (resultFormat)...this is 
>>
>> I'm surprised you didn't try to address that limitation.
>>
>>
>
> That would change the existing behavior of resultFormat, although not 
> terribly.  Currently, the server will spit back an error if you use 
> binary results but some type hasn't implemented a send/recv.  Instead 
> of an error, the server could "fallback" to the type's in/out routines 
> and mark the column as text format.
>
> I think the "fallback" approach is more intelligent behavior but such 
> a change could break libpq clients.  They might be blindly ASSuming if 
> the exec worked with resultFormat=1, that everything returned by 
> PQgetvalue will be binary (I'm guilty of this one, prior to libpqtypes).
>
> Our patch would work with no changes because it supports text and 
> binary results.  So, each type handler already toggles itself based on 
> PQfformat.

That makes it sound more like a protocol limitation, rather than a libpq 
limitation. Or am I misunderstanding?

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Merlin Moncure wrote:
> On Wed, Apr 9, 2008 at 8:04 AM, Andrew Dunstan <andrew@dunslane.net> wrote:
> \>  Merlin Moncure wrote:
>>> However, due to libpq limitations, if any datatype must
>>> return text the entire result must be text (resultFormat)...this is
>>> also interestingly true for functions that return 'void'.  So, at
>>> present, to use PQgetf, you result set must be binary.
>>  I'm surprised you didn't try to address that limitation.
> 
> 
> whoops! we did...thinko on my part.  Text results are fully supported
> save for composites and arrays.
> 
> merlin
> 

Yeah, currently composites and arrays only support binary results in libpqtypes.   This forces any array elementType or
anymember of a composite to have a 
 
send/recv routine.  Using the "fallback to text output" approach, this 
limitation on array elements and composite members would be removed.
>>That makes it sound more like a protocol limitation, rather than a>>libpq limitation. Or am I misunderstanding?
It looks like libpq, message 'T' handling in getRowDescriptions, reads a 
separate format for each column off the wire.  The protocol already has this 
ability.  The backend needs a ?minor? adjustment to make use of the existing 
capability.

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


Re: [PATCHES] libpq type system 0.9a

From
Michael Meskes
Date:
On Tue, Apr 08, 2008 at 07:18:31PM -0400, Tom Lane wrote:
> sure that there's much potential commonality.  The thing that's most
> problematic about ecpg is that it wants to offer client-side equivalents
> of some server datatype-manipulation functions; and I don't actually see
> much of any of that in the proposed patch.  All that's really here is
> format conversion stuff, so there's no hope of unifying that code
> unless this patch adopts ecpg's choices of client-side representation

ecpg for instance does not use a struct for time, so there doesn't seem
to be an advantance for ecpg in switching. On the other side there's a
disadvantage in that you can binary transfer right now given that you're
on the same architecture. But if the datatypes differ this would be
lost.

> (which I believe are mostly Informix legacy choices, so I'm not sure we
> want that).

Not really. ecpg's pgtypeslib uses the same datatypes as the backend
uses (well, mostly because numeric was changed in the backend after the
creation of pgtypeslib). Then there's a compatibility layer that maps
Informix functions and datatypes to our functions and datatypes. 

Michael
-- 
Michael Meskes
Email: Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
ICQ: 179140304, AIM/Yahoo: michaelmeskes, Jabber: meskes@jabber.org
Go VfL Borussia! Go SF 49ers! Use Debian GNU/Linux! Use PostgreSQL!


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> 
> Yeah, currently composites and arrays only support binary results in 
> libpqtypes.   This forces any array elementType or any member of a 
> composite to have a send/recv routine.  Using the "fallback to text 
> output" approach, this limitation on array elements and composite 
> members would be removed.
> 

Actually, I am confusing the way the protocol handles arrays and 
composites (as a single column value, vs. the way libpqtypes handles 
these (as a separate result object).  for instance, the members of a 
composite inherit the format of the column within the protocol.  To 
allow one member of a composite to be text formatted and another be 
binary, would require a change to the protocol, an additional format 
value per member header.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
>>
>> Well, I can get it working with a very small patch.  We actually don't 
>> need very much in libpq.  Although, making it somehow generic enough 
>> to be useful to other extensions is a bit tricky.  Please, suggestions 
>> would be helpful.
>>
> 

Quick question on the hook concept before I try to supply a new patch.
From my experience, redhat normally compiles everything into their 
packages; like apache modules.  Why would libpq be any different in 
regards to libpqtypes?

If they don't distribute libpqtypes, how does a libpq user link with 
libpqtypes?  They don't have the library.  Where would they get a 
libpqtypes.so that is compatible with redhat's supplied libpq.so?

The core of what I am trying to ask is, there doesn't appear to be an 
advantage to separating libpqtypes from libpq in terms of space.  If 
redhat follows their normal policy of include all (probably to make 
their distro as feature rich out-of-the-box as possible), then they 
would distribute libpqtypes.so which would use the same amount of space 
as if it were part of libpq.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> Andrew Chernow wrote:
>>>
>>> Well, I can get it working with a very small patch.  We actually 
>>> don't need very much in libpq.  Although, making it somehow generic 
>>> enough to be useful to other extensions is a bit tricky.  Please, 
>>> suggestions would be helpful.
>>>
>>
> 
> Quick question on the hook concept before I try to supply a new patch.
> 
>  From my experience, redhat normally compiles everything into their 
> packages; like apache modules.  Why would libpq be any different in 
> regards to libpqtypes?
> 
> If they don't distribute libpqtypes, how does a libpq user link with 
> libpqtypes?  They don't have the library.  Where would they get a 
> libpqtypes.so that is compatible with redhat's supplied libpq.so?
> 
> The core of what I am trying to ask is, there doesn't appear to be an 
> advantage to separating libpqtypes from libpq in terms of space.  If 
> redhat follows their normal policy of include all (probably to make 
> their distro as feature rich out-of-the-box as possible), then they 
> would distribute libpqtypes.so which would use the same amount of space 
> as if it were part of libpq.
> 


By the way, I offered up the idea of compiling our patch in or out, 
./configure --with-pqtypes.  But Tom had said
>>[shrug...] So the packagers will compile it out, and you're>>still hosed, or at least any users who'd like to use it
are.

If redhat would compile out our patch, no questions asked, why would 
they distribute libpqtypes.so.  Meaning, separating it out doesn't seem 
to unhose us :)

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Andrew Chernow wrote:
> Andrew Chernow wrote:
>>>
>>> Well, I can get it working with a very small patch.  We actually 
>>> don't need very much in libpq.  Although, making it somehow generic 
>>> enough to be useful to other extensions is a bit tricky.  Please, 
>>> suggestions would be helpful.
>>>
>>
>
> Quick question on the hook concept before I try to supply a new patch.
>
> From my experience, redhat normally compiles everything into their 
> packages; like apache modules.  Why would libpq be any different in 
> regards to libpqtypes?
>
> If they don't distribute libpqtypes, how does a libpq user link with 
> libpqtypes?  They don't have the library.  Where would they get a 
> libpqtypes.so that is compatible with redhat's supplied libpq.so?
>
> The core of what I am trying to ask is, there doesn't appear to be an 
> advantage to separating libpqtypes from libpq in terms of space.  If 
> redhat follows their normal policy of include all (probably to make 
> their distro as feature rich out-of-the-box as possible), then they 
> would distribute libpqtypes.so which would use the same amount of 
> space as if it were part of libpq.

They would get it the same way they would get anything else that uses 
libpq that isn't packaged with it (e.g.  DBD::Pg). They would either get 
the package that contains it, if it exists, or get the source and build 
it. The package with the dependent library might belong in the extras 
collection, while Tom's goal (and it's a good one) is to keep libpq in 
the core collection.

I don't get what you're not seeing about this.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
Alvaro Herrera
Date:
Andrew Chernow wrote:

> The core of what I am trying to ask is, there doesn't appear to be an  
> advantage to separating libpqtypes from libpq in terms of space.  If  
> redhat follows their normal policy of include all (probably to make  
> their distro as feature rich out-of-the-box as possible), then they  
> would distribute libpqtypes.so which would use the same amount of space  
> as if it were part of libpq.

My guess is that if we provide an useful library, Redhat will distribute
it some way or another.  In the worst case (i.e. Redhat does not
distribute it at all), it will still be available on PGDG rpm
repositories.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Dunstan wrote:
> 
> I don't get what you're not seeing about this.
> 
> 
> 

All I am trying to say is, redhat's core packages are normally very 
inclusive.  Like apache, which includes many/most modules in the core 
package.

I am still not convinced there is merit to a separate library.  But 
honestly, I'm indifferent at this point.  If the community wants it this 
way, whether or not I agree with the reasons, then consider it done.

It would be helpful to get some feedback about what the requirements are 
for a hooking mechanism for libpqtypes:

1. Do we make the hooking system generic, for other library to use?

2. If #1 is YES, then does this hooking system need to allow registering 
multiple hooks per app instance.  Meaning, should we implement a table 
of callbacks/hooks?  Like a linked list of them.

3. What design is preferred?
*) A single msg proc that uses a msg object which is either a big union 
or something that gets up casted.
*) A separate function pointer per hook, like conn_create, conn_destroy
*) A combo, where conn hooks are handled by one funcptr and result hooks 
by another.  But each only has one function.

Please think carefully about question #1, as this could lead to 
over-design or guess-design.

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> There is no need to pass hookData to the hook function.  libpqtypes already 
> accesses PGconn and PGresult directly so it can just access the hookData member.

That's a habit you'd really be best advised to stop, if you're going to
be a separate library.  Otherwise, any time we make an internal change
in the PGconn struct, it'll break your library --- and we have and will
feel free to do that without an external soname change.

What parts of PGconn/PGresult do you need to touch that aren't exposed
already?
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Dunstan
Date:

Andrew Chernow wrote:
> Andrew Dunstan wrote:
>>
>> I don't get what you're not seeing about this.
>>
>>
>>
>
> All I am trying to say is, redhat's core packages are normally very 
> inclusive.  Like apache, which includes many/most modules in the core 
> package.
>

There are plenty of modules that they don't include, e.g. mod_fastcgi. 
If you want that you download and build it against your installed 
apache. Or you get mod_fcgid from extras.

Your bolt-on client library would be in exactly the same boat as one of 
those.

cheers

andrew


Re: [PATCHES] libpq type system 0.9a

From
Bruce Momjian
Date:
Andrew Dunstan wrote:
> > All I am trying to say is, redhat's core packages are normally very 
> > inclusive.  Like apache, which includes many/most modules in the core 
> > package.
> >
> 
> There are plenty of modules that they don't include, e.g. mod_fastcgi. 
> If you want that you download and build it against your installed 
> apache. Or you get mod_fcgid from extras.
> 
> Your bolt-on client library would be in exactly the same boat as one of 
> those.

I think Andrew Chernow is fundamentally confused about dynamic linking,
which apache has to use because it doesn't know what type of file it has
to handle, with linking, which is bound to the application code. 
pgtypes is bound to the application code so it is not like apache --- an
application isn't going to be fed arbitrary pgtypes function calls it
has to handle.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Bruce Momjian wrote:
> 
> I think Andrew Chernow is fundamentally confused about dynamic linking,
> which apache has to use because it doesn't know what type of file it has
> to handle, with linking, which is bound to the application code. 
> pgtypes is bound to the application code so it is not like apache --- an
> application isn't going to be fed arbitrary pgtypes function calls it
> has to handle.
> 

This discussion is now completely pointless as we have conceeded to a 
separate library.  The community has spoken.  We are trying to move on 
and open a discussion on the hook design.

there are numbered questions:
http://archives.postgresql.org/pgsql-hackers/2008-04/msg00565.php

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> Andrew Chernow <ac@esilo.com> writes:
>> There is no need to pass hookData to the hook function.  libpqtypes already 
>> accesses PGconn and PGresult directly so it can just access the hookData member.
> 
> That's a habit you'd really be best advised to stop, if you're going to
> be a separate library.  Otherwise, any time we make an internal change
> in the PGconn struct, it'll break your library --- and we have and will
> feel free to do that without an external soname change.
> 
> What parts of PGconn/PGresult do you need to touch that aren't exposed
> already?
> 
>             regards, tom lane
> 

Well, we manually create a result for arrays and composites.  We also 
use pqResultAlloc in several places.  I will have to look at the code 
again but I'm not sure we can be completely abstracted from the result 
struct.

If you are suggesting that libpqtypes should not access internal libpq, 
than this idea won't work.  We can pull all the code out and hook in, as 
you suggested, but we had no plans of abstracting from internal libpq.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
>>
>> What parts of PGconn/PGresult do you need to touch that aren't exposed
>> already?

Don't need direct access to PGconn at all.

result:
null_field
tupArrSize
client_encoding (need a PGconn for this which might be dead)
pqSetResultError
pqResultAlloc
pqResultStrdup

Also, we basically need write access to every member inside a result 
object ... since we create our own for arrays and composites by copying 
the standard result members over.

/* taken from dupresult inside handlers/utils.c */

PGresult *r = (PGresult *)malloc(sizeof(PGresult));
memset(r, 0, sizeof(PGresult));

/* copy some data from source result */
r->binary          = args->get.result->binary;
r->resultStatus    = args->get.result->resultStatus;
r->noticeHooks     = args->get.result->noticeHooks;
r->client_encoding = args->get.result->client_encoding;
strcpy(r->cmdStatus, args->get.result->cmdStatus);

[snip...]

We can read args->get.result properties using PQfuncs with no problem. 
But we have no way of assign these values to our result 'r'.

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Alvaro Herrera <alvherre@commandprompt.com> writes:
> Andrew Chernow wrote:
>> The core of what I am trying to ask is, there doesn't appear to be an  
>> advantage to separating libpqtypes from libpq in terms of space.

> My guess is that if we provide an useful library, Redhat will distribute
> it some way or another.

The key phrase in that being "some way or another".  Red Hat works with
a concept of core vs extras (or another way to look at it being what
comes on the CDs vs what you have to download from someplace).  I think
it's highly likely that libpgtypes would end up in extras.  If you do
not make it possible to package it that way (ie, separately from libpq),
it's more likely that it won't get packaged at all than that it will be
put in core.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Wed, Apr 9, 2008 at 11:17 AM, Andrew Chernow <ac@esilo.com> wrote:
>  We can read args->get.result properties using PQfuncs with no problem. But
> we have no way of assign these values to our result 'r'.

By the way, our decision to 'create the result' when exposing arrays
and composites saved us from creating lot of interface code to access
these structures from user code...the result already gave us what we
needed.  Just in case anybody missed it, the way arrays of composites
would be handled in libpq would be like this:

PGarray array;
PQgetf(res, 0, "%foo[]", 0, &array); // foo being a composite(a int, b float)
PQclear(res);

for (i = 0; i < PQntuples(array.res);  i++)
{ a int; b float; PQgetf(array.res, i, "%int %float", 0, &a, 1, &b); [...]
}
PQclear(array.res);

In the getf call, the brackets tell libpq that this is an array and a
new result is created to present the array...one column for simple
array, multiple columns if the array is composite.  This can be
recursed if the composite is nested.  We support all the PGget*
functions for the newly created array, providing the OIDs of the
internal composite elements for example.  This is, IMO, payoff of
doing all the work with the type handlers...we don't have to make a
special version of getf that operates over arrays for example.

The upshot of this is that, however separation occurs, the PGresult is
a first class citizen to the types library.

merlin


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> 
> The key phrase in that being "some way or another".  Red Hat works with
> a concept of core vs extras (or another way to look at it being what
> comes on the CDs vs what you have to download from someplace).  I think
> it's highly likely that libpgtypes would end up in extras.  If you do
> not make it possible to package it that way (ie, separately from libpq),
> it's more likely that it won't get packaged at all than that it will be
> put in core.
> 
>             regards, tom lane
> 
> 

I'll buy this.  Better to be safe then sorry.  This patch becomes more 
flexible and distributable when separated.

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> If you are suggesting that libpqtypes should not access internal libpq, 
> than this idea won't work.  We can pull all the code out and hook in, as 
> you suggested, but we had no plans of abstracting from internal libpq.

That's exactly what I'm strongly suggesting.  If you need to include
libpq-int.h at all, then your library will be forever fragile, and could
very well end up classified as "don't ship this at all, it's too likely
to break".
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> 
> That's exactly what I'm strongly suggesting.  If you need to include
> libpq-int.h at all, then your library will be forever fragile, and could
> very well end up classified as "don't ship this at all, it's too likely
> to break".
> 
>             regards, tom lane
> 
> 

I see your point, and it has a lot of merit.  We am completely open to 
hearing how this can be solved.

How do we duplicate a result object and customize many member values 
after the dup?

Do we create a PGresultInfo struct containing all members of a result 
object that gets passed to "PGresuolt *PQresultDup(PGresult *source, 
PGresultInfo *info);"?  Maybe it has a flags member that indicates which 
PQresultInfo members contain values that should override the source result.

Any suggestions?  This is where we are stumped.  Everything else has 
several solutions.  We are not debating this anymore, we are trying to 
implement it.

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


Re: [PATCHES] libpq type system 0.9a

From
Jeff Davis
Date:
On Tue, 2008-04-08 at 21:49 -0400, Merlin Moncure wrote:
> >   * an "escapeIdent" function.
> 
> not sure what this is...
> 

Similar to the quote_ident() function in postgresql:
=> select quote_ident('foo"');quote_ident
-------------"foo"""
(1 row)

It could be called something like PQquoteIdent or PQescapeIdent.

Regards,Jeff Davis



Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
>>> What parts of PGconn/PGresult do you need to touch that aren't exposed
>>> already?

> Don't need direct access to PGconn at all.

Oh, good, that makes things much easier.

> Also, we basically need write access to every member inside a result 
> object ... since we create our own for arrays and composites by copying 
> the standard result members over.

Hmm.  I guess it wouldn't be completely out of the question to expose
the contents of PGresult as part of libpq's API.  We haven't changed it
often, and it's hard to imagine a change that wouldn't be associated
with a major-version change anyhow.  We could do some things to make it
a bit more bulletproof too, like change cmdStatus from fixed-size array
to pointer to allocated space so that CMDSTATUS_LEN doesn't become
part of the API.

Alternatively, we could keep it opaque and expose a bunch of manipulator
routines, but that might be a lot more cumbersome than it's worth.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> 
> Hmm.  I guess it wouldn't be completely out of the question to expose
> the contents of PGresult as part of libpq's API.  We haven't changed it
> often, and it's hard to imagine a change that wouldn't be associated
> with a major-version change anyhow.  We could do some things to make it
> a bit more bulletproof too, like change cmdStatus from fixed-size array
> to pointer to allocated space so that CMDSTATUS_LEN doesn't become
> part of the API.
> 
> Alternatively, we could keep it opaque and expose a bunch of manipulator
> routines, but that might be a lot more cumbersome than it's worth.
> 
>             regards, tom lane
> 

How about a proxy header (if such an animal exists).  Maybe it is 
possible to take pg_result, and all structs it references, and put it in 
result-int.h.  libpq-int.h would obviously include this.  Also, any 
external library, like libpqtypes, that need direct access to a result 
can include result-int.h.  This keeps pg_result and referenced structs 
out of libpq-fe.h.  From a libpq user's viewpoint, nothing has changed.

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


Re: [PATCHES] libpq type system 0.9a

From
Florian Pflug
Date:
Tom Lane wrote:
> But I'll agree that cross-version hazards are a much more clear and 
> present danger.  We've already broken binary compatibility at least
> once since the current binary-I/O system was instituted (intervals
> now have three fields not two) and there are obvious candidates for
> future breakage, such as text locale/encoding support.

But isn't that an argument *for* having support for the binary format in
libpq in a form similar to what this patch offers? Then at least you'd
be safe as long as your libpq-version is >= your server version.
Currently, there seems to be no safe way to use the binary format,
despite it's benefits for moving around large amounts of data.

regards, Florian Pflug



Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Florian Pflug <fgp.phlo.org@gmail.com> writes:
> But isn't that an argument *for* having support for the binary format in
> libpq in a form similar to what this patch offers? Then at least you'd
> be safe as long as your libpq-version is >= your server version.
> Currently, there seems to be no safe way to use the binary format,

That's right, there isn't, and it's folly to imagine that anything like
this will make it "safe".

What we really put in the binary I/O support for was for COPY BINARY,
with a rather limited use-case of fast dump and reload between similar
server versions (you'll notice pg_dump does NOT use it).  Yeah, we
expose it for clients to use, but they had better understand that they
are increasing their risk of cross-version portability problems.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> Tom Lane wrote:
>> Hmm.  I guess it wouldn't be completely out of the question to expose
>> the contents of PGresult as part of libpq's API.

> How about a proxy header (if such an animal exists).

A separate header might be a good idea to discourage unnecessary
reliance on the struct, but it doesn't change the basic fact that
we'd be adding the struct to our ABI and couldn't change it without
a major library version number bump.

Perhaps we could do a partial exposure, where the exported struct
declaration contains "public" fields and there are some "private" ones
after that.  This would still work for external creation of PGresults,
so long as all PGresults are initially manufactured by
PQmakeEmptyPGresult.  That would give us a little bit of wiggle room
... in particular I'd be very tempted not to expose the fields
associated with space allocation (we could export pqResultAlloc
instead), nor anything not foreseeably needed by libpgtypes.

> Maybe it is 
> possible to take pg_result, and all structs it references, and put it in 
> result-int.h.

I'd think something like libpq-result.h would be a better choice of
name.  The other seems likely to collide with who-knows-what from
other packages,
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> 
> Perhaps we could do a partial exposure, where the exported struct
> declaration contains "public" fields and there are some "private" ones
> after that.  
> 
> 

I have another idea.  It would remove a boat load of members that would need to 
be exposed (may remove them all).

Can we make a variant of PQmakeEmptyPGresult?  Maybe something like this:

PGresult *PQdupPGresult( // maybe not the best name?  PGconn *conn,  PGresult *source,  int numAttributes,  int
ntups);

This starts off by calling PQmakeEmptyPGresult and then copying the below 
members from the provided 'source' result argument.
- ExecStatusType resultStatus;
- char cmdStatus[CMDSTATUS_LEN];
- int binary;
- PGNoticeHooks noticeHooks;
- int client_encoding;

It would then preallocate attDescs and tuples which would also set 
numAttributes, ntups & tupArrSize.  attdescs and tuples are not duplicated, only 
allocated based on the 'numAttributes' and 'ntups' arguments.  Now libpqtypes 
only needs direct access to attDescs and tuples, for when it loops array 
elements or composite fields and copies stuff from the source result.

Any interest in this direction?  I am still thinking about how to abstract 
attDesc and tuples, I think it would require more API calls as well.

curBlock, curOffset and spaceLeft were never copied (intialized to zero).  We 
don't touch these.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> Tom Lane wrote:
>>
>> Perhaps we could do a partial exposure, where the exported struct
>> declaration contains "public" fields and there are some "private" ones
>> after that. 
>>
> 
> I have another idea.  It would remove a boat load of members that would 
> need to be exposed (may remove them all).
> 
> Can we make a variant of PQmakeEmptyPGresult?  Maybe something like this:
> 
> 

Here is a quick implementation demonstrating the idea.  It is very similar to 
the patches internal dupresult function (handlers/utils.c).

/* numParameters, paramDescs, errFields, curBlock, curOffset and spaceLeft * are not assigned at all, initialized to
zero. errMsg is handled by * PQmakeEmptyPGresult. */
 
PGresult *PQdupPGresult(  PGconn *conn,  PGresult *source,  int numAttributes,  int ntups)
{  PGresult *r;
  if(!source || numAttributes < 0 || ntups < 0)    return NULL;
  r = PQmakeEmptyPGresult(conn, source->resultStatus);  if(!r)    return NULL;
  r->binary = source->binary;  strcpy(r->cmdStatus, source->cmdStatus);
  /* assigned by PQmakeEmptyPGresult when conn is not NULL */  if(!conn)  {    r->noticeHooks = source->noticeHooks;
r->client_encoding= source->client_encoding;  }
 
  r->attDescs = (PGresAttDesc *)    pqResultAlloc(r, numAttributes * sizeof(PGresAttDesc), TRUE);
  if(!r->attDescs)  {    PQclear(r);    return NULL;  }
  r->numAttributes = numAttributes;
  r->tuples = (PGresAttValue **)    malloc(ntups * sizeof(PGresAttValue *));
  if(!r->tuples)  {    PQclear(r);    return NULL;  }
  r->ntups = ntups;  r->tupArrSize = ntups;
  return r;
}

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> Andrew Chernow <ac@esilo.com> writes:
>>>> What parts of PGconn/PGresult do you need to touch that aren't exposed
>>>> already?
> 
>> Don't need direct access to PGconn at all.
> 
> Oh, good, that makes things much easier.
> 

Shoot!  Feels like you always miss something.

The patch uses PGconn's PQExpBuffer to set errors on a conn.  Currently, 
there is no access to this buffer other than PQerrorMessage.  Is the 
below okay?

extern PQExpBuffer *PQgetErrorBuffer(PGconn *conn);
// OR PQsetErrorMessage(conn, errstr) -- this felt strange to me

The expbuffer API is public, so managing the returned PQExpBuffer would 
not require any additional API calls.

While I am on the subject of things I missed, the patch also uses 
pqSetResultError (mostly during PQgetf).

We no longer need direct access to anything inside pg_result.  However, 
we would need 3 new API calls that would dup a result, set field descs 
and add tuples to a result.  Below are prototypes of what I have so far 
(small footprint for all 3, maybe 100-150 lines).

/* numParameters, paramDescs, errFields, curBlock, * curOffset and spaceLeft are not assigned at all, * initialized to
zero. errMsg is handled by * PQmakeEmptyPGresult.  attDescs and tuples are not * duplicated, only allocated based on
'ntups'and * 'numAttributes'.  The idea is to dup the result * but customize attDescs and tuples. */
 
PGresult *PQresultDup(  PGconn *conn,  PGresult *source,  int ntups,  int numAttributes);

/* Only for results returned by PQresultDup.  This * will set the field descs for 'field_num'.  The * PGresAttDesc
structwas not used to avoid * exposing it. */
 
int PQresultSetFieldDesc(  PGresult *res,  int field_num,  const char *name,  Oid tableid,  int columnid,  int format,
Oidtypid,  int typlen,  int typmod)
 

/* Only for results returned by PQresultDup.  This * will append a new tuple to res.  A PGresAttValue * is allocated
andput at index 'res->ntups'.  This * is similar to pqAddTuple except that the tuples * table has been pre-allocated.
Inour case, ntups * and numAttributes are known when calling resultDup. */
 
int PQresultAddTuple(  PGresult *res,  char *value,  int len);

The above would allow an external app to dup a result and customize its 
rows and columns.  Our patch uses this for arrays and composites.

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


Re: [PATCHES] libpq type system 0.9a

From
Gregory Stark
Date:
"Andrew Chernow" <ac@esilo.com> writes:

> Shoot!  Feels like you always miss something.
>
> The patch uses PGconn's PQExpBuffer to set errors on a conn.  Currently, there
> is no access to this buffer other than PQerrorMessage.  Is the below okay?

Surely you would just provide a function to get pqtypes errors separate from
libpq errors?

--  Gregory Stark EnterpriseDB          http://www.enterprisedb.com Ask me about EnterpriseDB's PostGIS support!


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Gregory Stark wrote:
> "Andrew Chernow" <ac@esilo.com> writes:
> 
>> Shoot!  Feels like you always miss something.
>>
>> The patch uses PGconn's PQExpBuffer to set errors on a conn.  Currently, there
>> is no access to this buffer other than PQerrorMessage.  Is the below okay?
> 
> Surely you would just provide a function to get pqtypes errors separate from
> libpq errors?
> 

That's extremely akward.  Consider the below.

int getvalues(PGresult *res, int *x, char **t)
{  return PQgetf(res, "get the int and text);
}

if(getvalues(res, &x, &t))  printf("%s\n", PQresultErrorMessage(res));

How would the caller of getvalues know whether the error was generated 
by a libpqtypes API call or by a libpq API call (like PQgetvalue)? 
PQgetf should behave exactely as PQgetvalue does, in regards to errors.

Same holds true for PGconn.  Normally, you are using PQputf which sets 
the error in PQparamErrorMessage.  Then there is PQparamCreate(conn) or 
PQparamExec(conn, param, ...) and friends?  PQparamExec calls 
PQexecParams internally which can return NULL, setting an error message 
inside PGconn.  We felt our light-weight wrappers should be consistent 
in behavior.  If you get a NULL PGresult for a return value, 
PQerrorMessage should be checked.

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


Re: [PATCHES] libpq type system 0.9a

From
Gregory Stark
Date:
"Andrew Chernow" <ac@esilo.com> writes:

> How would the caller of getvalues know whether the error was generated by a
> libpqtypes API call or by a libpq API call (like PQgetvalue)? PQgetf should
> behave exactely as PQgetvalue does, in regards to errors.

Hm. Well I was thinking of errors from database operations rather than things
like PQgetvalue. 

I suppose we have to decide whether pqtypes is a "wrapper" around libpq in
which case your functions would have to take the libpq error and copy it into
your error state or an additional set of functions which are really part of
appendage of libpq




--  Gregory Stark EnterpriseDB          http://www.enterprisedb.com Ask me about EnterpriseDB's 24x7 Postgres support!


Re: [PATCHES] libpq type system 0.9a

From
"Merlin Moncure"
Date:
On Thu, Apr 10, 2008 at 10:56 AM, Gregory Stark <stark@enterprisedb.com> wrote:
> "Andrew Chernow" <ac@esilo.com> writes:
> > How would the caller of getvalues know whether the error was generated by a
>  > libpqtypes API call or by a libpq API call (like PQgetvalue)? PQgetf should
>  > behave exactely as PQgetvalue does, in regards to errors.
>
>  Hm. Well I was thinking of errors from database operations rather than things
>  like PQgetvalue.
>
>  I suppose we have to decide whether pqtypes is a "wrapper" around libpq in
>  which case your functions would have to take the libpq error and copy it into
>  your error state or an additional set of functions which are really part of
>  appendage of libpq

We see libpq types to be simply extending the api with more functions.We really only introduce new error handling with
thePGparam struct
 
that is following the same conventions that exist currently.  The
separation of libpqtypes out of libpq into a new library is an
architectural change for organization purposes.  We are not defining a
new api or wrapping an existing one for new functionality (which is
the same thing imo).  With that in mind, libpq's error system is
object based, not library based.  Thee three objects that set errors
are result, conn, (and now), param.  In libpq terms there is no global
error.  (no errno, getlasterror, etc).

So, if I understand you correctly, we see libpqtypes is an appendage
in your terms...were you thinking along different lines?  Consider
that we don't reproduce all the things libpq offers, we share the same
objects, etc. (In fact, we went though some acrobatics to introduce as
little new behavior as possible).

merlin


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> 
> /* Only for results returned by PQresultDup.  This
>  * will append a new tuple to res.  A PGresAttValue
>  * is allocated and put at index 'res->ntups'.  This
>  * is similar to pqAddTuple except that the tuples
>  * table has been pre-allocated.  In our case, ntups
>  * and numAttributes are known when calling resultDup.
>  */
> int PQresultAddTuple(
>   PGresult *res,
>   char *value,
>   int len);
> 

PQresultAddTuple is not quite correct.  The below is its replacement:

int PQresultSetFieldValue(  PGresult *res,  int tup_num,  int field_num,  char *value,  int len)

Recap: PQresultDup, PQresultSetFieldDesc and PQresultSetFieldValue.

We feel this approach, which we initially thought wouldn't work, is 
better than making pg_result public.

These functions could be useful outside of pqtypes, providing a way of 
filtering/modifying a result object ... consider:

PGresult *execit(conn, stmt)
{  res = PQexec(conn, stmt);  if(some_app_cond_is_true)  {    newres = PQresultDup();    // ... customize tups and
fields   //PQresultSetFieldDesc and PQresultSetFieldValue    PQclear(res);    res = newres;  }  return res;
 
}

// res could be custom built
res = execit(conn, stmt);
PQclear(res);

This is not an everyday need, but I'm sure it could provide some niche 
app functionality currently unavailable.  Possibly useful to libpq 
wrapper APIs.  Either way, it works great for pqtypes and avoids 
exposing pg_result.

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> Recap: PQresultDup, PQresultSetFieldDesc and PQresultSetFieldValue.
> We feel this approach, which we initially thought wouldn't work, is 
> better than making pg_result public.

That doesn't seem to me to fit very well with libpq's internals ---
in particular the PQresult struct is not designed to support dynamically
adding columns, which retail PQresultSetFieldDesc() calls would seem to
require, and it's definitely not designed to allow that to happen after
you've begun to store data, which the apparent freedom to intermix
PQresultSetFieldDesc and PQresultSetFieldValue calls would seem to
imply.

Instead of PQresultSetFieldDesc, I think it might be better to provide a
call that creates an empty (of data) PGresult with a specified tuple
descriptor in one go.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> Gregory Stark wrote:
>> Surely you would just provide a function to get pqtypes errors separate from
>> libpq errors?

> That's extremely akward.  Consider the below.

I'm just as suspicious of this as Greg is.  In particular, I really
disagree with PQgetf storing an error message into a PGresult, because
that creates a semantic inconsistency.  Up to now, PGresults have come
in two flavors, "okay" (which might hold data) and "error" (which hold
error messages).  Now you're proposing to stick an error message into
an "okay" data-holding PGresult.  Does that turn it into an "error"
result?  Does its PQresultStatus change?  Does it maybe forget the data
it used to hold?

An even more fundamental objection is that surely PQgetf's PGresult
argument should be const.

> int getvalues(PGresult *res, int *x, char **t)
> {
>    return PQgetf(res, "get the int and text);
> }

> if(getvalues(res, &x, &t))
>    printf("%s\n", PQresultErrorMessage(res));

This example is entirely unconvincing.  There is no reason to be checking
PQresultErrorMessage at this point --- if you haven't already checked the
PGresult to be "okay", you should certainly not be trying to extract
fields from it.  So I don't see that you are saving any steps here.

> PQgetf should behave exactely as PQgetvalue does, in regards to errors.

Uh-huh.  You'll notice that PQgetvalue treats the PGresult as const.

> Same holds true for PGconn.

I'm not convinced about that side either.  It doesn't fail the basic
const-ness test, perhaps, but it still looks mostly like you are trying
to avoid the necessity to think hard about how you're going to report
errors.  You're going to have to confront the issue for operations that
only take a PGresult, and once you've got a good solution on that side
it might be better to use it for PQputf too.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> Andrew Chernow <ac@esilo.com> writes:
>> Recap: PQresultDup, PQresultSetFieldDesc and PQresultSetFieldValue.
>> We feel this approach, which we initially thought wouldn't work, is 
>> better than making pg_result public.
> 
> That doesn't seem to me to fit very well with libpq's internals ---
> in particular the PQresult struct is not designed to support dynamically
> adding columns, which retail PQresultSetFieldDesc() calls would seem to
> require, and it's definitely not designed to allow that to happen after
> you've begun to store data, which the apparent freedom to intermix
> PQresultSetFieldDesc and PQresultSetFieldValue calls would seem to
> imply.
> 
> Instead of PQresultSetFieldDesc, I think it might be better to provide a
> call that creates an empty (of data) PGresult with a specified tuple
> descriptor in one go.
> 
>             regards, tom lane
> 
> 

Are you against exposing PGresAttDesc?

PGresult *PQresultDup(  PGconn *conn,  PGresult *res,  int ntups,  int numAttributes,  PGresAttDesc *attDescs);

If you don't want to expose PGresAttDesc, then the only other solution 
would be to pass parallel arrays of attname[], tableid[], columnid[], 
etc...  Not the most friendly solution, but it would do the trick.

Recap: Use new PQresultDup, throw out setfielddesc and keep 
setfieldvalue the same.

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:> PQresultErrorMessage at this point --- if you haven't already> checked the PGresult to be "okay", you
shouldcertainly not be> trying to extract fields from it.  So I don't see that you> are saving any steps here.
 

Correct, I agree.  Our thinking was flawed.  The issue we face is that, 
unlike getvalue, getf can fail in many ways ... like bad format string 
or type mismatch.  If you would rather us introduce a pqtypes specific 
error for getf.  putf doesn't suffer from this issue because it uses 
PGparamErrorMessage.
>> Same holds true for PGconn.>> I'm not convinced about that side either.  It doesn't fail the basic> const-ness test,
perhaps,but it still looks mostly like you>are trying to avoid the necessity to think hard about how you're>going to
report

The issue is not a matter of know-how, it is a matter of creating 
ambiguos situations in regards to where the error is (I'm thinking from 
a libpq user's perspective).  This only applies to PQparamExec and 
fiends, NOT PQputf.  All existing exec/send functions put an error in 
the conn (if the result is NULL check the conn).

paramexec can fail prior to internally calling PQexecParams, in which 
case it returns NULL because no result has been constructed yet.  The 
question is, where does the error go?

res = paramexec(conn, param, ...
if(!res)  // check pgconn or pgparam?  // can conn have an old error (false-pos)

Not using the conn's error msg means that one must check the param and 
conn if the return value is NULL.  I think the best behavior here is to 
check PQerrorMessage when any exec function returns a NULL result, 
including pqtypes.  If not, I think it could get confusing to the API user.

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


Re: [PATCHES] libpq type system 0.9a

From
Tom Lane
Date:
Andrew Chernow <ac@esilo.com> writes:
> PGresult *PQresultDup(
>    PGconn *conn,
>    PGresult *res,
>    int ntups,
>    int numAttributes,
>    PGresAttDesc *attDescs);

I don't understand why this is a "dup" operation.  How can you "dup"
if you are specifying a new tuple descriptor?  I'd have expected
something like

PGresult *PQmakeResult(PGconn *conn, int numAttributes, PGresAttDesc *attDescs)

producing a zero-row PGRES_TUPLES_OK result that you can then load with
data via PQresultSetFieldValue calls.  (Even the conn argument is a bit
of a wart, but I think we probably need it so we can copy some of its
private fields.)

Copying an existing PGresult might have some use too, but surely that
can't change its tuple descriptor.
        regards, tom lane


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Tom Lane wrote:
> Andrew Chernow <ac@esilo.com> writes:
>> PGresult *PQresultDup(
>>    PGconn *conn,
>>    PGresult *res,
>>    int ntups,
>>    int numAttributes,
>>    PGresAttDesc *attDescs);
> 
> I don't understand why this is a "dup" operation.  How can you "dup"
> if you are specifying a new tuple descriptor?  I'd have expected
> something like
> 
> PGresult *PQmakeResult(PGconn *conn, int numAttributes, PGresAttDesc *attDescs)
> 
> producing a zero-row PGRES_TUPLES_OK result that you can then load with
> data via PQresultSetFieldValue calls.  (Even the conn argument is a bit
> of a wart, but I think we probably need it so we can copy some of its
> private fields.)
> 
> Copying an existing PGresult might have some use too, but surely that
> can't change its tuple descriptor.
> 
>             regards, tom lane
> 

Yeah, "dup" wasn't the best name.

You need more arguments to makeresult though, since you reomved the 
'source' result.  You need binary, cmdStatus, noticeHooks and 
client_encoding.

PQmakeResult(conn,  PQcmdStatus(res),  PQbinaryTuples(res),  ?client_encoding?,  ?noticeHooks?,  ntups, /* this
interactswith setfieldvalue */  numAttributes,  attDescs);
 

For client_encoding and noticeHooks, the conn can be NULL.  Previously, 
we copied this info from the source result when conn was NULL.
> producing a zero-row PGRES_TUPLES_OK result that you can then>load with data via PQresultSetFieldValue calls.
I like this idea but you removed the 'ntups' argument.  There is no way 
to adjust ntups after the makeresult call, its a private member and 
setfieldvalue has no concept of incrementing ntups.  Since you are not 
appending a tuple like pqAddTuple, or inserting one, you can't increment 
ntups in setfieldvalue.

But, you could have a function like PQresultAddEmptyTuple(res) which 
would have to be called before you can set field values on a tup_num. 
The empty tuple would grow tuples when needed and increment ntups.  The 
new tuple would be zerod (all NULL values).

....something like below

res = PQmakeResult(...);
for(ntups)
{  PQresultAddEmptyTuple(res); // or PQresultMakeEmptyTuple?  for(nfields)    PQresultSetFieldValue(res, tup_num,
field_num,....);
 
}


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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> 
> For client_encoding and noticeHooks, the conn can be NULL.  Previously, 
> we copied this info from the source result when conn was NULL.
> 
> 

Looks like we don't need client_encoding.  My guess is, in our use case 
noticeHooks can probably be NULL for the created result, when makeresult 
is not provided a conn.
> ....something like below>> res = PQmakeResult(...);> for(ntups)> {>   PQresultAddEmptyTuple(res); // or
PQresultMakeEmptyTuple?>  for(nfields)>     PQresultSetFieldValue(res, tup_num, field_num, ....);> }>>
 

I think a better idea would be to make setfieldvalue more dynamic, 
removing the need for PQresultAddEmptyTuple.  Only allow tup_num to be 
<= res->ntups.  This will only allow adding one tuple at a time.  The 
other option would allow arbitray tup_nums to be passed in, like ntups 
is 1 but the provided tup_num is 67.  In this case, we would have to 
back fill.  It seems better to only grow by one tuple at a time.  We can 
get it working either way, we just prefer one tuple at a time allocation.

int PQresultSetFieldValue(  PGresult *res,  int tup_num,  int field_num,  char *value,  int len)
{  if(!check_field_value(res, field_num))    return FALSE;
  if(tup_num > res->ntups)    // error, tup_num must be <= res->ntups
  if(res->ntups >= res->tupArrSize)    // grow res->tuples
  if(tup_num == res->ntups && !res->tuples[tup_num])    // need to allocate tuples[tup_num]
  // blah ... blah ...
}


New PQmakeResult prototype:

PQmakeResult(  PGconn *conn,  const char *cmdStatus,  int binaryTuples,  int numAttributes,  PGresAttDesc *attDescs);

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


Re: [PATCHES] libpq type system 0.9a

From
Andrew Chernow
Date:
Andrew Chernow wrote:
> res = paramexec(conn, param, ...
> if(!res)
>   // check pgconn or pgparam?
>   // can conn have an old error (false-pos)
> 

We will just always dump the error message into the param.  If 
PQexecParams fails with a NULL result, we will copy PQerrorMessage over 
to param->errMsg.

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