LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - bool.c (source / functions) Coverage Total Hit LBC UIC UBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 91.3 % 150 137 2 9 2 41 1 95 11 39 1
Current Date: 2023-04-08 15:15:32 Functions: 90.0 % 20 18 2 15 1 2 2 15
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 CBC       68431 : parse_bool(const char *value, bool *result)
      31                 : {
      32           68431 :     return parse_bool_with_len(value, strlen(value), result);
      33                 : }
      34                 : 
      35                 : bool
      36         5706525 : parse_bool_with_len(const char *value, size_t len, bool *result)
      37                 : {
      38         5706525 :     switch (*value)
      39                 :     {
      40         1349101 :         case 't':
      41                 :         case 'T':
      42         1349101 :             if (pg_strncasecmp(value, "true", len) == 0)
      43                 :             {
      44         1349095 :                 if (result)
      45         1349095 :                     *result = true;
      46         1349095 :                 return true;
      47                 :             }
      48               6 :             break;
      49         4311376 :         case 'f':
      50                 :         case 'F':
      51         4311376 :             if (pg_strncasecmp(value, "false", len) == 0)
      52                 :             {
      53         4311370 :                 if (result)
      54         4311370 :                     *result = false;
      55         4311370 :                 return true;
      56                 :             }
      57               6 :             break;
      58             208 :         case 'y':
      59                 :         case 'Y':
      60             208 :             if (pg_strncasecmp(value, "yes", len) == 0)
      61                 :             {
      62             205 :                 if (result)
      63             205 :                     *result = true;
      64             205 :                 return true;
      65                 :             }
      66               3 :             break;
      67            4930 :         case 'n':
      68                 :         case 'N':
      69            4930 :             if (pg_strncasecmp(value, "no", len) == 0)
      70                 :             {
      71            4927 :                 if (result)
      72            4927 :                     *result = false;
      73            4927 :                 return true;
      74                 :             }
      75               3 :             break;
      76           34602 :         case 'o':
      77                 :         case 'O':
      78                 :             /* 'o' is not unique enough */
      79           34602 :             if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
      80                 :             {
      81           26613 :                 if (result)
      82           26613 :                     *result = true;
      83           26613 :                 return true;
      84                 :             }
      85            7989 :             else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
      86                 :             {
      87            7980 :                 if (result)
      88            7980 :                     *result = false;
      89            7980 :                 return true;
      90                 :             }
      91               9 :             break;
      92            3417 :         case '1':
      93            3417 :             if (len == 1)
      94                 :             {
      95            3405 :                 if (result)
      96            3405 :                     *result = true;
      97            3405 :                 return true;
      98                 :             }
      99              12 :             break;
     100            2867 :         case '0':
     101            2867 :             if (len == 1)
     102                 :             {
     103            2864 :                 if (result)
     104            2864 :                     *result = false;
     105            2864 :                 return true;
     106                 :             }
     107               3 :             break;
     108              24 :         default:
     109              24 :             break;
     110                 :     }
     111                 : 
     112              66 :     if (result)
     113              66 :         *result = false;        /* suppress compiler warning */
     114              66 :     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         5638094 : boolin(PG_FUNCTION_ARGS)
     131                 : {
     132         5638094 :     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         5638094 :     str = in_str;
     141         5638136 :     while (isspace((unsigned char) *str))
     142              42 :         str++;
     143                 : 
     144         5638094 :     len = strlen(str);
     145         5638139 :     while (len > 0 && isspace((unsigned char) str[len - 1]))
     146              45 :         len--;
     147                 : 
     148         5638094 :     if (parse_bool_with_len(str, len, &result))
     149         5638049 :         PG_RETURN_BOOL(result);
     150                 : 
     151 GNC          45 :     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 ECB             :  *      boolout         - converts 1 or 0 to "t" or "f"
     159                 :  */
     160                 : Datum
     161 CBC      768880 : boolout(PG_FUNCTION_ARGS)
     162                 : {
     163          768880 :     bool        b = PG_GETARG_BOOL(0);
     164          768880 :     char       *result = (char *) palloc(2);
     165 ECB             : 
     166 GIC      768880 :     result[0] = (b) ? 't' : 'f';
     167          768880 :     result[1] = '\0';
     168          768880 :     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 EUB             :  * as "true".
     176                 :  */
     177                 : Datum
     178 UIC           0 : boolrecv(PG_FUNCTION_ARGS)
     179                 : {
     180 UBC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     181 EUB             :     int         ext;
     182                 : 
     183 UIC           0 :     ext = pq_getmsgbyte(buf);
     184               0 :     PG_RETURN_BOOL(ext != 0);
     185                 : }
     186                 : 
     187                 : /*
     188 EUB             :  *      boolsend            - converts bool to binary format
     189                 :  */
     190                 : Datum
     191 UIC           0 : boolsend(PG_FUNCTION_ARGS)
     192                 : {
     193 UBC           0 :     bool        arg1 = PG_GETARG_BOOL(0);
     194 EUB             :     StringInfoData buf;
     195                 : 
     196 UIC           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 ECB             :  * this function follows the SQL-spec result (except for producing lower case)
     206                 :  */
     207                 : Datum
     208 GIC          63 : booltext(PG_FUNCTION_ARGS)
     209                 : {
     210 CBC          63 :     bool        arg1 = PG_GETARG_BOOL(0);
     211 ECB             :     const char *str;
     212                 : 
     213 CBC          63 :     if (arg1)
     214 GIC          27 :         str = "true";
     215 ECB             :     else
     216 GIC          36 :         str = "false";
     217                 : 
     218              63 :     PG_RETURN_TEXT_P(cstring_to_text(str));
     219                 : }
     220                 : 
     221                 : 
     222                 : /*****************************************************************************
     223                 :  *   PUBLIC ROUTINES                                                         *
     224 ECB             :  *****************************************************************************/
     225                 : 
     226                 : Datum
     227 CBC       98840 : booleq(PG_FUNCTION_ARGS)
     228                 : {
     229           98840 :     bool        arg1 = PG_GETARG_BOOL(0);
     230 GIC       98840 :     bool        arg2 = PG_GETARG_BOOL(1);
     231                 : 
     232           98840 :     PG_RETURN_BOOL(arg1 == arg2);
     233 ECB             : }
     234                 : 
     235                 : Datum
     236 CBC       37761 : boolne(PG_FUNCTION_ARGS)
     237                 : {
     238           37761 :     bool        arg1 = PG_GETARG_BOOL(0);
     239 GIC       37761 :     bool        arg2 = PG_GETARG_BOOL(1);
     240                 : 
     241           37761 :     PG_RETURN_BOOL(arg1 != arg2);
     242 ECB             : }
     243                 : 
     244                 : Datum
     245 CBC           5 : boollt(PG_FUNCTION_ARGS)
     246                 : {
     247               5 :     bool        arg1 = PG_GETARG_BOOL(0);
     248 GIC           5 :     bool        arg2 = PG_GETARG_BOOL(1);
     249                 : 
     250               5 :     PG_RETURN_BOOL(arg1 < arg2);
     251 ECB             : }
     252                 : 
     253                 : Datum
     254 CBC           5 : boolgt(PG_FUNCTION_ARGS)
     255                 : {
     256               5 :     bool        arg1 = PG_GETARG_BOOL(0);
     257 GIC           5 :     bool        arg2 = PG_GETARG_BOOL(1);
     258                 : 
     259               5 :     PG_RETURN_BOOL(arg1 > arg2);
     260 ECB             : }
     261                 : 
     262                 : Datum
     263 CBC           8 : boolle(PG_FUNCTION_ARGS)
     264                 : {
     265               8 :     bool        arg1 = PG_GETARG_BOOL(0);
     266 GIC           8 :     bool        arg2 = PG_GETARG_BOOL(1);
     267                 : 
     268               8 :     PG_RETURN_BOOL(arg1 <= arg2);
     269 ECB             : }
     270                 : 
     271                 : Datum
     272 CBC           8 : boolge(PG_FUNCTION_ARGS)
     273                 : {
     274               8 :     bool        arg1 = PG_GETARG_BOOL(0);
     275 GIC           8 :     bool        arg2 = PG_GETARG_BOOL(1);
     276                 : 
     277               8 :     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 ECB             :  * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
     289                 :  */
     290                 : Datum
     291 GIC          75 : booland_statefunc(PG_FUNCTION_ARGS)
     292                 : {
     293              75 :     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 ECB             :  * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
     301                 :  */
     302                 : Datum
     303 GIC          28 : boolor_statefunc(PG_FUNCTION_ARGS)
     304                 : {
     305              28 :     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 ECB             : } BoolAggState;
     313                 : 
     314                 : static BoolAggState *
     315 GIC           6 : makeBoolAggState(FunctionCallInfo fcinfo)
     316                 : {
     317 ECB             :     BoolAggState *state;
     318 EUB             :     MemoryContext agg_context;
     319                 : 
     320 CBC           6 :     if (!AggCheckCallContext(fcinfo, &agg_context))
     321 UIC           0 :         elog(ERROR, "aggregate function called in non-aggregate context");
     322 ECB             : 
     323 CBC           6 :     state = (BoolAggState *) MemoryContextAlloc(agg_context,
     324                 :                                                 sizeof(BoolAggState));
     325               6 :     state->aggcount = 0;
     326 GIC           6 :     state->aggtrue = 0;
     327                 : 
     328               6 :     return state;
     329 ECB             : }
     330                 : 
     331                 : Datum
     332 GIC          30 : bool_accum(PG_FUNCTION_ARGS)
     333 ECB             : {
     334                 :     BoolAggState *state;
     335                 : 
     336 CBC          30 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     337 ECB             : 
     338                 :     /* Create the state data on first call */
     339 CBC          30 :     if (state == NULL)
     340 GIC           6 :         state = makeBoolAggState(fcinfo);
     341 ECB             : 
     342 CBC          30 :     if (!PG_ARGISNULL(1))
     343 ECB             :     {
     344 GIC          30 :         state->aggcount++;
     345              30 :         if (PG_GETARG_BOOL(1))
     346 CBC          18 :             state->aggtrue++;
     347                 :     }
     348                 : 
     349 GIC          30 :     PG_RETURN_POINTER(state);
     350 ECB             : }
     351                 : 
     352                 : Datum
     353 GIC          24 : bool_accum_inv(PG_FUNCTION_ARGS)
     354 ECB             : {
     355                 :     BoolAggState *state;
     356                 : 
     357 CBC          24 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     358 EUB             : 
     359                 :     /* bool_accum should have created the state data */
     360 CBC          24 :     if (state == NULL)
     361 UIC           0 :         elog(ERROR, "bool_accum_inv called with NULL state");
     362 ECB             : 
     363 CBC          24 :     if (!PG_ARGISNULL(1))
     364 ECB             :     {
     365 GIC          24 :         state->aggcount--;
     366              24 :         if (PG_GETARG_BOOL(1))
     367 CBC          12 :             state->aggtrue--;
     368                 :     }
     369                 : 
     370 GIC          24 :     PG_RETURN_POINTER(state);
     371 ECB             : }
     372                 : 
     373                 : Datum
     374 GIC          15 : bool_alltrue(PG_FUNCTION_ARGS)
     375 ECB             : {
     376                 :     BoolAggState *state;
     377                 : 
     378 CBC          15 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     379 EUB             : 
     380                 :     /* if there were no non-null values, return NULL */
     381 GIC          15 :     if (state == NULL || state->aggcount == 0)
     382 LBC           0 :         PG_RETURN_NULL();
     383                 : 
     384                 :     /* true if all non-null values are true */
     385 GIC          15 :     PG_RETURN_BOOL(state->aggtrue == state->aggcount);
     386 ECB             : }
     387                 : 
     388                 : Datum
     389 GIC          15 : bool_anytrue(PG_FUNCTION_ARGS)
     390 ECB             : {
     391                 :     BoolAggState *state;
     392                 : 
     393 CBC          15 :     state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
     394 EUB             : 
     395                 :     /* if there were no non-null values, return NULL */
     396 GIC          15 :     if (state == NULL || state->aggcount == 0)
     397 LBC           0 :         PG_RETURN_NULL();
     398                 : 
     399                 :     /* true if any non-null value is true */
     400 GIC          15 :     PG_RETURN_BOOL(state->aggtrue > 0);
     401                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a