Re: Proposal: SELECT * EXCLUDE (...) command

From: Peter Eisentraut <peter(at)eisentraut(dot)org>
To: Hunaid Sohail <hunaidpgml(at)gmail(dot)com>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: Proposal: SELECT * EXCLUDE (...) command
Date: 2026-01-13 20:28:36
Message-ID: 63e1587b-4258-41de-b823-948f8cc692d9@eisentraut.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 08.01.26 11:17, Hunaid Sohail wrote:
> I would like feedback on the proposed feature: SELECT * EXCLUDE.

I proposed this feature to the SQL standard in September 2025. It was
generally welcome, but the processing was postponed because some other
people wanted to add even more clauses for postprocessing asterisk
expansions, such as REPLACE or RENAME, which are also present in some
other implementations. So we'll likely come back in a few months with
another proposal that includes more of that. But in the meantime, I
think implementation work can proceed.

I have attached my change proposal paper here. This shows the intended
semantics, and I think those were pretty much agreed upon by the SQL
working group.

I tested your patch against the examples given in that paper:

Example 2:

=> select * exclude (bar) from t1;
ERROR: 42703: column "bar" does not exist

Raising an error is correct, but you should do some work to get an error
indicator, like you get when you use a non-existing column in the select
list:

=> select bar from t1;
ERROR: 42703: column "bar" does not exist
LINE 1: select bar from t1;
^

Example 3:

=> select * exclude (foo) from t1;
ERROR: 02000: SELECT list is empty after excluding all columns

This is arguably correct, but I raise in the paper the possibility that
implementations that support zero-column tables should support this as
an extension. I suggest to do this here.

Example 5:

=> select * exclude (bar, bar) from t2;
ERROR: 42703: column "bar" does not exist

It is correct to raise an error for duplicate entries in the exclude
list, but the specific error raised here doesn't make sense.

Example 6:

=> select * exclude (foo) from t1, t2;
ERROR: 02000: SELECT list is empty after excluding all columns

My paper proposes that this should be an error because foo is ambiguous.
This is where DuckDB diverges, and you mentioned that you followed
DuckDB. But I think the SQL standard is not going to go that way. But
moreover, the error you raise here doesn't make sense. It looks like
your implementation is checking the empty select list case on a
per-table basis, which would be wrong.

Example 8:

=> select * exclude (t1.foo) from t1, t2;
ERROR: 02000: SELECT list is empty after excluding all columns

This is similarly wrong.

Example 11:

=> select foo, t1.* exclude (foo) from t1;
ERROR: 02000: SELECT list is empty after excluding all columns

And this error is also wrong for similar reasons.

You also need to be careful with column privileges. For example:

create table t5 (a int, b int, c int);
grant select (a) on table t5 to user2;
-- as user2
select * exclude (b, c) from t5;

At least under the SQL standard security model, this should be an error,
because you need to check the privileges of b and c. This is because
you shouldn't be able to use this feature to probe for the existence of
columns that you otherwise don't have access to. PostgreSQL doesn't
quite work that way, but I think for a new feature we should take this
into account. (My paper doesn't call this out because it falls out of
existing rules.)

So it looks like this implementation will need a bit of work, but I
welcome that this is taken up. In the meantime, if you or anyone has
comments on the SQL change proposal, let me know also. We can develop
these in parallel.

Attachment Content-Type Size
bcn036r1-Select list EXCLUDE.pdf application/pdf 186.2 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Geoghegan 2026-01-13 20:36:28 Re: index prefetching
Previous Message Andres Freund 2026-01-13 20:26:02 Re: Enhancing Memory Context Statistics Reporting