From 7945de1196cc72f28c31b7394a0720292f117895 Mon Sep 17 00:00:00 2001
From: Viktor Holmberg <v@viktorh.net>
Date: Wed, 11 Feb 2026 15:46:10 +0100
Subject: [PATCH v26 2/2] Refactor - remove redundant p_is_insert field from
 ParseState

The p_is_insert boolean field was used to distinguish INSERT from UPDATE
processing when handling indirection on assignment target columns (e.g.,
INSERT INTO table (col[1]) VALUES (...) vs UPDATE table SET col[1] = ...).

However, this information is already available via the exprKind parameter
passed to transformAssignedExpr(), which is always EXPR_KIND_INSERT_TARGET
for INSERT and EXPR_KIND_UPDATE_TARGET for UPDATE. The single use of
p_is_insert can be replaced with a simple exprKind check.

This simplifies state management during parsing and eliminates the need
to carefully set and update p_is_insert across multiple files, including
within complex statements like INSERT ... ON CONFLICT DO UPDATE and MERGE
that transition between INSERT and UPDATE semantics.
---
 src/backend/parser/analyze.c      | 7 -------
 src/backend/parser/parse_merge.c  | 3 ---
 src/backend/parser/parse_target.c | 2 +-
 src/include/parser/parse_node.h   | 5 -----
 4 files changed, 1 insertion(+), 16 deletions(-)

diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 503437da199..33972a766c2 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -657,7 +657,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
 	Assert(pstate->p_ctenamespace == NIL);
 
 	qry->commandType = CMD_INSERT;
-	pstate->p_is_insert = true;
 
 	/* process the WITH clause independently of all else */
 	if (stmt->withClause)
@@ -1247,14 +1246,9 @@ transformOnConflictClause(ParseState *pstate,
 
 		/*
 		 * Process the UPDATE SET clause.
-		 *
-		 * Expressions in the UPDATE targetlist need to be handled like UPDATE
-		 * not INSERT.  We don't need to save/restore p_is_insert because all
-		 * INSERT expressions have been parsed already.
 		 */
 		if (onConflictClause->action == ONCONFLICT_UPDATE)
 		{
-			pstate->p_is_insert = false;
 			onConflictSet =
 				transformUpdateTargetList(pstate, onConflictClause->targetList);
 		}
@@ -2515,7 +2509,6 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
 	Node	   *qual;
 
 	qry->commandType = CMD_UPDATE;
-	pstate->p_is_insert = false;
 
 	/* process the WITH clause independently of all else */
 	if (stmt->withClause)
diff --git a/src/backend/parser/parse_merge.c b/src/backend/parser/parse_merge.c
index e08dc18dd75..b7e3b13553b 100644
--- a/src/backend/parser/parse_merge.c
+++ b/src/backend/parser/parse_merge.c
@@ -307,8 +307,6 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
 					List	   *icolumns;
 					List	   *attrnos;
 
-					pstate->p_is_insert = true;
-
 					icolumns = checkInsertTargets(pstate,
 												  mergeWhenClause->targetList,
 												  &attrnos);
@@ -382,7 +380,6 @@ transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
 				break;
 			case CMD_UPDATE:
 				{
-					pstate->p_is_insert = false;
 					action->targetList =
 						transformUpdateTargetList(pstate,
 												  mergeWhenClause->targetList);
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index b5a2f915b67..ddd2c657d8f 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -530,7 +530,7 @@ transformAssignedExpr(ParseState *pstate,
 	{
 		Node	   *colVar;
 
-		if (pstate->p_is_insert)
+		if (exprKind == EXPR_KIND_INSERT_TARGET)
 		{
 			/*
 			 * The command is INSERT INTO table (col.something) ... so there
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index a9bffb8a78f..f23e21f318b 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -153,10 +153,6 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
  *
  * p_grouping_nsitem: the ParseNamespaceItem that represents the grouping step.
  *
- * p_is_insert: true to process assignment expressions like INSERT, false
- * to process them like UPDATE.  (Note this can change intra-statement, for
- * cases like INSERT ON CONFLICT UPDATE.)
- *
  * p_windowdefs: list of WindowDefs representing WINDOW and OVER clauses.
  * We collect these while transforming expressions and then transform them
  * afterwards (so that any resjunk tlist items needed for the sort/group
@@ -209,7 +205,6 @@ struct ParseState
 	Relation	p_target_relation;	/* INSERT/UPDATE/DELETE/MERGE target rel */
 	ParseNamespaceItem *p_target_nsitem;	/* target rel's NSItem, or NULL */
 	ParseNamespaceItem *p_grouping_nsitem;	/* NSItem for grouping, or NULL */
-	bool		p_is_insert;	/* process assignment like INSERT not UPDATE */
 	List	   *p_windowdefs;	/* raw representations of window clauses */
 	ParseExprKind p_expr_kind;	/* what kind of expression we're parsing */
 	int			p_next_resno;	/* next targetlist resno to assign */
-- 
2.48.1

