Expression index can get an empty generated column name

Started by Chauhan Dhruvabout 2 months ago3 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253215
psql -h localhost -U postgres

Built from patchset v3 (message #3), August 18, 2026 at 01:37 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253215_3 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253215_3 && git checkout t253215_3

Patchset v3 (message #3) is on t253215_3

Jump to latest
#1Chauhan Dhruv
chauhandhruv351@gmail.com

If you CREATE INDEX on an expression without naming the index, Postgres
generates a name for the index column from that expression. For some
expressions the generated name comes out empty, so the index column is
left with an empty attname.

Example (a whole-row reference):

CREATE TABLE t (a int, b int);
CREATE INDEX ON t ((t IS NOT NULL));

SELECT attname, length(attname)
FROM pg_attribute
WHERE attrelid = 't__idx'::regclass AND attnum = 1;
attname | length
---------+--------
| 0
(1 row)

The index is named "t__idx" -- the doubled underscore is where the
empty column name landed.

Cause: ChooseIndexExpressionName() builds the name from the Vars,
Consts, and function names in the expression. A whole-row Var is
skipped and a punctuation-only Const is stripped away, so such
expressions contribute no text and the result is empty. Before commit
181b6185c7, expression columns were always named "expr" (giving
"t_expr_idx" here).

Fix (attached): if the walk finds nothing usable, fall back to "expr".
Ordinary expressions are unaffected. Includes a regression test; make
check is green. Against the master.

Patch is attached.

Thanks,
Dhruv Chauhan

Attachments:

v1-0001-Avoid-generating-an-empty-name-for-an-expression-.patchtext/x-patch; charset=US-ASCII; name=v1-0001-Avoid-generating-an-empty-name-for-an-expression-.patchDownload+42-1
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chauhan Dhruv (#1)
Re: Expression index can get an empty generated column name

Chauhan Dhruv <chauhandhruv351@gmail.com> writes:

If you CREATE INDEX on an expression without naming the index, Postgres
generates a name for the index column from that expression. For some
expressions the generated name comes out empty, so the index column is
left with an empty attname.

Example (a whole-row reference):

CREATE TABLE t (a int, b int);
CREATE INDEX ON t ((t IS NOT NULL));

Hmm, yeah, that's not great, although I'd argue that the real issue in
this particular example is that we should treat the whole-row Var as
being named "t" rather than being ignored. Still, installing a
fallback of "expr" isn't a bad idea.

regards, tom lane

#3Chauhan Dhruv
chauhandhruv351@gmail.com
In reply to: Tom Lane (#2)
Re: Expression index can get an empty generated column name

Tom Lane <tgl@sss.pgh.pa.us> writes:

Hmm, yeah, that's not great, although I'd argue that the real issue in
this particular example is that we should treat the whole-row Var as
being named "t" rather than being ignored. Still, installing a
fallback of "expr" isn't a bad idea.

good idea! A whole-row Var now contributes the relation's name, and
"expr" remains as a fallback for expressions that still yield no text
(e.g. a constant that sanitizes away to nothing).

CREATE TABLE t (a int, b int);
CREATE INDEX ON t ((t IS NOT NULL)); -- index t_t_idx, column "t"
CREATE INDEX ON t ((','::text)); -- index t_expr_idx, column
"expr"
CREATE INDEX ON t ((a + b)); -- index t_a_b_idx, column "a_b"

Regression test updated. make check is green.

Patch is attached.

Thanks,
Dhruv

Attachments:

t253215_3
v2-0001-Avoid-empty-generated-names-for-expression-index-.patchtext/x-patch; charset=US-ASCII; name=v2-0001-Avoid-empty-generated-names-for-expression-index-.patchDownload+68-8