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

Generated by: LCOV version 1.14