1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-17 06:41:09 +03:00

Automatic view update rules

Bernd Helmle
This commit is contained in:
Peter Eisentraut
2009-01-22 17:27:55 +00:00
parent 5841aa86eb
commit dd7e54a17f
30 changed files with 2289 additions and 41 deletions

View File

@ -8,13 +8,14 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.134 2009/01/01 17:23:47 momjian Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.135 2009/01/22 17:27:54 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/heapam.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
@ -25,6 +26,7 @@
#include "parser/parse_utilcmd.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteRemove.h"
#include "rewrite/rewriteSupport.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@ -39,6 +41,7 @@ static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
bool isSelect);
static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
static void setRuleCheckAsUser_Query(Query *qry, Oid userid);
static const char *rule_event_string(CmdType evtype);
/*
@ -52,6 +55,7 @@ InsertRule(char *rulname,
Oid eventrel_oid,
AttrNumber evslot_index,
bool evinstead,
bool is_auto,
Node *event_qual,
List *action,
bool replace)
@ -84,6 +88,7 @@ InsertRule(char *rulname,
values[i++] = CharGetDatum(evtype + '0'); /* ev_type */
values[i++] = CharGetDatum(RULE_FIRES_ON_ORIGIN); /* ev_enabled */
values[i++] = BoolGetDatum(evinstead); /* is_instead */
values[i++] = BoolGetDatum(is_auto); /* is_auto */
values[i++] = CStringGetTextDatum(evqual); /* ev_qual */
values[i++] = CStringGetTextDatum(actiontree); /* ev_action */
@ -102,7 +107,11 @@ InsertRule(char *rulname,
if (HeapTupleIsValid(oldtup))
{
if (!replace)
/*
* If REPLACE was not used we still check if the old rule is
* automatic: Then we replace it anyway.
*/
if (!replace && !((Form_pg_rewrite) GETSTRUCT(oldtup))->is_auto)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("rule \"%s\" for relation \"%s\" already exists",
@ -115,6 +124,7 @@ InsertRule(char *rulname,
replaces[Anum_pg_rewrite_ev_attr - 1] = true;
replaces[Anum_pg_rewrite_ev_type - 1] = true;
replaces[Anum_pg_rewrite_is_instead - 1] = true;
replaces[Anum_pg_rewrite_is_auto - 1] = true;
replaces[Anum_pg_rewrite_ev_qual - 1] = true;
replaces[Anum_pg_rewrite_ev_action - 1] = true;
@ -205,6 +215,7 @@ DefineRule(RuleStmt *stmt, const char *queryString)
whereClause,
stmt->event,
stmt->instead,
false, /* not is_auto */
stmt->replace,
actions);
}
@ -223,6 +234,7 @@ DefineQueryRewrite(char *rulename,
Node *event_qual,
CmdType event_type,
bool is_instead,
bool is_auto,
bool replace,
List *action)
{
@ -446,6 +458,42 @@ DefineQueryRewrite(char *rulename,
RelationGetDescr(event_relation),
false);
}
/*
* If defining a non-automatic DO INSTEAD rule, drop all
* automatic rules on the same event.
*/
if (!is_auto && is_instead)
{
RemoveAutomaticRulesOnEvent(event_relation, event_type);
CommandCounterIncrement();
}
/*
* If defining an automatic rule and there is a manual rule on
* the same event, warn and don't do it.
*/
if (is_auto && event_relation->rd_rules != NULL)
{
int i;
for (i = 0; i < event_relation->rd_rules->numLocks; i++)
{
RewriteRule *rule = event_relation->rd_rules->rules[i];
if (rule->event == event_type && !rule->is_auto && rule->isInstead == is_instead)
{
ereport(WARNING,
(errmsg("automatic %s rule not created because manually created %s rule exists",
rule_event_string(event_type), rule_event_string(event_type)),
errhint("If you prefer to have the automatic rule, drop the manually created rule and run CREATE OR REPLACE VIEW again.")));
heap_close(event_relation, NoLock);
return;
}
}
}
}
/*
@ -461,6 +509,7 @@ DefineQueryRewrite(char *rulename,
event_relid,
event_attno,
is_instead,
is_auto,
event_qual,
action,
replace);
@ -754,3 +803,16 @@ RenameRewriteRule(Oid owningRel, const char *oldName,
}
#endif
static const char *
rule_event_string(CmdType type)
{
if (type == CMD_INSERT)
return "INSERT";
if (type == CMD_UPDATE)
return "UPDATE";
if (type == CMD_DELETE)
return "DELETE";
return "???";
}