8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.134 2009/01/01 17:23:47 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.135 2009/01/22 17:27:54 petere Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
15
15
#include "postgres.h"
16
16
17
17
#include "access/heapam.h"
18
+ #include "access/xact.h"
18
19
#include "catalog/dependency.h"
19
20
#include "catalog/indexing.h"
20
21
#include "catalog/namespace.h"
25
26
#include "parser/parse_utilcmd.h"
26
27
#include "rewrite/rewriteDefine.h"
27
28
#include "rewrite/rewriteManip.h"
29
+ #include "rewrite/rewriteRemove.h"
28
30
#include "rewrite/rewriteSupport.h"
29
31
#include "utils/acl.h"
30
32
#include "utils/builtins.h"
@@ -39,6 +41,7 @@ static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
39
41
bool isSelect );
40
42
static bool setRuleCheckAsUser_walker (Node * node ,Oid * context );
41
43
static void setRuleCheckAsUser_Query (Query * qry ,Oid userid );
44
+ static const char * rule_event_string (CmdType evtype );
42
45
43
46
44
47
/*
@@ -52,6 +55,7 @@ InsertRule(char *rulname,
52
55
Oid eventrel_oid ,
53
56
AttrNumber evslot_index ,
54
57
bool evinstead ,
58
+ bool is_auto ,
55
59
Node * event_qual ,
56
60
List * action ,
57
61
bool replace )
@@ -84,6 +88,7 @@ InsertRule(char *rulname,
84
88
values [i ++ ]= CharGetDatum (evtype + '0' );/* ev_type */
85
89
values [i ++ ]= CharGetDatum (RULE_FIRES_ON_ORIGIN );/* ev_enabled */
86
90
values [i ++ ]= BoolGetDatum (evinstead );/* is_instead */
91
+ values [i ++ ]= BoolGetDatum (is_auto );/* is_auto */
87
92
values [i ++ ]= CStringGetTextDatum (evqual );/* ev_qual */
88
93
values [i ++ ]= CStringGetTextDatum (actiontree );/* ev_action */
89
94
@@ -102,7 +107,11 @@ InsertRule(char *rulname,
102
107
103
108
if (HeapTupleIsValid (oldtup ))
104
109
{
105
- if (!replace )
110
+ /*
111
+ * If REPLACE was not used we still check if the old rule is
112
+ * automatic: Then we replace it anyway.
113
+ */
114
+ if (!replace && !((Form_pg_rewrite )GETSTRUCT (oldtup ))-> is_auto )
106
115
ereport (ERROR ,
107
116
(errcode (ERRCODE_DUPLICATE_OBJECT ),
108
117
errmsg ("rule \"%s\" for relation \"%s\" already exists" ,
@@ -115,6 +124,7 @@ InsertRule(char *rulname,
115
124
replaces [Anum_pg_rewrite_ev_attr - 1 ]= true;
116
125
replaces [Anum_pg_rewrite_ev_type - 1 ]= true;
117
126
replaces [Anum_pg_rewrite_is_instead - 1 ]= true;
127
+ replaces [Anum_pg_rewrite_is_auto - 1 ]= true;
118
128
replaces [Anum_pg_rewrite_ev_qual - 1 ]= true;
119
129
replaces [Anum_pg_rewrite_ev_action - 1 ]= true;
120
130
@@ -205,6 +215,7 @@ DefineRule(RuleStmt *stmt, const char *queryString)
205
215
whereClause ,
206
216
stmt -> event ,
207
217
stmt -> instead ,
218
+ false,/* not is_auto */
208
219
stmt -> replace ,
209
220
actions );
210
221
}
@@ -223,6 +234,7 @@ DefineQueryRewrite(char *rulename,
223
234
Node * event_qual ,
224
235
CmdType event_type ,
225
236
bool is_instead ,
237
+ bool is_auto ,
226
238
bool replace ,
227
239
List * action )
228
240
{
@@ -446,6 +458,42 @@ DefineQueryRewrite(char *rulename,
446
458
RelationGetDescr (event_relation ),
447
459
false);
448
460
}
461
+
462
+ /*
463
+ * If defining a non-automatic DO INSTEAD rule, drop all
464
+ * automatic rules on the same event.
465
+ */
466
+ if (!is_auto && is_instead )
467
+ {
468
+ RemoveAutomaticRulesOnEvent (event_relation ,event_type );
469
+ CommandCounterIncrement ();
470
+ }
471
+
472
+ /*
473
+ * If defining an automatic rule and there is a manual rule on
474
+ * the same event, warn and don't do it.
475
+ */
476
+ if (is_auto && event_relation -> rd_rules != NULL )
477
+ {
478
+ int i ;
479
+
480
+ for (i = 0 ;i < event_relation -> rd_rules -> numLocks ;i ++ )
481
+ {
482
+ RewriteRule * rule = event_relation -> rd_rules -> rules [i ];
483
+
484
+ if (rule -> event == event_type && !rule -> is_auto && rule -> isInstead == is_instead )
485
+ {
486
+ ereport (WARNING ,
487
+ (errmsg ("automatic %s rule not created because manually created %s rule exists" ,
488
+ rule_event_string (event_type ),rule_event_string (event_type )),
489
+ errhint ("If you prefer to have the automatic rule, drop the manually created rule and run CREATE OR REPLACE VIEW again." )));
490
+
491
+ heap_close (event_relation ,NoLock );
492
+ return ;
493
+ }
494
+ }
495
+ }
496
+
449
497
}
450
498
451
499
/*
@@ -461,6 +509,7 @@ DefineQueryRewrite(char *rulename,
461
509
event_relid ,
462
510
event_attno ,
463
511
is_instead ,
512
+ is_auto ,
464
513
event_qual ,
465
514
action ,
466
515
replace );
@@ -754,3 +803,16 @@ RenameRewriteRule(Oid owningRel, const char *oldName,
754
803
}
755
804
756
805
#endif
806
+
807
+
808
+ static const char *
809
+ rule_event_string (CmdType type )
810
+ {
811
+ if (type == CMD_INSERT )
812
+ return "INSERT" ;
813
+ if (type == CMD_UPDATE )
814
+ return "UPDATE" ;
815
+ if (type == CMD_DELETE )
816
+ return "DELETE" ;
817
+ return "???" ;
818
+ }