diff -cprN head/src/backend/commands/trigger.c work/src/backend/commands/trigger.c
*** head/src/backend/commands/trigger.c	2009-10-14 13:28:32.297915641 +0900
--- work/src/backend/commands/trigger.c	2009-10-14 13:18:14.881976192 +0900
*************** static void AfterTriggerSaveEvent(Result
*** 72,77 ****
--- 72,80 ----
  					  List *recheckIndexes, Bitmapset *modifiedCols);
  static bool TriggerEnabled(Trigger *trigger, Bitmapset *modifiedCols);
  
+ #define GetModifiedColumns(relinfo, estate) \
+ 	(rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->modifiedCols)
+ 
  
  /*
   * Create a trigger.  Returns the OID of the created trigger.
*************** ExecBSUpdateTriggers(EState *estate, Res
*** 1900,1905 ****
--- 1903,1909 ----
  	int		   *tgindx;
  	int			i;
  	TriggerData LocTriggerData;
+ 	Bitmapset   *modifiedCols;
  
  	trigdesc = relinfo->ri_TrigDesc;
  
*************** ExecBSUpdateTriggers(EState *estate, Res
*** 1912,1917 ****
--- 1916,1923 ----
  	if (ntrigs == 0)
  		return;
  
+ 	modifiedCols = GetModifiedColumns(relinfo, estate);
+ 
  	LocTriggerData.type = T_TriggerData;
  	LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
  		TRIGGER_EVENT_BEFORE;
*************** ExecBSUpdateTriggers(EState *estate, Res
*** 1925,1931 ****
  		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  		HeapTuple	newtuple;
  
! 		if (!TriggerEnabled(trigger, NULL))
  			continue;
  
  		LocTriggerData.tg_trigger = trigger;
--- 1931,1937 ----
  		Trigger    *trigger = &trigdesc->triggers[tgindx[i]];
  		HeapTuple	newtuple;
  
! 		if (!TriggerEnabled(trigger, modifiedCols))
  			continue;
  
  		LocTriggerData.tg_trigger = trigger;
*************** ExecASUpdateTriggers(EState *estate, Res
*** 1949,1955 ****
  
  	if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_UPDATE] > 0)
  		AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
! 							  false, NULL, NULL, NIL, NULL);
  }
  
  HeapTuple
--- 1955,1962 ----
  
  	if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_UPDATE] > 0)
  		AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
! 							  false, NULL, NULL, NIL,
! 							  GetModifiedColumns(relinfo, estate));
  }
  
  HeapTuple
*************** ExecBRUpdateTriggers(EState *estate, Pla
*** 1973,1979 ****
  	if (trigtuple == NULL)
  		return NULL;
  
! 	modifiedCols = rt_fetch(relinfo->ri_RangeTableIndex, estate->es_range_table)->modifiedCols;
  
  	/*
  	 * In READ COMMITTED isolation level it's possible that newtuple was
--- 1980,1986 ----
  	if (trigtuple == NULL)
  		return NULL;
  
! 	modifiedCols = GetModifiedColumns(relinfo, estate);
  
  	/*
  	 * In READ COMMITTED isolation level it's possible that newtuple was
*************** ExecARUpdateTriggers(EState *estate, Res
*** 2028,2034 ****
  
  		AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
  							  true, trigtuple, newtuple, recheckIndexes,
! 							  rt_fetch(relinfo->ri_RangeTableIndex, estate->es_range_table)->modifiedCols);
  		heap_freetuple(trigtuple);
  	}
  }
--- 2035,2041 ----
  
  		AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
  							  true, trigtuple, newtuple, recheckIndexes,
! 							  GetModifiedColumns(relinfo, estate));
  		heap_freetuple(trigtuple);
  	}
  }
*************** TriggerEnabled(Trigger *trigger, Bitmaps
*** 4015,4022 ****
  
  	/* Check for column-level triggers */
  	if (trigger->tgnattr > 0 && modifiedCols != NULL &&
! 		(trigger->tgtype & (TRIGGER_TYPE_UPDATE | TRIGGER_TYPE_ROW)) ==
! 		(TRIGGER_TYPE_UPDATE | TRIGGER_TYPE_ROW))
  	{
  		int			i;
  		bool		modified;
--- 4022,4028 ----
  
  	/* Check for column-level triggers */
  	if (trigger->tgnattr > 0 && modifiedCols != NULL &&
! 		(trigger->tgtype & TRIGGER_TYPE_UPDATE) != 0)
  	{
  		int			i;
  		bool		modified;
diff -cprN head/src/test/regress/expected/triggers.out work/src/test/regress/expected/triggers.out
*** head/src/test/regress/expected/triggers.out	2009-10-14 13:28:32.304917221 +0900
--- work/src/test/regress/expected/triggers.out	2009-10-14 13:25:21.409894000 +0900
*************** CREATE TRIGGER after_upd_b_row_trig AFTE
*** 330,335 ****
--- 330,339 ----
  FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_b_row');
  CREATE TRIGGER after_upd_a_b_row_trig AFTER UPDATE OF a, b ON main_table
  FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_a_b_row');
+ CREATE TRIGGER before_upd_a_stmt_trig BEFORE UPDATE OF a ON main_table
+ FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_upd_a_stmt');
+ CREATE TRIGGER after_upd_b_stmt_trig AFTER UPDATE OF b ON main_table
+ FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_upd_b_stmt');
  SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'after_upd_a_b_row_trig';
                                                               pg_get_triggerdef                                                             
  -------------------------------------------------------------------------------------------------------------------------------------------
*************** SELECT pg_get_triggerdef(oid, true) FROM
*** 346,351 ****
--- 350,356 ----
  (1 row)
  
  UPDATE main_table SET a = 50;
+ NOTICE:  trigger_func(before_upd_a_stmt) called: action = UPDATE, when = BEFORE, level = STATEMENT
  NOTICE:  trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW
  NOTICE:  trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW
  NOTICE:  trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW
*************** NOTICE:  trigger_func(after_upd_a_b_row)
*** 372,377 ****
--- 377,383 ----
  NOTICE:  trigger_func(after_upd_b_row) called: action = UPDATE, when = AFTER, level = ROW
  NOTICE:  trigger_func(after_upd_a_b_row) called: action = UPDATE, when = AFTER, level = ROW
  NOTICE:  trigger_func(after_upd_b_row) called: action = UPDATE, when = AFTER, level = ROW
+ NOTICE:  trigger_func(after_upd_b_stmt) called: action = UPDATE, when = AFTER, level = STATEMENT
  NOTICE:  trigger_func(after_upd_stmt) called: action = UPDATE, when = AFTER, level = STATEMENT
  CREATE TRIGGER error_upd_and_col BEFORE UPDATE OR UPDATE OF a ON main_table
  FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_upd_and_col');
*************** ALTER TABLE main_table DROP COLUMN b;
*** 385,393 ****
--- 391,401 ----
  ERROR:  cannot drop table main_table column b because other objects depend on it
  DETAIL:  trigger after_upd_b_row_trig on table main_table depends on table main_table column b
  trigger after_upd_a_b_row_trig on table main_table depends on table main_table column b
+ trigger after_upd_b_stmt_trig on table main_table depends on table main_table column b
  HINT:  Use DROP ... CASCADE to drop the dependent objects too.
  DROP TRIGGER after_upd_a_b_row_trig ON main_table;
  DROP TRIGGER after_upd_b_row_trig ON main_table;
+ DROP TRIGGER after_upd_b_stmt_trig ON main_table;
  ALTER TABLE main_table DROP COLUMN b;
  -- Test enable/disable triggers
  create table trigtest (i serial primary key);
diff -cprN head/src/test/regress/sql/triggers.sql work/src/test/regress/sql/triggers.sql
*** head/src/test/regress/sql/triggers.sql	2009-10-14 13:28:32.305925057 +0900
--- work/src/test/regress/sql/triggers.sql	2009-10-14 13:23:27.437208181 +0900
*************** FOR EACH ROW EXECUTE PROCEDURE trigger_f
*** 264,269 ****
--- 264,274 ----
  CREATE TRIGGER after_upd_a_b_row_trig AFTER UPDATE OF a, b ON main_table
  FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_a_b_row');
  
+ CREATE TRIGGER before_upd_a_stmt_trig BEFORE UPDATE OF a ON main_table
+ FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_upd_a_stmt');
+ CREATE TRIGGER after_upd_b_stmt_trig AFTER UPDATE OF b ON main_table
+ FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_upd_b_stmt');
+ 
  SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'after_upd_a_b_row_trig';
  SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'main_table'::regclass AND tgname = 'after_upd_a_b_row_trig';
  
*************** FOR EACH ROW EXECUTE PROCEDURE trigger_f
*** 278,283 ****
--- 283,289 ----
  ALTER TABLE main_table DROP COLUMN b;
  DROP TRIGGER after_upd_a_b_row_trig ON main_table;
  DROP TRIGGER after_upd_b_row_trig ON main_table;
+ DROP TRIGGER after_upd_b_stmt_trig ON main_table;
  ALTER TABLE main_table DROP COLUMN b;
  
  -- Test enable/disable triggers
