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