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