From 8c0f78631b5f8132e5319a30d8c2ff4db99a2dea Mon Sep 17 00:00:00 2001 From: jian he Date: Tue, 16 Dec 2025 14:22:14 +0800 Subject: [PATCH v1 1/2] add Location to IndexElem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add location information to each IndexElem so that error reporting can precisely identify the specific invalid element. This is particularly useful for subsequent refactoring in ComputeIndexAttrs. Author: Álvaro Herrera comitfest: https://commitfest.postgresql.org/patch/ discussion: https://postgr.es/m/ --- src/backend/bootstrap/bootparse.y | 1 + src/backend/nodes/nodeFuncs.c | 3 +++ src/backend/parser/gram.y | 5 +++++ src/backend/parser/parse_clause.c | 8 ++++---- src/backend/parser/parse_utilcmd.c | 4 ++++ src/include/nodes/parsenodes.h | 1 + 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 9833f52c1be..da0e7dea497 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -415,6 +415,7 @@ boot_index_param: n->opclass = list_make1(makeString($2)); n->ordering = SORTBY_DEFAULT; n->nulls_ordering = SORTBY_NULLS_DEFAULT; + n->location = -1; $$ = n; } ; diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 024a2b2fd84..89b7d80c0aa 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -1726,6 +1726,9 @@ exprLocation(const Node *expr) case T_ColumnDef: loc = ((const ColumnDef *) expr)->location; break; + case T_IndexElem: + loc = ((const IndexElem *) expr)->location; + break; case T_Constraint: loc = ((const Constraint *) expr)->location; break; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 28f4e11e30f..3f407e7d00f 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -8454,6 +8454,7 @@ index_elem_options: $$->opclassopts = NIL; $$->ordering = $3; $$->nulls_ordering = $4; + $$->location = @1; } | opt_collate any_name reloptions opt_asc_desc opt_nulls_order { @@ -8466,6 +8467,7 @@ index_elem_options: $$->opclassopts = $3; $$->ordering = $4; $$->nulls_ordering = $5; + $$->location = @1; } ; @@ -8478,16 +8480,19 @@ index_elem: ColId index_elem_options { $$ = $2; $$->name = $1; + $$->location = @1; } | func_expr_windowless index_elem_options { $$ = $2; $$->expr = $1; + $$->location = @1; } | '(' a_expr ')' index_elem_options { $$ = $4; $$->expr = $2; + $$->location = @1; } ; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 57609e2d55c..34693c8a9e6 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -3289,20 +3289,20 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer, errmsg("%s is not allowed in ON CONFLICT clause", "ASC/DESC"), parser_errposition(pstate, - exprLocation((Node *) infer)))); + exprLocation((Node *) ielem)))); if (ielem->nulls_ordering != SORTBY_NULLS_DEFAULT) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("%s is not allowed in ON CONFLICT clause", "NULLS FIRST/LAST"), parser_errposition(pstate, - exprLocation((Node *) infer)))); + exprLocation((Node *) ielem)))); if (ielem->opclassopts) ereport(ERROR, errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("operator class options are not allowed in ON CONFLICT clause"), parser_errposition(pstate, - exprLocation((Node *) infer))); + exprLocation((Node *) ielem))); if (!ielem->expr) { @@ -3342,7 +3342,7 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer, pInfer->infercollid = InvalidOid; else pInfer->infercollid = LookupCollation(pstate, ielem->collation, - exprLocation(pInfer->expr)); + exprLocation((Node *) ielem)); if (!ielem->opclass) pInfer->inferopclass = InvalidOid; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 375b40b29af..8ce0fb6ab37 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1883,6 +1883,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, int16 opt = source_idx->rd_indoption[keyno]; iparam = makeNode(IndexElem); + iparam->location = -1; if (AttributeNumberIsValid(attnum)) { @@ -1974,6 +1975,7 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, keyno); iparam = makeNode(IndexElem); + iparam->location = -1; if (AttributeNumberIsValid(attnum)) { @@ -2813,6 +2815,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) iparam->opclassopts = NIL; iparam->ordering = SORTBY_DEFAULT; iparam->nulls_ordering = SORTBY_NULLS_DEFAULT; + iparam->location = -1; index->indexParams = lappend(index->indexParams, iparam); } @@ -2929,6 +2932,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) iparam->collation = NIL; iparam->opclass = NIL; iparam->opclassopts = NIL; + iparam->location = -1; index->indexIncludingParams = lappend(index->indexIncludingParams, iparam); } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index bc7adba4a0f..b15b937660f 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -816,6 +816,7 @@ typedef struct IndexElem List *opclassopts; /* opclass-specific options, or NIL */ SortByDir ordering; /* ASC/DESC/default */ SortByNulls nulls_ordering; /* FIRST/LAST/default */ + ParseLoc location; /* token location, or -1 if unknown */ } IndexElem; /* -- 2.34.1