From 1b5cffacdffaf1cdedb60ff4bc160e65261eb4eb Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 12 Aug 2001 21:35:19 +0000
Subject: [PATCH] Make ALTER TABLE RENAME on a view rename the view's on-select
 rule too. Needed to keep pg_dump from getting confused.

---
 src/backend/commands/rename.c        | 17 +++++++++-
 src/backend/commands/view.c          | 36 ++------------------
 src/backend/rewrite/rewriteDefine.c  | 51 +++++++++++++++++++++++++++-
 src/backend/rewrite/rewriteSupport.c | 41 ++++++++++++++++++++--
 src/backend/utils/adt/ruleutils.c    |  4 +--
 src/include/commands/view.h          |  3 +-
 src/include/rewrite/rewriteDefine.h  |  4 ++-
 src/include/rewrite/rewriteSupport.h |  6 ++--
 8 files changed, 117 insertions(+), 45 deletions(-)

diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
index 52568f29f5f..d56c7f2652c 100644
--- a/src/backend/commands/rename.c
+++ b/src/backend/commands/rename.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.56 2001/03/22 03:59:23 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.57 2001/08/12 21:35:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,8 @@
 #include "miscadmin.h"
 #include "storage/smgr.h"
 #include "optimizer/prep.h"
+#include "rewrite/rewriteDefine.h"
+#include "rewrite/rewriteSupport.h"
 #include "utils/acl.h"
 #include "utils/relcache.h"
 #include "utils/syscache.h"
@@ -265,4 +267,17 @@ renamerel(const char *oldrelname, const char *newrelname)
 	 */
 	if (relkind != RELKIND_INDEX)
 		TypeRename(oldrelname, newrelname);
+
+	/*
+	 * If it's a view, must also rename the associated ON SELECT rule.
+	 */
+	if (relkind == RELKIND_VIEW)
+	{
+		char   *oldrulename,
+			   *newrulename;
+
+		oldrulename = MakeRetrieveViewRuleName(oldrelname);
+		newrulename = MakeRetrieveViewRuleName(newrelname);
+		RenameRewriteRule(oldrulename, newrulename);
+	}
 }
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index a8cddde2dd6..461ac162519 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -6,11 +6,10 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Id: view.c,v 1.55 2001/08/10 18:57:35 tgl Exp $
+ *	$Id: view.c,v 1.56 2001/08/12 21:35:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
-
 #include "postgres.h"
 
 #include "access/xact.h"
@@ -24,10 +23,8 @@
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteManip.h"
 #include "rewrite/rewriteRemove.h"
+#include "rewrite/rewriteSupport.h"
 
-#ifdef MULTIBYTE
-#include "mb/pg_wchar.h"
-#endif
 
 /*---------------------------------------------------------------------
  * DefineVirtualRelation
@@ -100,35 +97,6 @@ DefineVirtualRelation(char *relname, List *tlist)
 	DefineRelation(createStmt, RELKIND_VIEW);
 }
 
-/*------------------------------------------------------------------
- * makeViewRetrieveRuleName
- *
- * Given a view name, returns the name for the 'on retrieve to "view"'
- * rule.
- *------------------------------------------------------------------
- */
-char *
-MakeRetrieveViewRuleName(char *viewName)
-{
-	char	   *buf;
-	int			buflen,
-				maxlen;
-
-	buflen = strlen(viewName) + 5;
-	buf = palloc(buflen);
-	snprintf(buf, buflen, "_RET%s", viewName);
-	/* clip to less than NAMEDATALEN bytes, if necessary */
-#ifdef MULTIBYTE
-	maxlen = pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1);
-#else
-	maxlen = NAMEDATALEN - 1;
-#endif
-	if (maxlen < buflen)
-		buf[maxlen] = '\0';
-
-	return buf;
-}
-
 static RuleStmt *
 FormViewRetrieveRule(char *viewName, Query *viewParse)
 {
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 4cebece58cd..b0315157e4f 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.62 2001/05/03 21:16:48 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.63 2001/08/12 21:35:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@
 #include "rewrite/rewriteSupport.h"
 #include "storage/smgr.h"
 #include "utils/builtins.h"
+#include "utils/syscache.h"
 
 
 static void setRuleCheckAsUser(Query *qry, Oid userid);
@@ -478,3 +479,51 @@ setRuleCheckAsUser_walker(Node *node, Oid *context)
 	return expression_tree_walker(node, setRuleCheckAsUser_walker,
 								  (void *) context);
 }
+
+
+/*
+ * Rename an existing rewrite rule.
+ *
+ * There is not currently a user command to invoke this directly
+ * (perhaps there should be).  But we need it anyway to rename the
+ * ON SELECT rule associated with a view, when the view is renamed.
+ */
+void
+RenameRewriteRule(char *oldname, char *newname)
+{
+	Relation	pg_rewrite_desc;
+	HeapTuple	ruletup;
+
+	pg_rewrite_desc = heap_openr(RewriteRelationName, RowExclusiveLock);
+
+	ruletup = SearchSysCacheCopy(RULENAME,
+								 PointerGetDatum(oldname),
+								 0, 0, 0);
+	if (!HeapTupleIsValid(ruletup))
+		elog(ERROR, "RenameRewriteRule: rule \"%s\" does not exist", oldname);
+
+	/* should not already exist */
+	if (IsDefinedRewriteRule(newname))
+		elog(ERROR, "Attempt to rename rule \"%s\" failed: \"%s\" already exists",
+			 oldname, newname);
+
+	StrNCpy(NameStr(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename),
+			newname, NAMEDATALEN);
+
+	simple_heap_update(pg_rewrite_desc, &ruletup->t_self, ruletup);
+
+	/* keep system catalog indices current */
+	if (RelationGetForm(pg_rewrite_desc)->relhasindex)
+	{
+		Relation	idescs[Num_pg_rewrite_indices];
+
+		CatalogOpenIndices(Num_pg_rewrite_indices, Name_pg_rewrite_indices,
+						   idescs);
+		CatalogIndexInsert(idescs, Num_pg_rewrite_indices, pg_rewrite_desc,
+						   ruletup);
+		CatalogCloseIndices(Num_pg_rewrite_indices, idescs);
+	}
+
+	heap_freetuple(ruletup);
+	heap_close(pg_rewrite_desc, RowExclusiveLock);
+}
diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c
index 7578acbcedd..bc2f04932a4 100644
--- a/src/backend/rewrite/rewriteSupport.c
+++ b/src/backend/rewrite/rewriteSupport.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.48 2001/03/22 03:59:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.49 2001/08/12 21:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,15 +20,52 @@
 #include "rewrite/rewriteSupport.h"
 #include "utils/syscache.h"
 
+#ifdef MULTIBYTE
+#include "mb/pg_wchar.h"
+#endif
 
+
+/*
+ * Is there a rule by the given name?
+ */
 bool
-IsDefinedRewriteRule(char *ruleName)
+IsDefinedRewriteRule(const char *ruleName)
 {
 	return SearchSysCacheExists(RULENAME,
 								PointerGetDatum(ruleName),
 								0, 0, 0);
 }
 
+/*
+ * makeViewRetrieveRuleName
+ *
+ * Given a view name, returns the name for the associated ON SELECT rule.
+ *
+ * XXX this is not the only place in the backend that knows about the _RET
+ * name-forming convention.
+ */
+char *
+MakeRetrieveViewRuleName(const char *viewName)
+{
+	char	   *buf;
+	int			buflen,
+				maxlen;
+
+	buflen = strlen(viewName) + 5;
+	buf = palloc(buflen);
+	snprintf(buf, buflen, "_RET%s", viewName);
+	/* clip to less than NAMEDATALEN bytes, if necessary */
+#ifdef MULTIBYTE
+	maxlen = pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1);
+#else
+	maxlen = NAMEDATALEN - 1;
+#endif
+	if (maxlen < buflen)
+		buf[maxlen] = '\0';
+
+	return buf;
+}
+
 /*
  * SetRelationRuleStatus
  *		Set the value of the relation's relhasrules field in pg_class;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index bda842e794e..a5f9d2ace1a 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
  *				back to source text
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.81 2001/07/31 17:56:31 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.82 2001/08/12 21:35:19 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -44,7 +44,6 @@
 #include "catalog/pg_index.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_shadow.h"
-#include "commands/view.h"
 #include "executor/spi.h"
 #include "lib/stringinfo.h"
 #include "optimizer/clauses.h"
@@ -53,6 +52,7 @@
 #include "parser/parse_expr.h"
 #include "parser/parsetree.h"
 #include "rewrite/rewriteManip.h"
+#include "rewrite/rewriteSupport.h"
 #include "utils/lsyscache.h"
 
 
diff --git a/src/include/commands/view.h b/src/include/commands/view.h
index 7066cbc329f..b4b3d3228f8 100644
--- a/src/include/commands/view.h
+++ b/src/include/commands/view.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: view.h,v 1.9 2001/01/24 19:43:23 momjian Exp $
+ * $Id: view.h,v 1.10 2001/08/12 21:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,7 +16,6 @@
 
 #include "nodes/parsenodes.h"
 
-extern char *MakeRetrieveViewRuleName(char *view_name);
 extern void DefineView(char *view_name, Query *view_parse);
 extern void RemoveView(char *view_name);
 
diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h
index c0957109469..b46d57a4955 100644
--- a/src/include/rewrite/rewriteDefine.h
+++ b/src/include/rewrite/rewriteDefine.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteDefine.h,v 1.9 2001/01/24 19:43:27 momjian Exp $
+ * $Id: rewriteDefine.h,v 1.10 2001/08/12 21:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,4 +18,6 @@
 
 extern void DefineQueryRewrite(RuleStmt *args);
 
+extern void RenameRewriteRule(char *oldname, char *newname);
+
 #endif	 /* REWRITEDEFINE_H */
diff --git a/src/include/rewrite/rewriteSupport.h b/src/include/rewrite/rewriteSupport.h
index cda3d0f5d1c..81390ac209d 100644
--- a/src/include/rewrite/rewriteSupport.h
+++ b/src/include/rewrite/rewriteSupport.h
@@ -7,14 +7,16 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteSupport.h,v 1.16 2001/03/22 04:01:04 momjian Exp $
+ * $Id: rewriteSupport.h,v 1.17 2001/08/12 21:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef REWRITESUPPORT_H
 #define REWRITESUPPORT_H
 
-extern bool IsDefinedRewriteRule(char *ruleName);
+extern bool IsDefinedRewriteRule(const char *ruleName);
+
+extern char *MakeRetrieveViewRuleName(const char *view_name);
 
 extern void SetRelationRuleStatus(Oid relationId, bool relHasRules,
 					  bool relIsBecomingView);
-- 
GitLab