PostgreSQL Source Code  git master
bool.c
Go to the documentation of this file.
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 parse_bool(const char *value, bool *result)
32 {
33  return parse_bool_with_len(value, strlen(value), result);
34 }
35 
36 bool
37 parse_bool_with_len(const char *value, size_t len, bool *result)
38 {
39  /* Check the most-used possibilities first. */
40  switch (*value)
41  {
42  case 't':
43  case 'T':
44  if (pg_strncasecmp(value, "true", len) == 0)
45  {
46  if (result)
47  *result = true;
48  return true;
49  }
50  break;
51  case 'f':
52  case 'F':
53  if (pg_strncasecmp(value, "false", len) == 0)
54  {
55  if (result)
56  *result = false;
57  return true;
58  }
59  break;
60  case 'y':
61  case 'Y':
62  if (pg_strncasecmp(value, "yes", len) == 0)
63  {
64  if (result)
65  *result = true;
66  return true;
67  }
68  break;
69  case 'n':
70  case 'N':
71  if (pg_strncasecmp(value, "no", len) == 0)
72  {
73  if (result)
74  *result = false;
75  return true;
76  }
77  break;
78  case 'o':
79  case 'O':
80  /* 'o' is not unique enough */
81  if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
82  {
83  if (result)
84  *result = true;
85  return true;
86  }
87  else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
88  {
89  if (result)
90  *result = false;
91  return true;
92  }
93  break;
94  case '1':
95  if (len == 1)
96  {
97  if (result)
98  *result = true;
99  return true;
100  }
101  break;
102  case '0':
103  if (len == 1)
104  {
105  if (result)
106  *result = false;
107  return true;
108  }
109  break;
110  default:
111  break;
112  }
113 
114  if (result)
115  *result = false; /* suppress compiler warning */
116  return false;
117 }
118 
119 /*****************************************************************************
120  * USER I/O ROUTINES *
121  *****************************************************************************/
122 
123 /*
124  * boolin - input function for type boolean
125  */
126 Datum
128 {
129  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  str = in_str;
138  while (isspace((unsigned char) *str))
139  str++;
140 
141  len = strlen(str);
142  while (len > 0 && isspace((unsigned char) str[len - 1]))
143  len--;
144 
145  if (parse_bool_with_len(str, len, &result))
146  PG_RETURN_BOOL(result);
147 
148  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
159 {
160  bool b = PG_GETARG_BOOL(0);
161  char *result = (char *) palloc(2);
162 
163  result[0] = (b) ? 't' : 'f';
164  result[1] = '\0';
165  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
176 {
178  int ext;
179 
180  ext = pq_getmsgbyte(buf);
181  PG_RETURN_BOOL(ext != 0);
182 }
183 
184 /*
185  * boolsend - converts bool to binary format
186  */
187 Datum
189 {
190  bool arg1 = PG_GETARG_BOOL(0);
192 
194  pq_sendbyte(&buf, arg1 ? 1 : 0);
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
206 {
207  bool arg1 = PG_GETARG_BOOL(0);
208  const char *str;
209 
210  if (arg1)
211  str = "true";
212  else
213  str = "false";
214 
216 }
217 
218 
219 /*****************************************************************************
220  * PUBLIC ROUTINES *
221  *****************************************************************************/
222 
223 Datum
225 {
226  bool arg1 = PG_GETARG_BOOL(0);
227  bool arg2 = PG_GETARG_BOOL(1);
228 
229  PG_RETURN_BOOL(arg1 == arg2);
230 }
231 
232 Datum
234 {
235  bool arg1 = PG_GETARG_BOOL(0);
236  bool arg2 = PG_GETARG_BOOL(1);
237 
238  PG_RETURN_BOOL(arg1 != arg2);
239 }
240 
241 Datum
243 {
244  bool arg1 = PG_GETARG_BOOL(0);
245  bool arg2 = PG_GETARG_BOOL(1);
246 
247  PG_RETURN_BOOL(arg1 < arg2);
248 }
249 
250 Datum
252 {
253  bool arg1 = PG_GETARG_BOOL(0);
254  bool arg2 = PG_GETARG_BOOL(1);
255 
256  PG_RETURN_BOOL(arg1 > arg2);
257 }
258 
259 Datum
261 {
262  bool arg1 = PG_GETARG_BOOL(0);
263  bool arg2 = PG_GETARG_BOOL(1);
264 
265  PG_RETURN_BOOL(arg1 <= arg2);
266 }
267 
268 Datum
270 {
271  bool arg1 = PG_GETARG_BOOL(0);
272  bool arg2 = PG_GETARG_BOOL(1);
273 
274  PG_RETURN_BOOL(arg1 >= arg2);
275 }
276 
277 Datum
279 {
280  return hash_uint32((int32) PG_GETARG_BOOL(0));
281 }
282 
283 Datum
285 {
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
301 {
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
313 {
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 */
322 
323 static BoolAggState *
325 {
327  MemoryContext agg_context;
328 
329  if (!AggCheckCallContext(fcinfo, &agg_context))
330  elog(ERROR, "aggregate function called in non-aggregate context");
331 
332  state = (BoolAggState *) MemoryContextAlloc(agg_context,
333  sizeof(BoolAggState));
334  state->aggcount = 0;
335  state->aggtrue = 0;
336 
337  return state;
338 }
339 
340 Datum
342 {
344 
345  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
346 
347  /* Create the state data on first call */
348  if (state == NULL)
349  state = makeBoolAggState(fcinfo);
350 
351  if (!PG_ARGISNULL(1))
352  {
353  state->aggcount++;
354  if (PG_GETARG_BOOL(1))
355  state->aggtrue++;
356  }
357 
359 }
360 
361 Datum
363 {
365 
366  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
367 
368  /* bool_accum should have created the state data */
369  if (state == NULL)
370  elog(ERROR, "bool_accum_inv called with NULL state");
371 
372  if (!PG_ARGISNULL(1))
373  {
374  state->aggcount--;
375  if (PG_GETARG_BOOL(1))
376  state->aggtrue--;
377  }
378 
380 }
381 
382 Datum
384 {
386 
387  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
388 
389  /* if there were no non-null values, return NULL */
390  if (state == NULL || state->aggcount == 0)
391  PG_RETURN_NULL();
392 
393  /* true if all non-null values are true */
394  PG_RETURN_BOOL(state->aggtrue == state->aggcount);
395 }
396 
397 Datum
399 {
401 
402  state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
403 
404  /* if there were no non-null values, return NULL */
405  if (state == NULL || state->aggcount == 0)
406  PG_RETURN_NULL();
407 
408  /* true if any non-null value is true */
409  PG_RETURN_BOOL(state->aggtrue > 0);
410 }
Datum boolge(PG_FUNCTION_ARGS)
Definition: bool.c:269
static BoolAggState * makeBoolAggState(FunctionCallInfo fcinfo)
Definition: bool.c:324
Datum boolor_statefunc(PG_FUNCTION_ARGS)
Definition: bool.c:312
Datum boolle(PG_FUNCTION_ARGS)
Definition: bool.c:260
Datum boollt(PG_FUNCTION_ARGS)
Definition: bool.c:242
bool parse_bool(const char *value, bool *result)
Definition: bool.c:31
Datum boolin(PG_FUNCTION_ARGS)
Definition: bool.c:127
Datum hashbool(PG_FUNCTION_ARGS)
Definition: bool.c:278
Datum hashboolextended(PG_FUNCTION_ARGS)
Definition: bool.c:284
Datum boolgt(PG_FUNCTION_ARGS)
Definition: bool.c:251
Datum boolrecv(PG_FUNCTION_ARGS)
Definition: bool.c:175
Datum boolsend(PG_FUNCTION_ARGS)
Definition: bool.c:188
Datum boolout(PG_FUNCTION_ARGS)
Definition: bool.c:158
Datum booland_statefunc(PG_FUNCTION_ARGS)
Definition: bool.c:300
Datum bool_alltrue(PG_FUNCTION_ARGS)
Definition: bool.c:383
Datum booltext(PG_FUNCTION_ARGS)
Definition: bool.c:205
Datum booleq(PG_FUNCTION_ARGS)
Definition: bool.c:224
Datum bool_accum_inv(PG_FUNCTION_ARGS)
Definition: bool.c:362
Datum boolne(PG_FUNCTION_ARGS)
Definition: bool.c:233
Datum bool_anytrue(PG_FUNCTION_ARGS)
Definition: bool.c:398
Datum bool_accum(PG_FUNCTION_ARGS)
Definition: bool.c:341
bool parse_bool_with_len(const char *value, size_t len, bool *result)
Definition: bool.c:37
struct BoolAggState BoolAggState
signed int int32
Definition: c.h:494
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
const char * str
static struct @157 value
int b
Definition: isn.c:70
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void * palloc(Size size)
Definition: mcxt.c:1317
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4511
const void size_t len
static char * buf
Definition: pg_test_fsync.c:73
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
uintptr_t Datum
Definition: postgres.h:64
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:399
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:160
StringInfoData * StringInfo
Definition: stringinfo.h:54
int64 aggcount
Definition: bool.c:319
int64 aggtrue
Definition: bool.c:320
Definition: regguts.h:323
text * cstring_to_text(const char *s)
Definition: varlena.c:184