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

Generated by: LCOV version 1.13