From: Tom Lane Date: Sat, 4 Jul 2026 15:34:26 +0000 (-0400) Subject: Disallow renaming a rule to "_RETURN". X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e99fb3262441b47d88632b2857f03083be67f3e3;p=thirdparty%2Fpostgresql.git Disallow renaming a rule to "_RETURN". ON SELECT rules must be named "_RETURN", while other kinds of rules must not be; this ancient restriction is depended on by various client code. We successfully enforced this convention in most places, but ALTER RULE allowed renaming a non-SELECT rule to "_RETURN". Notably, that would break dump/restore, since the eventual CREATE RULE command would reject the name. While at it, remove DefineQueryRewrite's hack to substitute "_RETURN" for the convention that was used before 7.3. We dropped other server-side code that supported restoring pre-7.3 dumps some time ago (notably in e58a59975 and nearby commits), but this bit was missed. Bug: #19543 Reported-by: Adam Pickering Author: Tom Lane Discussion: https://postgr.es/m/19543-461228e77f3b32fc@postgresql.org Backpatch-through: 14 --- diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 6cc9a8d8bfe..601242ea26d 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -390,26 +390,11 @@ DefineQueryRewrite(const char *rulename, * ... and finally the rule must be named _RETURN. */ if (strcmp(rulename, ViewSelectRuleName) != 0) - { - /* - * In versions before 7.3, the expected name was _RETviewname. For - * backwards compatibility with old pg_dump output, accept that - * and silently change it to _RETURN. Since this is just a quick - * backwards-compatibility hack, limit the number of characters - * checked to a few less than NAMEDATALEN; this saves having to - * worry about where a multibyte character might have gotten - * truncated. - */ - if (strncmp(rulename, "_RET", 4) != 0 || - strncmp(rulename + 4, RelationGetRelationName(event_relation), - NAMEDATALEN - 4 - 4) != 0) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("view rule for \"%s\" must be named \"%s\"", - RelationGetRelationName(event_relation), - ViewSelectRuleName))); - rulename = pstrdup(ViewSelectRuleName); - } + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("view rule for \"%s\" must be named \"%s\"", + RelationGetRelationName(event_relation), + ViewSelectRuleName))); } else { @@ -844,6 +829,17 @@ RenameRewriteRule(RangeVar *relation, const char *oldName, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("renaming an ON SELECT rule is not allowed"))); + /* + * Conversely, if it's not an ON SELECT rule then it must *not* be named + * _RETURN. + */ + if (strcmp(newName, ViewSelectRuleName) == 0) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("non-view rule for \"%s\" must not be named \"%s\"", + RelationGetRelationName(targetrel), + ViewSelectRuleName))); + /* OK, do the update */ namestrcpy(&(ruleform->rulename), newName); diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 13178e2b3df..60eb4c431ce 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -3199,6 +3199,8 @@ ALTER RULE NewInsertRule ON rule_v1 RENAME TO "_RETURN"; -- already exists ERROR: rule "_RETURN" for relation "rule_v1" already exists ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renamed ERROR: renaming an ON SELECT rule is not allowed +ALTER RULE rtest_t4_ins1 ON rtest_t4 RENAME TO "_RETURN"; -- also disallowed +ERROR: non-view rule for "rtest_t4" must not be named "_RETURN" DROP VIEW rule_v1; DROP TABLE rule_t1; -- diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql index 4a5fa505855..999b53f51a5 100644 --- a/src/test/regress/sql/rules.sql +++ b/src/test/regress/sql/rules.sql @@ -1087,6 +1087,7 @@ SELECT * FROM rule_v1; ALTER RULE InsertRule ON rule_v1 RENAME TO NewInsertRule; -- doesn't exist ALTER RULE NewInsertRule ON rule_v1 RENAME TO "_RETURN"; -- already exists ALTER RULE "_RETURN" ON rule_v1 RENAME TO abc; -- ON SELECT rule cannot be renamed +ALTER RULE rtest_t4_ins1 ON rtest_t4 RENAME TO "_RETURN"; -- also disallowed DROP VIEW rule_v1; DROP TABLE rule_t1;