]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/bool.c
Add support for EUI-64 MAC addresses as macaddr8
[postgresql] / src / backend / utils / adt / bool.c
index 1a9d5100e4ec967bb5664232fb6b3cc1101fbf15..6c87e211407d5e506e5b0ebf7083f182a5c6d95d 100644 (file)
@@ -3,7 +3,7 @@
  * 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
  *
  *
@@ -150,7 +150,8 @@ boolin(PG_FUNCTION_ARGS)
 
        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);
@@ -283,8 +284,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 +296,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);
+}