diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 9a9f9b55bef5378e34f297aae5fde5b4b5e4c03e..31db6521c5efc270a99a12f960292046faf94cda 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.145 2007/02/14 01:58:55 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.146 2007/03/19 23:38:28 wieck Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
@@ -3639,6 +3639,20 @@
       </entry>
      </row>
 
+     <row>
+      <entry><structfield>ev_enabled</structfield></entry>
+      <entry><type>char</type></entry>
+      <entry></entry>
+      <entry>
+	   Controls in which <xref linkend="guc-session-replication-role"> modes
+	   the rule fires.
+	   <literal>O</> = rule fires in <quote>origin</> and <quote>local</> modes,
+	   <literal>D</> = rule is disabled,
+	   <literal>R</> = rule fires in <quote>replica</> mode,
+	   <literal>A</> = rule fires always.
+	  </entry>
+     </row>
+
      <row>
       <entry><structfield>is_instead</structfield></entry>
       <entry><type>bool</type></entry>
@@ -4178,9 +4192,16 @@
 
      <row>
       <entry><structfield>tgenabled</structfield></entry>
-      <entry><type>bool</type></entry>
+      <entry><type>char</type></entry>
       <entry></entry>
-      <entry>True if trigger is enabled</entry>
+      <entry>
+	   Controls in which <xref linkend="guc-session-replication-role"> modes
+	   the trigger fires.
+	   <literal>O</> = trigger fires in <quote>origin</> and <quote>local</> modes,
+	   <literal>D</> = trigger is disabled,
+	   <literal>R</> = trigger fires in <quote>replica</> mode,
+	   <literal>A</> = trigger fires always.
+	  </entry>
      </row>
 
      <row>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 17504b3d5e8a00aa358303284b92dd89ad6da16d..1fe39db2af7db0cad0759d29d6dfca043f4dfca9 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.115 2007/03/06 02:06:12 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.116 2007/03/19 23:38:28 wieck Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -3523,6 +3523,23 @@ SELECT * FROM parent WHERE key = 2400;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-session-replication-role" xreflabel="session_replication_role">
+      <term><varname>session_replication_role</varname> (<type>string</type>)</term>
+      <indexterm>
+       <primary><varname>session_replication_role</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+		Controls the trigger and rule firing for the current session.
+		See <xref linkend="sql-altertable"> for the different options to
+		enable or disable triggers and rules. Setting the variable requires
+		superuser privilege and can only be done before any query plans have
+		been cached. Possible values are <literal>origin</>,
+		<literal>replica</> and <literal>local</>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-vacuum-freeze-min-age" xreflabel="vacuum_freeze_min_age">
       <term><varname>vacuum_freeze_min_age</varname> (<type>integer</type>)</term>
       <indexterm>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 6ff289b21a40910e8f86c63d177f5a5aa49b1f14..9b34c4fb9934f3f60d2f99a963785e0efd79369a 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.94 2007/02/01 00:28:18 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.95 2007/03/19 23:38:29 wieck Exp $
 PostgreSQL documentation
 -->
 
@@ -43,6 +43,12 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
     DROP CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> [ RESTRICT | CASCADE ]
     DISABLE TRIGGER [ <replaceable class="PARAMETER">trigger_name</replaceable> | ALL | USER ]
     ENABLE TRIGGER [ <replaceable class="PARAMETER">trigger_name</replaceable> | ALL | USER ]
+    ENABLE REPLICA TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable>
+    ENABLE ALWAYS TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable>
+    DISABLE RULE <replaceable class="PARAMETER">rewrite_rule_name</replaceable>
+    ENABLE RULE <replaceable class="PARAMETER">rewrite_rule_name</replaceable>
+    ENABLE REPLICA RULE <replaceable class="PARAMETER">rewrite_rule_name</replaceable>
+    ENABLE ALWAYS RULE <replaceable class="PARAMETER">rewrite_rule_name</replaceable>
     CLUSTER ON <replaceable class="PARAMETER">index_name</replaceable>
     SET WITHOUT CLUSTER
     SET WITHOUT OIDS
@@ -193,10 +199,10 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
    </varlistentry>
 
    <varlistentry>
-    <term><literal>DISABLE</literal>/<literal>ENABLE TRIGGER</literal></term>
+    <term><literal>DISABLE</literal>/<literal>ENABLE [ REPLICA | ALWAYS ] TRIGGER</literal></term>
     <listitem>
      <para>
-      These forms disable or enable trigger(s) belonging to the table.
+      These forms configure the firing of trigger(s) belonging to the table.
       A disabled trigger is still known to the system, but is not executed
       when its triggering event occurs.  For a deferred trigger, the enable
       status is checked when the event occurs, not when the trigger function
@@ -207,6 +213,27 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
       requires superuser privileges; it should be done with caution since
       of course the integrity of the constraint cannot be guaranteed if the
       triggers are not executed.
+	  The trigger firing mechanism is also affected by the configuration
+	  variable <xref linkend="guc-session-replication-role">. Simply ENABLEd
+	  triggers will fire when the replication role is <quote>origin</>
+	  (the default) or <quote>local</>. Triggers configured ENABLE REPLICA 
+	  will only fire if the session is in <quote>replica</> mode and triggers 
+	  configured ENABLE ALWAYS will fire regardless of the current replication 
+	  mode.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>DISABLE</literal>/<literal>ENABLE [ REPLICA | ALWAYS ] RULE</literal></term>
+    <listitem>
+     <para>
+      These forms configure the firing of rewrite rules belonging to the table.
+      A disabled rule is still known to the system, but is not applied
+	  during query rewriting. The semantics are as for disabled/enabled
+	  triggers. This configuration is ignored for ON SELECT rules, which
+	  are always applied in order to keep views working even if the current
+	  session is in a non-default replication role.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ddc62086f51a8c6928d646715005a34d06878c5d..25e53a3dc43d10861fcff64e62a1e92c1da5b727 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.217 2007/03/13 00:33:39 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.218 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,7 @@
 #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,7 +254,9 @@ static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
 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);
+						   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,11 +1958,17 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			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,24 +2136,57 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
 		case AT_ResetRelOptions:		/* RESET (...) */
 			ATExecSetRelOptions(rel, (List *) cmd->def, true);
 			break;
-		case AT_EnableTrig:		/* ENABLE TRIGGER name */
-			ATExecEnableDisableTrigger(rel, cmd->name, true, false);
+
+		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, false, false);
+			ATExecEnableDisableTrigger(rel, cmd->name, 
+					TRIGGER_DISABLED, false);
 			break;
 		case AT_EnableTrigAll:	/* ENABLE TRIGGER ALL */
-			ATExecEnableDisableTrigger(rel, NULL, true, false);
+			ATExecEnableDisableTrigger(rel, NULL, 
+					TRIGGER_FIRES_ON_ORIGIN, false);
 			break;
 		case AT_DisableTrigAll:	/* DISABLE TRIGGER ALL */
-			ATExecEnableDisableTrigger(rel, NULL, false, false);
+			ATExecEnableDisableTrigger(rel, NULL, 
+					TRIGGER_DISABLED, false);
 			break;
 		case AT_EnableTrigUser:	/* ENABLE TRIGGER USER */
-			ATExecEnableDisableTrigger(rel, NULL, true, true);
+			ATExecEnableDisableTrigger(rel, NULL, 
+					TRIGGER_FIRES_ON_ORIGIN, true);
 			break;
 		case AT_DisableTrigUser:		/* DISABLE TRIGGER USER */
-			ATExecEnableDisableTrigger(rel, NULL, false, true);
+			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,7 +4422,7 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint,
 	MemSet(&trig, 0, sizeof(trig));
 	trig.tgoid = InvalidOid;
 	trig.tgname = fkconstraint->constr_name;
-	trig.tgenabled = TRUE;
+	trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
 	trig.tgisconstraint = TRUE;
 	trig.tgconstrrelid = RelationGetRelid(pkrel);
 	trig.tgconstraint = constraintOid;
@@ -5877,9 +5919,21 @@ copy_relation_data(Relation rel, SMgrRelation dst)
  */
 static void
 ATExecEnableDisableTrigger(Relation rel, char *trigname,
-						   bool enable, bool skip_system)
+						   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)
 {
-	EnableDisableTrigger(rel, trigname, enable, skip_system);
+	EnableDisableRule(rel, trigname, fires_when);
 }
 
 /*
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index c08525c2e040ffb41b44ce4fa9a060b4713c2cbe..e2dadb7a7e283c9c34d11d44414d6974cb4fd06c 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.213 2007/02/14 01:58:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.214 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,13 @@ static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
 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,7 +277,7 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
 												  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_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,11 +708,11 @@ renametrig(Oid relid,
  * EnableDisableTrigger()
  *
  *	Called by ALTER TABLE ENABLE/DISABLE TRIGGER
- *	to change 'tgenabled' flag for the specified trigger(s)
+ *	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 flag
+ * 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,7 +721,7 @@ renametrig(Oid relid,
  */
 void
 EnableDisableTrigger(Relation rel, const char *tgname,
-					 bool enable, bool skip_system)
+					 char fires_when, bool skip_system)
 {
 	Relation	tgrel;
 	int			nkeys;
@@ -765,13 +772,13 @@ EnableDisableTrigger(Relation rel, const char *tgname,
 
 		found = true;
 
-		if (oldtrig->tgenabled != enable)
+		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 = enable;
+			newtrig->tgenabled = fires_when;
 
 			simple_heap_update(tgrel, &newtup->t_self, newtup);
 
@@ -1333,8 +1340,18 @@ ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 		HeapTuple	newtuple;
 
-		if (!trigger->tgenabled)
-			continue;
+		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,8 +1399,18 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 	{
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 
-		if (!trigger->tgenabled)
-			continue;
+		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,8 +1471,18 @@ ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 		HeapTuple	newtuple;
 
-		if (!trigger->tgenabled)
-			continue;
+		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,8 +1537,18 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
 	{
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 
-		if (!trigger->tgenabled)
-			continue;
+		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,8 +1622,18 @@ ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 		HeapTuple	newtuple;
 
-		if (!trigger->tgenabled)
-			continue;
+		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,8 +1693,18 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 	{
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 
-		if (!trigger->tgenabled)
-			continue;
+		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,8 +3334,18 @@ AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
 		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
 
 		/* Ignore disabled triggers */
-		if (!trigger->tgenabled)
-			continue;
+		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
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 22d03f0b23461227ca331bbaa9220b5a4eb3fa8f..75404716d5a1f82a6a70d46188484e22fbe88ab4 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.582 2007/03/17 19:27:12 meskes Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.583 2007/03/19 23:38:29 wieck Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -365,7 +365,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 
 /* 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
+	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,8 +422,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 	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
+	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,6 +1480,22 @@ alter_table_cmd:
 					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,6 +1532,38 @@ alter_table_cmd:
 					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
 				{
@@ -8651,6 +8699,7 @@ unreserved_keyword:
 			| AGGREGATE
 			| ALSO
 			| ALTER
+			| ALWAYS
 			| ASSERTION
 			| ASSIGNMENT
 			| AT
@@ -8796,6 +8845,7 @@ unreserved_keyword:
 			| RENAME
 			| REPEATABLE
 			| REPLACE
+			| REPLICA
 			| RESET
 			| RESTART
 			| RESTRICT
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 368f3e06947972e98cc00c34508431f6b6b40b3f..9be91e7e6e62a43cb0b176d491669a56c93568c8 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.184 2007/01/25 11:53:51 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.185 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,6 +42,7 @@ static const ScanKeyword ScanKeywords[] = {
 	{"all", ALL},
 	{"also", ALSO},
 	{"alter", ALTER},
+	{"always", ALWAYS},
 	{"analyse", ANALYSE},		/* British spelling */
 	{"analyze", ANALYZE},
 	{"and", AND},
@@ -289,6 +290,7 @@ static const ScanKeyword ScanKeywords[] = {
 	{"rename", RENAME},
 	{"repeatable", REPEATABLE},
 	{"replace", REPLACE},
+	{"replica", REPLICA},
 	{"reset", RESET},
 	{"restart", RESTART},
 	{"restrict", RESTRICT},
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 64a2a96f0e9a8d7b1056c183f62fdeabaa698848..864b00f1e73554c208d4e37afb061fa9c21aca37 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.118 2007/03/13 00:33:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.119 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,6 +30,7 @@
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
+#include "utils/inval.h"
 
 
 static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
@@ -79,6 +80,7 @@ InsertRule(char *rulname,
 	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 */
@@ -628,6 +630,72 @@ setRuleCheckAsUser_Query(Query *qry, Oid userid)
 }
 
 
+/*
+ * 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.
  *
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index e5a1d4c74725f172e826eb917f683fef9a9d8693..cd1cb54e9af35d5b69658e89e4276cd79af6b8c1 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.172 2007/03/17 00:11:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.173 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,10 +21,12 @@
 #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 */
@@ -1035,6 +1037,29 @@ matchLocks(CmdType event,
 	{
 		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 ||
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 61a576d35d981928d9baade9ec64955729cdb8f9..4648b05803e13c4fb5065247a20f5f0b8e964260 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -33,7 +33,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.2 2007/03/15 23:12:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.3 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -860,3 +860,14 @@ InvalRelid(Oid relid, LOCKMODE lockmode, InvalRelidContext *context)
 	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);
+}
+
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 4ce955917a54a958001945faf2c2cc6b62d614e9..91b7f146b43abd96b9a8d1dcf2d9e0e169908856 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.257 2007/03/03 20:08:41 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.258 2007/03/19 23:38:29 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -651,6 +651,7 @@ RelationBuildRuleLock(Relation relation)
 
 		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;
 
 		/*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 8088432bac869555cd8373183ed3a97e623bcdd6..f921c75a60b6997e1acd18f131b10b70432e5944 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.382 2007/03/13 14:32:25 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.383 2007/03/19 23:38:30 wieck Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -34,6 +34,7 @@
 #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,6 +60,7 @@
 #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,6 +126,8 @@ static const char *assign_syslog_ident(const char *ident,
 
 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,6 +230,7 @@ static char *backslash_quote_string;
 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;
@@ -1928,6 +1933,16 @@ static struct config_string ConfigureNamesString[] =
 		"read committed", assign_defaultxactisolevel, NULL
 	},
 
+	{
+		{"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."),
@@ -6115,6 +6130,33 @@ assign_defaultxactisolevel(const char *newval, bool doit, GucSource source)
 	return newval;
 }
 
+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)
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index cf2dfdc099e07211e7bc1e48be80c9ce924ce5e2..22f9685bbdce04a4995c988cb0a6976f2191a7a0 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -408,6 +408,7 @@
 #default_transaction_isolation = 'read committed'
 #default_transaction_read_only = off
 #statement_timeout = 0			# 0 is disabled
+#session_replication_role = "origin"
 #vacuum_freeze_min_age = 100000000
 #xmlbinary = 'base64'
 #xmloption = 'content'
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index eef9a4c875a13a7861fc634124283a09348e0a30..90e78c36d15ff50396ebdfbc33aa01a7d4cd5549 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
  *	by PostgreSQL
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.460 2007/02/14 01:58:57 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.461 2007/03/19 23:38:30 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3699,15 +3699,26 @@ getRules(int *numRules)
 	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 >= 70100)
+	if (g_fout->remoteVersion >= 80300)
 	{
 		appendPQExpBuffer(query, "SELECT "
 						  "tableoid, oid, rulename, "
-						  "ev_class as ruletable, ev_type, is_instead "
+						  "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,7 +3727,8 @@ getRules(int *numRules)
 		appendPQExpBuffer(query, "SELECT "
 						  "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
 						  "oid, rulename, "
-						  "ev_class as ruletable, ev_type, is_instead "
+						  "ev_class as ruletable, ev_type, is_instead, "
+						  "'O'::char as ev_enabled "
 						  "FROM pg_rewrite "
 						  "ORDER BY oid");
 	}
@@ -3736,6 +3748,7 @@ getRules(int *numRules)
 	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,6 +3772,7 @@ getRules(int *numRules)
 		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,7 +3970,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
 			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].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,11 +8838,27 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 	}
 	appendPQExpBuffer(query, ");\n");
 
-	if (!tginfo->tgenabled)
+	if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
 	{
 		appendPQExpBuffer(query, "\nALTER TABLE %s ",
 						  fmtId(tbinfo->dobj.name));
-		appendPQExpBuffer(query, "DISABLE TRIGGER %s;\n",
+		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));
 	}
 
@@ -8914,6 +8944,33 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 
 	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
 	 */
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index b584ab1fe017ef9c88a4d7f442966d1428ef0c67..8694376b5299c42a29a5d04e3effb472fa2cffe5 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.133 2007/02/19 15:05:06 mha Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.134 2007/03/19 23:38:30 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -314,6 +314,7 @@ typedef struct _ruleInfo
 	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,7 +331,7 @@ typedef struct _triggerInfo
 	char	   *tgconstrname;
 	Oid			tgconstrrelid;
 	char	   *tgconstrrelname;
-	bool		tgenabled;
+	char		tgenabled;
 	bool		tgdeferrable;
 	bool		tginitdeferred;
 } TriggerInfo;
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 5dfaf9367a1da18d127b6bdd3323a3ccac21531e..13d3be678e84f6a22c9d5fb2c30004321ff4d6cd 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2007, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.154 2007/03/18 16:50:44 neilc Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.155 2007/03/19 23:38:31 wieck Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
@@ -1055,14 +1055,12 @@ describeOneTableDetails(const char *schemaname,
 				   *result3 = NULL,
 				   *result4 = NULL,
 				   *result5 = NULL,
-				   *result6 = NULL,
-				   *result7 = NULL;
+				   *result6 = 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;
 
@@ -1105,11 +1103,24 @@ describeOneTableDetails(const char *schemaname,
 		/* count rules */
 		if (tableinfo.hasrules)
 		{
-			printfPQExpBuffer(&buf,
-							  "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n"
+			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,10 +1136,10 @@ describeOneTableDetails(const char *schemaname,
 		if (tableinfo.triggers)
 		{
 			printfPQExpBuffer(&buf,
-					 "SELECT t.tgname, pg_catalog.pg_get_triggerdef(t.oid)\n"
+					 "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.tgenabled "
 							  "AND t.tgconstraint = 0\n"
 							  "ORDER BY 1",
 							  oid);
@@ -1142,27 +1153,6 @@ describeOneTableDetails(const char *schemaname,
 			}
 			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) */
@@ -1181,7 +1171,6 @@ describeOneTableDetails(const char *schemaname,
 				PQclear(result2);
 				PQclear(result3);
 				PQclear(result4);
-				PQclear(result7);
 				goto error_return;
 			}
 			else
@@ -1199,7 +1188,6 @@ describeOneTableDetails(const char *schemaname,
 			PQclear(result3);
 			PQclear(result4);
 			PQclear(result5);
-			PQclear(result7);
 			goto error_return;
 		}
 		else
@@ -1297,63 +1285,143 @@ describeOneTableDetails(const char *schemaname,
 		/* 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;
+			bool	have_heading;
+			int		category;
 
-				printfPQExpBuffer(&buf, "    %s", ruledef);
+			for (category = 0; category < 4; category++)
+			{
+				have_heading = false;
 
-				footers[count_footers++] = pg_strdup(buf.data);
+				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)
 		{
-			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++)
+			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++)
 			{
-				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);
+				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,7 +1460,6 @@ describeOneTableDetails(const char *schemaname,
 		PQclear(result4);
 		PQclear(result5);
 		PQclear(result6);
-		PQclear(result7);
 	}
 
 	printTable(title.data, headers,
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 91afb1419901fa5aa24ac61917470a5849030667..9996a67e4078aa8a039c5b15133be03d7573811d 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_rewrite.h,v 1.27 2007/01/05 22:19:53 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_rewrite.h,v 1.28 2007/03/19 23:38:31 wieck Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -42,6 +42,7 @@ CATALOG(pg_rewrite,2618)
 	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,13 +61,14 @@ typedef FormData_pg_rewrite *Form_pg_rewrite;
  *		compiler constants for pg_rewrite
  * ----------------
  */
-#define Natts_pg_rewrite				7
+#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_is_instead		5
-#define Anum_pg_rewrite_ev_qual			6
-#define Anum_pg_rewrite_ev_action		7
+#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 */
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index df22089e3107677cae40a8dede04fbef63e3e11e..b7a71b2f0709ae65d502e2820bbf3a7cd033e9a3 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_trigger.h,v 1.27 2007/02/14 01:58:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_trigger.h,v 1.28 2007/03/19 23:38:31 wieck Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -46,7 +46,8 @@ CATALOG(pg_trigger,2620)
 	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 */
+	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 */
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
index ac9eb7296d12e7bf5ab75c9db20ebaac58849c55..8fcd0bb6aa7e8144afd33fbdc20bd4ae1c38b318 100644
--- a/src/include/commands/trigger.h
+++ b/src/include/commands/trigger.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.61 2007/02/14 01:58:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.62 2007/03/19 23:38:31 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,6 +78,18 @@ typedef struct TriggerData
 #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,7 +100,7 @@ extern void RemoveTriggerById(Oid trigOid);
 extern void renametrig(Oid relid, const char *oldname, const char *newname);
 
 extern void EnableDisableTrigger(Relation rel, const char *tgname,
-					 bool enable, bool skip_system);
+					 char fires_when, bool skip_system);
 
 extern void RelationBuildTriggers(Relation relation);
 
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index e24b57e8a2326a1c4c4017104eef8923401193b2..c3a2bebca68b54e3e3d333fe83ea1dca21d98674 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.342 2007/03/13 00:33:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.343 2007/03/19 23:38:32 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -897,11 +897,17 @@ typedef enum AlterTableType
 	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;
diff --git a/src/include/rewrite/prs2lock.h b/src/include/rewrite/prs2lock.h
index d7ebbbe6bc107d46fd0901d1d1e1961a8e9bd754..17d045053e6ef19293f2fb70a656d0d9ae98092d 100644
--- a/src/include/rewrite/prs2lock.h
+++ b/src/include/rewrite/prs2lock.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/rewrite/prs2lock.h,v 1.22 2007/01/05 22:19:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/rewrite/prs2lock.h,v 1.23 2007/03/19 23:38:32 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@ typedef struct RewriteRule
 	AttrNumber	attrno;
 	Node	   *qual;
 	List	   *actions;
+	char		enabled;
 	bool		isInstead;
 } RewriteRule;
 
diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h
index d4673f82a6c048098900eccd91a2485169a6618e..5b21cf8e797b9970d1e8537b1f3186dfe24f913d 100644
--- a/src/include/rewrite/rewriteDefine.h
+++ b/src/include/rewrite/rewriteDefine.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/rewrite/rewriteDefine.h,v 1.24 2007/03/13 00:33:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/rewrite/rewriteDefine.h,v 1.25 2007/03/19 23:38:32 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,11 @@
 
 #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,4 +36,7 @@ extern void RenameRewriteRule(Oid owningRel, const char *oldName,
 
 extern void setRuleCheckAsUser(Node *node, Oid userid);
 
+extern void EnableDisableRule(Relation rel, const char *rulename,
+				  char fires_when);
+
 #endif   /* REWRITEDEFINE_H */
diff --git a/src/include/utils/plancache.h b/src/include/utils/plancache.h
index 4f03cd9e0a2c5fa36f963432487664499d330739..91101a318d719fc1b81d82e182fbd16bd023e113 100644
--- a/src/include/utils/plancache.h
+++ b/src/include/utils/plancache.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.2 2007/03/15 23:12:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/plancache.h,v 1.3 2007/03/19 23:38:32 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,5 +102,6 @@ extern CachedPlan *RevalidateCachedPlan(CachedPlanSource *plansource,
 										bool useResOwner);
 extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner);
 extern TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
+extern bool HaveCachedPlans(void);
 
 #endif   /* PLANCACHE_H */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 4065eced8211d896e1d7836d9253fbffc0689846..2963cc6616aae31030224a7fdf17869ed80aab71 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.98 2007/02/27 23:48:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.99 2007/03/19 23:38:32 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,7 +53,7 @@ typedef struct Trigger
 	char	   *tgname;
 	Oid			tgfoid;
 	int16		tgtype;
-	bool		tgenabled;
+	char		tgenabled;
 	bool		tgisconstraint;
 	Oid			tgconstrrelid;
 	Oid			tgconstraint;