1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-09 13:09:39 +03:00

Second phase of committing Rod Taylor's pg_depend/pg_constraint patch.

pg_relcheck is gone; CHECK, UNIQUE, PRIMARY KEY, and FOREIGN KEY
constraints all have real live entries in pg_constraint.  pg_depend
exists, and RESTRICT/CASCADE options work on most kinds of DROP;
however, pg_depend is not yet very well populated with dependencies.
(Most of the ones that are present at this point just replace formerly
hardwired associations, such as the implicit drop of a relation's pg_type
entry when the relation is dropped.)  Need to add more logic to create
dependency entries, improve pg_dump to dump constraints in place of
indexes and triggers, and add some regression tests.
This commit is contained in:
Tom Lane
2002-07-12 18:43:19 +00:00
parent 791a40f943
commit 7c6df91dda
77 changed files with 4074 additions and 1987 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.73 2002/06/20 20:29:33 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.74 2002/07/12 18:43:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,6 +16,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_rewrite.h"
#include "commands/view.h"
@@ -57,6 +58,8 @@ InsertRule(char *rulname,
TupleDesc tupDesc;
HeapTuple tup;
Oid rewriteObjectId;
ObjectAddress myself,
referenced;
if (IsDefinedRewriteRule(eventrel_oid, rulname))
elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists",
@@ -103,6 +106,23 @@ InsertRule(char *rulname,
heap_freetuple(tup);
/*
* Install dependency on rule's relation to ensure it will go away
* on relation deletion. If the rule is ON SELECT, make the dependency
* implicit --- this prevents deleting a view's SELECT rule. Other
* kinds of rules can be AUTO.
*/
myself.classId = RelationGetRelid(pg_rewrite_desc);
myself.objectId = rewriteObjectId;
myself.objectSubId = 0;
referenced.classId = RelOid_pg_class;
referenced.objectId = eventrel_oid;
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced,
(evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
heap_close(pg_rewrite_desc, RowExclusiveLock);
return rewriteObjectId;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.50 2002/06/20 20:29:34 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.51 2002/07/12 18:43:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,14 +17,15 @@
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_rewrite.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "rewrite/rewriteRemove.h"
#include "rewrite/rewriteSupport.h"
#include "utils/acl.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -34,15 +35,62 @@
* Delete a rule given its name.
*/
void
RemoveRewriteRule(Oid owningRel, const char *ruleName)
RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior)
{
HeapTuple tuple;
Oid eventRelationOid;
AclResult aclresult;
ObjectAddress object;
/*
* Find the tuple for the target rule.
*/
tuple = SearchSysCache(RULERELNAME,
ObjectIdGetDatum(owningRel),
PointerGetDatum(ruleName),
0, 0);
/*
* complain if no rule with such name exists
*/
if (!HeapTupleIsValid(tuple))
elog(ERROR, "Rule \"%s\" not found", ruleName);
/*
* Verify user has appropriate permissions.
*/
eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
Assert(eventRelationOid == owningRel);
aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_rel_name(eventRelationOid));
/*
* Do the deletion
*/
object.classId = get_system_catalog_relid(RewriteRelationName);
object.objectId = tuple->t_data->t_oid;
object.objectSubId = 0;
ReleaseSysCache(tuple);
performDeletion(&object, behavior);
}
/*
* Guts of rule deletion.
*/
void
RemoveRewriteRuleById(Oid ruleOid)
{
Relation RewriteRelation;
ScanKeyData skey[1];
SysScanDesc rcscan;
Relation event_relation;
HeapTuple tuple;
Oid ruleId;
Oid eventRelationOid;
bool hasMoreRules;
AclResult aclresult;
/*
* Open the pg_rewrite relation.
@@ -52,24 +100,18 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName)
/*
* Find the tuple for the target rule.
*/
tuple = SearchSysCacheCopy(RULERELNAME,
ObjectIdGetDatum(owningRel),
PointerGetDatum(ruleName),
0, 0);
ScanKeyEntryInitialize(&skey[0], 0x0,
ObjectIdAttributeNumber, F_OIDEQ,
ObjectIdGetDatum(ruleOid));
rcscan = systable_beginscan(RewriteRelation, RewriteOidIndex, true,
SnapshotNow, 1, skey);
tuple = systable_getnext(rcscan);
/*
* complain if no rule with such name existed
*/
if (!HeapTupleIsValid(tuple))
elog(ERROR, "Rule \"%s\" not found", ruleName);
/*
* Save the OID of the rule (i.e. the tuple's OID) and the event
* relation's OID
*/
ruleId = tuple->t_data->t_oid;
eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
Assert(eventRelationOid == owningRel);
elog(ERROR, "RemoveRewriteRuleById: Rule %u does not exist",
ruleOid);
/*
* We had better grab AccessExclusiveLock so that we know no other
@@ -77,34 +119,18 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName)
* cannot set relhasrules correctly. Besides, we don't want to be
* changing the ruleset while queries are executing on the rel.
*/
eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
/*
* Verify user has appropriate permissions.
*/
aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, RelationGetRelationName(event_relation));
/* do not allow the removal of a view's SELECT rule */
if (event_relation->rd_rel->relkind == RELKIND_VIEW &&
((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1')
elog(ERROR, "Cannot remove a view's SELECT rule");
hasMoreRules = event_relation->rd_rules != NULL &&
event_relation->rd_rules->numLocks > 1;
/*
* Delete any comments associated with this rule
*/
DeleteComments(ruleId, RelationGetRelid(RewriteRelation));
/*
* Now delete the pg_rewrite tuple for the rule
*/
simple_heap_delete(RewriteRelation, &tuple->t_self);
heap_freetuple(tuple);
systable_endscan(rcscan);
heap_close(RewriteRelation, RowExclusiveLock);
@@ -120,49 +146,3 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName)
/* Close rel, but keep lock till commit... */
heap_close(event_relation, NoLock);
}
/*
* RelationRemoveRules -
* removes all rules associated with the relation when the relation is
* being removed.
*/
void
RelationRemoveRules(Oid relid)
{
Relation RewriteRelation;
SysScanDesc scanDesc;
ScanKeyData scanKeyData;
HeapTuple tuple;
/*
* Open the pg_rewrite relation.
*/
RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
/*
* Scan pg_rewrite for all the tuples that have the same ev_class
* as relid (the relation to be removed).
*/
ScanKeyEntryInitialize(&scanKeyData,
0,
Anum_pg_rewrite_ev_class,
F_OIDEQ,
ObjectIdGetDatum(relid));
scanDesc = systable_beginscan(RewriteRelation,
RewriteRelRulenameIndex,
true, SnapshotNow,
1, &scanKeyData);
while (HeapTupleIsValid(tuple = systable_getnext(scanDesc)))
{
/* Delete any comments associated with this rule */
DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation));
simple_heap_delete(RewriteRelation, &tuple->t_self);
}
systable_endscan(scanDesc);
heap_close(RewriteRelation, RowExclusiveLock);
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.52 2002/06/20 20:29:34 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.53 2002/07/12 18:43:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "rewrite/rewriteSupport.h"
#include "utils/inval.h"
#include "utils/syscache.h"
@@ -44,9 +45,8 @@ IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
* NOTE: an important side-effect of this operation is that an SI invalidation
* message is sent out to all backends --- including me --- causing relcache
* entries to be flushed or updated with the new set of rules for the table.
* Therefore, we execute the update even if relhasrules has the right value
* already. Possible future improvement: skip the disk update and just send
* an SI message in that case.
* This must happen even if we find that no change is needed in the pg_class
* row.
*/
void
SetRelationRuleStatus(Oid relationId, bool relHasRules,
@@ -54,6 +54,7 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules,
{
Relation relationRelation;
HeapTuple tuple;
Form_pg_class classForm;
Relation idescs[Num_pg_class_indices];
/*
@@ -66,18 +67,28 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules,
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "SetRelationRuleStatus: cache lookup failed for relation %u", relationId);
classForm = (Form_pg_class) GETSTRUCT(tuple);
/* Do the update */
((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relHasRules;
if (relIsBecomingView)
((Form_pg_class) GETSTRUCT(tuple))->relkind = RELKIND_VIEW;
if (classForm->relhasrules != relHasRules ||
(relIsBecomingView && classForm->relkind != RELKIND_VIEW))
{
/* Do the update */
classForm->relhasrules = relHasRules;
if (relIsBecomingView)
classForm->relkind = RELKIND_VIEW;
simple_heap_update(relationRelation, &tuple->t_self, tuple);
simple_heap_update(relationRelation, &tuple->t_self, tuple);
/* Keep the catalog indices up to date */
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple);
CatalogCloseIndices(Num_pg_class_indices, idescs);
/* Keep the catalog indices up to date */
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple);
CatalogCloseIndices(Num_pg_class_indices, idescs);
}
else
{
/* no need to change tuple, but force relcache rebuild anyway */
CacheInvalidateRelcache(relationId);
}
heap_freetuple(tuple);
heap_close(relationRelation, RowExclusiveLock);