mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Rule names are now unique per-relation, rather than unique globally.
DROP RULE and COMMENT ON RULE syntax adds an 'ON tablename' clause, similar to TRIGGER syntaxes. To allow loading of existing pg_dump files containing COMMENT ON RULE, the COMMENT code will still accept the old syntax --- but only if the target rulename is unique across the whole database.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.41 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.42 2002/04/18 20:01:09 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -472,44 +472,105 @@ CommentDatabase(List *qualname, char *comment)
|
||||
* CommentRule --
|
||||
*
|
||||
* This routine is used to add/drop any user-comments a user might
|
||||
* have regarding a specified RULE. The rule is specified by name
|
||||
* and, if found, and the user has appropriate permissions, a
|
||||
* comment will be added/dropped using the CreateComments() routine.
|
||||
* have regarding a specified RULE. The rule for commenting is determined by
|
||||
* both its name and the relation to which it refers. The arguments to this
|
||||
* function are the rule name and relation name (merged into a qualified
|
||||
* name), and the comment to add/drop.
|
||||
*
|
||||
* Before PG 7.3, rules had unique names across the whole database, and so
|
||||
* the syntax was just COMMENT ON RULE rulename, with no relation name.
|
||||
* For purposes of backwards compatibility, we support that as long as there
|
||||
* is only one rule by the specified name in the database.
|
||||
*/
|
||||
static void
|
||||
CommentRule(List *qualname, char *comment)
|
||||
{
|
||||
char *rule;
|
||||
int nnames;
|
||||
List *relname;
|
||||
char *rulename;
|
||||
RangeVar *rel;
|
||||
Relation relation;
|
||||
HeapTuple tuple;
|
||||
Oid reloid;
|
||||
Oid ruleoid;
|
||||
Oid classoid;
|
||||
int32 aclcheck;
|
||||
|
||||
/* XXX this is gonna change soon */
|
||||
if (length(qualname) != 1)
|
||||
elog(ERROR, "CommentRule: rule name may not be qualified");
|
||||
rule = strVal(lfirst(qualname));
|
||||
/* Separate relname and trig name */
|
||||
nnames = length(qualname);
|
||||
if (nnames == 1)
|
||||
{
|
||||
/* Old-style: only a rule name is given */
|
||||
Relation RewriteRelation;
|
||||
HeapScanDesc scanDesc;
|
||||
ScanKeyData scanKeyData;
|
||||
|
||||
/* Find the rule's pg_rewrite tuple, get its OID and its table's OID */
|
||||
rulename = strVal(lfirst(qualname));
|
||||
|
||||
tuple = SearchSysCache(RULENAME,
|
||||
PointerGetDatum(rule),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "rule '%s' does not exist", rule);
|
||||
/* Search pg_rewrite for such a rule */
|
||||
ScanKeyEntryInitialize(&scanKeyData,
|
||||
0,
|
||||
Anum_pg_rewrite_rulename,
|
||||
F_NAMEEQ,
|
||||
PointerGetDatum(rulename));
|
||||
|
||||
reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
|
||||
ruleoid = tuple->t_data->t_oid;
|
||||
RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock);
|
||||
scanDesc = heap_beginscan(RewriteRelation,
|
||||
0, SnapshotNow, 1, &scanKeyData);
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
tuple = heap_getnext(scanDesc, 0);
|
||||
if (HeapTupleIsValid(tuple))
|
||||
{
|
||||
reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
|
||||
ruleoid = tuple->t_data->t_oid;
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "rule '%s' does not exist", rulename);
|
||||
reloid = ruleoid = 0; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
if (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
|
||||
elog(ERROR, "There are multiple rules '%s'"
|
||||
"\n\tPlease specify a relation name as well as a rule name",
|
||||
rulename);
|
||||
|
||||
heap_endscan(scanDesc);
|
||||
heap_close(RewriteRelation, AccessShareLock);
|
||||
|
||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||
relation = heap_open(reloid, AccessShareLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* New-style: rule and relname both provided */
|
||||
Assert(nnames >= 2);
|
||||
relname = ltruncate(nnames-1, listCopy(qualname));
|
||||
rulename = strVal(nth(nnames-1, qualname));
|
||||
|
||||
/* Open the owning relation to ensure it won't go away meanwhile */
|
||||
rel = makeRangeVarFromNameList(relname);
|
||||
relation = heap_openrv(rel, AccessShareLock);
|
||||
reloid = RelationGetRelid(relation);
|
||||
|
||||
/* Find the rule's pg_rewrite tuple, get its OID */
|
||||
tuple = SearchSysCache(RULERELNAME,
|
||||
ObjectIdGetDatum(reloid),
|
||||
PointerGetDatum(rulename),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "rule '%s' does not exist", rulename);
|
||||
Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
|
||||
ruleoid = tuple->t_data->t_oid;
|
||||
ReleaseSysCache(tuple);
|
||||
}
|
||||
|
||||
/* Check object security */
|
||||
|
||||
aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE);
|
||||
if (aclcheck != ACLCHECK_OK)
|
||||
elog(ERROR, "you are not permitted to comment on rule '%s'",
|
||||
rule);
|
||||
rulename);
|
||||
|
||||
/* pg_rewrite doesn't have a hard-coded OID, so must look it up */
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.2 2002/04/15 23:45:07 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.3 2002/04/18 20:01:09 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1423,8 +1423,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
Relation ridescs[Num_pg_class_indices];
|
||||
Oid toast_relid;
|
||||
Oid toast_idxid;
|
||||
char toast_relname[NAMEDATALEN + 1];
|
||||
char toast_idxname[NAMEDATALEN + 1];
|
||||
char toast_relname[NAMEDATALEN];
|
||||
char toast_idxname[NAMEDATALEN];
|
||||
IndexInfo *indexInfo;
|
||||
Oid classObjectId[2];
|
||||
|
||||
@ -1667,7 +1667,7 @@ needs_toast_table(Relation rel)
|
||||
Oid
|
||||
DefineRelation(CreateStmt *stmt, char relkind)
|
||||
{
|
||||
char *relname = palloc(NAMEDATALEN);
|
||||
char relname[NAMEDATALEN];
|
||||
Oid namespaceId;
|
||||
List *schema = stmt->tableElts;
|
||||
int numberOfAttributes;
|
||||
@ -1686,7 +1686,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
* Truncate relname to appropriate length (probably a waste of time,
|
||||
* as parser should have done this already).
|
||||
*/
|
||||
StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN);
|
||||
StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
|
||||
|
||||
/*
|
||||
* Look up the namespace in which we are supposed to create the
|
||||
@ -2642,8 +2642,8 @@ renameatt(Oid relid,
|
||||
0, 0))
|
||||
elog(ERROR, "renameatt: attribute \"%s\" exists", newattname);
|
||||
|
||||
StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
|
||||
newattname, NAMEDATALEN);
|
||||
namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
|
||||
newattname);
|
||||
|
||||
simple_heap_update(attrelation, &atttup->t_self, atttup);
|
||||
|
||||
@ -2699,8 +2699,8 @@ renameatt(Oid relid,
|
||||
/*
|
||||
* Update the (copied) attribute tuple.
|
||||
*/
|
||||
StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
|
||||
newattname, NAMEDATALEN);
|
||||
namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
|
||||
newattname);
|
||||
|
||||
simple_heap_update(attrelation, &atttup->t_self, atttup);
|
||||
|
||||
@ -2753,6 +2753,7 @@ renamerel(Oid relid, const char *newrelname)
|
||||
Relation relrelation; /* for RELATION relation */
|
||||
HeapTuple reltup;
|
||||
Oid namespaceId;
|
||||
char *oldrelname;
|
||||
char relkind;
|
||||
bool relhastriggers;
|
||||
Relation irelations[Num_pg_class_indices];
|
||||
@ -2763,13 +2764,14 @@ renamerel(Oid relid, const char *newrelname)
|
||||
*/
|
||||
targetrelation = relation_open(relid, AccessExclusiveLock);
|
||||
|
||||
oldrelname = pstrdup(RelationGetRelationName(targetrelation));
|
||||
namespaceId = RelationGetNamespace(targetrelation);
|
||||
|
||||
/* Validity checks */
|
||||
if (!allowSystemTableMods &&
|
||||
IsSystemRelation(targetrelation))
|
||||
elog(ERROR, "renamerel: system relation \"%s\" may not be renamed",
|
||||
RelationGetRelationName(targetrelation));
|
||||
oldrelname);
|
||||
|
||||
relkind = targetrelation->rd_rel->relkind;
|
||||
relhastriggers = (targetrelation->rd_rel->reltriggers > 0);
|
||||
@ -2785,7 +2787,7 @@ renamerel(Oid relid, const char *newrelname)
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(reltup))
|
||||
elog(ERROR, "renamerel: relation \"%s\" does not exist",
|
||||
RelationGetRelationName(targetrelation));
|
||||
oldrelname);
|
||||
|
||||
if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
|
||||
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
|
||||
@ -2794,8 +2796,7 @@ renamerel(Oid relid, const char *newrelname)
|
||||
* Update pg_class tuple with new relname. (Scribbling on reltup is
|
||||
* OK because it's a copy...)
|
||||
*/
|
||||
StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
|
||||
newrelname, NAMEDATALEN);
|
||||
namestrcpy(&(((Form_pg_class) GETSTRUCT(reltup))->relname), newrelname);
|
||||
|
||||
simple_heap_update(relrelation, &reltup->t_self, reltup);
|
||||
|
||||
@ -2811,8 +2812,7 @@ renamerel(Oid relid, const char *newrelname)
|
||||
* Also rename the associated type, if any.
|
||||
*/
|
||||
if (relkind != RELKIND_INDEX)
|
||||
TypeRename(RelationGetRelationName(targetrelation), namespaceId,
|
||||
newrelname);
|
||||
TypeRename(oldrelname, namespaceId, newrelname);
|
||||
|
||||
/*
|
||||
* If it's a view, must also rename the associated ON SELECT rule.
|
||||
@ -2822,9 +2822,9 @@ renamerel(Oid relid, const char *newrelname)
|
||||
char *oldrulename,
|
||||
*newrulename;
|
||||
|
||||
oldrulename = MakeRetrieveViewRuleName(RelationGetRelationName(targetrelation));
|
||||
oldrulename = MakeRetrieveViewRuleName(oldrelname);
|
||||
newrulename = MakeRetrieveViewRuleName(newrelname);
|
||||
RenameRewriteRule(oldrulename, newrulename);
|
||||
RenameRewriteRule(relid, oldrulename, newrulename);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2834,12 +2834,12 @@ renamerel(Oid relid, const char *newrelname)
|
||||
{
|
||||
/* update tgargs where relname is primary key */
|
||||
update_ri_trigger_args(relid,
|
||||
RelationGetRelationName(targetrelation),
|
||||
oldrelname,
|
||||
newrelname,
|
||||
false, true);
|
||||
/* update tgargs where relname is foreign key */
|
||||
update_ri_trigger_args(relid,
|
||||
RelationGetRelationName(targetrelation),
|
||||
oldrelname,
|
||||
newrelname,
|
||||
true, true);
|
||||
}
|
||||
|
Reference in New Issue
Block a user