Subject: Object IDs in Parse message

From: Malcolm Matalka <[email-masked]>
Date: Tue, 03 Sep 2019 22:01:28 +0200

Hello, I'm implementing my own pgsql client for fun and I'm trying to
understand how to send a Parse message.  The final parameter to Parse is
a series of Int32s with the description:

Specifies the object ID of the parameter data type. Placing a zero here
is equivalent to leaving the type unspecified.

But where do I find the list of object IDs?  Doing some internet
searches didn't bring up much.  Poking around the code I came across the
file:

./src/backend/catalog/pg_type_d.h

And that has a series of OID's with integer values.  Is this the mapping
I'm looking for?

If so, It's not clear how to express some things.  For example there is
a MONEYARRAYOID, but no MONEYOID.  Would I use, for example, NUMERICOID
for money?  If so, why does MONEYARRAYOID exist rather than using
NUMERICOID?

Thanks,
/Malcolm

---

From: Dave Cramer <[email-masked]>
Date: Tue, 3 Sep 2019 16:02:24 -0400

select oid, * from pg_type

Dave Cramer

[email-masked]
www.postgresintl.com

---

From: Tom Lane <[email-masked]>
Date: Tue, 03 Sep 2019 16:24:39 -0400

> But where do I find the list of object IDs?

SELECT oid, typname FROM pg_type;

> a MONEYARRAYOID, but no MONEYOID.

For historical reasons, the macro for money's OID is CASHOID.
There's no grandfathered symbol for money[], though, so that
gets a name constructed per standard rules (cf form_pg_type_symbol
in genbki.pl).

However, I fail to see why a generic client would need to know that.
If you're hard-wiring OIDs into your code for anything beyond very
basic types like int4, you're probably doing it wrong.  Remember
that PG is an extensible system and you may be called on to handle
queries that deal with non-built-in types, so even if you had
code for everything appearing in pg_type_d.h, it wouldn't be
exhaustive.  Better to look up type OIDs at runtime.  In the case
of Parse messages, you likely want to let the backend resolve
the parameter types anyway, ie just send zeroes.

			regards, tom lane

---

From: Malcolm Matalka <[email-masked]>
Date: Wed, 04 Sep 2019 09:39:47 +0200

> basic types like int4, you're probably doing it wrong.  Remember

Ok, it wasn't clear to me if and when I should pass this data in.  I
couldn't find any documentation for this translating to performance
improvement, or addressing any possible errors due to ambiguity in
types.  In general, should an interface no pass that information in on a
Parse?  Is there a reason to do it?

> the parameter types anyway, ie just send zeroes.

Thank you for the detailed response

---

From: Dave Cramer <[email-masked]>
Date: Wed, 4 Sep 2019 05:49:21 -0400

> Parse?  Is there a reason to do it?

Yes, if you ever decide to use binary mode for the parameters and the
results then you need to know the type
The jdbc driver and the .net driver both do this.

Dave

---

From: Tom Lane <[email-masked]>
Date: Wed, 04 Sep 2019 10:05:03 -0400

> Parse?  Is there a reason to do it?

You should only pass type OIDs if you know for sure what they should be,
which an interface library passing on a query generated elsewhere will
not know --- unless it provides an API for the caller to tell it.

The convention that seems to have evolved in places that lack such APIs
is to pass zeroes, and instruct human authors of queries that if the
server doesn't resolve the types of parameter placeholders the way they
want, force it with a cast in the text of the query, eg "$1::int8".
Otherwise you need to add some out-of-band notation for specifying the
types, plus a way to resolve that notation into numeric OIDs, and it's
all a giant pain in the rear for all concerned.

Passing zeroes is more workable than you might think, since the
server can correctly guess the type of a placeholder in a lot
of cases.  However, it might be best to avoid it if you intend
to pass parameter values in binary, since that will lose a lot
of the safety margin for detecting wrong guesses.

			regards, tom lane