On 3/16/2007 12:12 AM, Jan Wieck wrote:
On 3/15/2007 11:16 PM, Tom Lane wrote:
The SPI_savedplans part of this is pretty bletcherous, and has been
overtaken by events anyway.  I'd suggest testing whether plancache.c
has anything in its list.


[...]

After a quick look it seems that another little function in there, checking if (cached_plans_list == NIL), would do exactly that.

Changed patch is attached.


Jan

--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== [EMAIL PROTECTED] #
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.217
diff -c -r1.217 tablecmds.c
*** src/backend/commands/tablecmds.c    13 Mar 2007 00:33:39 -0000      1.217
--- src/backend/commands/tablecmds.c    16 Mar 2007 12:06:33 -0000
***************
*** 53,58 ****
--- 53,59 ----
  #include "parser/parse_relation.h"
  #include "parser/parse_type.h"
  #include "parser/parser.h"
+ #include "rewrite/rewriteDefine.h"
  #include "rewrite/rewriteHandler.h"
  #include "storage/smgr.h"
  #include "utils/acl.h"
***************
*** 253,259 ****
  static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace);
  static void ATExecSetRelOptions(Relation rel, List *defList, bool isReset);
  static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
!                                                  bool enable, bool 
skip_system);
  static void ATExecAddInherit(Relation rel, RangeVar *parent);
  static void ATExecDropInherit(Relation rel, RangeVar *parent);
  static void copy_relation_data(Relation rel, SMgrRelation dst);
--- 254,262 ----
  static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace);
  static void ATExecSetRelOptions(Relation rel, List *defList, bool isReset);
  static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
!                                                  char fires_when, bool 
skip_system);
! static void ATExecEnableDisableRule(Relation rel, char *rulename,
!                                                  char fires_when);
  static void ATExecAddInherit(Relation rel, RangeVar *parent);
  static void ATExecDropInherit(Relation rel, RangeVar *parent);
  static void copy_relation_data(Relation rel, SMgrRelation dst);
***************
*** 1955,1965 ****
--- 1958,1974 ----
                        pass = AT_PASS_MISC;
                        break;
                case AT_EnableTrig:             /* ENABLE TRIGGER variants */
+               case AT_EnableAlwaysTrig:
+               case AT_EnableReplicaTrig:
                case AT_EnableTrigAll:
                case AT_EnableTrigUser:
                case AT_DisableTrig:    /* DISABLE TRIGGER variants */
                case AT_DisableTrigAll:
                case AT_DisableTrigUser:
+               case AT_EnableRule:             /* ENABLE/DISABLE RULE variants 
*/
+               case AT_EnableAlwaysRule:
+               case AT_EnableReplicaRule:
+               case AT_DisableRule:
                case AT_AddInherit:             /* INHERIT / NO INHERIT */
                case AT_DropInherit:
                        ATSimplePermissions(rel, false);
***************
*** 2127,2150 ****
                case AT_ResetRelOptions:                /* RESET (...) */
                        ATExecSetRelOptions(rel, (List *) cmd->def, true);
                        break;
!               case AT_EnableTrig:             /* ENABLE TRIGGER name */
!                       ATExecEnableDisableTrigger(rel, cmd->name, true, false);
                        break;
                case AT_DisableTrig:    /* DISABLE TRIGGER name */
!                       ATExecEnableDisableTrigger(rel, cmd->name, false, 
false);
                        break;
                case AT_EnableTrigAll:  /* ENABLE TRIGGER ALL */
!                       ATExecEnableDisableTrigger(rel, NULL, true, false);
                        break;
                case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
!                       ATExecEnableDisableTrigger(rel, NULL, false, false);
                        break;
                case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
!                       ATExecEnableDisableTrigger(rel, NULL, true, true);
                        break;
                case AT_DisableTrigUser:                /* DISABLE TRIGGER USER 
*/
!                       ATExecEnableDisableTrigger(rel, NULL, false, true);
                        break;
                case AT_AddInherit:
                        ATExecAddInherit(rel, (RangeVar *) cmd->def);
                        break;
--- 2136,2192 ----
                case AT_ResetRelOptions:                /* RESET (...) */
                        ATExecSetRelOptions(rel, (List *) cmd->def, true);
                        break;
! 
!               case AT_EnableTrig:                     /* ENABLE TRIGGER name 
*/
!                       ATExecEnableDisableTrigger(rel, cmd->name, 
!                                       TRIGGER_FIRES_ON_ORIGIN, false);
!                       break;
!               case AT_EnableAlwaysTrig:       /* ENABLE ALWAYS TRIGGER name */
!                       ATExecEnableDisableTrigger(rel, cmd->name, 
!                                       TRIGGER_FIRES_ALWAYS, false);
!                       break;
!               case AT_EnableReplicaTrig:      /* ENABLE REPLICA TRIGGER name 
*/
!                       ATExecEnableDisableTrigger(rel, cmd->name, 
!                                       TRIGGER_FIRES_ON_REPLICA, false);
                        break;
                case AT_DisableTrig:    /* DISABLE TRIGGER name */
!                       ATExecEnableDisableTrigger(rel, cmd->name, 
!                                       TRIGGER_DISABLED, false);
                        break;
                case AT_EnableTrigAll:  /* ENABLE TRIGGER ALL */
!                       ATExecEnableDisableTrigger(rel, NULL, 
!                                       TRIGGER_FIRES_ON_ORIGIN, false);
                        break;
                case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
!                       ATExecEnableDisableTrigger(rel, NULL, 
!                                       TRIGGER_DISABLED, false);
                        break;
                case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
!                       ATExecEnableDisableTrigger(rel, NULL, 
!                                       TRIGGER_FIRES_ON_ORIGIN, true);
                        break;
                case AT_DisableTrigUser:                /* DISABLE TRIGGER USER 
*/
!                       ATExecEnableDisableTrigger(rel, NULL, 
!                                       TRIGGER_DISABLED, true);
!                       break;
! 
!               case AT_EnableRule:                     /* ENABLE RULE name */
!                       ATExecEnableDisableRule(rel, cmd->name, 
!                                       RULE_FIRES_ON_ORIGIN);
!                       break;
!               case AT_EnableAlwaysRule:       /* ENABLE ALWAYS RULE name */
!                       ATExecEnableDisableRule(rel, cmd->name, 
!                                       RULE_FIRES_ALWAYS);
                        break;
+               case AT_EnableReplicaRule:      /* ENABLE REPLICA RULE name */
+                       ATExecEnableDisableRule(rel, cmd->name, 
+                                       RULE_FIRES_ON_REPLICA);
+                       break;
+               case AT_DisableRule:    /* DISABLE RULE name */
+                       ATExecEnableDisableRule(rel, cmd->name, 
+                                       RULE_DISABLED);
+                       break;
+ 
                case AT_AddInherit:
                        ATExecAddInherit(rel, (RangeVar *) cmd->def);
                        break;
***************
*** 4380,4386 ****
        MemSet(&trig, 0, sizeof(trig));
        trig.tgoid = InvalidOid;
        trig.tgname = fkconstraint->constr_name;
!       trig.tgenabled = TRUE;
        trig.tgisconstraint = TRUE;
        trig.tgconstrrelid = RelationGetRelid(pkrel);
        trig.tgconstraint = constraintOid;
--- 4422,4428 ----
        MemSet(&trig, 0, sizeof(trig));
        trig.tgoid = InvalidOid;
        trig.tgname = fkconstraint->constr_name;
!       trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
        trig.tgisconstraint = TRUE;
        trig.tgconstrrelid = RelationGetRelid(pkrel);
        trig.tgconstraint = constraintOid;
***************
*** 5877,5885 ****
   */
  static void
  ATExecEnableDisableTrigger(Relation rel, char *trigname,
!                                                  bool enable, bool 
skip_system)
  {
!       EnableDisableTrigger(rel, trigname, enable, skip_system);
  }
  
  /*
--- 5919,5939 ----
   */
  static void
  ATExecEnableDisableTrigger(Relation rel, char *trigname,
!                                                  char fires_when, bool 
skip_system)
! {
!       EnableDisableTrigger(rel, trigname, fires_when, skip_system);
! }
! 
! /*
!  * ALTER TABLE ENABLE/DISABLE RULE
!  *
!  * We just pass this off to rewriteDefine.c.
!  */
! static void
! ATExecEnableDisableRule(Relation rel, char *trigname,
!                                                  char fires_when)
  {
!       EnableDisableRule(rel, trigname, fires_when);
  }
  
  /*
Index: src/backend/commands/trigger.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/commands/trigger.c,v
retrieving revision 1.213
diff -c -r1.213 trigger.c
*** src/backend/commands/trigger.c      14 Feb 2007 01:58:56 -0000      1.213
--- src/backend/commands/trigger.c      16 Mar 2007 12:06:33 -0000
***************
*** 54,59 ****
--- 54,66 ----
  static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
                                          bool row_trigger, HeapTuple oldtup, 
HeapTuple newtup);
  
+ /*
+  * SessionReplicationRole -
+  *
+  *    Global variable that controls the trigger firing behaviour based
+  *    on pg_trigger.tgenabled. This is maintained from misc/guc.c.
+  */
+ int   SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
  
  /*
   * Create a trigger.  Returns the OID of the created trigger.
***************
*** 270,276 ****
                                                                                
                  CStringGetDatum(trigname));
        values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
        values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
!       values[Anum_pg_trigger_tgenabled - 1] = BoolGetDatum(true);
        values[Anum_pg_trigger_tgisconstraint - 1] = 
BoolGetDatum(stmt->isconstraint);
        values[Anum_pg_trigger_tgconstrname - 1] = DirectFunctionCall1(namein,
                                                                                
                CStringGetDatum(constrname));
--- 277,283 ----
                                                                                
                  CStringGetDatum(trigname));
        values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
        values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
!       values[Anum_pg_trigger_tgenabled - 1] = 
CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
        values[Anum_pg_trigger_tgisconstraint - 1] = 
BoolGetDatum(stmt->isconstraint);
        values[Anum_pg_trigger_tgconstrname - 1] = DirectFunctionCall1(namein,
                                                                                
                CStringGetDatum(constrname));
***************
*** 701,711 ****
   * EnableDisableTrigger()
   *
   *    Called by ALTER TABLE ENABLE/DISABLE TRIGGER
!  *    to change 'tgenabled' flag for the specified trigger(s)
   *
   * rel: relation to process (caller must hold suitable lock on it)
   * tgname: trigger to process, or NULL to scan all triggers
!  * enable: new value for tgenabled flag
   * skip_system: if true, skip "system" triggers (constraint triggers)
   *
   * Caller should have checked permissions for the table; here we also
--- 708,718 ----
   * EnableDisableTrigger()
   *
   *    Called by ALTER TABLE ENABLE/DISABLE TRIGGER
!  *    to change 'tgenabled' field for the specified trigger(s)
   *
   * rel: relation to process (caller must hold suitable lock on it)
   * tgname: trigger to process, or NULL to scan all triggers
!  * enable: new value for tgenabled field
   * skip_system: if true, skip "system" triggers (constraint triggers)
   *
   * Caller should have checked permissions for the table; here we also
***************
*** 714,720 ****
   */
  void
  EnableDisableTrigger(Relation rel, const char *tgname,
!                                        bool enable, bool skip_system)
  {
        Relation        tgrel;
        int                     nkeys;
--- 721,727 ----
   */
  void
  EnableDisableTrigger(Relation rel, const char *tgname,
!                                        char fires_when, bool skip_system)
  {
        Relation        tgrel;
        int                     nkeys;
***************
*** 765,777 ****
  
                found = true;
  
!               if (oldtrig->tgenabled != enable)
                {
                        /* need to change this one ... make a copy to scribble 
on */
                        HeapTuple       newtup = heap_copytuple(tuple);
                        Form_pg_trigger newtrig = (Form_pg_trigger) 
GETSTRUCT(newtup);
  
!                       newtrig->tgenabled = enable;
  
                        simple_heap_update(tgrel, &newtup->t_self, newtup);
  
--- 772,784 ----
  
                found = true;
  
!               if (oldtrig->tgenabled != fires_when)
                {
                        /* need to change this one ... make a copy to scribble 
on */
                        HeapTuple       newtup = heap_copytuple(tuple);
                        Form_pg_trigger newtrig = (Form_pg_trigger) 
GETSTRUCT(newtup);
  
!                       newtrig->tgenabled = fires_when;
  
                        simple_heap_update(tgrel, &newtup->t_self, newtup);
  
***************
*** 1333,1340 ****
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
                HeapTuple       newtuple;
  
!               if (!trigger->tgenabled)
!                       continue;
                LocTriggerData.tg_trigger = trigger;
                newtuple = ExecCallTriggerFunc(&LocTriggerData,
                                                                           
tgindx[i],
--- 1340,1357 ----
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
                HeapTuple       newtuple;
  
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
                LocTriggerData.tg_trigger = trigger;
                newtuple = ExecCallTriggerFunc(&LocTriggerData,
                                                                           
tgindx[i],
***************
*** 1382,1389 ****
        {
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
!               if (!trigger->tgenabled)
!                       continue;
                LocTriggerData.tg_trigtuple = oldtuple = newtuple;
                LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
                LocTriggerData.tg_trigger = trigger;
--- 1399,1416 ----
        {
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
                LocTriggerData.tg_trigtuple = oldtuple = newtuple;
                LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
                LocTriggerData.tg_trigger = trigger;
***************
*** 1444,1451 ****
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
                HeapTuple       newtuple;
  
!               if (!trigger->tgenabled)
!                       continue;
                LocTriggerData.tg_trigger = trigger;
                newtuple = ExecCallTriggerFunc(&LocTriggerData,
                                                                           
tgindx[i],
--- 1471,1488 ----
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
                HeapTuple       newtuple;
  
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
                LocTriggerData.tg_trigger = trigger;
                newtuple = ExecCallTriggerFunc(&LocTriggerData,
                                                                           
tgindx[i],
***************
*** 1500,1507 ****
        {
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
!               if (!trigger->tgenabled)
!                       continue;
                LocTriggerData.tg_trigtuple = trigtuple;
                LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
                LocTriggerData.tg_trigger = trigger;
--- 1537,1554 ----
        {
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
                LocTriggerData.tg_trigtuple = trigtuple;
                LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
                LocTriggerData.tg_trigger = trigger;
***************
*** 1575,1582 ****
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
                HeapTuple       newtuple;
  
!               if (!trigger->tgenabled)
!                       continue;
                LocTriggerData.tg_trigger = trigger;
                newtuple = ExecCallTriggerFunc(&LocTriggerData,
                                                                           
tgindx[i],
--- 1622,1639 ----
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
                HeapTuple       newtuple;
  
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
                LocTriggerData.tg_trigger = trigger;
                newtuple = ExecCallTriggerFunc(&LocTriggerData,
                                                                           
tgindx[i],
***************
*** 1636,1643 ****
        {
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
!               if (!trigger->tgenabled)
!                       continue;
                LocTriggerData.tg_trigtuple = trigtuple;
                LocTriggerData.tg_newtuple = oldtuple = newtuple;
                LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
--- 1693,1710 ----
        {
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
                LocTriggerData.tg_trigtuple = trigtuple;
                LocTriggerData.tg_newtuple = oldtuple = newtuple;
                LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
***************
*** 3267,3274 ****
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
                /* Ignore disabled triggers */
!               if (!trigger->tgenabled)
!                       continue;
  
                /*
                 * If this is an UPDATE of a PK table or FK table that does not 
change
--- 3334,3351 ----
                Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  
                /* Ignore disabled triggers */
!               if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
!               else /* ORIGIN or LOCAL role */
!               {
!                       if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
!                               trigger->tgenabled == TRIGGER_DISABLED)
!                               continue;
!               }
  
                /*
                 * If this is an UPDATE of a PK table or FK table that does not 
change
Index: src/backend/parser/gram.y
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.581
diff -c -r2.581 gram.y
*** src/backend/parser/gram.y   13 Mar 2007 00:33:41 -0000      2.581
--- src/backend/parser/gram.y   16 Mar 2007 12:06:33 -0000
***************
*** 365,371 ****
  
  /* ordinary key words in alphabetical order */
  %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
!       AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
        ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
  
        BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
--- 365,371 ----
  
  /* ordinary key words in alphabetical order */
  %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
!       AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
        ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
  
        BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
***************
*** 422,429 ****
        QUOTE
  
        READ REAL REASSIGN RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME
!       REPEATABLE REPLACE RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT
!       ROLE ROLLBACK ROW ROWS RULE
  
        SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
        SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
--- 422,429 ----
        QUOTE
  
        READ REAL REASSIGN RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME
!       REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURNING RETURNS 
REVOKE
!       RIGHT ROLE ROLLBACK ROW ROWS RULE
  
        SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
        SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
***************
*** 1480,1485 ****
--- 1480,1501 ----
                                        n->name = $3;
                                        $$ = (Node *)n;
                                }
+                       /* ALTER TABLE <name> ENABLE ALWAYS TRIGGER <trig> */
+                       | ENABLE_P ALWAYS TRIGGER name
+                               {
+                                       AlterTableCmd *n = 
makeNode(AlterTableCmd);
+                                       n->subtype = AT_EnableAlwaysTrig;
+                                       n->name = $4;
+                                       $$ = (Node *)n;
+                               }
+                       /* ALTER TABLE <name> ENABLE REPLICA TRIGGER <trig> */
+                       | ENABLE_P REPLICA TRIGGER name
+                               {
+                                       AlterTableCmd *n = 
makeNode(AlterTableCmd);
+                                       n->subtype = AT_EnableReplicaTrig;
+                                       n->name = $4;
+                                       $$ = (Node *)n;
+                               }
                        /* ALTER TABLE <name> ENABLE TRIGGER ALL */
                        | ENABLE_P TRIGGER ALL
                                {
***************
*** 1516,1521 ****
--- 1532,1569 ----
                                        n->subtype = AT_DisableTrigUser;
                                        $$ = (Node *)n;
                                }
+                       /* ALTER TABLE <name> ENABLE RULE <rule> */
+                       | ENABLE_P RULE name
+                               {
+                                       AlterTableCmd *n = 
makeNode(AlterTableCmd);
+                                       n->subtype = AT_EnableRule;
+                                       n->name = $3;
+                                       $$ = (Node *)n;
+                               }
+                       /* ALTER TABLE <name> ENABLE ALWAYS RULE <rule> */
+                       | ENABLE_P ALWAYS RULE name
+                               {
+                                       AlterTableCmd *n = 
makeNode(AlterTableCmd);
+                                       n->subtype = AT_EnableAlwaysRule;
+                                       n->name = $4;
+                                       $$ = (Node *)n;
+                               }
+                       /* ALTER TABLE <name> ENABLE REPLICA RULE <rule> */
+                       | ENABLE_P REPLICA RULE name
+                               {
+                                       AlterTableCmd *n = 
makeNode(AlterTableCmd);
+                                       n->subtype = AT_EnableReplicaRule;
+                                       n->name = $4;
+                                       $$ = (Node *)n;
+                               }
+                       /* ALTER TABLE <name> DISABLE RULE <rule> */
+                       | DISABLE_P RULE name
+                               {
+                                       AlterTableCmd *n = 
makeNode(AlterTableCmd);
+                                       n->subtype = AT_DisableRule;
+                                       n->name = $3;
+                                       $$ = (Node *)n;
+                               }
                        /* ALTER TABLE <name> INHERIT <parent> */
                        | INHERIT qualified_name
                                {
***************
*** 8667,8672 ****
--- 8715,8721 ----
                        | AGGREGATE
                        | ALSO
                        | ALTER
+                       | ALWAYS
                        | ASSERTION
                        | ASSIGNMENT
                        | AT
***************
*** 8812,8817 ****
--- 8861,8867 ----
                        | RENAME
                        | REPEATABLE
                        | REPLACE
+                       | REPLICA
                        | RESET
                        | RESTART
                        | RESTRICT
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.184
diff -c -r1.184 keywords.c
*** src/backend/parser/keywords.c       25 Jan 2007 11:53:51 -0000      1.184
--- src/backend/parser/keywords.c       16 Mar 2007 12:06:33 -0000
***************
*** 42,47 ****
--- 42,48 ----
        {"all", ALL},
        {"also", ALSO},
        {"alter", ALTER},
+       {"always", ALWAYS},
        {"analyse", ANALYSE},           /* British spelling */
        {"analyze", ANALYZE},
        {"and", AND},
***************
*** 289,294 ****
--- 290,296 ----
        {"rename", RENAME},
        {"repeatable", REPEATABLE},
        {"replace", REPLACE},
+       {"replica", REPLICA},
        {"reset", RESET},
        {"restart", RESTART},
        {"restrict", RESTRICT},
Index: src/backend/rewrite/rewriteDefine.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/rewrite/rewriteDefine.c,v
retrieving revision 1.118
diff -c -r1.118 rewriteDefine.c
*** src/backend/rewrite/rewriteDefine.c 13 Mar 2007 00:33:42 -0000      1.118
--- src/backend/rewrite/rewriteDefine.c 16 Mar 2007 12:06:33 -0000
***************
*** 30,35 ****
--- 30,36 ----
  #include "utils/builtins.h"
  #include "utils/lsyscache.h"
  #include "utils/syscache.h"
+ #include "utils/inval.h"
  
  
  static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
***************
*** 79,84 ****
--- 80,86 ----
        values[i++] = ObjectIdGetDatum(eventrel_oid);           /* ev_class */
        values[i++] = Int16GetDatum(evslot_index);      /* ev_attr */
        values[i++] = CharGetDatum(evtype + '0');       /* ev_type */
+       values[i++] = CharGetDatum(RULE_FIRES_ON_ORIGIN);       /* ev_enabled */
        values[i++] = BoolGetDatum(evinstead);          /* is_instead */
        values[i++] = DirectFunctionCall1(textin, CStringGetDatum(evqual)); /* 
ev_qual */
        values[i++] = DirectFunctionCall1(textin, CStringGetDatum(actiontree)); 
        /* ev_action */
***************
*** 629,634 ****
--- 631,702 ----
  
  
  /*
+  * Change the firing semantics of an existing rule.
+  *
+  */
+ void
+ EnableDisableRule(Relation rel, const char *rulename,
+                                 char fires_when)
+ {
+       Relation        pg_rewrite_desc;
+       Oid                     owningRel = RelationGetRelid(rel);
+       Oid                     eventRelationOid;
+       HeapTuple       ruletup;
+       bool            changed = false;
+ 
+       /*
+        * Find the rule tuple to change.
+        */
+       pg_rewrite_desc = heap_open(RewriteRelationId, RowExclusiveLock);
+       ruletup = SearchSysCacheCopy(RULERELNAME,
+                                                                
ObjectIdGetDatum(owningRel),
+                                                                
PointerGetDatum(rulename),
+                                                                0, 0);
+       if (!HeapTupleIsValid(ruletup))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("rule \"%s\" for relation \"%s\" does 
not exist",
+                                               rulename, 
get_rel_name(owningRel))));
+ 
+       /*
+        * Verify that the user has appropriate permissions.
+        */
+       eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_class;
+       Assert(eventRelationOid == owningRel);
+       if (!pg_class_ownercheck(eventRelationOid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
+                                               get_rel_name(eventRelationOid));
+       
+       /*
+        * Change ev_enabled if it is different from the desired new state.
+        */
+       if (DatumGetChar(((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_enabled) !=
+                       fires_when)
+               {
+               ((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_enabled =
+                                       CharGetDatum(fires_when);
+               simple_heap_update(pg_rewrite_desc, &ruletup->t_self, ruletup);
+ 
+               /* keep system catalog indexes current */
+               CatalogUpdateIndexes(pg_rewrite_desc, ruletup);
+ 
+               changed = true;
+       }
+ 
+       heap_freetuple(ruletup);
+       heap_close(pg_rewrite_desc, RowExclusiveLock);
+ 
+       /*
+        * If we changed anything, broadcast a SI inval message to force each
+        * backend (including our own!) to rebuild relation's relcache entry.
+        * Otherwise they will fail to apply the change promptly.
+        */
+       if (changed)
+               CacheInvalidateRelcache(rel);
+ }
+ 
+ 
+ /*
   * Rename an existing rewrite rule.
   *
   * This is unused code at the moment.
Index: src/backend/rewrite/rewriteHandler.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/rewrite/rewriteHandler.c,v
retrieving revision 1.171
diff -c -r1.171 rewriteHandler.c
*** src/backend/rewrite/rewriteHandler.c        1 Mar 2007 18:50:28 -0000       
1.171
--- src/backend/rewrite/rewriteHandler.c        16 Mar 2007 12:06:33 -0000
***************
*** 21,30 ****
--- 21,32 ----
  #include "parser/parse_coerce.h"
  #include "parser/parse_expr.h"
  #include "parser/parsetree.h"
+ #include "rewrite/rewriteDefine.h"
  #include "rewrite/rewriteHandler.h"
  #include "rewrite/rewriteManip.h"
  #include "utils/builtins.h"
  #include "utils/lsyscache.h"
+ #include "commands/trigger.h"
  
  
  /* We use a list of these to detect recursion in RewriteQuery */
***************
*** 1033,1038 ****
--- 1035,1063 ----
        {
                RewriteRule *oneLock = rulelocks->rules[i];
  
+               /*
+                * Suppress ON INSERT/UPDATE/DELETE rules that are disabled
+                * or configured to not fire during the current sessions
+                * replication role. ON SELECT rules will always be applied
+                * in order to keep views working even in LOCAL or REPLICA
+                * role.
+                */
+               if (oneLock->event != CMD_SELECT)
+               {
+                       if (SessionReplicationRole == 
SESSION_REPLICATION_ROLE_REPLICA)
+                       {
+                               if (oneLock->enabled == RULE_FIRES_ON_ORIGIN ||
+                                       oneLock->enabled == RULE_DISABLED)
+                                       continue;
+                       }
+                       else /* ORIGIN or LOCAL ROLE */
+                       {
+                               if (oneLock->enabled == RULE_FIRES_ON_REPLICA ||
+                                       oneLock->enabled == RULE_DISABLED)
+                                       continue;
+                       }
+               }
+ 
                if (oneLock->event == event)
                {
                        if (parsetree->commandType != CMD_SELECT ||
Index: src/backend/utils/cache/plancache.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/utils/cache/plancache.c,v
retrieving revision 1.2
diff -c -r1.2 plancache.c
*** src/backend/utils/cache/plancache.c 15 Mar 2007 23:12:06 -0000      1.2
--- src/backend/utils/cache/plancache.c 16 Mar 2007 12:38:58 -0000
***************
*** 860,862 ****
--- 860,873 ----
        if (relid == context->inval_relid)
                context->plan->dead = true;
  }
+ 
+ /*
+  * HaveCachedPlans 
+  *            Check if the plancache has stored any plans at all.
+  */
+ bool
+ HaveCachedPlans(void)
+ {
+       return (cached_plans_list != NIL);
+ }
+ 
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.257
diff -c -r1.257 relcache.c
*** src/backend/utils/cache/relcache.c  3 Mar 2007 20:08:41 -0000       1.257
--- src/backend/utils/cache/relcache.c  16 Mar 2007 12:06:33 -0000
***************
*** 651,656 ****
--- 651,657 ----
  
                rule->event = rewrite_form->ev_type - '0';
                rule->attrno = rewrite_form->ev_attr;
+               rule->enabled = rewrite_form->ev_enabled;
                rule->isInstead = rewrite_form->is_instead;
  
                /*
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.382
diff -c -r1.382 guc.c
*** src/backend/utils/misc/guc.c        13 Mar 2007 14:32:25 -0000      1.382
--- src/backend/utils/misc/guc.c        16 Mar 2007 12:18:34 -0000
***************
*** 34,39 ****
--- 34,40 ----
  #include "commands/async.h"
  #include "commands/vacuum.h"
  #include "commands/variable.h"
+ #include "commands/trigger.h"
  #include "funcapi.h"
  #include "libpq/auth.h"
  #include "libpq/pqformat.h"
***************
*** 59,64 ****
--- 60,66 ----
  #include "utils/guc_tables.h"
  #include "utils/memutils.h"
  #include "utils/pg_locale.h"
+ #include "utils/plancache.h"
  #include "utils/ps_status.h"
  #include "utils/tzparser.h"
  #include "utils/xml.h"
***************
*** 124,129 ****
--- 126,133 ----
  
  static const char *assign_defaultxactisolevel(const char *newval, bool doit,
                                                   GucSource source);
+ static const char *assign_session_replication_role(const char *newval, bool 
doit,
+                                                  GucSource source);
  static const char *assign_log_min_messages(const char *newval, bool doit,
                                                GucSource source);
  static const char *assign_client_min_messages(const char *newval,
***************
*** 226,231 ****
--- 230,236 ----
  static char *client_encoding_string;
  static char *datestyle_string;
  static char *default_iso_level_string;
+ static char *session_replication_role_string;
  static char *locale_collate;
  static char *locale_ctype;
  static char *regex_flavor_string;
***************
*** 1929,1934 ****
--- 1934,1949 ----
        },
  
        {
+               {"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
+                       gettext_noop("Sets the sessions behaviour for triggers 
and rewrite rules."),
+                       gettext_noop("Each session can be either"
+                                                " \"origin\", \"replica\" or 
\"local\".")
+               },
+               &session_replication_role_string,
+               "origin", assign_session_replication_role, NULL
+       },
+ 
+       {
                {"dynamic_library_path", PGC_SUSET, CLIENT_CONN_OTHER,
                        gettext_noop("Sets the path for dynamically loadable 
modules."),
                        gettext_noop("If a dynamically loadable module needs to 
be opened and "
***************
*** 6116,6121 ****
--- 6131,6163 ----
  }
  
  static const char *
+ assign_session_replication_role(const char *newval, bool doit, GucSource 
source)
+ {
+       if (HaveCachedPlans())
+               elog(ERROR, "session_replication_role cannot be changed "
+                                       "after prepared plans have been 
cached");
+ 
+       if (pg_strcasecmp(newval, "origin") == 0)
+       {
+               if (doit)
+                       SessionReplicationRole = 
SESSION_REPLICATION_ROLE_ORIGIN;
+       }
+       else if (pg_strcasecmp(newval, "replica") == 0)
+       {
+               if (doit)
+                       SessionReplicationRole = 
SESSION_REPLICATION_ROLE_REPLICA;
+       }
+       else if (pg_strcasecmp(newval, "local") == 0)
+       {
+               if (doit)
+                       SessionReplicationRole = SESSION_REPLICATION_ROLE_LOCAL;
+       }
+       else
+               return NULL;
+       return newval;
+ }
+ 
+ static const char *
  assign_log_min_messages(const char *newval,
                                                bool doit, GucSource source)
  {
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.460
diff -c -r1.460 pg_dump.c
*** src/bin/pg_dump/pg_dump.c   14 Feb 2007 01:58:57 -0000      1.460
--- src/bin/pg_dump/pg_dump.c   16 Mar 2007 12:06:33 -0000
***************
*** 3699,3713 ****
        int                     i_ruletable;
        int                     i_ev_type;
        int                     i_is_instead;
  
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
  
!       if (g_fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(query, "SELECT "
                                                  "tableoid, oid, rulename, "
!                                                 "ev_class as ruletable, 
ev_type, is_instead "
                                                  "FROM pg_rewrite "
                                                  "ORDER BY oid");
        }
--- 3699,3724 ----
        int                     i_ruletable;
        int                     i_ev_type;
        int                     i_is_instead;
+       int                     i_ev_enabled;
  
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
  
!       if (g_fout->remoteVersion >= 80300)
!       {
!               appendPQExpBuffer(query, "SELECT "
!                                                 "tableoid, oid, rulename, "
!                                                 "ev_class as ruletable, 
ev_type, is_instead, "
!                                                 "ev_enabled "
!                                                 "FROM pg_rewrite "
!                                                 "ORDER BY oid");
!       }
!       else if (g_fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(query, "SELECT "
                                                  "tableoid, oid, rulename, "
!                                                 "ev_class as ruletable, 
ev_type, is_instead, "
!                                                 "'O'::char as ev_enabled "
                                                  "FROM pg_rewrite "
                                                  "ORDER BY oid");
        }
***************
*** 3716,3722 ****
                appendPQExpBuffer(query, "SELECT "
                                                  "(SELECT oid FROM pg_class 
WHERE relname = 'pg_rewrite') AS tableoid, "
                                                  "oid, rulename, "
!                                                 "ev_class as ruletable, 
ev_type, is_instead "
                                                  "FROM pg_rewrite "
                                                  "ORDER BY oid");
        }
--- 3727,3734 ----
                appendPQExpBuffer(query, "SELECT "
                                                  "(SELECT oid FROM pg_class 
WHERE relname = 'pg_rewrite') AS tableoid, "
                                                  "oid, rulename, "
!                                                 "ev_class as ruletable, 
ev_type, is_instead, "
!                                                 "'O'::char as ev_enabled "
                                                  "FROM pg_rewrite "
                                                  "ORDER BY oid");
        }
***************
*** 3736,3741 ****
--- 3748,3754 ----
        i_ruletable = PQfnumber(res, "ruletable");
        i_ev_type = PQfnumber(res, "ev_type");
        i_is_instead = PQfnumber(res, "is_instead");
+       i_ev_enabled = PQfnumber(res, "ev_enabled");
  
        for (i = 0; i < ntups; i++)
        {
***************
*** 3759,3764 ****
--- 3772,3778 ----
                ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
                ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
                ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 
't';
+               ruleinfo[i].ev_enabled = *(PQgetvalue(res, i, i_ev_enabled));
                if (ruleinfo[i].ruletable)
                {
                        /*
***************
*** 3956,3962 ****
                        tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
                        tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs));
                        tginfo[j].tgisconstraint = *(PQgetvalue(res, j, 
i_tgisconstraint)) == 't';
!                       tginfo[j].tgenabled = *(PQgetvalue(res, j, 
i_tgenabled)) == 't';
                        tginfo[j].tgdeferrable = *(PQgetvalue(res, j, 
i_tgdeferrable)) == 't';
                        tginfo[j].tginitdeferred = *(PQgetvalue(res, j, 
i_tginitdeferred)) == 't';
  
--- 3970,3976 ----
                        tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
                        tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs));
                        tginfo[j].tgisconstraint = *(PQgetvalue(res, j, 
i_tgisconstraint)) == 't';
!                       tginfo[j].tgenabled = *(PQgetvalue(res, j, 
i_tgenabled));
                        tginfo[j].tgdeferrable = *(PQgetvalue(res, j, 
i_tgdeferrable)) == 't';
                        tginfo[j].tginitdeferred = *(PQgetvalue(res, j, 
i_tginitdeferred)) == 't';
  
***************
*** 8824,8834 ****
        }
        appendPQExpBuffer(query, ");\n");
  
!       if (!tginfo->tgenabled)
        {
                appendPQExpBuffer(query, "\nALTER TABLE %s ",
                                                  fmtId(tbinfo->dobj.name));
!               appendPQExpBuffer(query, "DISABLE TRIGGER %s;\n",
                                                  fmtId(tginfo->dobj.name));
        }
  
--- 8838,8864 ----
        }
        appendPQExpBuffer(query, ");\n");
  
!       if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
        {
                appendPQExpBuffer(query, "\nALTER TABLE %s ",
                                                  fmtId(tbinfo->dobj.name));
!               switch (tginfo->tgenabled)
!               {
!                       case 'D':
!                       case 'f':
!                               appendPQExpBuffer(query, "DISABLE");
!                               break;
!                       case 'A':
!                               appendPQExpBuffer(query, "ENABLE ALWAYS");
!                               break;
!                       case 'R':
!                               appendPQExpBuffer(query, "ENABLE REPLICA");
!                               break;
!                       default:
!                               appendPQExpBuffer(query, "ENABLE");
!                               break;
!               }
!               appendPQExpBuffer(query, " TRIGGER %s;\n",
                                                  fmtId(tginfo->dobj.name));
        }
  
***************
*** 8915,8920 ****
--- 8945,8977 ----
        printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
  
        /*
+        * Add the command to alter the rules replication firing semantics
+        * if it differs from the default.
+        */
+       if (rinfo->ev_enabled != 'O')
+       {
+               appendPQExpBuffer(cmd, "ALTER TABLE %s.",
+                                       
fmtId(tbinfo->dobj.namespace->dobj.name));
+               appendPQExpBuffer(cmd, "%s ",
+                                       fmtId(tbinfo->dobj.name));
+               switch (rinfo->ev_enabled)
+               {
+                       case 'A':
+                               appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE 
%s;\n",
+                                                       
fmtId(rinfo->dobj.name));
+                               break;
+                       case 'R':
+                               appendPQExpBuffer(cmd, "ENABLE REPLICA RULE 
%s;\n",
+                                                       
fmtId(rinfo->dobj.name));
+                               break;
+                       case 'D':
+                               appendPQExpBuffer(cmd, "DISABLE RULE %s;\n",
+                                                       
fmtId(rinfo->dobj.name));
+                               break;
+               }
+       }
+ 
+       /*
         * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delcmd, "DROP RULE %s ",
Index: src/bin/pg_dump/pg_dump.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/bin/pg_dump/pg_dump.h,v
retrieving revision 1.133
diff -c -r1.133 pg_dump.h
*** src/bin/pg_dump/pg_dump.h   19 Feb 2007 15:05:06 -0000      1.133
--- src/bin/pg_dump/pg_dump.h   16 Mar 2007 12:06:33 -0000
***************
*** 314,319 ****
--- 314,320 ----
        TableInfo  *ruletable;          /* link to table the rule is for */
        char            ev_type;
        bool            is_instead;
+       char            ev_enabled;
        bool            separate;               /* TRUE if must dump as 
separate item */
        /* separate is always true for non-ON SELECT rules */
  } RuleInfo;
***************
*** 330,336 ****
        char       *tgconstrname;
        Oid                     tgconstrrelid;
        char       *tgconstrrelname;
!       bool            tgenabled;
        bool            tgdeferrable;
        bool            tginitdeferred;
  } TriggerInfo;
--- 331,337 ----
        char       *tgconstrname;
        Oid                     tgconstrrelid;
        char       *tgconstrrelname;
!       char            tgenabled;
        bool            tgdeferrable;
        bool            tginitdeferred;
  } TriggerInfo;
Index: src/bin/psql/describe.c
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/bin/psql/describe.c,v
retrieving revision 1.153
diff -c -r1.153 describe.c
*** src/bin/psql/describe.c     16 Mar 2007 08:28:01 -0000      1.153
--- src/bin/psql/describe.c     16 Mar 2007 12:44:05 -0000
***************
*** 1055,1068 ****
                                   *result3 = NULL,
                                   *result4 = NULL,
                                   *result5 = NULL,
!                                  *result6 = NULL,
!                                  *result7 = NULL;
                int                     check_count = 0,
                                        index_count = 0,
                                        foreignkey_count = 0,
                                        rule_count = 0,
                                        trigger_count = 0,
-                                       disabled_trigger_count = 0,
                                        inherits_count = 0;
                int                     count_footers = 0;
  
--- 1055,1066 ----
                                   *result3 = NULL,
                                   *result4 = NULL,
                                   *result5 = NULL,
!                                  *result6 = NULL;
                int                     check_count = 0,
                                        index_count = 0,
                                        foreignkey_count = 0,
                                        rule_count = 0,
                                        trigger_count = 0,
                                        inherits_count = 0;
                int                     count_footers = 0;
  
***************
*** 1105,1115 ****
                /* count rules */
                if (tableinfo.hasrules)
                {
!                       printfPQExpBuffer(&buf,
!                                                         "SELECT r.rulename, 
trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n"
                                                          "FROM 
pg_catalog.pg_rewrite r\n"
                                                          "WHERE r.ev_class = 
'%s' ORDER BY 1",
                                                          oid);
                        result3 = PSQLexec(buf.data, false);
                        if (!result3)
                        {
--- 1103,1126 ----
                /* count rules */
                if (tableinfo.hasrules)
                {
!                       if (pset.sversion < 80300)
!                       {
!                               printfPQExpBuffer(&buf,
!                                                         "SELECT r.rulename, 
trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
!                                                         "'O'::char AS 
ev_enabled\n"
                                                          "FROM 
pg_catalog.pg_rewrite r\n"
                                                          "WHERE r.ev_class = 
'%s' ORDER BY 1",
                                                          oid);
+                       }
+                       else
+                       {
+                               printfPQExpBuffer(&buf,
+                                                         "SELECT r.rulename, 
trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), "
+                                                         "ev_enabled\n"
+                                                         "FROM 
pg_catalog.pg_rewrite r\n"
+                                                         "WHERE r.ev_class = 
'%s' ORDER BY 1",
+                                                         oid);
+                       }
                        result3 = PSQLexec(buf.data, false);
                        if (!result3)
                        {
***************
*** 1125,1134 ****
                if (tableinfo.triggers)
                {
                        printfPQExpBuffer(&buf,
!                                        "SELECT t.tgname, 
pg_catalog.pg_get_triggerdef(t.oid)\n"
                                                          "FROM 
pg_catalog.pg_trigger t\n"
                                                          "WHERE t.tgrelid = 
'%s' "
-                                                         "AND t.tgenabled "
                                                          "AND t.tgconstraint = 
0\n"
                                                          "ORDER BY 1",
                                                          oid);
--- 1136,1145 ----
                if (tableinfo.triggers)
                {
                        printfPQExpBuffer(&buf,
!                                        "SELECT t.tgname, 
pg_catalog.pg_get_triggerdef(t.oid), "
!                                                       "t.tgenabled\n"
                                                          "FROM 
pg_catalog.pg_trigger t\n"
                                                          "WHERE t.tgrelid = 
'%s' "
                                                          "AND t.tgconstraint = 
0\n"
                                                          "ORDER BY 1",
                                                          oid);
***************
*** 1142,1168 ****
                        }
                        else
                                trigger_count = PQntuples(result4);
- 
-                       /* acquire disabled triggers as a separate list */
-                       printfPQExpBuffer(&buf,
-                                        "SELECT t.tgname, 
pg_catalog.pg_get_triggerdef(t.oid)\n"
-                                                         "FROM 
pg_catalog.pg_trigger t\n"
-                                                         "WHERE t.tgrelid = 
'%s' "
-                                                         "AND NOT t.tgenabled "
-                                                         "AND t.tgconstraint = 
0\n"
-                                                         "ORDER BY 1",
-                                                         oid);
-                       result7 = PSQLexec(buf.data, false);
-                       if (!result7)
-                       {
-                               PQclear(result1);
-                               PQclear(result2);
-                               PQclear(result3);
-                               PQclear(result4);
-                               goto error_return;
-                       }
-                       else
-                               disabled_trigger_count = PQntuples(result7);
                }
  
                /* count foreign-key constraints (there are none if no 
triggers) */
--- 1153,1158 ----
***************
*** 1181,1187 ****
                                PQclear(result2);
                                PQclear(result3);
                                PQclear(result4);
-                               PQclear(result7);
                                goto error_return;
                        }
                        else
--- 1171,1176 ----
***************
*** 1199,1205 ****
                        PQclear(result3);
                        PQclear(result4);
                        PQclear(result5);
-                       PQclear(result7);
                        goto error_return;
                }
                else
--- 1188,1193 ----
***************
*** 1297,1359 ****
                /* print rules */
                if (rule_count > 0)
                {
!                       printfPQExpBuffer(&buf, _("Rules:"));
!                       footers[count_footers++] = pg_strdup(buf.data);
!                       for (i = 0; i < rule_count; i++)
!                       {
!                               const char *ruledef;
  
!                               /* Everything after "CREATE RULE" is echoed 
verbatim */
!                               ruledef = PQgetvalue(result3, i, 1);
!                               ruledef += 12;
  
!                               printfPQExpBuffer(&buf, "    %s", ruledef);
  
!                               footers[count_footers++] = pg_strdup(buf.data);
                        }
                }
  
                /* print triggers */
                if (trigger_count > 0)
                {
!                       printfPQExpBuffer(&buf, _("Triggers:"));
!                       footers[count_footers++] = pg_strdup(buf.data);
!                       for (i = 0; i < trigger_count; i++)
!                       {
!                               const char *tgdef;
!                               const char *usingpos;
! 
!                               /* Everything after "TRIGGER" is echoed 
verbatim */
!                               tgdef = PQgetvalue(result4, i, 1);
!                               usingpos = strstr(tgdef, " TRIGGER ");
!                               if (usingpos)
!                                       tgdef = usingpos + 9;
! 
!                               printfPQExpBuffer(&buf, "    %s", tgdef);
  
!                               footers[count_footers++] = pg_strdup(buf.data);
!                       }
!               }
! 
!               /* print disabled triggers */
!               if (disabled_trigger_count > 0)
!               {
!                       printfPQExpBuffer(&buf, _("Disabled triggers:"));
!                       footers[count_footers++] = pg_strdup(buf.data);
!                       for (i = 0; i < disabled_trigger_count; i++)
                        {
!                               const char *tgdef;
!                               const char *usingpos;
! 
!                               /* Everything after "TRIGGER" is echoed 
verbatim */
!                               tgdef = PQgetvalue(result7, i, 1);
!                               usingpos = strstr(tgdef, " TRIGGER ");
!                               if (usingpos)
!                                       tgdef = usingpos + 9;
! 
!                               printfPQExpBuffer(&buf, "    %s", tgdef);
  
!                               footers[count_footers++] = pg_strdup(buf.data);
                        }
                }
  
--- 1285,1427 ----
                /* print rules */
                if (rule_count > 0)
                {
!                       bool    have_heading;
!                       int             category;
  
!                       for (category = 0; category < 4; category++)
!                       {
!                               have_heading = false;
  
!                               for (i = 0; i < rule_count; i++)
!                               {
!                                       const char *ruledef;
!                                       bool            list_rule = false;
  
!                                       switch (category)
!                                       {
!                                               case 0:
!                                                       if 
(*PQgetvalue(result3, i, 2) == 'O')
!                                                               list_rule = 
true;
!                                                       break;
!                                               case 1:
!                                                       if 
(*PQgetvalue(result3, i, 2) == 'D')
!                                                               list_rule = 
true;
!                                                       break;
!                                               case 2:
!                                                       if 
(*PQgetvalue(result3, i, 2) == 'A')
!                                                               list_rule = 
true;
!                                                       break;
!                                               case 3:
!                                                       if 
(*PQgetvalue(result3, i, 2) == 'R')
!                                                               list_rule = 
true;
!                                                       break;
!                                       }
!                                       if (!list_rule)
!                                               continue;
! 
!                                       if (!have_heading)
!                                       {
!                                               switch (category)
!                                               {
!                                                       case 0:
!                                                               
printfPQExpBuffer(&buf, _("Rules:"));
!                                                               break;
!                                                       case 1:
!                                                               
printfPQExpBuffer(&buf, _("Disabled Rules:"));
!                                                               break;
!                                                       case 2:
!                                                               
printfPQExpBuffer(&buf, _("Rules firing always:"));
!                                                               break;
!                                                       case 3:
!                                                               
printfPQExpBuffer(&buf, _("Rules firing on replica only:"));
!                                                               break;
!                                               }
!                                               footers[count_footers++] = 
pg_strdup(buf.data);
!                                               have_heading = true;
!                                       }
! 
!                                       /* Everything after "CREATE RULE" is 
echoed verbatim */
!                                       ruledef = PQgetvalue(result3, i, 1);
!                                       ruledef += 12;
!                                       printfPQExpBuffer(&buf, "    %s", 
ruledef);
!                                       footers[count_footers++] = 
pg_strdup(buf.data);
!                               }
                        }
                }
  
                /* print triggers */
                if (trigger_count > 0)
                {
!                       bool    have_heading;
!                       int             category;
  
!                       /* split the output into 4 different categories.
!                        * Enabled triggers, disabled triggers and the two
!                        * special ALWAYS and REPLICA configurations.
!                        */
!                       for (category = 0; category < 4; category++)
                        {
!                               have_heading = false;
!                               for (i = 0; i < trigger_count; i++)
!                               {
!                                       bool            list_trigger;
!                                       const char *tgdef;
!                                       const char *usingpos;
!                                       const char *tgenabled;
! 
!                                       /* Check if this trigger falls into the 
current category */
!                                       tgenabled = PQgetvalue(result4, i, 2);
!                                       list_trigger = false;
!                                       switch (category)
!                                       {
!                                               case 0:         if (*tgenabled 
== 'O' || *tgenabled == 't')
!                                                                               
list_trigger = true;
!                                                                       break;
!                                               case 1:         if (*tgenabled 
== 'D' || *tgenabled == 'f')
!                                                                               
list_trigger = true;
!                                                                       break;
!                                               case 2:         if (*tgenabled 
== 'A')
!                                                                               
list_trigger = true;
!                                                                       break;
!                                               case 3:         if (*tgenabled 
== 'R')
!                                                                               
list_trigger = true;
!                                                                       break;
!                                       }
!                                       if (list_trigger == false)
!                                               continue;
! 
!                                       /* Print the category heading once */
!                                       if (have_heading == false)
!                                       {
!                                               switch (category)
!                                               {
!                                                       case 0:
!                                                               
printfPQExpBuffer(&buf, _("Triggers:"));
!                                                               break;
!                                                       case 1:
!                                                               
printfPQExpBuffer(&buf, _("Disabled Triggers:"));
!                                                               break;
!                                                       case 2:
!                                                               
printfPQExpBuffer(&buf, _("Triggers firing always:"));
!                                                               break;
!                                                       case 3:
!                                                               
printfPQExpBuffer(&buf, _("Triggers firing on replica only:"));
!                                                               break;
!                                                               
!                                               }
!                                               footers[count_footers++] = 
pg_strdup(buf.data);
!                                               have_heading = true;
!                                       }
! 
!                                       /* Everything after "TRIGGER" is echoed 
verbatim */
!                                       tgdef = PQgetvalue(result4, i, 1);
!                                       usingpos = strstr(tgdef, " TRIGGER ");
!                                       if (usingpos)
!                                               tgdef = usingpos + 9;
  
!                                       printfPQExpBuffer(&buf, "    %s", 
tgdef);
!                                       footers[count_footers++] = 
pg_strdup(buf.data);
!                               }
                        }
                }
  
***************
*** 1392,1398 ****
                PQclear(result4);
                PQclear(result5);
                PQclear(result6);
-               PQclear(result7);
        }
  
        printTable(title.data, headers,
--- 1460,1465 ----
Index: src/include/catalog/pg_rewrite.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/catalog/pg_rewrite.h,v
retrieving revision 1.27
diff -c -r1.27 pg_rewrite.h
*** src/include/catalog/pg_rewrite.h    5 Jan 2007 22:19:53 -0000       1.27
--- src/include/catalog/pg_rewrite.h    16 Mar 2007 12:06:33 -0000
***************
*** 42,47 ****
--- 42,48 ----
        Oid                     ev_class;
        int2            ev_attr;
        char            ev_type;
+       char            ev_enabled;
        bool            is_instead;
  
        /* NB: remaining fields must be accessed via heap_getattr */
***************
*** 60,72 ****
   *            compiler constants for pg_rewrite
   * ----------------
   */
! #define Natts_pg_rewrite                              7
  #define Anum_pg_rewrite_rulename              1
  #define Anum_pg_rewrite_ev_class              2
  #define Anum_pg_rewrite_ev_attr                       3
  #define Anum_pg_rewrite_ev_type                       4
! #define Anum_pg_rewrite_is_instead            5
! #define Anum_pg_rewrite_ev_qual                       6
! #define Anum_pg_rewrite_ev_action             7
  
  #endif   /* PG_REWRITE_H */
--- 61,74 ----
   *            compiler constants for pg_rewrite
   * ----------------
   */
! #define Natts_pg_rewrite                              8
  #define Anum_pg_rewrite_rulename              1
  #define Anum_pg_rewrite_ev_class              2
  #define Anum_pg_rewrite_ev_attr                       3
  #define Anum_pg_rewrite_ev_type                       4
! #define Anum_pg_rewrite_ev_enabled            5
! #define Anum_pg_rewrite_is_instead            6
! #define Anum_pg_rewrite_ev_qual                       7
! #define Anum_pg_rewrite_ev_action             8
  
  #endif   /* PG_REWRITE_H */
Index: src/include/catalog/pg_trigger.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/catalog/pg_trigger.h,v
retrieving revision 1.27
diff -c -r1.27 pg_trigger.h
*** src/include/catalog/pg_trigger.h    14 Feb 2007 01:58:58 -0000      1.27
--- src/include/catalog/pg_trigger.h    16 Mar 2007 12:06:33 -0000
***************
*** 46,52 ****
        Oid                     tgfoid;                 /* OID of function to 
be called */
        int2            tgtype;                 /* BEFORE/AFTER 
UPDATE/DELETE/INSERT
                                                                 * 
ROW/STATEMENT; see below */
!       bool            tgenabled;              /* trigger is enabled/disabled 
*/
        bool            tgisconstraint; /* trigger is a constraint trigger */
        NameData        tgconstrname;   /* constraint name */
        Oid                     tgconstrrelid;  /* constraint's FROM table, if 
any */
--- 46,53 ----
        Oid                     tgfoid;                 /* OID of function to 
be called */
        int2            tgtype;                 /* BEFORE/AFTER 
UPDATE/DELETE/INSERT
                                                                 * 
ROW/STATEMENT; see below */
!       char            tgenabled;              /* trigger's firing 
configuration
!                                                                * WRT 
session_replication_role */
        bool            tgisconstraint; /* trigger is a constraint trigger */
        NameData        tgconstrname;   /* constraint name */
        Oid                     tgconstrrelid;  /* constraint's FROM table, if 
any */
Index: src/include/commands/trigger.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/commands/trigger.h,v
retrieving revision 1.61
diff -c -r1.61 trigger.h
*** src/include/commands/trigger.h      14 Feb 2007 01:58:58 -0000      1.61
--- src/include/commands/trigger.h      16 Mar 2007 12:06:34 -0000
***************
*** 78,83 ****
--- 78,95 ----
  #define TRIGGER_FIRED_AFTER(event)                            \
                (!TRIGGER_FIRED_BEFORE (event))
  
+ /*
+  * Definitions for the replication role based firing.
+  */
+ #define SESSION_REPLICATION_ROLE_ORIGIN               0
+ #define SESSION_REPLICATION_ROLE_REPLICA      1
+ #define SESSION_REPLICATION_ROLE_LOCAL                2
+ extern int    SessionReplicationRole;
+ 
+ #define       TRIGGER_FIRES_ON_ORIGIN                         'O'
+ #define       TRIGGER_FIRES_ALWAYS                            'A'
+ #define       TRIGGER_FIRES_ON_REPLICA                        'R'
+ #define       TRIGGER_DISABLED                                        'D'
  
  extern Oid    CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid);
  
***************
*** 88,94 ****
  extern void renametrig(Oid relid, const char *oldname, const char *newname);
  
  extern void EnableDisableTrigger(Relation rel, const char *tgname,
!                                        bool enable, bool skip_system);
  
  extern void RelationBuildTriggers(Relation relation);
  
--- 100,106 ----
  extern void renametrig(Oid relid, const char *oldname, const char *newname);
  
  extern void EnableDisableTrigger(Relation rel, const char *tgname,
!                                        char fires_when, bool skip_system);
  
  extern void RelationBuildTriggers(Relation relation);
  
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.342
diff -c -r1.342 parsenodes.h
*** src/include/nodes/parsenodes.h      13 Mar 2007 00:33:43 -0000      1.342
--- src/include/nodes/parsenodes.h      16 Mar 2007 12:06:34 -0000
***************
*** 897,907 ****
--- 897,913 ----
        AT_SetRelOptions,                       /* SET (...) -- AM specific 
parameters */
        AT_ResetRelOptions,                     /* RESET (...) -- AM specific 
parameters */
        AT_EnableTrig,                          /* ENABLE TRIGGER name */
+       AT_EnableAlwaysTrig,            /* ENABLE ALWAYS TRIGGER name */
+       AT_EnableReplicaTrig,           /* ENABLE REPLICA TRIGGER name */
        AT_DisableTrig,                         /* DISABLE TRIGGER name */
        AT_EnableTrigAll,                       /* ENABLE TRIGGER ALL */
        AT_DisableTrigAll,                      /* DISABLE TRIGGER ALL */
        AT_EnableTrigUser,                      /* ENABLE TRIGGER USER */
        AT_DisableTrigUser,                     /* DISABLE TRIGGER USER */
+       AT_EnableRule,                          /* ENABLE RULE name */
+       AT_EnableAlwaysRule,            /* ENABLE ALWAYS RULE name */
+       AT_EnableReplicaRule,           /* ENABLE REPLICA RULE name */
+       AT_DisableRule,                         /* DISABLE RULE name */
        AT_AddInherit,                          /* INHERIT parent */
        AT_DropInherit                          /* NO INHERIT parent */
  } AlterTableType;
Index: src/include/rewrite/prs2lock.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/rewrite/prs2lock.h,v
retrieving revision 1.22
diff -c -r1.22 prs2lock.h
*** src/include/rewrite/prs2lock.h      5 Jan 2007 22:19:57 -0000       1.22
--- src/include/rewrite/prs2lock.h      16 Mar 2007 12:06:34 -0000
***************
*** 28,33 ****
--- 28,34 ----
        AttrNumber      attrno;
        Node       *qual;
        List       *actions;
+       char            enabled;
        bool            isInstead;
  } RewriteRule;
  
Index: src/include/rewrite/rewriteDefine.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/rewrite/rewriteDefine.h,v
retrieving revision 1.24
diff -c -r1.24 rewriteDefine.h
*** src/include/rewrite/rewriteDefine.h 13 Mar 2007 00:33:43 -0000      1.24
--- src/include/rewrite/rewriteDefine.h 16 Mar 2007 12:06:34 -0000
***************
*** 16,21 ****
--- 16,26 ----
  
  #include "nodes/parsenodes.h"
  
+ #define       RULE_FIRES_ON_ORIGIN    'O'
+ #define       RULE_FIRES_ALWAYS               'A'
+ #define       RULE_FIRES_ON_REPLICA   'R'
+ #define       RULE_DISABLED                   'D'
+ 
  extern void DefineRule(RuleStmt *stmt, const char *queryString);
  
  extern void DefineQueryRewrite(char *rulename,
***************
*** 31,34 ****
--- 36,42 ----
  
  extern void setRuleCheckAsUser(Node *node, Oid userid);
  
+ extern void EnableDisableRule(Relation rel, const char *rulename,
+                                 char fires_when);
+ 
  #endif   /* REWRITEDEFINE_H */
Index: src/include/utils/plancache.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/utils/plancache.h,v
retrieving revision 1.2
diff -c -r1.2 plancache.h
*** src/include/utils/plancache.h       15 Mar 2007 23:12:07 -0000      1.2
--- src/include/utils/plancache.h       16 Mar 2007 12:41:19 -0000
***************
*** 102,106 ****
--- 102,107 ----
                                                                                
bool useResOwner);
  extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner);
  extern TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
+ extern bool HaveCachedPlans(void);
  
  #endif   /* PLANCACHE_H */
Index: src/include/utils/rel.h
===================================================================
RCS file: /usr/local/pgsql/CvsRoot/pgsql/src/include/utils/rel.h,v
retrieving revision 1.98
diff -c -r1.98 rel.h
*** src/include/utils/rel.h     27 Feb 2007 23:48:10 -0000      1.98
--- src/include/utils/rel.h     16 Mar 2007 12:06:34 -0000
***************
*** 53,59 ****
        char       *tgname;
        Oid                     tgfoid;
        int16           tgtype;
!       bool            tgenabled;
        bool            tgisconstraint;
        Oid                     tgconstrrelid;
        Oid                     tgconstraint;
--- 53,59 ----
        char       *tgname;
        Oid                     tgfoid;
        int16           tgtype;
!       char            tgenabled;
        bool            tgisconstraint;
        Oid                     tgconstrrelid;
        Oid                     tgconstraint;
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings

Reply via email to