* bool.c
* Functions for the built-in type "bool".
*
- * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type boolean: \"%s\"", in_str)));
+ errmsg("invalid input syntax for type %s: \"%s\"",
+ "boolean", in_str)));
/* not reached */
PG_RETURN_BOOL(false);
* 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)
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);
+}