Alter_Rule_Rename.patch
application/octet-stream
Filename: Alter_Rule_Rename.patch
Type: application/octet-stream
Part: 0
Message:
Re: missing rename support
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: unified
| File | + | − |
|---|---|---|
| src/backend/commands/alter.c | 4 | 0 |
| src/backend/parser/gram.y | 10 | 0 |
| src/backend/rewrite/rewriteDefine.c | 25 | 7 |
| src/include/rewrite/rewriteDefine.h | 1 | 1 |
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);