]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/bool.c
Fix initialization of fake LSN for unlogged relations
[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-2019, 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 %s: \"%s\"",
154                                         "boolean", in_str)));
155
156         /* not reached */
157         PG_RETURN_BOOL(false);
158 }
159
160 /*
161  *              boolout                 - converts 1 or 0 to "t" or "f"
162  */
163 Datum
164 boolout(PG_FUNCTION_ARGS)
165 {
166         bool            b = PG_GETARG_BOOL(0);
167         char       *result = (char *) palloc(2);
168
169         result[0] = (b) ? 't' : 'f';
170         result[1] = '\0';
171         PG_RETURN_CSTRING(result);
172 }
173
174 /*
175  *              boolrecv                        - converts external binary format to bool
176  *
177  * The external representation is one byte.  Any nonzero value is taken
178  * as "true".
179  */
180 Datum
181 boolrecv(PG_FUNCTION_ARGS)
182 {
183         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
184         int                     ext;
185
186         ext = pq_getmsgbyte(buf);
187         PG_RETURN_BOOL((ext != 0) ? true : false);
188 }
189
190 /*
191  *              boolsend                        - converts bool to binary format
192  */
193 Datum
194 boolsend(PG_FUNCTION_ARGS)
195 {
196         bool            arg1 = PG_GETARG_BOOL(0);
197         StringInfoData buf;
198
199         pq_begintypsend(&buf);
200         pq_sendbyte(&buf, arg1 ? 1 : 0);
201         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
202 }
203
204 /*
205  *              booltext                        - cast function for bool => text
206  *
207  * We need this because it's different from the behavior of boolout();
208  * this function follows the SQL-spec result (except for producing lower case)
209  */
210 Datum
211 booltext(PG_FUNCTION_ARGS)
212 {
213         bool            arg1 = PG_GETARG_BOOL(0);
214         const char *str;
215
216         if (arg1)
217                 str = "true";
218         else
219                 str = "false";
220
221         PG_RETURN_TEXT_P(cstring_to_text(str));
222 }
223
224
225 /*****************************************************************************
226  *       PUBLIC ROUTINES                                                                                                                 *
227  *****************************************************************************/
228
229 Datum
230 booleq(PG_FUNCTION_ARGS)
231 {
232         bool            arg1 = PG_GETARG_BOOL(0);
233         bool            arg2 = PG_GETARG_BOOL(1);
234
235         PG_RETURN_BOOL(arg1 == arg2);
236 }
237
238 Datum
239 boolne(PG_FUNCTION_ARGS)
240 {
241         bool            arg1 = PG_GETARG_BOOL(0);
242         bool            arg2 = PG_GETARG_BOOL(1);
243
244         PG_RETURN_BOOL(arg1 != arg2);
245 }
246
247 Datum
248 boollt(PG_FUNCTION_ARGS)
249 {
250         bool            arg1 = PG_GETARG_BOOL(0);
251         bool            arg2 = PG_GETARG_BOOL(1);
252
253         PG_RETURN_BOOL(arg1 < arg2);
254 }
255
256 Datum
257 boolgt(PG_FUNCTION_ARGS)
258 {
259         bool            arg1 = PG_GETARG_BOOL(0);
260         bool            arg2 = PG_GETARG_BOOL(1);
261
262         PG_RETURN_BOOL(arg1 > arg2);
263 }
264
265 Datum
266 boolle(PG_FUNCTION_ARGS)
267 {
268         bool            arg1 = PG_GETARG_BOOL(0);
269         bool            arg2 = PG_GETARG_BOOL(1);
270
271         PG_RETURN_BOOL(arg1 <= arg2);
272 }
273
274 Datum
275 boolge(PG_FUNCTION_ARGS)
276 {
277         bool            arg1 = PG_GETARG_BOOL(0);
278         bool            arg2 = PG_GETARG_BOOL(1);
279
280         PG_RETURN_BOOL(arg1 >= arg2);
281 }
282
283 /*
284  * boolean-and and boolean-or aggregates.
285  */
286
287 /*
288  * Function for standard EVERY aggregate conforming to SQL 2003.
289  * The aggregate is also named bool_and for consistency.
290  *
291  * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
292  */
293 Datum
294 booland_statefunc(PG_FUNCTION_ARGS)
295 {
296         PG_RETURN_BOOL(PG_GETARG_BOOL(0) && PG_GETARG_BOOL(1));
297 }
298
299 /*
300  * Function for standard ANY/SOME aggregate conforming to SQL 2003.
301  * The aggregate is named bool_or, because ANY/SOME have parsing conflicts.
302  *
303  * Note: this is only used in plain aggregate mode, not moving-aggregate mode.
304  */
305 Datum
306 boolor_statefunc(PG_FUNCTION_ARGS)
307 {
308         PG_RETURN_BOOL(PG_GETARG_BOOL(0) || PG_GETARG_BOOL(1));
309 }
310
311 typedef struct BoolAggState
312 {
313         int64           aggcount;               /* number of non-null values aggregated */
314         int64           aggtrue;                /* number of values aggregated that are true */
315 } BoolAggState;
316
317 static BoolAggState *
318 makeBoolAggState(FunctionCallInfo fcinfo)
319 {
320         BoolAggState *state;
321         MemoryContext agg_context;
322
323         if (!AggCheckCallContext(fcinfo, &agg_context))
324                 elog(ERROR, "aggregate function called in non-aggregate context");
325
326         state = (BoolAggState *) MemoryContextAlloc(agg_context,
327                                                                                                 sizeof(BoolAggState));
328         state->aggcount = 0;
329         state->aggtrue = 0;
330
331         return state;
332 }
333
334 Datum
335 bool_accum(PG_FUNCTION_ARGS)
336 {
337         BoolAggState *state;
338
339         state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
340
341         /* Create the state data on first call */
342         if (state == NULL)
343                 state = makeBoolAggState(fcinfo);
344
345         if (!PG_ARGISNULL(1))
346         {
347                 state->aggcount++;
348                 if (PG_GETARG_BOOL(1))
349                         state->aggtrue++;
350         }
351
352         PG_RETURN_POINTER(state);
353 }
354
355 Datum
356 bool_accum_inv(PG_FUNCTION_ARGS)
357 {
358         BoolAggState *state;
359
360         state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
361
362         /* bool_accum should have created the state data */
363         if (state == NULL)
364                 elog(ERROR, "bool_accum_inv called with NULL state");
365
366         if (!PG_ARGISNULL(1))
367         {
368                 state->aggcount--;
369                 if (PG_GETARG_BOOL(1))
370                         state->aggtrue--;
371         }
372
373         PG_RETURN_POINTER(state);
374 }
375
376 Datum
377 bool_alltrue(PG_FUNCTION_ARGS)
378 {
379         BoolAggState *state;
380
381         state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
382
383         /* if there were no non-null values, return NULL */
384         if (state == NULL || state->aggcount == 0)
385                 PG_RETURN_NULL();
386
387         /* true if all non-null values are true */
388         PG_RETURN_BOOL(state->aggtrue == state->aggcount);
389 }
390
391 Datum
392 bool_anytrue(PG_FUNCTION_ARGS)
393 {
394         BoolAggState *state;
395
396         state = PG_ARGISNULL(0) ? NULL : (BoolAggState *) PG_GETARG_POINTER(0);
397
398         /* if there were no non-null values, return NULL */
399         if (state == NULL || state->aggcount == 0)
400                 PG_RETURN_NULL();
401
402         /* true if any non-null value is true */
403         PG_RETURN_BOOL(state->aggtrue > 0);
404 }