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