Age Owner Branch data TLA Line data Source code
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
6025 peter_e@gmx.net 31 :CBC 81461 : parse_bool(const char *value, bool *result)
32 : : {
33 : 81461 : return parse_bool_with_len(value, strlen(value), result);
34 : : }
35 : :
36 : : bool
37 : 1652096 : parse_bool_with_len(const char *value, size_t len, bool *result)
38 : : {
39 : : /* Check the most-used possibilities first. */
40 [ + + + + : 1652096 : switch (*value)
+ + + + ]
41 : : {
42 : 236649 : case 't':
43 : : case 'T':
44 [ + + ]: 236649 : if (pg_strncasecmp(value, "true", len) == 0)
45 : : {
46 [ + - ]: 236643 : if (result)
47 : 236643 : *result = true;
48 : 236643 : return true;
49 : : }
50 : 6 : break;
51 : 1357211 : case 'f':
52 : : case 'F':
53 [ + + ]: 1357211 : if (pg_strncasecmp(value, "false", len) == 0)
54 : : {
55 [ + - ]: 1357202 : if (result)
56 : 1357202 : *result = false;
57 : 1357202 : return true;
58 : : }
59 : 9 : break;
60 : 1171 : case 'y':
61 : : case 'Y':
62 [ + + ]: 1171 : if (pg_strncasecmp(value, "yes", len) == 0)
63 : : {
64 [ + - ]: 1168 : if (result)
65 : 1168 : *result = true;
66 : 1168 : return true;
67 : : }
68 : 3 : break;
69 : 2182 : case 'n':
70 : : case 'N':
71 [ + + ]: 2182 : if (pg_strncasecmp(value, "no", len) == 0)
72 : : {
73 [ + - ]: 2173 : if (result)
74 : 2173 : *result = false;
75 : 2173 : return true;
76 : : }
77 : 9 : break;
78 : 48411 : case 'o':
79 : : case 'O':
80 : : /* 'o' is not unique enough */
81 [ + + ]: 48411 : if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
82 : : {
83 [ + - ]: 36319 : if (result)
84 : 36319 : *result = true;
85 : 36319 : return true;
86 : : }
87 [ + + ]: 12092 : else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
88 : : {
89 [ + - ]: 12083 : if (result)
90 : 12083 : *result = false;
91 : 12083 : return true;
92 : : }
93 : 9 : break;
94 : 3528 : case '1':
95 [ + + ]: 3528 : if (len == 1)
96 : : {
97 [ + - ]: 3504 : if (result)
98 : 3504 : *result = true;
99 : 3504 : return true;
100 : : }
101 : 24 : break;
102 : 2893 : case '0':
103 [ + + ]: 2893 : if (len == 1)
104 : : {
105 [ + - ]: 2890 : if (result)
106 : 2890 : *result = false;
107 : 2890 : return true;
108 : : }
109 : 3 : break;
110 : 51 : default:
111 : 51 : break;
112 : : }
113 : :
114 [ + - ]: 114 : if (result)
5931 bruce@momjian.us 115 : 114 : *result = false; /* suppress compiler warning */
6025 peter_e@gmx.net 116 : 114 : return false;
117 : : }
118 : :
119 : : /*****************************************************************************
120 : : * USER I/O ROUTINES *
121 : : *****************************************************************************/
122 : :
123 : : /*
124 : : * boolin - input function for type boolean
125 : : */
126 : : Datum
9224 tgl@sss.pgh.pa.us 127 : 1570635 : boolin(PG_FUNCTION_ARGS)
128 : : {
6505 bruce@momjian.us 129 : 1570635 : 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 : : */
6672 neilc@samurai.com 137 : 1570635 : str = in_str;
138 [ + + ]: 1570677 : while (isspace((unsigned char) *str))
139 : 42 : str++;
140 : :
141 : 1570635 : len = strlen(str);
142 [ + + + + ]: 1570680 : while (len > 0 && isspace((unsigned char) str[len - 1]))
143 : 45 : len--;
144 : :
6025 peter_e@gmx.net 145 [ + + ]: 1570635 : if (parse_bool_with_len(str, len, &result))
146 : 1570569 : PG_RETURN_BOOL(result);
147 : :
1002 tgl@sss.pgh.pa.us 148 [ + + ]: 66 : 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
9224 158 : 1431516 : boolout(PG_FUNCTION_ARGS)
159 : : {
160 : 1431516 : bool b = PG_GETARG_BOOL(0);
10225 bruce@momjian.us 161 : 1431516 : char *result = (char *) palloc(2);
162 : :
9224 tgl@sss.pgh.pa.us 163 [ + + ]: 1431516 : result[0] = (b) ? 't' : 'f';
10226 bruce@momjian.us 164 : 1431516 : result[1] = '\0';
9224 tgl@sss.pgh.pa.us 165 : 1431516 : 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
8153 tgl@sss.pgh.pa.us 175 :UBC 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);
1459 michael@paquier.xyz 181 : 0 : PG_RETURN_BOOL(ext != 0);
182 : : }
183 : :
184 : : /*
185 : : * boolsend - converts bool to binary format
186 : : */
187 : : Datum
8153 tgl@sss.pgh.pa.us 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
6672 neilc@samurai.com 205 :CBC 72 : booltext(PG_FUNCTION_ARGS)
206 : : {
6505 bruce@momjian.us 207 : 72 : bool arg1 = PG_GETARG_BOOL(0);
208 : : const char *str;
209 : :
6672 neilc@samurai.com 210 [ + + ]: 72 : if (arg1)
211 : 33 : str = "true";
212 : : else
213 : 39 : str = "false";
214 : :
6374 tgl@sss.pgh.pa.us 215 : 72 : PG_RETURN_TEXT_P(cstring_to_text(str));
216 : : }
217 : :
218 : :
219 : : /*****************************************************************************
220 : : * PUBLIC ROUTINES *
221 : : *****************************************************************************/
222 : :
223 : : Datum
9224 224 : 179340 : booleq(PG_FUNCTION_ARGS)
225 : : {
226 : 179340 : bool arg1 = PG_GETARG_BOOL(0);
227 : 179340 : bool arg2 = PG_GETARG_BOOL(1);
228 : :
229 : 179340 : PG_RETURN_BOOL(arg1 == arg2);
230 : : }
231 : :
232 : : Datum
233 : 39276 : boolne(PG_FUNCTION_ARGS)
234 : : {
235 : 39276 : bool arg1 = PG_GETARG_BOOL(0);
236 : 39276 : bool arg2 = PG_GETARG_BOOL(1);
237 : :
238 : 39276 : PG_RETURN_BOOL(arg1 != arg2);
239 : : }
240 : :
241 : : Datum
242 : 5 : boollt(PG_FUNCTION_ARGS)
243 : : {
244 : 5 : bool arg1 = PG_GETARG_BOOL(0);
245 : 5 : bool arg2 = PG_GETARG_BOOL(1);
246 : :
247 : 5 : PG_RETURN_BOOL(arg1 < arg2);
248 : : }
249 : :
250 : : Datum
251 : 5 : boolgt(PG_FUNCTION_ARGS)
252 : : {
253 : 5 : bool arg1 = PG_GETARG_BOOL(0);
254 : 5 : bool arg2 = PG_GETARG_BOOL(1);
255 : :
256 : 5 : PG_RETURN_BOOL(arg1 > arg2);
257 : : }
258 : :
259 : : Datum
260 : 8 : boolle(PG_FUNCTION_ARGS)
261 : : {
262 : 8 : bool arg1 = PG_GETARG_BOOL(0);
263 : 8 : bool arg2 = PG_GETARG_BOOL(1);
264 : :
265 : 8 : PG_RETURN_BOOL(arg1 <= arg2);
266 : : }
267 : :
268 : : Datum
269 : 8 : boolge(PG_FUNCTION_ARGS)
270 : : {
271 : 8 : bool arg1 = PG_GETARG_BOOL(0);
272 : 8 : bool arg2 = PG_GETARG_BOOL(1);
273 : :
274 : 8 : PG_RETURN_BOOL(arg1 >= arg2);
275 : : }
276 : :
277 : : Datum
359 peter@eisentraut.org 278 : 44806 : hashbool(PG_FUNCTION_ARGS)
279 : : {
280 : 44806 : return hash_uint32((int32) PG_GETARG_BOOL(0));
281 : : }
282 : :
283 : : Datum
359 peter@eisentraut.org 284 :UBC 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
7678 bruce@momjian.us 300 :CBC 12063 : booland_statefunc(PG_FUNCTION_ARGS)
301 : : {
7773 302 [ + + + + ]: 12063 : 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
7678 312 : 27 : boolor_statefunc(PG_FUNCTION_ARGS)
313 : : {
7773 314 [ + + + + ]: 27 : 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 *
4164 tgl@sss.pgh.pa.us 324 : 6 : makeBoolAggState(FunctionCallInfo fcinfo)
325 : : {
326 : : BoolAggState *state;
327 : : MemoryContext agg_context;
328 : :
329 [ - + ]: 6 : if (!AggCheckCallContext(fcinfo, &agg_context))
4164 tgl@sss.pgh.pa.us 330 [ # # ]:UBC 0 : elog(ERROR, "aggregate function called in non-aggregate context");
331 : :
4164 tgl@sss.pgh.pa.us 332 :CBC 6 : state = (BoolAggState *) MemoryContextAlloc(agg_context,
333 : : sizeof(BoolAggState));
334 : 6 : state->aggcount = 0;
335 : 6 : state->aggtrue = 0;
336 : :
337 : 6 : return state;
338 : : }
339 : :
340 : : Datum
341 : 30 : bool_accum(PG_FUNCTION_ARGS)
342 : : {
343 : : BoolAggState *state;
344 : :
345 [ + + ]: 30 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
346 : :
347 : : /* Create the state data on first call */
348 [ + + ]: 30 : if (state == NULL)
349 : 6 : state = makeBoolAggState(fcinfo);
350 : :
351 [ + - ]: 30 : if (!PG_ARGISNULL(1))
352 : : {
353 : 30 : state->aggcount++;
354 [ + + ]: 30 : if (PG_GETARG_BOOL(1))
355 : 18 : state->aggtrue++;
356 : : }
357 : :
358 : 30 : PG_RETURN_POINTER(state);
359 : : }
360 : :
361 : : Datum
362 : 24 : bool_accum_inv(PG_FUNCTION_ARGS)
363 : : {
364 : : BoolAggState *state;
365 : :
366 [ + - ]: 24 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
367 : :
368 : : /* bool_accum should have created the state data */
369 [ - + ]: 24 : if (state == NULL)
4164 tgl@sss.pgh.pa.us 370 [ # # ]:UBC 0 : elog(ERROR, "bool_accum_inv called with NULL state");
371 : :
4164 tgl@sss.pgh.pa.us 372 [ + - ]:CBC 24 : if (!PG_ARGISNULL(1))
373 : : {
374 : 24 : state->aggcount--;
375 [ + + ]: 24 : if (PG_GETARG_BOOL(1))
376 : 12 : state->aggtrue--;
377 : : }
378 : :
379 : 24 : PG_RETURN_POINTER(state);
380 : : }
381 : :
382 : : Datum
383 : 15 : bool_alltrue(PG_FUNCTION_ARGS)
384 : : {
385 : : BoolAggState *state;
386 : :
387 [ + - ]: 15 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
388 : :
389 : : /* if there were no non-null values, return NULL */
390 [ + - - + ]: 15 : if (state == NULL || state->aggcount == 0)
4164 tgl@sss.pgh.pa.us 391 :UBC 0 : PG_RETURN_NULL();
392 : :
393 : : /* true if all non-null values are true */
4164 tgl@sss.pgh.pa.us 394 :CBC 15 : PG_RETURN_BOOL(state->aggtrue == state->aggcount);
395 : : }
396 : :
397 : : Datum
398 : 15 : bool_anytrue(PG_FUNCTION_ARGS)
399 : : {
400 : : BoolAggState *state;
401 : :
402 [ + - ]: 15 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
403 : :
404 : : /* if there were no non-null values, return NULL */
405 [ + - - + ]: 15 : if (state == NULL || state->aggcount == 0)
4164 tgl@sss.pgh.pa.us 406 :UBC 0 : PG_RETURN_NULL();
407 : :
408 : : /* true if any non-null value is true */
4164 tgl@sss.pgh.pa.us 409 :CBC 15 : PG_RETURN_BOOL(state->aggtrue > 0);
410 : : }
|