From ac80ccfa486551e4bf519cf67c16a80da7259214 Mon Sep 17 00:00:00 2001 From: jian he Date: Fri, 9 Oct 2026 16:35:25 +0800 Subject: [PATCH v1 1/1] using indnkeyatts not using indnatts in some loops rd_indcollation, rd_opfamily and rd_opcintype only have entries for key columns, so loops that read them must be bounded by indnkeyatts not indnatts. We can use the existing convenient macro IndexRelationGetNumberOfKeyAttributes() for this. --- contrib/bloom/blutils.c | 6 ++---- src/backend/access/brin/brin.c | 4 ++-- src/backend/access/gin/ginutil.c | 2 +- src/backend/commands/analyze.c | 4 ++++ src/backend/optimizer/util/plancat.c | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c index 5111cdc6dd6..834ea271e43 100644 --- a/contrib/bloom/blutils.c +++ b/contrib/bloom/blutils.c @@ -166,12 +166,10 @@ blhandler(PG_FUNCTION_ARGS) void initBloomState(BloomState *state, Relation index) { - int i; - - state->nColumns = index->rd_att->natts; + state->nColumns = IndexRelationGetNumberOfKeyAttributes(index); /* Initialize hash function for each attribute */ - for (i = 0; i < index->rd_att->natts; i++) + for (int i = 0; i < state->nColumns; i++) { fmgr_info_copy(&(state->hashFn[i]), index_getprocinfo(index, i + 1, BLOOM_HASH_PROC), diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 5059da8dce7..41cb3896112 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -2103,7 +2103,7 @@ union_tuples(BrinDesc *bdesc, BrinMemTuple *a, BrinTuple *b) } /* Now we know neither range is empty. */ - for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++) + for (keyno = 0; keyno < IndexRelationGetNumberOfKeyAttributes(bdesc->bd_index); keyno++) { FmgrInfo *unionFn; BrinValues *col_a = &a->bt_columns[keyno]; @@ -2233,7 +2233,7 @@ add_values_to_range(Relation idxRel, BrinDesc *bdesc, BrinMemTuple *dtup, * Make a note of whether this happens, so that we know to insert the * modified tuple later. */ - for (keyno = 0; keyno < bdesc->bd_tupdesc->natts; keyno++) + for (keyno = 0; keyno < IndexRelationGetNumberOfKeyAttributes(bdesc->bd_index); keyno++) { Datum result; BrinValues *bval; diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index e7cba81d477..b64305f44c4 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -112,7 +112,7 @@ initGinState(GinState *state, Relation index) state->oneCol = (origTupdesc->natts == 1); state->origTupdesc = origTupdesc; - for (i = 0; i < origTupdesc->natts; i++) + for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(index); i++) { Form_pg_attribute attr = TupleDescAttr(origTupdesc, i); diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 518d7526255..2ec01399268 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -1140,6 +1140,10 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr) * If a collation has been specified for the index column, use that in * preference to anything else; but if not, fall back to whatever we * can get from the expression. + * + * Note: rd_indcollation covers only key columns. That is OK here, + * because INCLUDE columns cannot be expressions, so index_expr is + * always a key column. */ if (OidIsValid(onerel->rd_indcollation[attnum - 1])) stats->attrcollid = onerel->rd_indcollation[attnum - 1]; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index d067368cfc1..a8005017d91 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1219,7 +1219,7 @@ infer_collation_opclass_match(InferenceElem *elem, Relation idxRel, inferopcinputtype = get_opclass_input_type(elem->inferopclass); } - for (natt = 1; natt <= idxRel->rd_att->natts; natt++) + for (natt = 1; natt <= IndexRelationGetNumberOfKeyAttributes(idxRel); natt++) { Oid opfamily = idxRel->rd_opfamily[natt - 1]; Oid opcinputtype = idxRel->rd_opcintype[natt - 1]; -- 2.34.1