1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

CREATE OR REPLACE VIEW, CREATE OR REPLACE RULE.

Gavin Sherry, Neil Conway, and Tom Lane all got their hands dirty
on this one ...
This commit is contained in:
Tom Lane
2002-09-02 02:13:02 +00:00
parent c7a165adc6
commit 248c67d7ed
12 changed files with 290 additions and 70 deletions

View File

@ -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);
tup = heap_formtuple(tupDesc,
values,
nulls);
if (HeapTupleIsValid(oldtup))
{
if (!replace)
elog(ERROR,"Attempt to insert rule \"%s\" failed: already exists",
rulname);
rewriteObjectId = simple_heap_insert(pg_rewrite_desc, tup);
/*
* 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);
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);
}
/* 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