@@ -283,20 +283,121 @@ boolge(PG_FUNCTION_ARGS)
283283 * boolean-and and boolean-or aggregates.
284284 */
285285
286- /* function for standard EVERY aggregate implementation conforming to SQL 2003.
287- * must be strict. It is also named bool_and for homogeneity.
286+ /*
287+ * Function for standard EVERY aggregate conforming to SQL 2003.
288+ * The aggregate is also named bool_and for consistency.
289+ *
290+ * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
288291 */
289292Datum
290293booland_statefunc (PG_FUNCTION_ARGS )
291294{
292295PG_RETURN_BOOL (PG_GETARG_BOOL (0 )&& PG_GETARG_BOOL (1 ));
293296}
294297
295- /* function for standard ANY/SOME aggregate conforming to SQL 2003.
296- * must be strict. The name of the aggregate is bool_or. See the doc.
298+ /*
299+ * Function for standard ANY/SOME aggregate conforming to SQL 2003.
300+ * The aggregate is named bool_or, because ANY/SOME have parsing conflicts.
301+ *
302+ * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
297303 */
298304Datum
299305boolor_statefunc (PG_FUNCTION_ARGS )
300306{
301307PG_RETURN_BOOL (PG_GETARG_BOOL (0 )|| PG_GETARG_BOOL (1 ));
302308}
309+
310+ typedef struct BoolAggState
311+ {
312+ int64 aggcount ;/* number of non-null values aggregated */
313+ int64 aggtrue ;/* number of values aggregated that are true */
314+ }BoolAggState ;
315+
316+ static BoolAggState *
317+ makeBoolAggState (FunctionCallInfo fcinfo )
318+ {
319+ BoolAggState * state ;
320+ MemoryContext agg_context ;
321+
322+ if (!AggCheckCallContext (fcinfo ,& agg_context ))
323+ elog (ERROR ,"aggregate function called in non-aggregate context" );
324+
325+ state = (BoolAggState * )MemoryContextAlloc (agg_context ,
326+ sizeof (BoolAggState ));
327+ state -> aggcount = 0 ;
328+ state -> aggtrue = 0 ;
329+
330+ return state ;
331+ }
332+
333+ Datum
334+ bool_accum (PG_FUNCTION_ARGS )
335+ {
336+ BoolAggState * state ;
337+
338+ state = PG_ARGISNULL (0 ) ?NULL : (BoolAggState * )PG_GETARG_POINTER (0 );
339+
340+ /* Create the state data on first call */
341+ if (state == NULL )
342+ state = makeBoolAggState (fcinfo );
343+
344+ if (!PG_ARGISNULL (1 ))
345+ {
346+ state -> aggcount ++ ;
347+ if (PG_GETARG_BOOL (1 ))
348+ state -> aggtrue ++ ;
349+ }
350+
351+ PG_RETURN_POINTER (state );
352+ }
353+
354+ Datum
355+ bool_accum_inv (PG_FUNCTION_ARGS )
356+ {
357+ BoolAggState * state ;
358+
359+ state = PG_ARGISNULL (0 ) ?NULL : (BoolAggState * )PG_GETARG_POINTER (0 );
360+
361+ /* bool_accum should have created the state data */
362+ if (state == NULL )
363+ elog (ERROR ,"bool_accum_inv called with NULL state" );
364+
365+ if (!PG_ARGISNULL (1 ))
366+ {
367+ state -> aggcount -- ;
368+ if (PG_GETARG_BOOL (1 ))
369+ state -> aggtrue -- ;
370+ }
371+
372+ PG_RETURN_POINTER (state );
373+ }
374+
375+ Datum
376+ bool_alltrue (PG_FUNCTION_ARGS )
377+ {
378+ BoolAggState * state ;
379+
380+ state = PG_ARGISNULL (0 ) ?NULL : (BoolAggState * )PG_GETARG_POINTER (0 );
381+
382+ /* if there were no non-null values, return NULL */
383+ if (state == NULL || state -> aggcount == 0 )
384+ PG_RETURN_NULL ();
385+
386+ /* true if all non-null values are true */
387+ PG_RETURN_BOOL (state -> aggtrue == state -> aggcount );
388+ }
389+
390+ Datum
391+ bool_anytrue (PG_FUNCTION_ARGS )
392+ {
393+ BoolAggState * state ;
394+
395+ state = PG_ARGISNULL (0 ) ?NULL : (BoolAggState * )PG_GETARG_POINTER (0 );
396+
397+ /* if there were no non-null values, return NULL */
398+ if (state == NULL || state -> aggcount == 0 )
399+ PG_RETURN_NULL ();
400+
401+ /* true if any non-null value is true */
402+ PG_RETURN_BOOL (state -> aggtrue > 0 );
403+ }