diff --git a/src/backend/utils/adt/bool.c b/src/backend/utils/adt/bool.c
index d419b4a..593460d 100644
*** a/src/backend/utils/adt/bool.c
--- b/src/backend/utils/adt/bool.c
*************** boolge(PG_FUNCTION_ARGS)
*** 285,290 ****
--- 285,292 ----
  
  /* function for standard EVERY aggregate implementation conforming to SQL 2003.
   * must be strict. It is also named bool_and for homogeneity.
+  * Note: this is no longer used for the bool_and() and every() aggregate
+  * functions.
   */
  Datum
  booland_statefunc(PG_FUNCTION_ARGS)
*************** booland_statefunc(PG_FUNCTION_ARGS)
*** 294,302 ****
--- 296,400 ----
  
  /* function for standard ANY/SOME aggregate conforming to SQL 2003.
   * must be strict. The name of the aggregate is bool_or. See the doc.
+  * Note: this is no longer used for the bool_or aggregate function.
   */
  Datum
  boolor_statefunc(PG_FUNCTION_ARGS)
  {
  	PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1));
  }
+ 
+ typedef struct BoolAggState
+ {
+ 	int64 aggcount; /* number of values aggregated */
+ 	int64 aggtrue; /* number of values aggregated which are true */
+ } BoolAggState;
+ 
+ static BoolAggState *
+ makeBoolAggState(FunctionCallInfo fcinfo)
+ {
+ 	BoolAggState *state;
+ 	MemoryContext agg_context;
+ 	MemoryContext old_context;
+ 
+ 	if (!AggCheckCallContext(fcinfo, &agg_context))
+ 		elog(ERROR, "aggregate function called in non-aggregate context");
+ 
+ 	old_context = MemoryContextSwitchTo(agg_context);
+ 
+ 	state = (BoolAggState *) palloc(sizeof(BoolAggState));
+ 	state->aggcount = 0;
+ 	state->aggtrue = 0;
+ 
+ 	MemoryContextSwitchTo(old_context);
+ 
+ 	return state;
+ }
+ 
+ Datum
+ bool_accum(PG_FUNCTION_ARGS)
+ {
+ 	BoolAggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* Create the state data on first call */
+ 	if (state == NULL)
+ 		state = makeBoolAggState(fcinfo);
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		state->aggcount++;
+ 		if (PG_GETARG_BOOL(1))
+ 			state->aggtrue++;
+ 	}
+ 
+ 	PG_RETURN_POINTER(state);
+ }
+ 
+ Datum
+ bool_accum_inv(PG_FUNCTION_ARGS)
+ {
+ 	BoolAggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
+ 
+ 	/* bool_accum should have created the state data */
+ 	if (state == NULL)
+ 		elog(ERROR, "bool_accum_inv called with NULL state");
+ 
+ 	if (!PG_ARGISNULL(1))
+ 	{
+ 		state->aggcount--;
+ 		if (PG_GETARG_BOOL(1))
+ 			state->aggtrue--;
+ 	}
+ 
+ 	PG_RETURN_POINTER(state);
+ }
+ 
+ Datum
+ bool_alltrue(PG_FUNCTION_ARGS)
+ {
+ 	BoolAggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
+ 	if (state == NULL || state->aggcount == 0)			/* there were no non-null inputs */
+ 		PG_RETURN_NULL();
+ 
+ 	/* true if all values are true */
+ 	PG_RETURN_BOOL(state->aggcount == state->aggtrue);
+ }
+ 
+ Datum
+ bool_anytrue(PG_FUNCTION_ARGS)
+ {
+ 	BoolAggState *state;
+ 
+ 	state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
+ 	if (state == NULL || state->aggcount == 0)			/* there were no non-null inputs */
+ 		PG_RETURN_NULL();
+ 
+ 	/* true if any value is true */
+ 	PG_RETURN_BOOL(state->aggtrue > 0);
+ }
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 3412661..7289487 100644
*** a/src/include/catalog/pg_aggregate.h
--- b/src/include/catalog/pg_aggregate.h
*************** DATA(insert ( 2828	n 0 float8_regr_accum
*** 232,240 ****
  DATA(insert ( 2829	n 0 float8_regr_accum	-	float8_corr				0	1022	0	"{0,0,0,0,0,0}" ));
  
  /* boolean-and and boolean-or */
! DATA(insert ( 2517	n 0 booland_statefunc	-	-			58	16		0	_null_ ));
! DATA(insert ( 2518	n 0 boolor_statefunc	-	-			59	16		0	_null_ ));
! DATA(insert ( 2519	n 0 booland_statefunc	-	-			58	16		0	_null_ ));
  
  /* bitwise integer */
  DATA(insert ( 2236	n 0 int2and		-	-					0	21		0	_null_ ));
--- 232,240 ----
  DATA(insert ( 2829	n 0 float8_regr_accum	-	float8_corr				0	1022	0	"{0,0,0,0,0,0}" ));
  
  /* boolean-and and boolean-or */
! DATA(insert ( 2517	n 0 bool_accum		bool_accum_inv		bool_alltrue	58	2281		16	_null_ ));
! DATA(insert ( 2518	n 0 bool_accum		bool_accum_inv		bool_anytrue	59	2281		16	_null_ ));
! DATA(insert ( 2519	n 0 bool_accum		bool_accum_inv		bool_alltrue	58	2281		16	_null_ ));
  
  /* bitwise integer */
  DATA(insert ( 2236	n 0 int2and		-	-					0	21		0	_null_ ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 334e6b8..41031cd 100644
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID = 939  (  generate_serie
*** 3860,3869 ****
--- 3860,3871 ----
  DESCR("non-persistent series generator");
  
  /* boolean aggregates */
+ /* previous aggregate transition functions, unused now */
  DATA(insert OID = 2515 ( booland_statefunc			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "16 16" _null_ _null_ _null_ _null_ booland_statefunc _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
  DATA(insert OID = 2516 ( boolor_statefunc			   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "16 16" _null_ _null_ _null_ _null_ boolor_statefunc _null_ _null_ _null_ ));
  DESCR("aggregate transition function");
+ /* aggregates and new invertible transition functions */
  DATA(insert OID = 2517 ( bool_and					   PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 16 "16" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
  DESCR("boolean-and aggregate");
  /* ANY, SOME? These names conflict with subquery operators. See doc. */
*************** DATA(insert OID = 2518 ( bool_or					   
*** 3871,3876 ****
--- 3873,3886 ----
  DESCR("boolean-or aggregate");
  DATA(insert OID = 2519 ( every						   PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 16 "16" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
  DESCR("boolean-and aggregate");
+ DATA(insert OID = 4069 ( bool_accum					   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 16" _null_ _null_ _null_ _null_ bool_accum _null_ _null_ _null_ ));
+ DESCR("aggregate transition function");
+ DATA(insert OID = 4070 ( bool_accum_inv				   PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 16" _null_ _null_ _null_ _null_ bool_accum_inv _null_ _null_ _null_ ));
+ DESCR("inverse aggregate transition function");
+ DATA(insert OID = 4071 ( bool_alltrue				   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 16 "2281" _null_ _null_ _null_ _null_ bool_alltrue _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
+ DATA(insert OID = 4072 ( bool_anytrue				   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 16 "2281" _null_ _null_ _null_ _null_ bool_anytrue _null_ _null_ _null_ ));
+ DESCR("aggregate final function");
  
  /* bitwise integer aggregates */
  DATA(insert OID = 2236 ( bit_and					   PGNSP PGUID 12 1 0 0 0 t f f f f f i 1 0 21 "21" _null_ _null_ _null_ _null_ aggregate_dummy _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 031a43a..d6f2e2f 100644
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
*************** extern Datum boolle(PG_FUNCTION_ARGS);
*** 121,126 ****
--- 121,130 ----
  extern Datum boolge(PG_FUNCTION_ARGS);
  extern Datum booland_statefunc(PG_FUNCTION_ARGS);
  extern Datum boolor_statefunc(PG_FUNCTION_ARGS);
+ extern Datum bool_accum(PG_FUNCTION_ARGS);
+ extern Datum bool_accum_inv(PG_FUNCTION_ARGS);
+ extern Datum bool_alltrue(PG_FUNCTION_ARGS);
+ extern Datum bool_anytrue(PG_FUNCTION_ARGS);
  extern bool parse_bool(const char *value, bool *result);
  extern bool parse_bool_with_len(const char *value, size_t len, bool *result);
  
diff --git a/src/test/regress/expected/window.out b/src/test/regress/expected/window.out
index e3eba47..fcb07c8 100644
*** a/src/test/regress/expected/window.out
--- b/src/test/regress/expected/window.out
*************** DROP FUNCTION logging_sfunc_nonstrict(te
*** 1300,1305 ****
--- 1300,1317 ----
  -- Test the boolean inverse transition functions
  --
  --
+ SELECT b,bool_and(b) OVER w, bool_or(b) OVER w
+ FROM (VALUES(1,true),(2,true),(3,false),(4,false),(5,true)) v(i,b)
+ WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING);
+  b | bool_and | bool_or 
+ ---+----------+---------
+  t | t        | t
+  t | f        | t
+  f | f        | f
+  f | f        | t
+  t | t        | t
+ (5 rows)
+ 
  --
  --
  -- Test the MIN and MAX inverse transition functions
diff --git a/src/test/regress/sql/window.sql b/src/test/regress/sql/window.sql
index bd8dbdc..dcb410e 100644
*** a/src/test/regress/sql/window.sql
--- b/src/test/regress/sql/window.sql
*************** DROP FUNCTION logging_sfunc_nonstrict(te
*** 482,487 ****
--- 482,491 ----
  --
  --
  
+ SELECT b,bool_and(b) OVER w, bool_or(b) OVER w
+ FROM (VALUES(1,true),(2,true),(3,false),(4,false),(5,true)) v(i,b)
+ WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING);
+ 
  --
  --
  -- Test the MIN and MAX inverse transition functions
