1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Provide moving-aggregate support for boolean aggregates.

David Rowley and Florian Pflug, reviewed by Dean Rasheed
This commit is contained in:
Tom Lane
2014-04-13 00:01:46 -04:00
parent 842faa714c
commit d95425c8b9
7 changed files with 137 additions and 8 deletions

View File

@ -283,8 +283,11 @@ boolge(PG_FUNCTION_ARGS)
* boolean-and and boolean-or aggregates.
*/
/* function for standard EVERY aggregate implementation conforming to SQL 2003.
* must be strict. It is also named bool_and for homogeneity.
/*
* Function for standard EVERY aggregate conforming to SQL 2003.
* The aggregate is also named bool_and for consistency.
*
* Note: this is only used in plain aggregate mode, not moving-aggregate mode.
*/
Datum
booland_statefunc(PG_FUNCTION_ARGS)
@ -292,11 +295,109 @@ booland_statefunc(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(PG_GETARG_BOOL(0) && PG_GETARG_BOOL(1));
}
/* function for standard ANY/SOME aggregate conforming to SQL 2003.
* must be strict. The name of the aggregate is bool_or. See the doc.
/*
* Function for standard ANY/SOME aggregate conforming to SQL 2003.
* The aggregate is named bool_or, because ANY/SOME have parsing conflicts.
*
* Note: this is only used in plain aggregate mode, not moving-aggregate mode.
*/
Datum
boolor_statefunc(PG_FUNCTION_ARGS)
{
PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1));
}
typedef struct BoolAggState
{
int64 aggcount; /* number of non-null values aggregated */
int64 aggtrue; /* number of values aggregated that are true */
} BoolAggState;
static BoolAggState *
makeBoolAggState(FunctionCallInfo fcinfo)
{
BoolAggState *state;
MemoryContext agg_context;
if (!AggCheckCallContext(fcinfo, &agg_context))
elog(ERROR, "aggregate function called in non-aggregate context");
state = (BoolAggState *) MemoryContextAlloc(agg_context,
sizeof(BoolAggState));
state->aggcount = 0;
state->aggtrue = 0;
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 there were no non-null values, return NULL */
if (state == NULL || state->aggcount == 0)
PG_RETURN_NULL();
/* true if all non-null values are true */
PG_RETURN_BOOL(state->aggtrue == state->aggcount);
}
Datum
bool_anytrue(PG_FUNCTION_ARGS)
{
BoolAggState *state;
state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
/* if there were no non-null values, return NULL */
if (state == NULL || state->aggcount == 0)
PG_RETURN_NULL();
/* true if any non-null value is true */
PG_RETURN_BOOL(state->aggtrue > 0);
}