*** pgsql/src/backend/rewrite/rewriteDefine.c 2009/01/01 17:23:47 1.134 --- pgsql/src/backend/rewrite/rewriteDefine.c 2009/01/22 17:27:54 1.135 *************** *** 8,20 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.133 2008/11/19 10:34:52 heikki Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "access/heapam.h" #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" --- 8,21 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.134 2009/01/01 17:23:47 momjian 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,30 **** --- 26,32 ---- #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" *************** static void checkRuleResultList(List *ta *** 39,44 **** --- 41,47 ---- 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); /* *************** InsertRule(char *rulname, *** 52,57 **** --- 55,61 ---- Oid eventrel_oid, AttrNumber evslot_index, bool evinstead, + bool is_auto, Node *event_qual, List *action, bool replace) *************** InsertRule(char *rulname, *** 84,89 **** --- 88,94 ---- 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 */ *************** InsertRule(char *rulname, *** 102,108 **** if (HeapTupleIsValid(oldtup)) { ! if (!replace) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("rule \"%s\" for relation \"%s\" already exists", --- 107,117 ---- if (HeapTupleIsValid(oldtup)) { ! /* ! * 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", *************** InsertRule(char *rulname, *** 115,120 **** --- 124,130 ---- 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; *************** DefineRule(RuleStmt *stmt, const char *q *** 205,210 **** --- 215,221 ---- whereClause, stmt->event, stmt->instead, + false, /* not is_auto */ stmt->replace, actions); } *************** DefineQueryRewrite(char *rulename, *** 223,228 **** --- 234,240 ---- Node *event_qual, CmdType event_type, bool is_instead, + bool is_auto, bool replace, List *action) { *************** DefineQueryRewrite(char *rulename, *** 446,451 **** --- 458,499 ---- 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; + } + } + } + } /* *************** DefineQueryRewrite(char *rulename, *** 461,466 **** --- 509,515 ---- event_relid, event_attno, is_instead, + is_auto, event_qual, action, replace); *************** RenameRewriteRule(Oid owningRel, const c *** 754,756 **** --- 803,818 ---- } #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 "???"; + }