v8-0003-Check-FOR-PORTION-OF-against-INSTEAD-OF-triggers-.patch

text/x-patch

Filename: v8-0003-Check-FOR-PORTION-OF-against-INSTEAD-OF-triggers-.patch
Type: text/x-patch
Part: 0
Message: Re: [PATCH] Fix null pointer dereference in PG19

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v8-0003
Subject: Check FOR PORTION OF against INSTEAD OF triggers during rewriting
File+
src/backend/parser/analyze.c 0 11
src/backend/rewrite/rewriteHandler.c 8 0
src/test/regress/expected/updatable_views.out 0 8
From d0661fdf84e6d16af5cb59b18360cc08b51f8ab0 Mon Sep 17 00:00:00 2001
From: "Paul A. Jungwirth" <pj@illuminatedcomputing.com>
Date: Tue, 7 Jul 2026 17:21:34 -0700
Subject: [PATCH v8 3/4] Check FOR PORTION OF against INSTEAD OF triggers
 during rewriting

Move the INSTEAD OF trigger check to the rewriter. This loses the error
position but gives the check better locality with where we look up the
triggers.

Discussion: https://www.postgresql.org/message-id/CAJ7c6TME%2Bix6VRf-2TPnVTsj8qn_hy6sYAOmMhZEivwsu2wS6g%40mail.gmail.com
---
 src/backend/parser/analyze.c                  | 11 -----------
 src/backend/rewrite/rewriteHandler.c          |  8 ++++++++
 src/test/regress/expected/updatable_views.out |  8 --------
 3 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 1e6fbc95964..2932d17a107 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1344,17 +1344,6 @@ transformForPortionOfClause(ParseState *pstate,
 				errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				errmsg("WHERE CURRENT OF with FOR PORTION OF is not implemented"));
 
-	/* We don't support FOR PORTION OF on views with INSTEAD OF triggers. */
-	if (targetrel->rd_rel->relkind == RELKIND_VIEW &&
-		targetrel->rd_rel->relhastriggers &&
-		targetrel->trigdesc != NULL &&
-		(isUpdate ? targetrel->trigdesc->trig_update_instead_row
-				  : targetrel->trigdesc->trig_delete_instead_row))
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("views with INSTEAD OF triggers do not support FOR PORTION OF"),
-				 parser_errposition(pstate, forPortionOf->location)));
-
 	result = makeNode(ForPortionOfExpr);
 
 	/* Look up the FOR PORTION OF name requested. */
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index e7ae9cce65f..38f54b57eec 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -4171,6 +4171,14 @@ RewriteQuery(Query *parsetree, List *rewrite_events, int orig_rt_length,
 		 */
 		rt_entry_relation = relation_open(rt_entry->relid, NoLock);
 
+		/* We don't support FOR PORTION OF on views with INSTEAD OF triggers. */
+		if (parsetree->forPortionOf &&
+			rt_entry_relation->rd_rel->relkind == RELKIND_VIEW &&
+			view_has_instead_trigger(rt_entry_relation, event, NIL))
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("views with INSTEAD OF triggers do not support FOR PORTION OF")));
+
 		/*
 		 * Rewrite the targetlist as needed for the command type.
 		 */
diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out
index e6232a5f8c0..9c6bb2219f9 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -4179,28 +4179,20 @@ update uv_fpo_instead_view
   for portion of valid_at from '2015-01-01' to '2020-01-01'
   set b = 99 where id = '[1,1]'; -- error
 ERROR:  views with INSTEAD OF triggers do not support FOR PORTION OF
-LINE 2:   for portion of valid_at from '2015-01-01' to '2020-01-01'
-                         ^
 delete from uv_fpo_instead_view
   for portion of valid_at from '2017-01-01' to '2022-01-01'
   where id = '[1,1]'; -- error
 ERROR:  views with INSTEAD OF triggers do not support FOR PORTION OF
-LINE 2:   for portion of valid_at from '2017-01-01' to '2022-01-01'
-                         ^
 -- The check does not depend on which rows match, so it errors even when
 -- no rows do.
 update uv_fpo_instead_view
   for portion of valid_at from '2015-01-01' to '2020-01-01'
   set b = 99 where id = '[9,9]'; -- error, even with no matching rows
 ERROR:  views with INSTEAD OF triggers do not support FOR PORTION OF
-LINE 2:   for portion of valid_at from '2015-01-01' to '2020-01-01'
-                         ^
 delete from uv_fpo_instead_view
   for portion of valid_at from '2017-01-01' to '2022-01-01'
   where id = '[9,9]'; -- error, even with no matching rows
 ERROR:  views with INSTEAD OF triggers do not support FOR PORTION OF
-LINE 2:   for portion of valid_at from '2017-01-01' to '2022-01-01'
-                         ^
 drop view uv_fpo_instead_view;
 drop function uv_fpo_instead_trig();
 -- Forbid INSTEAD OF triggers with FOR PORTION OF even if the FOR PORTION OF
-- 
2.47.3