Coverage Report

Created: 2025-09-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/adt/bool.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * bool.c
4
 *    Functions for the built-in type "bool".
5
 *
6
 * Portions Copyright (c) 1996-2025, 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
parse_bool(const char *value, bool *result)
32
4
{
33
4
  return parse_bool_with_len(value, strlen(value), result);
34
4
}
35
36
bool
37
parse_bool_with_len(const char *value, size_t len, bool *result)
38
4
{
39
  /* Check the most-used possibilities first. */
40
4
  switch (*value)
41
4
  {
42
0
    case 't':
43
0
    case 'T':
44
0
      if (pg_strncasecmp(value, "true", len) == 0)
45
0
      {
46
0
        if (result)
47
0
          *result = true;
48
0
        return true;
49
0
      }
50
0
      break;
51
0
    case 'f':
52
0
    case 'F':
53
0
      if (pg_strncasecmp(value, "false", len) == 0)
54
0
      {
55
0
        if (result)
56
0
          *result = false;
57
0
        return true;
58
0
      }
59
0
      break;
60
0
    case 'y':
61
0
    case 'Y':
62
0
      if (pg_strncasecmp(value, "yes", len) == 0)
63
0
      {
64
0
        if (result)
65
0
          *result = true;
66
0
        return true;
67
0
      }
68
0
      break;
69
4
    case 'n':
70
4
    case 'N':
71
4
      if (pg_strncasecmp(value, "no", len) == 0)
72
4
      {
73
4
        if (result)
74
4
          *result = false;
75
4
        return true;
76
4
      }
77
0
      break;
78
0
    case 'o':
79
0
    case 'O':
80
      /* 'o' is not unique enough */
81
0
      if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
82
0
      {
83
0
        if (result)
84
0
          *result = true;
85
0
        return true;
86
0
      }
87
0
      else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
88
0
      {
89
0
        if (result)
90
0
          *result = false;
91
0
        return true;
92
0
      }
93
0
      break;
94
0
    case '1':
95
0
      if (len == 1)
96
0
      {
97
0
        if (result)
98
0
          *result = true;
99
0
        return true;
100
0
      }
101
0
      break;
102
0
    case '0':
103
0
      if (len == 1)
104
0
      {
105
0
        if (result)
106
0
          *result = false;
107
0
        return true;
108
0
      }
109
0
      break;
110
0
    default:
111
0
      break;
112
4
  }
113
114
0
  if (result)
115
0
    *result = false;   /* suppress compiler warning */
116
0
  return false;
117
4
}
118
119
/*****************************************************************************
120
 *   USER I/O ROUTINES                             *
121
 *****************************************************************************/
122
123
/*
124
 *    boolin      - input function for type boolean
125
 */
126
Datum
127
boolin(PG_FUNCTION_ARGS)
128
0
{
129
0
  const char *in_str = PG_GETARG_CSTRING(0);
130
0
  const char *str;
131
0
  size_t    len;
132
0
  bool    result;
133
134
  /*
135
   * Skip leading and trailing whitespace
136
   */
137
0
  str = in_str;
138
0
  while (isspace((unsigned char) *str))
139
0
    str++;
140
141
0
  len = strlen(str);
142
0
  while (len > 0 && isspace((unsigned char) str[len - 1]))
143
0
    len--;
144
145
0
  if (parse_bool_with_len(str, len, &result))
146
0
    PG_RETURN_BOOL(result);
147
148
0
  ereturn(fcinfo->context, (Datum) 0,
149
0
      (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
150
0
       errmsg("invalid input syntax for type %s: \"%s\"",
151
0
          "boolean", in_str)));
152
0
}
153
154
/*
155
 *    boolout     - converts 1 or 0 to "t" or "f"
156
 */
157
Datum
158
boolout(PG_FUNCTION_ARGS)
159
0
{
160
0
  bool    b = PG_GETARG_BOOL(0);
161
0
  char     *result = (char *) palloc(2);
162
163
0
  result[0] = (b) ? 't' : 'f';
164
0
  result[1] = '\0';
165
0
  PG_RETURN_CSTRING(result);
166
0
}
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
boolrecv(PG_FUNCTION_ARGS)
176
0
{
177
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
178
0
  int     ext;
179
180
0
  ext = pq_getmsgbyte(buf);
181
0
  PG_RETURN_BOOL(ext != 0);
182
0
}
183
184
/*
185
 *    boolsend      - converts bool to binary format
186
 */
187
Datum
188
boolsend(PG_FUNCTION_ARGS)
189
0
{
190
0
  bool    arg1 = PG_GETARG_BOOL(0);
191
0
  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
0
}
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
booltext(PG_FUNCTION_ARGS)
206
0
{
207
0
  bool    arg1 = PG_GETARG_BOOL(0);
208
0
  const char *str;
209
210
0
  if (arg1)
211
0
    str = "true";
212
0
  else
213
0
    str = "false";
214
215
0
  PG_RETURN_TEXT_P(cstring_to_text(str));
216
0
}
217
218
219
/*****************************************************************************
220
 *   PUBLIC ROUTINES                             *
221
 *****************************************************************************/
222
223
Datum
224
booleq(PG_FUNCTION_ARGS)
225
0
{
226
0
  bool    arg1 = PG_GETARG_BOOL(0);
227
0
  bool    arg2 = PG_GETARG_BOOL(1);
228
229
0
  PG_RETURN_BOOL(arg1 == arg2);
230
0
}
231
232
Datum
233
boolne(PG_FUNCTION_ARGS)
234
0
{
235
0
  bool    arg1 = PG_GETARG_BOOL(0);
236
0
  bool    arg2 = PG_GETARG_BOOL(1);
237
238
0
  PG_RETURN_BOOL(arg1 != arg2);
239
0
}
240
241
Datum
242
boollt(PG_FUNCTION_ARGS)
243
0
{
244
0
  bool    arg1 = PG_GETARG_BOOL(0);
245
0
  bool    arg2 = PG_GETARG_BOOL(1);
246
247
0
  PG_RETURN_BOOL(arg1 < arg2);
248
0
}
249
250
Datum
251
boolgt(PG_FUNCTION_ARGS)
252
0
{
253
0
  bool    arg1 = PG_GETARG_BOOL(0);
254
0
  bool    arg2 = PG_GETARG_BOOL(1);
255
256
0
  PG_RETURN_BOOL(arg1 > arg2);
257
0
}
258
259
Datum
260
boolle(PG_FUNCTION_ARGS)
261
0
{
262
0
  bool    arg1 = PG_GETARG_BOOL(0);
263
0
  bool    arg2 = PG_GETARG_BOOL(1);
264
265
0
  PG_RETURN_BOOL(arg1 <= arg2);
266
0
}
267
268
Datum
269
boolge(PG_FUNCTION_ARGS)
270
0
{
271
0
  bool    arg1 = PG_GETARG_BOOL(0);
272
0
  bool    arg2 = PG_GETARG_BOOL(1);
273
274
0
  PG_RETURN_BOOL(arg1 >= arg2);
275
0
}
276
277
Datum
278
hashbool(PG_FUNCTION_ARGS)
279
0
{
280
0
  return hash_uint32((int32) PG_GETARG_BOOL(0));
281
0
}
282
283
Datum
284
hashboolextended(PG_FUNCTION_ARGS)
285
0
{
286
0
  return hash_uint32_extended((int32) PG_GETARG_BOOL(0), PG_GETARG_INT64(1));
287
0
}
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
booland_statefunc(PG_FUNCTION_ARGS)
301
0
{
302
0
  PG_RETURN_BOOL(PG_GETARG_BOOL(0) && PG_GETARG_BOOL(1));
303
0
}
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
boolor_statefunc(PG_FUNCTION_ARGS)
313
0
{
314
0
  PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1));
315
0
}
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
makeBoolAggState(FunctionCallInfo fcinfo)
325
0
{
326
0
  BoolAggState *state;
327
0
  MemoryContext agg_context;
328
329
0
  if (!AggCheckCallContext(fcinfo, &agg_context))
330
0
    elog(ERROR, "aggregate function called in non-aggregate context");
331
332
0
  state = (BoolAggState *) MemoryContextAlloc(agg_context,
333
0
                        sizeof(BoolAggState));
334
0
  state->aggcount = 0;
335
0
  state->aggtrue = 0;
336
337
0
  return state;
338
0
}
339
340
Datum
341
bool_accum(PG_FUNCTION_ARGS)
342
0
{
343
0
  BoolAggState *state;
344
345
0
  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
346
347
  /* Create the state data on first call */
348
0
  if (state == NULL)
349
0
    state = makeBoolAggState(fcinfo);
350
351
0
  if (!PG_ARGISNULL(1))
352
0
  {
353
0
    state->aggcount++;
354
0
    if (PG_GETARG_BOOL(1))
355
0
      state->aggtrue++;
356
0
  }
357
358
0
  PG_RETURN_POINTER(state);
359
0
}
360
361
Datum
362
bool_accum_inv(PG_FUNCTION_ARGS)
363
0
{
364
0
  BoolAggState *state;
365
366
0
  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
367
368
  /* bool_accum should have created the state data */
369
0
  if (state == NULL)
370
0
    elog(ERROR, "bool_accum_inv called with NULL state");
371
372
0
  if (!PG_ARGISNULL(1))
373
0
  {
374
0
    state->aggcount--;
375
0
    if (PG_GETARG_BOOL(1))
376
0
      state->aggtrue--;
377
0
  }
378
379
0
  PG_RETURN_POINTER(state);
380
0
}
381
382
Datum
383
bool_alltrue(PG_FUNCTION_ARGS)
384
0
{
385
0
  BoolAggState *state;
386
387
0
  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
388
389
  /* if there were no non-null values, return NULL */
390
0
  if (state == NULL || state->aggcount == 0)
391
0
    PG_RETURN_NULL();
392
393
  /* true if all non-null values are true */
394
0
  PG_RETURN_BOOL(state->aggtrue == state->aggcount);
395
0
}
396
397
Datum
398
bool_anytrue(PG_FUNCTION_ARGS)
399
0
{
400
0
  BoolAggState *state;
401
402
0
  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
403
404
  /* if there were no non-null values, return NULL */
405
0
  if (state == NULL || state->aggcount == 0)
406
0
    PG_RETURN_NULL();
407
408
  /* true if any non-null value is true */
409
0
  PG_RETURN_BOOL(state->aggtrue > 0);
410
0
}