diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 9e271c3..85703b6 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -107,6 +107,10 @@ ExecRenameStmt(RenameStmt *stmt)
 			RenameRole(stmt->subname, stmt->newname);
 			break;
 
+		case OBJECT_RULE:
+			RenameRewriteRule(stmt->relation, stmt->subname, stmt->newname);
+			break;
+
 		case OBJECT_SCHEMA:
 			RenameSchema(stmt->subname, stmt->newname);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ad98b36..e993c5a 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -7028,6 +7028,16 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
 					n->missing_ok = false;
 					$$ = (Node *)n;
 				}
+			| ALTER RULE name ON any_name RENAME TO name
+				{
+					RenameStmt *n = makeNode(RenameStmt);
+					n->renameType = OBJECT_RULE;
+					n->relation = makeRangeVarFromAnyName($5, @5, yyscanner);
+					n->subname = $3;
+					n->newname = $8;
+					n->missing_ok = false;
+					$$ = (Node *)n;
+				}
 			| ALTER USER RoleId RENAME TO RoleId
 				{
 					RenameStmt *n = makeNode(RenameStmt);
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 55b0fed..d8d0dd6 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -750,35 +750,55 @@ EnableDisableRule(Relation rel, const char *rulename,
 
 /*
  * Rename an existing rewrite rule.
- *
- * This is unused code at the moment.  Note that it lacks a permissions check.
  */
-#ifdef NOT_USED
 void
-RenameRewriteRule(Oid owningRel, const char *oldName,
+RenameRewriteRule(RangeVar* relation, const char *oldName,
 				  const char *newName)
 {
 	Relation	pg_rewrite_desc;
 	HeapTuple	ruletup;
+	Oid owningRel;
+
+	owningRel = RangeVarGetRelid(relation, AccessExclusiveLock, false);
+
+	/*
+	 * check if user has permission to rename rule on this relation.
+	 */
+	if (!pg_class_ownercheck(owningRel, GetUserId()))
+		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+					   get_rel_name(owningRel));
 
 	pg_rewrite_desc = heap_open(RewriteRelationId, RowExclusiveLock);
 
 	ruletup = SearchSysCacheCopy2(RULERELNAME,
 								  ObjectIdGetDatum(owningRel),
 								  PointerGetDatum(oldName));
+
+	/* old rule should already exist */
 	if (!HeapTupleIsValid(ruletup))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("rule \"%s\" for relation \"%s\" does not exist",
 						oldName, get_rel_name(owningRel))));
 
-	/* should not already exist */
+	/* rule with the new name should not already exist */
 	if (IsDefinedRewriteRule(owningRel, newName))
 		ereport(ERROR,
 				(errcode(ERRCODE_DUPLICATE_OBJECT),
 				 errmsg("rule \"%s\" for relation \"%s\" already exists",
 						newName, get_rel_name(owningRel))));
 
+	/* ON SELECT rule must always be named "_RETURN" */
+	if (((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_type - '0' == CMD_SELECT)
+	{
+		if (strcmp(newName, ViewSelectRuleName) != 0)
+			ereport(ERROR,
+			(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				errmsg("view rule for \"%s\" must be named \"%s\"",
+					get_rel_name(owningRel),
+					ViewSelectRuleName)));
+	}
+
 	namestrcpy(&(((Form_pg_rewrite) GETSTRUCT(ruletup))->rulename), newName);
 
 	simple_heap_update(pg_rewrite_desc, &ruletup->t_self, ruletup);
@@ -789,5 +809,3 @@ RenameRewriteRule(Oid owningRel, const char *oldName,
 	heap_freetuple(ruletup);
 	heap_close(pg_rewrite_desc, RowExclusiveLock);
 }
-
-#endif
diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h
index 6061725..d7e0def 100644
--- a/src/include/rewrite/rewriteDefine.h
+++ b/src/include/rewrite/rewriteDefine.h
@@ -32,7 +32,7 @@ extern void DefineQueryRewrite(char *rulename,
 				   bool replace,
 				   List *action);
 
-extern void RenameRewriteRule(Oid owningRel, const char *oldName,
+extern void RenameRewriteRule(RangeVar* relation, const char *oldName,
 				  const char *newName);
 
 extern void setRuleCheckAsUser(Node *node, Oid userid);
