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:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user