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-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 "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
5515 peter_e@gmx.net 30 :CBC 74020 : parse_bool(const char *value, bool *result)
31 : : {
32 : 74020 : return parse_bool_with_len(value, strlen(value), result);
33 : : }
34 : :
35 : : bool
36 : 1472883 : parse_bool_with_len(const char *value, size_t len, bool *result)
37 : : {
38 : : /* Check the most-used possibilities first. */
39 [ + + + + : 1472883 : switch (*value)
+ + + + ]
40 : : {
41 : 179618 : case 't':
42 : : case 'T':
43 [ + + ]: 179618 : if (pg_strncasecmp(value, "true", len) == 0)
44 : : {
45 [ + - ]: 179612 : if (result)
46 : 179612 : *result = true;
47 : 179612 : return true;
48 : : }
49 : 6 : break;
50 : 1239691 : case 'f':
51 : : case 'F':
52 [ + + ]: 1239691 : if (pg_strncasecmp(value, "false", len) == 0)
53 : : {
54 [ + - ]: 1239682 : if (result)
55 : 1239682 : *result = false;
56 : 1239682 : return true;
57 : : }
58 : 9 : break;
59 : 241 : case 'y':
60 : : case 'Y':
61 [ + + ]: 241 : if (pg_strncasecmp(value, "yes", len) == 0)
62 : : {
63 [ + - ]: 238 : if (result)
64 : 238 : *result = true;
65 : 238 : return true;
66 : : }
67 : 3 : break;
68 : 2688 : case 'n':
69 : : case 'N':
70 [ + + ]: 2688 : if (pg_strncasecmp(value, "no", len) == 0)
71 : : {
72 [ + - ]: 2679 : if (result)
73 : 2679 : *result = false;
74 : 2679 : return true;
75 : : }
76 : 9 : break;
77 : 44221 : case 'o':
78 : : case 'O':
79 : : /* 'o' is not unique enough */
80 [ + + ]: 44221 : if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
81 : : {
82 [ + - ]: 33991 : if (result)
83 : 33991 : *result = true;
84 : 33991 : return true;
85 : : }
86 [ + + ]: 10230 : else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
87 : : {
88 [ + - ]: 10221 : if (result)
89 : 10221 : *result = false;
90 : 10221 : return true;
91 : : }
92 : 9 : break;
93 : 3500 : case '1':
94 [ + + ]: 3500 : if (len == 1)
95 : : {
96 [ + - ]: 3476 : if (result)
97 : 3476 : *result = true;
98 : 3476 : return true;
99 : : }
100 : 24 : break;
101 : 2873 : case '0':
102 [ + + ]: 2873 : if (len == 1)
103 : : {
104 [ + - ]: 2870 : if (result)
105 : 2870 : *result = false;
106 : 2870 : return true;
107 : : }
108 : 3 : break;
109 : 51 : default:
110 : 51 : break;
111 : : }
112 : :
113 [ + - ]: 114 : if (result)
5421 bruce@momjian.us 114 : 114 : *result = false; /* suppress compiler warning */
5515 peter_e@gmx.net 115 : 114 : return false;
116 : : }
117 : :
118 : : /*****************************************************************************
119 : : * USER I/O ROUTINES *
120 : : *****************************************************************************/
121 : :
122 : : /*
123 : : * boolin - input function for type boolean
124 : : */
125 : : Datum
8714 tgl@sss.pgh.pa.us 126 : 1398863 : boolin(PG_FUNCTION_ARGS)
127 : : {
5995 bruce@momjian.us 128 : 1398863 : const char *in_str = PG_GETARG_CSTRING(0);
129 : : const char *str;
130 : : size_t len;
131 : : bool result;
132 : :
133 : : /*
134 : : * Skip leading and trailing whitespace
135 : : */
6162 neilc@samurai.com 136 : 1398863 : str = in_str;
137 [ + + ]: 1398905 : while (isspace((unsigned char) *str))
138 : 42 : str++;
139 : :
140 : 1398863 : len = strlen(str);
141 [ + + + + ]: 1398908 : while (len > 0 && isspace((unsigned char) str[len - 1]))
142 : 45 : len--;
143 : :
5515 peter_e@gmx.net 144 [ + + ]: 1398863 : if (parse_bool_with_len(str, len, &result))
145 : 1398797 : PG_RETURN_BOOL(result);
146 : :
492 tgl@sss.pgh.pa.us 147 [ + + ]: 66 : ereturn(fcinfo->context, (Datum) 0,
148 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
149 : : errmsg("invalid input syntax for type %s: \"%s\"",
150 : : "boolean", in_str)));
151 : : }
152 : :
153 : : /*
154 : : * boolout - converts 1 or 0 to "t" or "f"
155 : : */
156 : : Datum
8714 157 : 980063 : boolout(PG_FUNCTION_ARGS)
158 : : {
159 : 980063 : bool b = PG_GETARG_BOOL(0);
9715 bruce@momjian.us 160 : 980063 : char *result = (char *) palloc(2);
161 : :
8714 tgl@sss.pgh.pa.us 162 [ + + ]: 980063 : result[0] = (b) ? 't' : 'f';
9716 bruce@momjian.us 163 : 980063 : result[1] = '\0';
8714 tgl@sss.pgh.pa.us 164 : 980063 : PG_RETURN_CSTRING(result);
165 : : }
166 : :
167 : : /*
168 : : * boolrecv - converts external binary format to bool
169 : : *
170 : : * The external representation is one byte. Any nonzero value is taken
171 : : * as "true".
172 : : */
173 : : Datum
7643 tgl@sss.pgh.pa.us 174 :UBC 0 : boolrecv(PG_FUNCTION_ARGS)
175 : : {
176 : 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
177 : : int ext;
178 : :
179 : 0 : ext = pq_getmsgbyte(buf);
949 michael@paquier.xyz 180 : 0 : PG_RETURN_BOOL(ext != 0);
181 : : }
182 : :
183 : : /*
184 : : * boolsend - converts bool to binary format
185 : : */
186 : : Datum
7643 tgl@sss.pgh.pa.us 187 : 0 : boolsend(PG_FUNCTION_ARGS)
188 : : {
189 : 0 : bool arg1 = PG_GETARG_BOOL(0);
190 : : StringInfoData buf;
191 : :
192 : 0 : pq_begintypsend(&buf);
193 : 0 : pq_sendbyte(&buf, arg1 ? 1 : 0);
194 : 0 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
195 : : }
196 : :
197 : : /*
198 : : * booltext - cast function for bool => text
199 : : *
200 : : * We need this because it's different from the behavior of boolout();
201 : : * this function follows the SQL-spec result (except for producing lower case)
202 : : */
203 : : Datum
6162 neilc@samurai.com 204 :CBC 78 : booltext(PG_FUNCTION_ARGS)
205 : : {
5995 bruce@momjian.us 206 : 78 : bool arg1 = PG_GETARG_BOOL(0);
207 : : const char *str;
208 : :
6162 neilc@samurai.com 209 [ + + ]: 78 : if (arg1)
210 : 33 : str = "true";
211 : : else
212 : 45 : str = "false";
213 : :
5864 tgl@sss.pgh.pa.us 214 : 78 : PG_RETURN_TEXT_P(cstring_to_text(str));
215 : : }
216 : :
217 : :
218 : : /*****************************************************************************
219 : : * PUBLIC ROUTINES *
220 : : *****************************************************************************/
221 : :
222 : : Datum
8714 223 : 150442 : booleq(PG_FUNCTION_ARGS)
224 : : {
225 : 150442 : bool arg1 = PG_GETARG_BOOL(0);
226 : 150442 : bool arg2 = PG_GETARG_BOOL(1);
227 : :
228 : 150442 : PG_RETURN_BOOL(arg1 == arg2);
229 : : }
230 : :
231 : : Datum
232 : 37881 : boolne(PG_FUNCTION_ARGS)
233 : : {
234 : 37881 : bool arg1 = PG_GETARG_BOOL(0);
235 : 37881 : bool arg2 = PG_GETARG_BOOL(1);
236 : :
237 : 37881 : PG_RETURN_BOOL(arg1 != arg2);
238 : : }
239 : :
240 : : Datum
241 : 5 : boollt(PG_FUNCTION_ARGS)
242 : : {
243 : 5 : bool arg1 = PG_GETARG_BOOL(0);
244 : 5 : bool arg2 = PG_GETARG_BOOL(1);
245 : :
246 : 5 : PG_RETURN_BOOL(arg1 < arg2);
247 : : }
248 : :
249 : : Datum
250 : 5 : boolgt(PG_FUNCTION_ARGS)
251 : : {
252 : 5 : bool arg1 = PG_GETARG_BOOL(0);
253 : 5 : bool arg2 = PG_GETARG_BOOL(1);
254 : :
255 : 5 : PG_RETURN_BOOL(arg1 > arg2);
256 : : }
257 : :
258 : : Datum
259 : 8 : boolle(PG_FUNCTION_ARGS)
260 : : {
261 : 8 : bool arg1 = PG_GETARG_BOOL(0);
262 : 8 : bool arg2 = PG_GETARG_BOOL(1);
263 : :
264 : 8 : PG_RETURN_BOOL(arg1 <= arg2);
265 : : }
266 : :
267 : : Datum
268 : 8 : boolge(PG_FUNCTION_ARGS)
269 : : {
270 : 8 : bool arg1 = PG_GETARG_BOOL(0);
271 : 8 : bool arg2 = PG_GETARG_BOOL(1);
272 : :
273 : 8 : PG_RETURN_BOOL(arg1 >= arg2);
274 : : }
275 : :
276 : : /*
277 : : * boolean-and and boolean-or aggregates.
278 : : */
279 : :
280 : : /*
281 : : * Function for standard EVERY aggregate conforming to SQL 2003.
282 : : * The aggregate is also named bool_and for consistency.
283 : : *
284 : : * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
285 : : */
286 : : Datum
7168 bruce@momjian.us 287 : 69 : booland_statefunc(PG_FUNCTION_ARGS)
288 : : {
7263 289 [ + + + + ]: 69 : PG_RETURN_BOOL(PG_GETARG_BOOL(0) && PG_GETARG_BOOL(1));
290 : : }
291 : :
292 : : /*
293 : : * Function for standard ANY/SOME aggregate conforming to SQL 2003.
294 : : * The aggregate is named bool_or, because ANY/SOME have parsing conflicts.
295 : : *
296 : : * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
297 : : */
298 : : Datum
7168 299 : 28 : boolor_statefunc(PG_FUNCTION_ARGS)
300 : : {
7263 301 [ + + + + ]: 28 : PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1));
302 : : }
303 : :
304 : : typedef struct BoolAggState
305 : : {
306 : : int64 aggcount; /* number of non-null values aggregated */
307 : : int64 aggtrue; /* number of values aggregated that are true */
308 : : } BoolAggState;
309 : :
310 : : static BoolAggState *
3654 tgl@sss.pgh.pa.us 311 : 6 : makeBoolAggState(FunctionCallInfo fcinfo)
312 : : {
313 : : BoolAggState *state;
314 : : MemoryContext agg_context;
315 : :
316 [ - + ]: 6 : if (!AggCheckCallContext(fcinfo, &agg_context))
3654 tgl@sss.pgh.pa.us 317 [ # # ]:UBC 0 : elog(ERROR, "aggregate function called in non-aggregate context");
318 : :
3654 tgl@sss.pgh.pa.us 319 :CBC 6 : state = (BoolAggState *) MemoryContextAlloc(agg_context,
320 : : sizeof(BoolAggState));
321 : 6 : state->aggcount = 0;
322 : 6 : state->aggtrue = 0;
323 : :
324 : 6 : return state;
325 : : }
326 : :
327 : : Datum
328 : 30 : bool_accum(PG_FUNCTION_ARGS)
329 : : {
330 : : BoolAggState *state;
331 : :
332 [ + + ]: 30 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
333 : :
334 : : /* Create the state data on first call */
335 [ + + ]: 30 : if (state == NULL)
336 : 6 : state = makeBoolAggState(fcinfo);
337 : :
338 [ + - ]: 30 : if (!PG_ARGISNULL(1))
339 : : {
340 : 30 : state->aggcount++;
341 [ + + ]: 30 : if (PG_GETARG_BOOL(1))
342 : 18 : state->aggtrue++;
343 : : }
344 : :
345 : 30 : PG_RETURN_POINTER(state);
346 : : }
347 : :
348 : : Datum
349 : 24 : bool_accum_inv(PG_FUNCTION_ARGS)
350 : : {
351 : : BoolAggState *state;
352 : :
353 [ + - ]: 24 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
354 : :
355 : : /* bool_accum should have created the state data */
356 [ - + ]: 24 : if (state == NULL)
3654 tgl@sss.pgh.pa.us 357 [ # # ]:UBC 0 : elog(ERROR, "bool_accum_inv called with NULL state");
358 : :
3654 tgl@sss.pgh.pa.us 359 [ + - ]:CBC 24 : if (!PG_ARGISNULL(1))
360 : : {
361 : 24 : state->aggcount--;
362 [ + + ]: 24 : if (PG_GETARG_BOOL(1))
363 : 12 : state->aggtrue--;
364 : : }
365 : :
366 : 24 : PG_RETURN_POINTER(state);
367 : : }
368 : :
369 : : Datum
370 : 15 : bool_alltrue(PG_FUNCTION_ARGS)
371 : : {
372 : : BoolAggState *state;
373 : :
374 [ + - ]: 15 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
375 : :
376 : : /* if there were no non-null values, return NULL */
377 [ + - - + ]: 15 : if (state == NULL || state->aggcount == 0)
3654 tgl@sss.pgh.pa.us 378 :UBC 0 : PG_RETURN_NULL();
379 : :
380 : : /* true if all non-null values are true */
3654 tgl@sss.pgh.pa.us 381 :CBC 15 : PG_RETURN_BOOL(state->aggtrue == state->aggcount);
382 : : }
383 : :
384 : : Datum
385 : 15 : bool_anytrue(PG_FUNCTION_ARGS)
386 : : {
387 : : BoolAggState *state;
388 : :
389 [ + - ]: 15 : state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
390 : :
391 : : /* if there were no non-null values, return NULL */
392 [ + - - + ]: 15 : if (state == NULL || state->aggcount == 0)
3654 tgl@sss.pgh.pa.us 393 :UBC 0 : PG_RETURN_NULL();
394 : :
395 : : /* true if any non-null value is true */
3654 tgl@sss.pgh.pa.us 396 :CBC 15 : PG_RETURN_BOOL(state->aggtrue > 0);
397 : : }
|