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:
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user