LCOV - code coverage report
Current view: top level - src/backend/utils/adt - bool.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 137 150 91.3 %
Date: 2024-04-19 13:11:37 Functions: 18 20 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * bool.c
       4             :  *    Functions for the built-in type "bool".
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/adt/bool.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include <ctype.h>
      19             : 
      20             : #include "libpq/pqformat.h"
      21             : #include "utils/builtins.h"
      22             : 
      23             : /*
      24             :  * Try to interpret value as boolean value.  Valid values are: true,
      25             :  * false, yes, no, on, off, 1, 0; as well as unique prefixes thereof.
      26             :  * If the string parses okay, return true, else false.
      27             :  * If okay and result is not NULL, return the value in *result.
      28             :  */
      29             : bool
      30      134006 : parse_bool(const char *value, bool *result)
      31             : {
      32      134006 :     return parse_bool_with_len(value, strlen(value), result);
      33             : }
      34             : 
      35             : bool
      36     2999984 : parse_bool_with_len(const char *value, size_t len, bool *result)
      37             : {
      38             :     /* Check the most-used possibilities first. */
      39     2999984 :     switch (*value)
      40             :     {
      41      367886 :         case 't':
      42             :         case 'T':
      43      367886 :             if (pg_strncasecmp(value, "true", len) == 0)
      44             :             {
      45      367874 :                 if (result)
      46      367874 :                     *result = true;
      47      367874 :                 return true;
      48             :             }
      49          12 :             break;
      50     2533808 :         case 'f':
      51             :         case 'F':
      52     2533808 :             if (pg_strncasecmp(value, "false", len) == 0)
      53             :             {
      54     2533790 :                 if (result)
      55     2533790 :                     *result = false;
      56     2533790 :                 return true;
      57             :             }
      58          18 :             break;
      59         464 :         case 'y':
      60             :         case 'Y':
      61         464 :             if (pg_strncasecmp(value, "yes", len) == 0)
      62             :             {
      63         458 :                 if (result)
      64         458 :                     *result = true;
      65         458 :                 return true;
      66             :             }
      67           6 :             break;
      68        5292 :         case 'n':
      69             :         case 'N':
      70        5292 :             if (pg_strncasecmp(value, "no", len) == 0)
      71             :             {
      72        5274 :                 if (result)
      73        5274 :                     *result = false;
      74        5274 :                 return true;
      75             :             }
      76          18 :             break;
      77       79722 :         case 'o':
      78             :         case 'O':
      79             :             /* 'o' is not unique enough */
      80       79722 :             if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
      81             :             {
      82       62330 :                 if (result)
      83       62330 :                     *result = true;
      84       62330 :                 return true;
      85             :             }
      86       17392 :             else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
      87             :             {
      88       17374 :                 if (result)
      89       17374 :                     *result = false;
      90       17374 :                 return true;
      91             :             }
      92          18 :             break;
      93        6972 :         case '1':
      94        6972 :             if (len == 1)
      95             :             {
      96        6924 :                 if (result)
      97        6924 :                     *result = true;
      98        6924 :                 return true;
      99             :             }
     100          48 :             break;
     101        5738 :         case '0':
     102        5738 :             if (len == 1)
     103             :             {
     104        5732 :                 if (result)
     105        5732 :                     *result = false;
     106        5732 :                 return true;
     107             :             }
     108           6 :             break;
     109         102 :         default:
     110         102 :             break;
     111             :     }
     112             : 
     113         228 :     if (result)
     114         228 :         *result = false;        /* suppress compiler warning */
     115         228 :     return false;
     116             : }
     117             : 
     118             : /*****************************************************************************
     119             :  *   USER I/O ROUTINES                                                       *
     120             :  *****************************************************************************/
     121             : 
     122             : /*
     123             :  *      boolin          - input function for type boolean
     124             :  */
     125             : Datum
     126     2865978 : boolin(PG_FUNCTION_ARGS)
     127             : {
     128     2865978 :     const char *in_str = PG_GETARG_CSTRING(0);
     129             :     const char *str;
     130             :     size_t      len;
     131             :     bool        result;
     132             : 
     133             :     /*
     134             :      * Skip leading and trailing whitespace
     135             :      */
     136     2865978 :     str = in_str;
     137     2866062 :     while (isspace((unsigned char) *str))
     138          84 :         str++;
     139             : 
     140     2865978 :     len = strlen(str);
     141     2866068 :     while (len > 0 && isspace((unsigned char) str[len - 1]))
     142          90 :         len--;
     143             : 
     144     2865978 :     if (parse_bool_with_len(str, len, &result))
     145     2865846 :         PG_RETURN_BOOL(result);
     146             : 
     147         132 :     ereturn(fcinfo->context, (Datum) 0,
     148             :             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     149             :              errmsg("invalid input syntax for type %s: \"%s\"",
     150             :                     "boolean", in_str)));
     151             : }
     152             : 
     153             : /*
     154             :  *      boolout         - converts 1 or 0 to "t" or "f"
     155             :  */
     156             : Datum
     157     1932628 : boolout(PG_FUNCTION_ARGS)
     158             : {
     159     1932628 :     bool        b = PG_GETARG_BOOL(0);
     160     1932628 :     char       *result = (char *) palloc(2);
     161             : 
     162     1932628 :     result[0] = (b) ? 't' : 'f';
     163     1932628 :     result[1] = '\0';
     164     1932628 :     PG_RETURN_CSTRING(result);
     165             : }
     166             : 
     167             : /*
     168             :  *      boolrecv            - converts external binary format to bool
     169             :  *
     170             :  * The external representation is one byte.  Any nonzero value is taken
     171             :  * as "true".
     172             :  */
     173             : Datum
     174           0 : boolrecv(PG_FUNCTION_ARGS)
     175             : {
     176           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     177             :     int         ext;
     178             : 
     179           0 :     ext = pq_getmsgbyte(buf);
     180           0 :     PG_RETURN_BOOL(ext != 0);
     181             : }
     182             : 
     183             : /*
     184             :  *      boolsend            - converts bool to binary format
     185             :  */
     186             : Datum
     187           0 : boolsend(PG_FUNCTION_ARGS)
     188             : {
     189           0 :     bool        arg1 = PG_GETARG_BOOL(0);
     190             :     StringInfoData buf;
     191             : 
     192           0 :     pq_begintypsend(&buf);
     193           0 :     pq_sendbyte(&buf, arg1 ? 1 : 0);
     194           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     195             : }
     196             : 
     197             : /*
     198             :  *      booltext            - cast function for bool => text
     199             :  *
     200             :  * We need this because it's different from the behavior of boolout();
     201             :  * this function follows the SQL-spec result (except for producing lower case)
     202             :  */
     203             : Datum
     204         156 : booltext(PG_FUNCTION_ARGS)
     205             : {
     206         156 :     bool        arg1 = PG_GETARG_BOOL(0);
     207             :     const char *str;
     208             : 
     209         156 :     if (arg1)
     210          66 :         str = "true";
     211             :     else
     212          90 :         str = "false";
     213             : 
     214         156 :     PG_RETURN_TEXT_P(cstring_to_text(str));
     215             : }
     216             : 
     217             : 
     218             : /*****************************************************************************
     219             :  *   PUBLIC ROUTINES                                                         *
     220             :  *****************************************************************************/
     221             : 
     222             : Datum
     223      288866 : booleq(PG_FUNCTION_ARGS)
     224             : {
     225      288866 :     bool        arg1 = PG_GETARG_BOOL(0);
     226      288866 :     bool        arg2 = PG_GETARG_BOOL(1);
     227             : 
     228      288866 :     PG_RETURN_BOOL(arg1 == arg2);
     229             : }
     230             : 
     231             : Datum
     232       75798 : boolne(PG_FUNCTION_ARGS)
     233             : {
     234       75798 :     bool        arg1 = PG_GETARG_BOOL(0);
     235       75798 :     bool        arg2 = PG_GETARG_BOOL(1);
     236             : 
     237       75798 :     PG_RETURN_BOOL(arg1 != arg2);
     238             : }
     239             : 
     240             : Datum
     241          10 : boollt(PG_FUNCTION_ARGS)
     242             : {
     243          10 :     bool        arg1 = PG_GETARG_BOOL(0);
     244          10 :     bool        arg2 = PG_GETARG_BOOL(1);
     245             : 
     246          10 :     PG_RETURN_BOOL(arg1 < arg2);
     247             : }
     248             : 
     249             : Datum
     250          10 : boolgt(PG_FUNCTION_ARGS)
     251             : {
     252          10 :     bool        arg1 = PG_GETARG_BOOL(0);
     253          10 :     bool        arg2 = PG_GETARG_BOOL(1);
     254             : 
     255          10 :     PG_RETURN_BOOL(arg1 > arg2);
     256             : }
     257             : 
     258             : Datum
     259          16 : boolle(PG_FUNCTION_ARGS)
     260             : {
     261          16 :     bool        arg1 = PG_GETARG_BOOL(0);
     262          16 :     bool        arg2 = PG_GETARG_BOOL(1);
     263             : 
     264          16 :     PG_RETURN_BOOL(arg1 <= arg2);
     265             : }
     266             : 
     267             : Datum
     268          16 : boolge(PG_FUNCTION_ARGS)
     269             : {
     270          16 :     bool        arg1 = PG_GETARG_BOOL(0);
     271          16 :     bool        arg2 = PG_GETARG_BOOL(1);
     272             : 
     273          16 :     PG_RETURN_BOOL(arg1 >= arg2);
     274             : }
     275             : 
     276             : /*
     277             :  * boolean-and and boolean-or aggregates.
     278             :  */
     279             : 
     280             : /*
     281             :  * Function for standard EVERY aggregate conforming to SQL 2003.
     282             :  * The aggregate is also named bool_and for consistency.
     283             :  *
     284             :  * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
     285             :  */
     286             : Datum
     287         120 : booland_statefunc(PG_FUNCTION_ARGS)
     288             : {
     289         120 :     PG_RETURN_BOOL(PG_GETARG_BOOL(0) && PG_GETARG_BOOL(1));
     290             : }
     291             : 
     292             : /*
     293             :  * Function for standard ANY/SOME aggregate conforming to SQL 2003.
     294             :  * The aggregate is named bool_or, because ANY/SOME have parsing conflicts.
     295             :  *
     296             :  * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
     297             :  */
     298             : Datum
     299          56 : boolor_statefunc(PG_FUNCTION_ARGS)
     300             : {
     301          56 :     PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1));
     302             : }
     303             : 
     304             : typedef struct BoolAggState
     305             : {
     306             :     int64       aggcount;       /* number of non-null values aggregated */
     307             :     int64       aggtrue;        /* number of values aggregated that are true */
     308             : } BoolAggState;
     309             : 
     310             : static BoolAggState *
     311          12 : makeBoolAggState(FunctionCallInfo fcinfo)
     312             : {
     313             :     BoolAggState *state;
     314             :     MemoryContext agg_context;
     315             : 
     316          12 :     if (!AggCheckCallContext(fcinfo, &agg_context))
     317           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
     318             : 
     319          12 :     state = (BoolAggState *) MemoryContextAlloc(agg_context,
     320             :                                                 sizeof(BoolAggState));
     321          12 :     state->aggcount = 0;
     322          12 :     state->aggtrue = 0;
     323             : 
     324          12 :     return state;
     325             : }
     326             : 
     327             : Datum
     328          60 : bool_accum(PG_FUNCTION_ARGS)
     329             : {
     330             :     BoolAggState *state;
     331             : 
     332          60 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     333             : 
     334             :     /* Create the state data on first call */
     335          60 :     if (state == NULL)
     336          12 :         state = makeBoolAggState(fcinfo);
     337             : 
     338          60 :     if (!PG_ARGISNULL(1))
     339             :     {
     340          60 :         state->aggcount++;
     341          60 :         if (PG_GETARG_BOOL(1))
     342          36 :             state->aggtrue++;
     343             :     }
     344             : 
     345          60 :     PG_RETURN_POINTER(state);
     346             : }
     347             : 
     348             : Datum
     349          48 : bool_accum_inv(PG_FUNCTION_ARGS)
     350             : {
     351             :     BoolAggState *state;
     352             : 
     353          48 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     354             : 
     355             :     /* bool_accum should have created the state data */
     356          48 :     if (state == NULL)
     357           0 :         elog(ERROR, "bool_accum_inv called with NULL state");
     358             : 
     359          48 :     if (!PG_ARGISNULL(1))
     360             :     {
     361          48 :         state->aggcount--;
     362          48 :         if (PG_GETARG_BOOL(1))
     363          24 :             state->aggtrue--;
     364             :     }
     365             : 
     366          48 :     PG_RETURN_POINTER(state);
     367             : }
     368             : 
     369             : Datum
     370          30 : bool_alltrue(PG_FUNCTION_ARGS)
     371             : {
     372             :     BoolAggState *state;
     373             : 
     374          30 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     375             : 
     376             :     /* if there were no non-null values, return NULL */
     377          30 :     if (state == NULL || state->aggcount == 0)
     378           0 :         PG_RETURN_NULL();
     379             : 
     380             :     /* true if all non-null values are true */
     381          30 :     PG_RETURN_BOOL(state->aggtrue == state->aggcount);
     382             : }
     383             : 
     384             : Datum
     385          30 : bool_anytrue(PG_FUNCTION_ARGS)
     386             : {
     387             :     BoolAggState *state;
     388             : 
     389          30 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     390             : 
     391             :     /* if there were no non-null values, return NULL */
     392          30 :     if (state == NULL || state->aggcount == 0)
     393           0 :         PG_RETURN_NULL();
     394             : 
     395             :     /* true if any non-null value is true */
     396          30 :     PG_RETURN_BOOL(state->aggtrue > 0);
     397             : }

Generated by: LCOV version 1.14