From 79eed418f2c23da23f7380b823008ad2ccb4aab6 Mon Sep 17 00:00:00 2001
From: Pengzhou Tang <ptang@pivotal.io>
Date: Tue, 3 Dec 2019 05:04:03 -0500
Subject: [PATCH] Rewrite the target view if it has conditional-INSTEAD rule

When UPDATE on a view with conditional INSTEAD rules, we always
get the ERROR "no relation entry for relid 2", for conditional
INSTEAD OF rules, the original UPDATE operation also need to
perform on the view, however, we didn't rewrite the target view
for any view with INSTEAD rules.

There should be only two cases that you can skip the rewrite of
target view:
1) the view has INSTEAD OF triggers on the operations, the
   operations will be replaced by trigger-defined
2) the view has INSTEAD OF rules and it is non conditional
   rules, the operations will be replaced by
   actions.

It should be a typo in commit a99c42f291421572aef2, there is
a description in documents:
"There is a catch if you try to use conditional rules
for complex view updates: there must be an unconditional
INSTEAD rule for each action you wish to allow on the view."

commit a99c42f291421572aef2 explicitly change the description
that the restriction only applies to complex view, conditional INSTEAD
rule should work for a simple view.
---
 src/backend/rewrite/rewriteHandler.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 3e38007..05fc6d7 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -3647,18 +3647,32 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
 		}
 
 		/*
-		 * If there were no INSTEAD rules, and the target relation is a view
-		 * without any INSTEAD OF triggers, see if the view can be
+		 * If the target relation is a view, the target view must be
+		 * rewritten except the cases shown bellow:
+		 * 1) the view has INSTEAD OF triggers on the operations, the
+		 *    operations will be replaced by trigger-defined actions.
+		 * 2) the view has INSTEAD OF rules and it is non conditional
+		 *    rules, the operations will be replaced by rule-defined
+		 *    actions.
+		 *
+		 * If target view need to be rewritten, see if the view can be
 		 * automatically updated.  If so, we perform the necessary query
 		 * transformation here and add the resulting query to the
 		 * product_queries list, so that it gets recursively rewritten if
 		 * necessary.
 		 */
-		if (!instead && qual_product == NULL &&
-			rt_entry_relation->rd_rel->relkind == RELKIND_VIEW &&
-			!view_has_instead_trigger(rt_entry_relation, event))
+		if (rt_entry_relation->rd_rel->relkind == RELKIND_VIEW &&
+			!view_has_instead_trigger(rt_entry_relation, event) &&
+			!(instead && qual_product == NULL))
 		{
 			/*
+			 * For target view has conditional INSTEAD OF rules, we must 
+			 * rewrite the modified original query.
+			 */
+			if (qual_product)
+				parsetree = qual_product;
+
+			/*
 			 * This throws an error if the view can't be automatically
 			 * updated, but that's OK since the query would fail at runtime
 			 * anyway.
-- 
1.8.3.1

