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

Generated by: LCOV version 1.14