Thread: Information about columns

Information about columns

From
Dario Teixeira
Date:
Hi,

Is there some way to find out meta-information about the columns generated
by any SELECT query?  If the SELECT returns values from a regular table or
a view, I can use pg_class and pg_attribute to get the info I need:

CREATE TABLE foobar (quant int);
SELECT quant FROM foobar;
SELECT attname, attnum FROM pg_attribute, pg_class WHERE attrelid=pg_class.oid AND relname='foobar';

But what if the columns belong to a "virtual" table instead, as per the
(silly) example below?

SELECT 1, 2*quant FROM foobar;

Thanks in advance for any help you might give me!
Best regards,
Dario Teixeira





Re: Information about columns

From
Craig Ringer
Date:
On Mon, 2009-06-22 at 05:26 -0700, Dario Teixeira wrote:

> Is there some way to find out meta-information about the columns generated
> by any SELECT query?

How are you talking to the database ? ODBC? JDBC? LibPQ? Something else?
Or do you want this from within PL/PgSQL ?

You'll usually find that this information is most easily obtained via
your client driver. I don't know if it's exposed at the SQL level, but
it's certainly available from the underlying PostgreSQL network
protocol.

--
Craig Ringer


Re: Information about columns

From
Pavel Stehule
Date:
2009/6/22 Dario Teixeira <darioteixeira@yahoo.com>:
>
> Hi,
>
> Is there some way to find out meta-information about the columns generated
> by any SELECT query?  If the SELECT returns values from a regular table or
> a view, I can use pg_class and pg_attribute to get the info I need:
>
> CREATE TABLE foobar (quant int);
> SELECT quant FROM foobar;
> SELECT attname, attnum FROM pg_attribute, pg_class WHERE attrelid=pg_class.oid AND relname='foobar';
>
> But what if the columns belong to a "virtual" table instead, as per the
> (silly) example below?
>
> SELECT 1, 2*quant FROM foobar;
>


you can do it on low level - look on functions

PQdescribePrepared
PQdescribePortal

regards
Pavel Stehule

> Thanks in advance for any help you might give me!
> Best regards,
> Dario Teixeira
>
>
>
>
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

Re: Information about columns

From
Dario Teixeira
Date:
Hi,

> How are you talking to the database ? ODBC? JDBC? LibPQ? Something else?
> Or do you want this from within PL/PgSQL ?

I'm hacking on a client-side library which talks directly to the Postmaster
using the wire protocol [1]. I need this information to improve some of the
nullability-detection heuristics used by the library.

Cheers,
Dario

[1] http://pgocaml.berlios.de/





Re: Information about columns

From
John DeSoi
Date:
On Jun 22, 2009, at 11:43 AM, Dario Teixeira wrote:

>> How are you talking to the database ? ODBC? JDBC? LibPQ? Something
>> else?
>> Or do you want this from within PL/PgSQL ?
>
> I'm hacking on a client-side library which talks directly to the
> Postmaster
> using the wire protocol [1]. I need this information to improve some
> of the
> nullability-detection heuristics used by the library.

The information you want is always returned from the query as a row
description message. This includes the type oid of real and computed
columns.

See the RowDescription message on this page for details:

http://www.postgresql.org/docs/8.3/static/protocol-message-formats.html



John DeSoi, Ph.D.





Re: Information about columns

From
Dario Teixeira
Date:
Hi,

> The information you want is always returned from the query
> as a row description message. This includes the type oid of
> real and computed columns.
>
> See the RowDescription message on this page for details:

Thanks for the reply.  Note that is in fact RowDescription that PG'OCaml
is already using to obtain the type oid of real and computed columns.
The problem is that in some circumstances RowDescription does not provide
a pg_class OID where I (naïvely perhaps) expect it.

To be more precise, when issuing a SELECT for tables and views, the
associated pg_class OID is always provided.  Doing a SELECT on 'foobar'
and 'foobar1' will work:

CREATE TABLE foobar (quant int);

CREATE VIEW foobar1 AS SELECT * FROM foobar;

*However*, if I create a new type (which has an associated pg_class entry),
and define a function which returns a SETOF that type, RowDescription will
not tell me its OID.  For example:

CREATE TYPE foobar_t AS (quant int);

CREATE FUNCTION foobar2 () RETURNS SETOF foobar_t AS
'SELECT * FROM foobar' LANGUAGE sql STABLE;

Is this a bug or a conscious decision?  And on the latter case, how can
I retrieve the pg_class OID of foobar_t?

Thanks again,
Dario Teixeira





Re: Information about columns

From
John DeSoi
Date:
On Jun 22, 2009, at 4:57 PM, Dario Teixeira wrote:

> *However*, if I create a new type (which has an associated pg_class
> entry),
> and define a function which returns a SETOF that type,
> RowDescription will
> not tell me its OID.  For example:
>
> CREATE TYPE foobar_t AS (quant int);
>
> CREATE FUNCTION foobar2 () RETURNS SETOF foobar_t AS
> 'SELECT * FROM foobar' LANGUAGE sql STABLE;
>
> Is this a bug or a conscious decision?  And on the latter case, how
> can
> I retrieve the pg_class OID of foobar_t?

I don't think it is a bug because the documentation clearly states "if
the field can be identified as a column of a specific table, the
object ID of the table; otherwise zero." A type is not the same as a
table.

It is not as elegant as you would like, but maybe one idea is to
create your own alias of the built in type so you can determine the
answer just by looking at the column type. For example, instead of
using "int" in CREATE TYPE above, create a your own type equivalent to
an integer.



John DeSoi, Ph.D.





Re: Information about columns

From
Tom Lane
Date:
Dario Teixeira <darioteixeira@yahoo.com> writes:
> *However*, if I create a new type (which has an associated pg_class entry),
> and define a function which returns a SETOF that type, RowDescription will
> not tell me its OID.  For example:
> ...
> Is this a bug or a conscious decision?

It's intentional; IIRC, the current behavior is defined that way because
that's what the JDBC driver needs to implement the JDBC specs.  Putting
information about composite types where information about tables is
expected would confuse the heck out of existing client code.

            regards, tom lane

Re: Information about columns

From
Dario Teixeira
Date:
Hi,

> It is not as elegant as you would like, but maybe one idea
> is to create your own alias of the built in type so you can
> determine the answer just by looking at the column type. For
> example, instead of using "int" in CREATE TYPE above, create
> a your own type equivalent to an integer.

Thanks for the suggestion.  Yes, that should work, but it really
is a very cumbersome and brittle solution.

Cheers,
Dario





Re: Information about columns

From
darioteixeira@yahoo.com
Date:
Hi,

> It's intentional; IIRC, the current behavior is defined that way because
> that's what the JDBC driver needs to implement the JDBC specs.  Putting
> information about composite types where information about tables is
> expected would confuse the heck out of existing client code.

Thanks for the info.  So, given that RowDescription is a dead-end, is there
any other way I can determine the composite type associated with a function
return?  If, for example, I have the following defined in the database,

CREATE TABLE foobar (quant int);
CREATE TYPE foobar_t AS (quant int);
CREATE FUNCTION foobar2 () RETURNS SETOF foobar_t AS
'SELECT * FROM foobar' LANGUAGE sql STABLE;

and the client side issues a "SELECT * FROM foobar2 ()", is there some
means of determining that a function "foobar2" returning "foobar_t" was
invoked?  I don't care how convoluted the steps may be, since all of this
happens at compile-time and has a zero runtime penalty.

Barring client-side parsing of SQL (a dumb idea), the only solution I can
think of requires the client code to explicitly mark the function invoked.
I would rather avoid this solution, however, since it is error prone and
defeats the premise of the library.

Thanks again for your time and attention!
Cheers,
Dario





Re: Information about columns

From
Tom Lane
Date:
darioteixeira@yahoo.com writes:
> Thanks for the info.� So, given that RowDescription is a dead-end, is there
> any other way I can determine the composite type associated with a function
> return?

Why do you think that's a useful activity for client-side code to engage
in?

            regards, tom lane

Re: Information about columns

From
Dario Teixeira
Date:
Hi,

> Why do you think that's a useful activity for client-side
> code to engage in?

Strongly typed languages like Ocaml and Haskell deal with the possibility
of missing values by having "option types".  Though at first glance SQL's
NULL seems like a similar concept, in fact NULL is more like a constraint
on a table column instead of defining a different type.  This impedance
mismatch causes some trouble when writing bindings that aim to preserve
type-safety.

I doubt there is a clean way around this (barring Postgresql implementing
option types).  Therefore, I'm working on a workaround that involves the
Postgresql side annotating the nullability of type definitions by issuing
comments on the type (using COMMENT ON).  Yes, it is a hack, but will solve
my problem as long as I can determine the return type (and thus fetch its
comment) associated with a query.

I know other people faced this problem before when writing Ocaml or Haskell
bindings, and that is why I know there is no straightforward solution.  Still,
I welcome any thinking-outside-the-box suggestions...

Cheers,
Dario Teixeira





Re: Information about columns

From
Tom Lane
Date:
Dario Teixeira <darioteixeira@yahoo.com> writes:
> I doubt there is a clean way around this (barring Postgresql implementing
> option types).  Therefore, I'm working on a workaround that involves the
> Postgresql side annotating the nullability of type definitions by issuing
> comments on the type (using COMMENT ON).  Yes, it is a hack, but will solve
> my problem as long as I can determine the return type (and thus fetch its
> comment) associated with a query.

Okay, but that has nothing to do with either functions or composite
types.

The reasonable way to handle this in Postgres (IMHO) would be to define
not-null domains over the types you care about, and then lobby us to
have RowDescription return domain OIDs instead of smashing domains to
their base types.  I don't recall the exact reasoning for the domain
smashing behavior; perhaps it could be made adjustable.

            regards, tom lane