1 /*-------------------------------------------------------------------------
2 *
3 * int.c
4 * Functions for the built-in integer types (except int8).
5 *
6 * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/int.c
12 *
13 *-------------------------------------------------------------------------
14 */
15 /*
16 * OLD COMMENTS
17 * I/O routines:
18 * int2in, int2out, int2recv, int2send
19 * int4in, int4out, int4recv, int4send
20 * int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
21 * Boolean operators:
22 * inteq, intne, intlt, intle, intgt, intge
23 * Arithmetic operators:
24 * intpl, intmi, int4mul, intdiv
25 *
26 * Arithmetic operators:
27 * intmod
28 */
29 #include "postgres.h"
30
31 #include <ctype.h>
32 #include <limits.h>
33 #include <math.h>
34
35 #include "catalog/pg_type.h"
36 #include "common/int.h"
37 #include "funcapi.h"
38 #include "libpq/pqformat.h"
39 #include "nodes/nodeFuncs.h"
40 #include "nodes/supportnodes.h"
41 #include "optimizer/optimizer.h"
42 #include "utils/array.h"
43 #include "utils/builtins.h"
44
45 #define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16))
46
47 typedef struct
48 {
49 int32 current;
50 int32 finish;
51 int32 step;
52 } generate_series_fctx;
53
54
55 /*****************************************************************************
56 * USER I/O ROUTINES *
57 *****************************************************************************/
58
59 /*
60 * int2in - converts "num" to short
61 */
62 Datum
int2in(PG_FUNCTION_ARGS)63 int2in(PG_FUNCTION_ARGS)
64 {
65 char *num = PG_GETARG_CSTRING(0);
66
67 PG_RETURN_INT16(pg_strtoint16(num));
68 }
69
70 /*
71 * int2out - converts short to "num"
72 */
73 Datum
int2out(PG_FUNCTION_ARGS)74 int2out(PG_FUNCTION_ARGS)
75 {
76 int16 arg1 = PG_GETARG_INT16(0);
77 char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
78
79 pg_itoa(arg1, result);
80 PG_RETURN_CSTRING(result);
81 }
82
83 /*
84 * int2recv - converts external binary format to int2
85 */
86 Datum
int2recv(PG_FUNCTION_ARGS)87 int2recv(PG_FUNCTION_ARGS)
88 {
89 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
90
91 PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
92 }
93
94 /*
95 * int2send - converts int2 to binary format
96 */
97 Datum
int2send(PG_FUNCTION_ARGS)98 int2send(PG_FUNCTION_ARGS)
99 {
100 int16 arg1 = PG_GETARG_INT16(0);
101 StringInfoData buf;
102
103 pq_begintypsend(&buf);
104 pq_sendint16(&buf, arg1);
105 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
106 }
107
108 /*
109 * construct int2vector given a raw array of int2s
110 *
111 * If int2s is NULL then caller must fill values[] afterward
112 */
113 int2vector *
buildint2vector(const int16 * int2s,int n)114 buildint2vector(const int16 *int2s, int n)
115 {
116 int2vector *result;
117
118 result = (int2vector *) palloc0(Int2VectorSize(n));
119
120 if (n > 0 && int2s)
121 memcpy(result->values, int2s, n * sizeof(int16));
122
123 /*
124 * Attach standard array header. For historical reasons, we set the index
125 * lower bound to 0 not 1.
126 */
127 SET_VARSIZE(result, Int2VectorSize(n));
128 result->ndim = 1;
129 result->dataoffset = 0; /* never any nulls */
130 result->elemtype = INT2OID;
131 result->dim1 = n;
132 result->lbound1 = 0;
133
134 return result;
135 }
136
137 /*
138 * int2vectorin - converts "num num ..." to internal form
139 */
140 Datum
int2vectorin(PG_FUNCTION_ARGS)141 int2vectorin(PG_FUNCTION_ARGS)
142 {
143 char *intString = PG_GETARG_CSTRING(0);
144 int2vector *result;
145 int n;
146
147 result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
148
149 for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
150 {
151 while (*intString && isspace((unsigned char) *intString))
152 intString++;
153 if (*intString == '\0')
154 break;
155 result->values[n] = pg_atoi(intString, sizeof(int16), ' ');
156 while (*intString && !isspace((unsigned char) *intString))
157 intString++;
158 }
159 while (*intString && isspace((unsigned char) *intString))
160 intString++;
161 if (*intString)
162 ereport(ERROR,
163 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
164 errmsg("int2vector has too many elements")));
165
166 SET_VARSIZE(result, Int2VectorSize(n));
167 result->ndim = 1;
168 result->dataoffset = 0; /* never any nulls */
169 result->elemtype = INT2OID;
170 result->dim1 = n;
171 result->lbound1 = 0;
172
173 PG_RETURN_POINTER(result);
174 }
175
176 /*
177 * int2vectorout - converts internal form to "num num ..."
178 */
179 Datum
int2vectorout(PG_FUNCTION_ARGS)180 int2vectorout(PG_FUNCTION_ARGS)
181 {
182 int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
183 int num,
184 nnums = int2Array->dim1;
185 char *rp;
186 char *result;
187
188 /* assumes sign, 5 digits, ' ' */
189 rp = result = (char *) palloc(nnums * 7 + 1);
190 for (num = 0; num < nnums; num++)
191 {
192 if (num != 0)
193 *rp++ = ' ';
194 pg_itoa(int2Array->values[num], rp);
195 while (*++rp != '\0')
196 ;
197 }
198 *rp = '\0';
199 PG_RETURN_CSTRING(result);
200 }
201
202 /*
203 * int2vectorrecv - converts external binary format to int2vector
204 */
205 Datum
int2vectorrecv(PG_FUNCTION_ARGS)206 int2vectorrecv(PG_FUNCTION_ARGS)
207 {
208 LOCAL_FCINFO(locfcinfo, 3);
209 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
210 int2vector *result;
211
212 /*
213 * Normally one would call array_recv() using DirectFunctionCall3, but
214 * that does not work since array_recv wants to cache some data using
215 * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
216 * parameter.
217 */
218 InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
219 InvalidOid, NULL, NULL);
220
221 locfcinfo->args[0].value = PointerGetDatum(buf);
222 locfcinfo->args[0].isnull = false;
223 locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID);
224 locfcinfo->args[1].isnull = false;
225 locfcinfo->args[2].value = Int32GetDatum(-1);
226 locfcinfo->args[2].isnull = false;
227
228 result = (int2vector *) DatumGetPointer(array_recv(locfcinfo));
229
230 Assert(!locfcinfo->isnull);
231
232 /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
233 if (ARR_NDIM(result) != 1 ||
234 ARR_HASNULL(result) ||
235 ARR_ELEMTYPE(result) != INT2OID ||
236 ARR_LBOUND(result)[0] != 0)
237 ereport(ERROR,
238 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
239 errmsg("invalid int2vector data")));
240
241 /* check length for consistency with int2vectorin() */
242 if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
243 ereport(ERROR,
244 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
245 errmsg("oidvector has too many elements")));
246
247 PG_RETURN_POINTER(result);
248 }
249
250 /*
251 * int2vectorsend - converts int2vector to binary format
252 */
253 Datum
int2vectorsend(PG_FUNCTION_ARGS)254 int2vectorsend(PG_FUNCTION_ARGS)
255 {
256 return array_send(fcinfo);
257 }
258
259
260 /*****************************************************************************
261 * PUBLIC ROUTINES *
262 *****************************************************************************/
263
264 /*
265 * int4in - converts "num" to int4
266 */
267 Datum
int4in(PG_FUNCTION_ARGS)268 int4in(PG_FUNCTION_ARGS)
269 {
270 char *num = PG_GETARG_CSTRING(0);
271
272 PG_RETURN_INT32(pg_strtoint32(num));
273 }
274
275 /*
276 * int4out - converts int4 to "num"
277 */
278 Datum
int4out(PG_FUNCTION_ARGS)279 int4out(PG_FUNCTION_ARGS)
280 {
281 int32 arg1 = PG_GETARG_INT32(0);
282 char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
283
284 pg_ltoa(arg1, result);
285 PG_RETURN_CSTRING(result);
286 }
287
288 /*
289 * int4recv - converts external binary format to int4
290 */
291 Datum
int4recv(PG_FUNCTION_ARGS)292 int4recv(PG_FUNCTION_ARGS)
293 {
294 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
295
296 PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
297 }
298
299 /*
300 * int4send - converts int4 to binary format
301 */
302 Datum
int4send(PG_FUNCTION_ARGS)303 int4send(PG_FUNCTION_ARGS)
304 {
305 int32 arg1 = PG_GETARG_INT32(0);
306 StringInfoData buf;
307
308 pq_begintypsend(&buf);
309 pq_sendint32(&buf, arg1);
310 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
311 }
312
313
314 /*
315 * ===================
316 * CONVERSION ROUTINES
317 * ===================
318 */
319
320 Datum
i2toi4(PG_FUNCTION_ARGS)321 i2toi4(PG_FUNCTION_ARGS)
322 {
323 int16 arg1 = PG_GETARG_INT16(0);
324
325 PG_RETURN_INT32((int32) arg1);
326 }
327
328 Datum
i4toi2(PG_FUNCTION_ARGS)329 i4toi2(PG_FUNCTION_ARGS)
330 {
331 int32 arg1 = PG_GETARG_INT32(0);
332
333 if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
334 ereport(ERROR,
335 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
336 errmsg("smallint out of range")));
337
338 PG_RETURN_INT16((int16) arg1);
339 }
340
341 /* Cast int4 -> bool */
342 Datum
int4_bool(PG_FUNCTION_ARGS)343 int4_bool(PG_FUNCTION_ARGS)
344 {
345 if (PG_GETARG_INT32(0) == 0)
346 PG_RETURN_BOOL(false);
347 else
348 PG_RETURN_BOOL(true);
349 }
350
351 /* Cast bool -> int4 */
352 Datum
bool_int4(PG_FUNCTION_ARGS)353 bool_int4(PG_FUNCTION_ARGS)
354 {
355 if (PG_GETARG_BOOL(0) == false)
356 PG_RETURN_INT32(0);
357 else
358 PG_RETURN_INT32(1);
359 }
360
361 /*
362 * ============================
363 * COMPARISON OPERATOR ROUTINES
364 * ============================
365 */
366
367 /*
368 * inteq - returns 1 iff arg1 == arg2
369 * intne - returns 1 iff arg1 != arg2
370 * intlt - returns 1 iff arg1 < arg2
371 * intle - returns 1 iff arg1 <= arg2
372 * intgt - returns 1 iff arg1 > arg2
373 * intge - returns 1 iff arg1 >= arg2
374 */
375
376 Datum
int4eq(PG_FUNCTION_ARGS)377 int4eq(PG_FUNCTION_ARGS)
378 {
379 int32 arg1 = PG_GETARG_INT32(0);
380 int32 arg2 = PG_GETARG_INT32(1);
381
382 PG_RETURN_BOOL(arg1 == arg2);
383 }
384
385 Datum
int4ne(PG_FUNCTION_ARGS)386 int4ne(PG_FUNCTION_ARGS)
387 {
388 int32 arg1 = PG_GETARG_INT32(0);
389 int32 arg2 = PG_GETARG_INT32(1);
390
391 PG_RETURN_BOOL(arg1 != arg2);
392 }
393
394 Datum
int4lt(PG_FUNCTION_ARGS)395 int4lt(PG_FUNCTION_ARGS)
396 {
397 int32 arg1 = PG_GETARG_INT32(0);
398 int32 arg2 = PG_GETARG_INT32(1);
399
400 PG_RETURN_BOOL(arg1 < arg2);
401 }
402
403 Datum
int4le(PG_FUNCTION_ARGS)404 int4le(PG_FUNCTION_ARGS)
405 {
406 int32 arg1 = PG_GETARG_INT32(0);
407 int32 arg2 = PG_GETARG_INT32(1);
408
409 PG_RETURN_BOOL(arg1 <= arg2);
410 }
411
412 Datum
int4gt(PG_FUNCTION_ARGS)413 int4gt(PG_FUNCTION_ARGS)
414 {
415 int32 arg1 = PG_GETARG_INT32(0);
416 int32 arg2 = PG_GETARG_INT32(1);
417
418 PG_RETURN_BOOL(arg1 > arg2);
419 }
420
421 Datum
int4ge(PG_FUNCTION_ARGS)422 int4ge(PG_FUNCTION_ARGS)
423 {
424 int32 arg1 = PG_GETARG_INT32(0);
425 int32 arg2 = PG_GETARG_INT32(1);
426
427 PG_RETURN_BOOL(arg1 >= arg2);
428 }
429
430 Datum
int2eq(PG_FUNCTION_ARGS)431 int2eq(PG_FUNCTION_ARGS)
432 {
433 int16 arg1 = PG_GETARG_INT16(0);
434 int16 arg2 = PG_GETARG_INT16(1);
435
436 PG_RETURN_BOOL(arg1 == arg2);
437 }
438
439 Datum
int2ne(PG_FUNCTION_ARGS)440 int2ne(PG_FUNCTION_ARGS)
441 {
442 int16 arg1 = PG_GETARG_INT16(0);
443 int16 arg2 = PG_GETARG_INT16(1);
444
445 PG_RETURN_BOOL(arg1 != arg2);
446 }
447
448 Datum
int2lt(PG_FUNCTION_ARGS)449 int2lt(PG_FUNCTION_ARGS)
450 {
451 int16 arg1 = PG_GETARG_INT16(0);
452 int16 arg2 = PG_GETARG_INT16(1);
453
454 PG_RETURN_BOOL(arg1 < arg2);
455 }
456
457 Datum
int2le(PG_FUNCTION_ARGS)458 int2le(PG_FUNCTION_ARGS)
459 {
460 int16 arg1 = PG_GETARG_INT16(0);
461 int16 arg2 = PG_GETARG_INT16(1);
462
463 PG_RETURN_BOOL(arg1 <= arg2);
464 }
465
466 Datum
int2gt(PG_FUNCTION_ARGS)467 int2gt(PG_FUNCTION_ARGS)
468 {
469 int16 arg1 = PG_GETARG_INT16(0);
470 int16 arg2 = PG_GETARG_INT16(1);
471
472 PG_RETURN_BOOL(arg1 > arg2);
473 }
474
475 Datum
int2ge(PG_FUNCTION_ARGS)476 int2ge(PG_FUNCTION_ARGS)
477 {
478 int16 arg1 = PG_GETARG_INT16(0);
479 int16 arg2 = PG_GETARG_INT16(1);
480
481 PG_RETURN_BOOL(arg1 >= arg2);
482 }
483
484 Datum
int24eq(PG_FUNCTION_ARGS)485 int24eq(PG_FUNCTION_ARGS)
486 {
487 int16 arg1 = PG_GETARG_INT16(0);
488 int32 arg2 = PG_GETARG_INT32(1);
489
490 PG_RETURN_BOOL(arg1 == arg2);
491 }
492
493 Datum
int24ne(PG_FUNCTION_ARGS)494 int24ne(PG_FUNCTION_ARGS)
495 {
496 int16 arg1 = PG_GETARG_INT16(0);
497 int32 arg2 = PG_GETARG_INT32(1);
498
499 PG_RETURN_BOOL(arg1 != arg2);
500 }
501
502 Datum
int24lt(PG_FUNCTION_ARGS)503 int24lt(PG_FUNCTION_ARGS)
504 {
505 int16 arg1 = PG_GETARG_INT16(0);
506 int32 arg2 = PG_GETARG_INT32(1);
507
508 PG_RETURN_BOOL(arg1 < arg2);
509 }
510
511 Datum
int24le(PG_FUNCTION_ARGS)512 int24le(PG_FUNCTION_ARGS)
513 {
514 int16 arg1 = PG_GETARG_INT16(0);
515 int32 arg2 = PG_GETARG_INT32(1);
516
517 PG_RETURN_BOOL(arg1 <= arg2);
518 }
519
520 Datum
int24gt(PG_FUNCTION_ARGS)521 int24gt(PG_FUNCTION_ARGS)
522 {
523 int16 arg1 = PG_GETARG_INT16(0);
524 int32 arg2 = PG_GETARG_INT32(1);
525
526 PG_RETURN_BOOL(arg1 > arg2);
527 }
528
529 Datum
int24ge(PG_FUNCTION_ARGS)530 int24ge(PG_FUNCTION_ARGS)
531 {
532 int16 arg1 = PG_GETARG_INT16(0);
533 int32 arg2 = PG_GETARG_INT32(1);
534
535 PG_RETURN_BOOL(arg1 >= arg2);
536 }
537
538 Datum
int42eq(PG_FUNCTION_ARGS)539 int42eq(PG_FUNCTION_ARGS)
540 {
541 int32 arg1 = PG_GETARG_INT32(0);
542 int16 arg2 = PG_GETARG_INT16(1);
543
544 PG_RETURN_BOOL(arg1 == arg2);
545 }
546
547 Datum
int42ne(PG_FUNCTION_ARGS)548 int42ne(PG_FUNCTION_ARGS)
549 {
550 int32 arg1 = PG_GETARG_INT32(0);
551 int16 arg2 = PG_GETARG_INT16(1);
552
553 PG_RETURN_BOOL(arg1 != arg2);
554 }
555
556 Datum
int42lt(PG_FUNCTION_ARGS)557 int42lt(PG_FUNCTION_ARGS)
558 {
559 int32 arg1 = PG_GETARG_INT32(0);
560 int16 arg2 = PG_GETARG_INT16(1);
561
562 PG_RETURN_BOOL(arg1 < arg2);
563 }
564
565 Datum
int42le(PG_FUNCTION_ARGS)566 int42le(PG_FUNCTION_ARGS)
567 {
568 int32 arg1 = PG_GETARG_INT32(0);
569 int16 arg2 = PG_GETARG_INT16(1);
570
571 PG_RETURN_BOOL(arg1 <= arg2);
572 }
573
574 Datum
int42gt(PG_FUNCTION_ARGS)575 int42gt(PG_FUNCTION_ARGS)
576 {
577 int32 arg1 = PG_GETARG_INT32(0);
578 int16 arg2 = PG_GETARG_INT16(1);
579
580 PG_RETURN_BOOL(arg1 > arg2);
581 }
582
583 Datum
int42ge(PG_FUNCTION_ARGS)584 int42ge(PG_FUNCTION_ARGS)
585 {
586 int32 arg1 = PG_GETARG_INT32(0);
587 int16 arg2 = PG_GETARG_INT16(1);
588
589 PG_RETURN_BOOL(arg1 >= arg2);
590 }
591
592
593 /*----------------------------------------------------------
594 * in_range functions for int4 and int2,
595 * including cross-data-type comparisons.
596 *
597 * Note: we provide separate intN_int8 functions for performance
598 * reasons. This forces also providing intN_int2, else cases with a
599 * smallint offset value would fail to resolve which function to use.
600 * But that's an unlikely situation, so don't duplicate code for it.
601 *---------------------------------------------------------*/
602
603 Datum
in_range_int4_int4(PG_FUNCTION_ARGS)604 in_range_int4_int4(PG_FUNCTION_ARGS)
605 {
606 int32 val = PG_GETARG_INT32(0);
607 int32 base = PG_GETARG_INT32(1);
608 int32 offset = PG_GETARG_INT32(2);
609 bool sub = PG_GETARG_BOOL(3);
610 bool less = PG_GETARG_BOOL(4);
611 int32 sum;
612
613 if (offset < 0)
614 ereport(ERROR,
615 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
616 errmsg("invalid preceding or following size in window function")));
617
618 if (sub)
619 offset = -offset; /* cannot overflow */
620
621 if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
622 {
623 /*
624 * If sub is false, the true sum is surely more than val, so correct
625 * answer is the same as "less". If sub is true, the true sum is
626 * surely less than val, so the answer is "!less".
627 */
628 PG_RETURN_BOOL(sub ? !less : less);
629 }
630
631 if (less)
632 PG_RETURN_BOOL(val <= sum);
633 else
634 PG_RETURN_BOOL(val >= sum);
635 }
636
637 Datum
in_range_int4_int2(PG_FUNCTION_ARGS)638 in_range_int4_int2(PG_FUNCTION_ARGS)
639 {
640 /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
641 return DirectFunctionCall5(in_range_int4_int4,
642 PG_GETARG_DATUM(0),
643 PG_GETARG_DATUM(1),
644 Int32GetDatum((int32) PG_GETARG_INT16(2)),
645 PG_GETARG_DATUM(3),
646 PG_GETARG_DATUM(4));
647 }
648
649 Datum
in_range_int4_int8(PG_FUNCTION_ARGS)650 in_range_int4_int8(PG_FUNCTION_ARGS)
651 {
652 /* We must do all the math in int64 */
653 int64 val = (int64) PG_GETARG_INT32(0);
654 int64 base = (int64) PG_GETARG_INT32(1);
655 int64 offset = PG_GETARG_INT64(2);
656 bool sub = PG_GETARG_BOOL(3);
657 bool less = PG_GETARG_BOOL(4);
658 int64 sum;
659
660 if (offset < 0)
661 ereport(ERROR,
662 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
663 errmsg("invalid preceding or following size in window function")));
664
665 if (sub)
666 offset = -offset; /* cannot overflow */
667
668 if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
669 {
670 /*
671 * If sub is false, the true sum is surely more than val, so correct
672 * answer is the same as "less". If sub is true, the true sum is
673 * surely less than val, so the answer is "!less".
674 */
675 PG_RETURN_BOOL(sub ? !less : less);
676 }
677
678 if (less)
679 PG_RETURN_BOOL(val <= sum);
680 else
681 PG_RETURN_BOOL(val >= sum);
682 }
683
684 Datum
in_range_int2_int4(PG_FUNCTION_ARGS)685 in_range_int2_int4(PG_FUNCTION_ARGS)
686 {
687 /* We must do all the math in int32 */
688 int32 val = (int32) PG_GETARG_INT16(0);
689 int32 base = (int32) PG_GETARG_INT16(1);
690 int32 offset = PG_GETARG_INT32(2);
691 bool sub = PG_GETARG_BOOL(3);
692 bool less = PG_GETARG_BOOL(4);
693 int32 sum;
694
695 if (offset < 0)
696 ereport(ERROR,
697 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
698 errmsg("invalid preceding or following size in window function")));
699
700 if (sub)
701 offset = -offset; /* cannot overflow */
702
703 if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
704 {
705 /*
706 * If sub is false, the true sum is surely more than val, so correct
707 * answer is the same as "less". If sub is true, the true sum is
708 * surely less than val, so the answer is "!less".
709 */
710 PG_RETURN_BOOL(sub ? !less : less);
711 }
712
713 if (less)
714 PG_RETURN_BOOL(val <= sum);
715 else
716 PG_RETURN_BOOL(val >= sum);
717 }
718
719 Datum
in_range_int2_int2(PG_FUNCTION_ARGS)720 in_range_int2_int2(PG_FUNCTION_ARGS)
721 {
722 /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
723 return DirectFunctionCall5(in_range_int2_int4,
724 PG_GETARG_DATUM(0),
725 PG_GETARG_DATUM(1),
726 Int32GetDatum((int32) PG_GETARG_INT16(2)),
727 PG_GETARG_DATUM(3),
728 PG_GETARG_DATUM(4));
729 }
730
731 Datum
in_range_int2_int8(PG_FUNCTION_ARGS)732 in_range_int2_int8(PG_FUNCTION_ARGS)
733 {
734 /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
735 return DirectFunctionCall5(in_range_int4_int8,
736 Int32GetDatum((int32) PG_GETARG_INT16(0)),
737 Int32GetDatum((int32) PG_GETARG_INT16(1)),
738 PG_GETARG_DATUM(2),
739 PG_GETARG_DATUM(3),
740 PG_GETARG_DATUM(4));
741 }
742
743
744 /*
745 * int[24]pl - returns arg1 + arg2
746 * int[24]mi - returns arg1 - arg2
747 * int[24]mul - returns arg1 * arg2
748 * int[24]div - returns arg1 / arg2
749 */
750
751 Datum
int4um(PG_FUNCTION_ARGS)752 int4um(PG_FUNCTION_ARGS)
753 {
754 int32 arg = PG_GETARG_INT32(0);
755
756 if (unlikely(arg == PG_INT32_MIN))
757 ereport(ERROR,
758 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
759 errmsg("integer out of range")));
760 PG_RETURN_INT32(-arg);
761 }
762
763 Datum
int4up(PG_FUNCTION_ARGS)764 int4up(PG_FUNCTION_ARGS)
765 {
766 int32 arg = PG_GETARG_INT32(0);
767
768 PG_RETURN_INT32(arg);
769 }
770
771 Datum
int4pl(PG_FUNCTION_ARGS)772 int4pl(PG_FUNCTION_ARGS)
773 {
774 int32 arg1 = PG_GETARG_INT32(0);
775 int32 arg2 = PG_GETARG_INT32(1);
776 int32 result;
777
778 if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
779 ereport(ERROR,
780 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
781 errmsg("integer out of range")));
782 PG_RETURN_INT32(result);
783 }
784
785 Datum
int4mi(PG_FUNCTION_ARGS)786 int4mi(PG_FUNCTION_ARGS)
787 {
788 int32 arg1 = PG_GETARG_INT32(0);
789 int32 arg2 = PG_GETARG_INT32(1);
790 int32 result;
791
792 if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
793 ereport(ERROR,
794 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
795 errmsg("integer out of range")));
796 PG_RETURN_INT32(result);
797 }
798
799 Datum
int4mul(PG_FUNCTION_ARGS)800 int4mul(PG_FUNCTION_ARGS)
801 {
802 int32 arg1 = PG_GETARG_INT32(0);
803 int32 arg2 = PG_GETARG_INT32(1);
804 int32 result;
805
806 if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
807 ereport(ERROR,
808 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
809 errmsg("integer out of range")));
810 PG_RETURN_INT32(result);
811 }
812
813 Datum
int4div(PG_FUNCTION_ARGS)814 int4div(PG_FUNCTION_ARGS)
815 {
816 int32 arg1 = PG_GETARG_INT32(0);
817 int32 arg2 = PG_GETARG_INT32(1);
818 int32 result;
819
820 if (arg2 == 0)
821 {
822 ereport(ERROR,
823 (errcode(ERRCODE_DIVISION_BY_ZERO),
824 errmsg("division by zero")));
825 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
826 PG_RETURN_NULL();
827 }
828
829 /*
830 * INT_MIN / -1 is problematic, since the result can't be represented on a
831 * two's-complement machine. Some machines produce INT_MIN, some produce
832 * zero, some throw an exception. We can dodge the problem by recognizing
833 * that division by -1 is the same as negation.
834 */
835 if (arg2 == -1)
836 {
837 if (unlikely(arg1 == PG_INT32_MIN))
838 ereport(ERROR,
839 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
840 errmsg("integer out of range")));
841 result = -arg1;
842 PG_RETURN_INT32(result);
843 }
844
845 /* No overflow is possible */
846
847 result = arg1 / arg2;
848
849 PG_RETURN_INT32(result);
850 }
851
852 Datum
int4inc(PG_FUNCTION_ARGS)853 int4inc(PG_FUNCTION_ARGS)
854 {
855 int32 arg = PG_GETARG_INT32(0);
856 int32 result;
857
858 if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
859 ereport(ERROR,
860 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
861 errmsg("integer out of range")));
862
863 PG_RETURN_INT32(result);
864 }
865
866 Datum
int2um(PG_FUNCTION_ARGS)867 int2um(PG_FUNCTION_ARGS)
868 {
869 int16 arg = PG_GETARG_INT16(0);
870
871 if (unlikely(arg == PG_INT16_MIN))
872 ereport(ERROR,
873 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
874 errmsg("smallint out of range")));
875 PG_RETURN_INT16(-arg);
876 }
877
878 Datum
int2up(PG_FUNCTION_ARGS)879 int2up(PG_FUNCTION_ARGS)
880 {
881 int16 arg = PG_GETARG_INT16(0);
882
883 PG_RETURN_INT16(arg);
884 }
885
886 Datum
int2pl(PG_FUNCTION_ARGS)887 int2pl(PG_FUNCTION_ARGS)
888 {
889 int16 arg1 = PG_GETARG_INT16(0);
890 int16 arg2 = PG_GETARG_INT16(1);
891 int16 result;
892
893 if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
894 ereport(ERROR,
895 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
896 errmsg("smallint out of range")));
897 PG_RETURN_INT16(result);
898 }
899
900 Datum
int2mi(PG_FUNCTION_ARGS)901 int2mi(PG_FUNCTION_ARGS)
902 {
903 int16 arg1 = PG_GETARG_INT16(0);
904 int16 arg2 = PG_GETARG_INT16(1);
905 int16 result;
906
907 if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
908 ereport(ERROR,
909 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
910 errmsg("smallint out of range")));
911 PG_RETURN_INT16(result);
912 }
913
914 Datum
int2mul(PG_FUNCTION_ARGS)915 int2mul(PG_FUNCTION_ARGS)
916 {
917 int16 arg1 = PG_GETARG_INT16(0);
918 int16 arg2 = PG_GETARG_INT16(1);
919 int16 result;
920
921 if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
922 ereport(ERROR,
923 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
924 errmsg("smallint out of range")));
925
926 PG_RETURN_INT16(result);
927 }
928
929 Datum
int2div(PG_FUNCTION_ARGS)930 int2div(PG_FUNCTION_ARGS)
931 {
932 int16 arg1 = PG_GETARG_INT16(0);
933 int16 arg2 = PG_GETARG_INT16(1);
934 int16 result;
935
936 if (arg2 == 0)
937 {
938 ereport(ERROR,
939 (errcode(ERRCODE_DIVISION_BY_ZERO),
940 errmsg("division by zero")));
941 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
942 PG_RETURN_NULL();
943 }
944
945 /*
946 * SHRT_MIN / -1 is problematic, since the result can't be represented on
947 * a two's-complement machine. Some machines produce SHRT_MIN, some
948 * produce zero, some throw an exception. We can dodge the problem by
949 * recognizing that division by -1 is the same as negation.
950 */
951 if (arg2 == -1)
952 {
953 if (unlikely(arg1 == PG_INT16_MIN))
954 ereport(ERROR,
955 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
956 errmsg("smallint out of range")));
957 result = -arg1;
958 PG_RETURN_INT16(result);
959 }
960
961 /* No overflow is possible */
962
963 result = arg1 / arg2;
964
965 PG_RETURN_INT16(result);
966 }
967
968 Datum
int24pl(PG_FUNCTION_ARGS)969 int24pl(PG_FUNCTION_ARGS)
970 {
971 int16 arg1 = PG_GETARG_INT16(0);
972 int32 arg2 = PG_GETARG_INT32(1);
973 int32 result;
974
975 if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
976 ereport(ERROR,
977 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
978 errmsg("integer out of range")));
979 PG_RETURN_INT32(result);
980 }
981
982 Datum
int24mi(PG_FUNCTION_ARGS)983 int24mi(PG_FUNCTION_ARGS)
984 {
985 int16 arg1 = PG_GETARG_INT16(0);
986 int32 arg2 = PG_GETARG_INT32(1);
987 int32 result;
988
989 if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
990 ereport(ERROR,
991 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
992 errmsg("integer out of range")));
993 PG_RETURN_INT32(result);
994 }
995
996 Datum
int24mul(PG_FUNCTION_ARGS)997 int24mul(PG_FUNCTION_ARGS)
998 {
999 int16 arg1 = PG_GETARG_INT16(0);
1000 int32 arg2 = PG_GETARG_INT32(1);
1001 int32 result;
1002
1003 if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
1004 ereport(ERROR,
1005 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1006 errmsg("integer out of range")));
1007 PG_RETURN_INT32(result);
1008 }
1009
1010 Datum
int24div(PG_FUNCTION_ARGS)1011 int24div(PG_FUNCTION_ARGS)
1012 {
1013 int16 arg1 = PG_GETARG_INT16(0);
1014 int32 arg2 = PG_GETARG_INT32(1);
1015
1016 if (unlikely(arg2 == 0))
1017 {
1018 ereport(ERROR,
1019 (errcode(ERRCODE_DIVISION_BY_ZERO),
1020 errmsg("division by zero")));
1021 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1022 PG_RETURN_NULL();
1023 }
1024
1025 /* No overflow is possible */
1026 PG_RETURN_INT32((int32) arg1 / arg2);
1027 }
1028
1029 Datum
int42pl(PG_FUNCTION_ARGS)1030 int42pl(PG_FUNCTION_ARGS)
1031 {
1032 int32 arg1 = PG_GETARG_INT32(0);
1033 int16 arg2 = PG_GETARG_INT16(1);
1034 int32 result;
1035
1036 if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
1037 ereport(ERROR,
1038 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1039 errmsg("integer out of range")));
1040 PG_RETURN_INT32(result);
1041 }
1042
1043 Datum
int42mi(PG_FUNCTION_ARGS)1044 int42mi(PG_FUNCTION_ARGS)
1045 {
1046 int32 arg1 = PG_GETARG_INT32(0);
1047 int16 arg2 = PG_GETARG_INT16(1);
1048 int32 result;
1049
1050 if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
1051 ereport(ERROR,
1052 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1053 errmsg("integer out of range")));
1054 PG_RETURN_INT32(result);
1055 }
1056
1057 Datum
int42mul(PG_FUNCTION_ARGS)1058 int42mul(PG_FUNCTION_ARGS)
1059 {
1060 int32 arg1 = PG_GETARG_INT32(0);
1061 int16 arg2 = PG_GETARG_INT16(1);
1062 int32 result;
1063
1064 if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
1065 ereport(ERROR,
1066 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1067 errmsg("integer out of range")));
1068 PG_RETURN_INT32(result);
1069 }
1070
1071 Datum
int42div(PG_FUNCTION_ARGS)1072 int42div(PG_FUNCTION_ARGS)
1073 {
1074 int32 arg1 = PG_GETARG_INT32(0);
1075 int16 arg2 = PG_GETARG_INT16(1);
1076 int32 result;
1077
1078 if (unlikely(arg2 == 0))
1079 {
1080 ereport(ERROR,
1081 (errcode(ERRCODE_DIVISION_BY_ZERO),
1082 errmsg("division by zero")));
1083 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1084 PG_RETURN_NULL();
1085 }
1086
1087 /*
1088 * INT_MIN / -1 is problematic, since the result can't be represented on a
1089 * two's-complement machine. Some machines produce INT_MIN, some produce
1090 * zero, some throw an exception. We can dodge the problem by recognizing
1091 * that division by -1 is the same as negation.
1092 */
1093 if (arg2 == -1)
1094 {
1095 if (unlikely(arg1 == PG_INT32_MIN))
1096 ereport(ERROR,
1097 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1098 errmsg("integer out of range")));
1099 result = -arg1;
1100 PG_RETURN_INT32(result);
1101 }
1102
1103 /* No overflow is possible */
1104
1105 result = arg1 / arg2;
1106
1107 PG_RETURN_INT32(result);
1108 }
1109
1110 Datum
int4mod(PG_FUNCTION_ARGS)1111 int4mod(PG_FUNCTION_ARGS)
1112 {
1113 int32 arg1 = PG_GETARG_INT32(0);
1114 int32 arg2 = PG_GETARG_INT32(1);
1115
1116 if (unlikely(arg2 == 0))
1117 {
1118 ereport(ERROR,
1119 (errcode(ERRCODE_DIVISION_BY_ZERO),
1120 errmsg("division by zero")));
1121 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1122 PG_RETURN_NULL();
1123 }
1124
1125 /*
1126 * Some machines throw a floating-point exception for INT_MIN % -1, which
1127 * is a bit silly since the correct answer is perfectly well-defined,
1128 * namely zero.
1129 */
1130 if (arg2 == -1)
1131 PG_RETURN_INT32(0);
1132
1133 /* No overflow is possible */
1134
1135 PG_RETURN_INT32(arg1 % arg2);
1136 }
1137
1138 Datum
int2mod(PG_FUNCTION_ARGS)1139 int2mod(PG_FUNCTION_ARGS)
1140 {
1141 int16 arg1 = PG_GETARG_INT16(0);
1142 int16 arg2 = PG_GETARG_INT16(1);
1143
1144 if (unlikely(arg2 == 0))
1145 {
1146 ereport(ERROR,
1147 (errcode(ERRCODE_DIVISION_BY_ZERO),
1148 errmsg("division by zero")));
1149 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1150 PG_RETURN_NULL();
1151 }
1152
1153 /*
1154 * Some machines throw a floating-point exception for INT_MIN % -1, which
1155 * is a bit silly since the correct answer is perfectly well-defined,
1156 * namely zero. (It's not clear this ever happens when dealing with
1157 * int16, but we might as well have the test for safety.)
1158 */
1159 if (arg2 == -1)
1160 PG_RETURN_INT16(0);
1161
1162 /* No overflow is possible */
1163
1164 PG_RETURN_INT16(arg1 % arg2);
1165 }
1166
1167
1168 /* int[24]abs()
1169 * Absolute value
1170 */
1171 Datum
int4abs(PG_FUNCTION_ARGS)1172 int4abs(PG_FUNCTION_ARGS)
1173 {
1174 int32 arg1 = PG_GETARG_INT32(0);
1175 int32 result;
1176
1177 if (unlikely(arg1 == PG_INT32_MIN))
1178 ereport(ERROR,
1179 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1180 errmsg("integer out of range")));
1181 result = (arg1 < 0) ? -arg1 : arg1;
1182 PG_RETURN_INT32(result);
1183 }
1184
1185 Datum
int2abs(PG_FUNCTION_ARGS)1186 int2abs(PG_FUNCTION_ARGS)
1187 {
1188 int16 arg1 = PG_GETARG_INT16(0);
1189 int16 result;
1190
1191 if (unlikely(arg1 == PG_INT16_MIN))
1192 ereport(ERROR,
1193 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1194 errmsg("smallint out of range")));
1195 result = (arg1 < 0) ? -arg1 : arg1;
1196 PG_RETURN_INT16(result);
1197 }
1198
1199 /*
1200 * Greatest Common Divisor
1201 *
1202 * Returns the largest positive integer that exactly divides both inputs.
1203 * Special cases:
1204 * - gcd(x, 0) = gcd(0, x) = abs(x)
1205 * because 0 is divisible by anything
1206 * - gcd(0, 0) = 0
1207 * complies with the previous definition and is a common convention
1208 *
1209 * Special care must be taken if either input is INT_MIN --- gcd(0, INT_MIN),
1210 * gcd(INT_MIN, 0) and gcd(INT_MIN, INT_MIN) are all equal to abs(INT_MIN),
1211 * which cannot be represented as a 32-bit signed integer.
1212 */
1213 static int32
int4gcd_internal(int32 arg1,int32 arg2)1214 int4gcd_internal(int32 arg1, int32 arg2)
1215 {
1216 int32 swap;
1217 int32 a1,
1218 a2;
1219
1220 /*
1221 * Put the greater absolute value in arg1.
1222 *
1223 * This would happen automatically in the loop below, but avoids an
1224 * expensive modulo operation, and simplifies the special-case handling
1225 * for INT_MIN below.
1226 *
1227 * We do this in negative space in order to handle INT_MIN.
1228 */
1229 a1 = (arg1 < 0) ? arg1 : -arg1;
1230 a2 = (arg2 < 0) ? arg2 : -arg2;
1231 if (a1 > a2)
1232 {
1233 swap = arg1;
1234 arg1 = arg2;
1235 arg2 = swap;
1236 }
1237
1238 /* Special care needs to be taken with INT_MIN. See comments above. */
1239 if (arg1 == PG_INT32_MIN)
1240 {
1241 if (arg2 == 0 || arg2 == PG_INT32_MIN)
1242 ereport(ERROR,
1243 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1244 errmsg("integer out of range")));
1245
1246 /*
1247 * Some machines throw a floating-point exception for INT_MIN % -1,
1248 * which is a bit silly since the correct answer is perfectly
1249 * well-defined, namely zero. Guard against this and just return the
1250 * result, gcd(INT_MIN, -1) = 1.
1251 */
1252 if (arg2 == -1)
1253 return 1;
1254 }
1255
1256 /* Use the Euclidean algorithm to find the GCD */
1257 while (arg2 != 0)
1258 {
1259 swap = arg2;
1260 arg2 = arg1 % arg2;
1261 arg1 = swap;
1262 }
1263
1264 /*
1265 * Make sure the result is positive. (We know we don't have INT_MIN
1266 * anymore).
1267 */
1268 if (arg1 < 0)
1269 arg1 = -arg1;
1270
1271 return arg1;
1272 }
1273
1274 Datum
int4gcd(PG_FUNCTION_ARGS)1275 int4gcd(PG_FUNCTION_ARGS)
1276 {
1277 int32 arg1 = PG_GETARG_INT32(0);
1278 int32 arg2 = PG_GETARG_INT32(1);
1279 int32 result;
1280
1281 result = int4gcd_internal(arg1, arg2);
1282
1283 PG_RETURN_INT32(result);
1284 }
1285
1286 /*
1287 * Least Common Multiple
1288 */
1289 Datum
int4lcm(PG_FUNCTION_ARGS)1290 int4lcm(PG_FUNCTION_ARGS)
1291 {
1292 int32 arg1 = PG_GETARG_INT32(0);
1293 int32 arg2 = PG_GETARG_INT32(1);
1294 int32 gcd;
1295 int32 result;
1296
1297 /*
1298 * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case. This prevents a
1299 * division-by-zero error below when x is zero, and an overflow error from
1300 * the GCD computation when x = INT_MIN.
1301 */
1302 if (arg1 == 0 || arg2 == 0)
1303 PG_RETURN_INT32(0);
1304
1305 /* lcm(x, y) = abs(x / gcd(x, y) * y) */
1306 gcd = int4gcd_internal(arg1, arg2);
1307 arg1 = arg1 / gcd;
1308
1309 if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
1310 ereport(ERROR,
1311 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1312 errmsg("integer out of range")));
1313
1314 /* If the result is INT_MIN, it cannot be represented. */
1315 if (unlikely(result == PG_INT32_MIN))
1316 ereport(ERROR,
1317 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1318 errmsg("integer out of range")));
1319
1320 if (result < 0)
1321 result = -result;
1322
1323 PG_RETURN_INT32(result);
1324 }
1325
1326 Datum
int2larger(PG_FUNCTION_ARGS)1327 int2larger(PG_FUNCTION_ARGS)
1328 {
1329 int16 arg1 = PG_GETARG_INT16(0);
1330 int16 arg2 = PG_GETARG_INT16(1);
1331
1332 PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1333 }
1334
1335 Datum
int2smaller(PG_FUNCTION_ARGS)1336 int2smaller(PG_FUNCTION_ARGS)
1337 {
1338 int16 arg1 = PG_GETARG_INT16(0);
1339 int16 arg2 = PG_GETARG_INT16(1);
1340
1341 PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
1342 }
1343
1344 Datum
int4larger(PG_FUNCTION_ARGS)1345 int4larger(PG_FUNCTION_ARGS)
1346 {
1347 int32 arg1 = PG_GETARG_INT32(0);
1348 int32 arg2 = PG_GETARG_INT32(1);
1349
1350 PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1351 }
1352
1353 Datum
int4smaller(PG_FUNCTION_ARGS)1354 int4smaller(PG_FUNCTION_ARGS)
1355 {
1356 int32 arg1 = PG_GETARG_INT32(0);
1357 int32 arg2 = PG_GETARG_INT32(1);
1358
1359 PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1360 }
1361
1362 /*
1363 * Bit-pushing operators
1364 *
1365 * int[24]and - returns arg1 & arg2
1366 * int[24]or - returns arg1 | arg2
1367 * int[24]xor - returns arg1 # arg2
1368 * int[24]not - returns ~arg1
1369 * int[24]shl - returns arg1 << arg2
1370 * int[24]shr - returns arg1 >> arg2
1371 */
1372
1373 Datum
int4and(PG_FUNCTION_ARGS)1374 int4and(PG_FUNCTION_ARGS)
1375 {
1376 int32 arg1 = PG_GETARG_INT32(0);
1377 int32 arg2 = PG_GETARG_INT32(1);
1378
1379 PG_RETURN_INT32(arg1 & arg2);
1380 }
1381
1382 Datum
int4or(PG_FUNCTION_ARGS)1383 int4or(PG_FUNCTION_ARGS)
1384 {
1385 int32 arg1 = PG_GETARG_INT32(0);
1386 int32 arg2 = PG_GETARG_INT32(1);
1387
1388 PG_RETURN_INT32(arg1 | arg2);
1389 }
1390
1391 Datum
int4xor(PG_FUNCTION_ARGS)1392 int4xor(PG_FUNCTION_ARGS)
1393 {
1394 int32 arg1 = PG_GETARG_INT32(0);
1395 int32 arg2 = PG_GETARG_INT32(1);
1396
1397 PG_RETURN_INT32(arg1 ^ arg2);
1398 }
1399
1400 Datum
int4shl(PG_FUNCTION_ARGS)1401 int4shl(PG_FUNCTION_ARGS)
1402 {
1403 int32 arg1 = PG_GETARG_INT32(0);
1404 int32 arg2 = PG_GETARG_INT32(1);
1405
1406 PG_RETURN_INT32(arg1 << arg2);
1407 }
1408
1409 Datum
int4shr(PG_FUNCTION_ARGS)1410 int4shr(PG_FUNCTION_ARGS)
1411 {
1412 int32 arg1 = PG_GETARG_INT32(0);
1413 int32 arg2 = PG_GETARG_INT32(1);
1414
1415 PG_RETURN_INT32(arg1 >> arg2);
1416 }
1417
1418 Datum
int4not(PG_FUNCTION_ARGS)1419 int4not(PG_FUNCTION_ARGS)
1420 {
1421 int32 arg1 = PG_GETARG_INT32(0);
1422
1423 PG_RETURN_INT32(~arg1);
1424 }
1425
1426 Datum
int2and(PG_FUNCTION_ARGS)1427 int2and(PG_FUNCTION_ARGS)
1428 {
1429 int16 arg1 = PG_GETARG_INT16(0);
1430 int16 arg2 = PG_GETARG_INT16(1);
1431
1432 PG_RETURN_INT16(arg1 & arg2);
1433 }
1434
1435 Datum
int2or(PG_FUNCTION_ARGS)1436 int2or(PG_FUNCTION_ARGS)
1437 {
1438 int16 arg1 = PG_GETARG_INT16(0);
1439 int16 arg2 = PG_GETARG_INT16(1);
1440
1441 PG_RETURN_INT16(arg1 | arg2);
1442 }
1443
1444 Datum
int2xor(PG_FUNCTION_ARGS)1445 int2xor(PG_FUNCTION_ARGS)
1446 {
1447 int16 arg1 = PG_GETARG_INT16(0);
1448 int16 arg2 = PG_GETARG_INT16(1);
1449
1450 PG_RETURN_INT16(arg1 ^ arg2);
1451 }
1452
1453 Datum
int2not(PG_FUNCTION_ARGS)1454 int2not(PG_FUNCTION_ARGS)
1455 {
1456 int16 arg1 = PG_GETARG_INT16(0);
1457
1458 PG_RETURN_INT16(~arg1);
1459 }
1460
1461
1462 Datum
int2shl(PG_FUNCTION_ARGS)1463 int2shl(PG_FUNCTION_ARGS)
1464 {
1465 int16 arg1 = PG_GETARG_INT16(0);
1466 int32 arg2 = PG_GETARG_INT32(1);
1467
1468 PG_RETURN_INT16(arg1 << arg2);
1469 }
1470
1471 Datum
int2shr(PG_FUNCTION_ARGS)1472 int2shr(PG_FUNCTION_ARGS)
1473 {
1474 int16 arg1 = PG_GETARG_INT16(0);
1475 int32 arg2 = PG_GETARG_INT32(1);
1476
1477 PG_RETURN_INT16(arg1 >> arg2);
1478 }
1479
1480 /*
1481 * non-persistent numeric series generator
1482 */
1483 Datum
generate_series_int4(PG_FUNCTION_ARGS)1484 generate_series_int4(PG_FUNCTION_ARGS)
1485 {
1486 return generate_series_step_int4(fcinfo);
1487 }
1488
1489 Datum
generate_series_step_int4(PG_FUNCTION_ARGS)1490 generate_series_step_int4(PG_FUNCTION_ARGS)
1491 {
1492 FuncCallContext *funcctx;
1493 generate_series_fctx *fctx;
1494 int32 result;
1495 MemoryContext oldcontext;
1496
1497 /* stuff done only on the first call of the function */
1498 if (SRF_IS_FIRSTCALL())
1499 {
1500 int32 start = PG_GETARG_INT32(0);
1501 int32 finish = PG_GETARG_INT32(1);
1502 int32 step = 1;
1503
1504 /* see if we were given an explicit step size */
1505 if (PG_NARGS() == 3)
1506 step = PG_GETARG_INT32(2);
1507 if (step == 0)
1508 ereport(ERROR,
1509 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1510 errmsg("step size cannot equal zero")));
1511
1512 /* create a function context for cross-call persistence */
1513 funcctx = SRF_FIRSTCALL_INIT();
1514
1515 /*
1516 * switch to memory context appropriate for multiple function calls
1517 */
1518 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1519
1520 /* allocate memory for user context */
1521 fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1522
1523 /*
1524 * Use fctx to keep state from call to call. Seed current with the
1525 * original start value
1526 */
1527 fctx->current = start;
1528 fctx->finish = finish;
1529 fctx->step = step;
1530
1531 funcctx->user_fctx = fctx;
1532 MemoryContextSwitchTo(oldcontext);
1533 }
1534
1535 /* stuff done on every call of the function */
1536 funcctx = SRF_PERCALL_SETUP();
1537
1538 /*
1539 * get the saved state and use current as the result for this iteration
1540 */
1541 fctx = funcctx->user_fctx;
1542 result = fctx->current;
1543
1544 if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1545 (fctx->step < 0 && fctx->current >= fctx->finish))
1546 {
1547 /*
1548 * Increment current in preparation for next iteration. If next-value
1549 * computation overflows, this is the final result.
1550 */
1551 if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
1552 fctx->step = 0;
1553
1554 /* do when there is more left to send */
1555 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1556 }
1557 else
1558 /* do when there is no more left */
1559 SRF_RETURN_DONE(funcctx);
1560 }
1561
1562 /*
1563 * Planner support function for generate_series(int4, int4 [, int4])
1564 */
1565 Datum
generate_series_int4_support(PG_FUNCTION_ARGS)1566 generate_series_int4_support(PG_FUNCTION_ARGS)
1567 {
1568 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1569 Node *ret = NULL;
1570
1571 if (IsA(rawreq, SupportRequestRows))
1572 {
1573 /* Try to estimate the number of rows returned */
1574 SupportRequestRows *req = (SupportRequestRows *) rawreq;
1575
1576 if (is_funcclause(req->node)) /* be paranoid */
1577 {
1578 List *args = ((FuncExpr *) req->node)->args;
1579 Node *arg1,
1580 *arg2,
1581 *arg3;
1582
1583 /* We can use estimated argument values here */
1584 arg1 = estimate_expression_value(req->root, linitial(args));
1585 arg2 = estimate_expression_value(req->root, lsecond(args));
1586 if (list_length(args) >= 3)
1587 arg3 = estimate_expression_value(req->root, lthird(args));
1588 else
1589 arg3 = NULL;
1590
1591 /*
1592 * If any argument is constant NULL, we can safely assume that
1593 * zero rows are returned. Otherwise, if they're all non-NULL
1594 * constants, we can calculate the number of rows that will be
1595 * returned. Use double arithmetic to avoid overflow hazards.
1596 */
1597 if ((IsA(arg1, Const) &&
1598 ((Const *) arg1)->constisnull) ||
1599 (IsA(arg2, Const) &&
1600 ((Const *) arg2)->constisnull) ||
1601 (arg3 != NULL && IsA(arg3, Const) &&
1602 ((Const *) arg3)->constisnull))
1603 {
1604 req->rows = 0;
1605 ret = (Node *) req;
1606 }
1607 else if (IsA(arg1, Const) &&
1608 IsA(arg2, Const) &&
1609 (arg3 == NULL || IsA(arg3, Const)))
1610 {
1611 double start,
1612 finish,
1613 step;
1614
1615 start = DatumGetInt32(((Const *) arg1)->constvalue);
1616 finish = DatumGetInt32(((Const *) arg2)->constvalue);
1617 step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
1618
1619 /* This equation works for either sign of step */
1620 if (step != 0)
1621 {
1622 req->rows = floor((finish - start + step) / step);
1623 ret = (Node *) req;
1624 }
1625 }
1626 }
1627 }
1628
1629 PG_RETURN_POINTER(ret);
1630 }
1631