agora inbox for pgsql-docs@postgresql.org
help / color / mirror / Atom feedFrom: Tom Lane <tgl@sss.pgh.pa.us>
To: David G. Johnston <david.g.johnston@gmail.com>
Cc: kengruven@gmail.com <kengruven@gmail.com>
Cc: pgsql-docs@lists.postgresql.org <pgsql-docs@lists.postgresql.org>
Subject: Re: Anonymous record member access
Date: Tue, 15 Sep 2026 10:19:30 -0400
Message-ID: <274668.1789481970@sss.pgh.pa.us> (raw)
In-Reply-To: <CAKFQuwYXTCWcLMDPXQYTuZPJ+oW89kTT=ikyi-PSya+nRqW_0w@mail.gmail.com>
References: <178941114936.1263.15482664434063598995@wrigleys.postgresql.org>
<CAKFQuwYXTCWcLMDPXQYTuZPJ+oW89kTT=ikyi-PSya+nRqW_0w@mail.gmail.com>
"David G. Johnston" <david.g.johnston@gmail.com> writes:
> On Monday, September 14, 2026, PG Doc comments form <noreply@postgresql.org>
> wrote:
>> To summarize, things I don't understand from the docs:
>> - where exactly the .f1 notation is documented
> It probably isn’t documented behavior and thus should not be relied upon.
Yeah, it's not documented in any user-facing place, AFAICS. That's
because it's not a feature so much as a collection of legacy behaviors.
>> - where/why it's not allowed to be used
>> - how/why a ROW changes behavior when returned from a FUNCTION
> I suspect these are just boundary issues that would be considered bugs if
> this entire thing were considered documented behavior.
The key thing to understand is static versus dynamic typing.
If foo() is declared to return a named composite type, then
when you write
SELECT (foo(...)).x
the parser can look up the composite type and identify that yes,
x is a column of that type, it has position n and data type so-and-so,
and then it knows the result type of that expression and can continue
parsing. But if foo() is declared to return record then no such
information is available, and the parser must throw up its hands.
The function might return one thing today and something entirely
different tomorrow.
ROW() constructors do need to assign column names in the
anonymous record type they construct, and what they use is
indeed f1,f2,etc. But for most purposes in SQL you can't
see that because SQL is mostly a statically-typed language,
so it can't do much with an anonymous record value other
than pass it around. There are functions like to_json()
that are declared to accept type record, which means that
they can work on any composite type whatever. They use
below-SQL-level implementation details to find out what are
the column names and datatypes inside whatever they're handed.
You can do some of this stuff in plpgsql or other PLs, which
are less resolute about being statically typed than the main
SQL grammar. There are also behaviors that are just plain
warts, such as your example
SELECT (ROW(3,4,5)).f1; -- returns 3
On what I've been telling you, that ought to fail. It does
work, because the parser logic that looks up the composite
type of the left-hand side of a field accessor dot has a
special case for when that left-hand side is exactly a RowExpr.
(I think yours truly might be responsible for that, but it's
still a wart.)
So it's all pretty messy and no one has cared to try to make it
coherent enough to be document-able. I join with David in
recommending that you avoid relying on this. If we ever did
try to make it coherent, we'd likely elect to break some
behaviors that happen to work today.
regards, tom lane
view thread (3+ messages)
Message-ID: <274668.1789481970@sss.pgh.pa.us>
Permalink: ../274668.1789481970@sss.pgh.pa.us/
Also on: postgresql.org/message-id/274668.1789481970@sss.pgh.pa.us
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-docs@postgresql.org
Cc: tgl@sss.pgh.pa.us, david.g.johnston@gmail.com, kengruven@gmail.com, pgsql-docs@lists.postgresql.org
Subject: Re: Anonymous record member access
In-Reply-To: <274668.1789481970@sss.pgh.pa.us>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox