summaryrefslogtreecommitdiff
path: root/src/backend/rewrite
diff options
context:
space:
mode:
authorTom Lane2002-09-02 02:13:02 +0000
committerTom Lane2002-09-02 02:13:02 +0000
commit248c67d7ed505d98d3a94cd3954835255317ff16 (patch)
treedc45c941a494e35842a70e1383129d31aa8f25e0 /src/backend/rewrite
parentc7a165adc64e3e67e0dcee4088d84a0638b3515a (diff)
CREATE OR REPLACE VIEW, CREATE OR REPLACE RULE.
Gavin Sherry, Neil Conway, and Tom Lane all got their hands dirty on this one ...
Diffstat (limited to 'src/backend/rewrite')
-rw-r--r--src/backend/rewrite/rewriteDefine.c77
1 files changed, 59 insertions, 18 deletions
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 80952d7ddc..f276189426 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.77 2002/08/05 03:29:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.78 2002/09/02 02:13:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,24 +48,23 @@ InsertRule(char *rulname,
AttrNumber evslot_index,
bool evinstead,
Node *event_qual,
- List *action)
+ List *action,
+ bool replace)
{
char *evqual = nodeToString(event_qual);
char *actiontree = nodeToString((Node *) action);
int i;
Datum values[Natts_pg_rewrite];
char nulls[Natts_pg_rewrite];
+ char replaces[Natts_pg_rewrite];
NameData rname;
Relation pg_rewrite_desc;
- TupleDesc tupDesc;
- HeapTuple tup;
+ HeapTuple tup,
+ oldtup;
Oid rewriteObjectId;
ObjectAddress myself,
referenced;
-
- if (IsDefinedRewriteRule(eventrel_oid, rulname))
- elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists",
- rulname);
+ bool is_update = false;
/*
* Set up *nulls and *values arrays
@@ -83,22 +82,61 @@ InsertRule(char *rulname,
values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree)); /* ev_action */
/*
- * create a new pg_rewrite tuple
+ * Ready to store new pg_rewrite tuple
*/
pg_rewrite_desc = heap_openr(RewriteRelationName, RowExclusiveLock);
- tupDesc = pg_rewrite_desc->rd_att;
+ /*
+ * Check to see if we are replacing an existing tuple
+ */
+ oldtup = SearchSysCache(RULERELNAME,
+ ObjectIdGetDatum(eventrel_oid),
+ PointerGetDatum(rulname),
+ 0, 0);
+
+ if (HeapTupleIsValid(oldtup))
+ {
+ if (!replace)
+ elog(ERROR,"Attempt to insert rule \"%s\" failed: already exists",
+ rulname);
+
+ /*
+ * When replacing, we don't need to replace every attribute
+ */
+ MemSet(replaces, ' ', sizeof(replaces));
+ replaces[Anum_pg_rewrite_ev_attr - 1] = 'r';
+ replaces[Anum_pg_rewrite_ev_type - 1] = 'r';
+ replaces[Anum_pg_rewrite_is_instead - 1] = 'r';
+ replaces[Anum_pg_rewrite_ev_qual - 1] = 'r';
+ replaces[Anum_pg_rewrite_ev_action - 1] = 'r';
+
+ tup = heap_modifytuple(oldtup, pg_rewrite_desc,
+ values, nulls, replaces);
+
+ simple_heap_update(pg_rewrite_desc, &tup->t_self, tup);
- tup = heap_formtuple(tupDesc,
- values,
- nulls);
+ ReleaseSysCache(oldtup);
+
+ rewriteObjectId = HeapTupleGetOid(tup);
+ is_update = true;
+ }
+ else
+ {
+ tup = heap_formtuple(pg_rewrite_desc->rd_att, values, nulls);
- rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup);
+ rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup);
+ }
+ /* Need to update indexes in either case */
CatalogUpdateIndexes(pg_rewrite_desc, tup);
heap_freetuple(tup);
+ /* If replacing, get rid of old dependencies and make new ones */
+ if (is_update)
+ deleteDependencyRecordsFor(RelationGetRelid(pg_rewrite_desc),
+ rewriteObjectId);
+
/*
* Install dependency on rule's relation to ensure it will go away
* on relation deletion. If the rule is ON SELECT, make the dependency
@@ -114,13 +152,14 @@ InsertRule(char *rulname,
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced,
- (evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
+ (evtype == CMD_SELECT) ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
/*
* Also install dependencies on objects referenced in action and qual.
*/
recordDependencyOnExpr(&myself, (Node *) action, NIL,
DEPENDENCY_NORMAL);
+
if (event_qual != NULL)
{
/* Find query containing OLD/NEW rtable entries */
@@ -143,6 +182,7 @@ DefineQueryRewrite(RuleStmt *stmt)
Node *event_qual = stmt->whereClause;
CmdType event_type = stmt->event;
bool is_instead = stmt->instead;
+ bool replace = stmt->replace;
List *action = stmt->actions;
Relation event_relation;
Oid ev_relid;
@@ -232,7 +272,7 @@ DefineQueryRewrite(RuleStmt *stmt)
* event relation, ...
*/
i = 0;
- foreach(tllist, query->targetList)
+ foreach (tllist, query->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tllist);
Resdom *resdom = tle->resdom;
@@ -282,7 +322,7 @@ DefineQueryRewrite(RuleStmt *stmt)
/*
* ... there must not be another ON SELECT rule already ...
*/
- if (event_relation->rd_rules != NULL)
+ if (!replace && event_relation->rd_rules != NULL)
{
for (i = 0; i < event_relation->rd_rules->numLocks; i++)
{
@@ -364,7 +404,8 @@ DefineQueryRewrite(RuleStmt *stmt)
event_attno,
is_instead,
event_qual,
- action);
+ action,
+ replace);
/*
* Set pg_class 'relhasrules' field TRUE for event relation. If