PostgreSQL Source Code  git master
int.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * int.c
4  * Functions for the built-in integer types (except int8).
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/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 
34 #include "catalog/pg_type.h"
35 #include "common/int.h"
36 #include "funcapi.h"
37 #include "libpq/pqformat.h"
38 #include "utils/array.h"
39 #include "utils/builtins.h"
40 
41 #define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16))
42 
43 typedef struct
44 {
49 
50 
51 /*****************************************************************************
52  * USER I/O ROUTINES *
53  *****************************************************************************/
54 
55 /*
56  * int2in - converts "num" to short
57  */
58 Datum
60 {
61  char *num = PG_GETARG_CSTRING(0);
62 
63  PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
64 }
65 
66 /*
67  * int2out - converts short to "num"
68  */
69 Datum
71 {
72  int16 arg1 = PG_GETARG_INT16(0);
73  char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
74 
75  pg_itoa(arg1, result);
76  PG_RETURN_CSTRING(result);
77 }
78 
79 /*
80  * int2recv - converts external binary format to int2
81  */
82 Datum
84 {
86 
87  PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
88 }
89 
90 /*
91  * int2send - converts int2 to binary format
92  */
93 Datum
95 {
96  int16 arg1 = PG_GETARG_INT16(0);
98 
99  pq_begintypsend(&buf);
100  pq_sendint16(&buf, arg1);
102 }
103 
104 /*
105  * construct int2vector given a raw array of int2s
106  *
107  * If int2s is NULL then caller must fill values[] afterward
108  */
109 int2vector *
110 buildint2vector(const int16 *int2s, int n)
111 {
112  int2vector *result;
113 
114  result = (int2vector *) palloc0(Int2VectorSize(n));
115 
116  if (n > 0 && int2s)
117  memcpy(result->values, int2s, n * sizeof(int16));
118 
119  /*
120  * Attach standard array header. For historical reasons, we set the index
121  * lower bound to 0 not 1.
122  */
123  SET_VARSIZE(result, Int2VectorSize(n));
124  result->ndim = 1;
125  result->dataoffset = 0; /* never any nulls */
126  result->elemtype = INT2OID;
127  result->dim1 = n;
128  result->lbound1 = 0;
129 
130  return result;
131 }
132 
133 /*
134  * int2vectorin - converts "num num ..." to internal form
135  */
136 Datum
138 {
139  char *intString = PG_GETARG_CSTRING(0);
140  int2vector *result;
141  int n;
142 
144 
145  for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
146  {
147  while (*intString && isspace((unsigned char) *intString))
148  intString++;
149  if (*intString == '\0')
150  break;
151  result->values[n] = pg_atoi(intString, sizeof(int16), ' ');
152  while (*intString && !isspace((unsigned char) *intString))
153  intString++;
154  }
155  while (*intString && isspace((unsigned char) *intString))
156  intString++;
157  if (*intString)
158  ereport(ERROR,
159  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
160  errmsg("int2vector has too many elements")));
161 
162  SET_VARSIZE(result, Int2VectorSize(n));
163  result->ndim = 1;
164  result->dataoffset = 0; /* never any nulls */
165  result->elemtype = INT2OID;
166  result->dim1 = n;
167  result->lbound1 = 0;
168 
169  PG_RETURN_POINTER(result);
170 }
171 
172 /*
173  * int2vectorout - converts internal form to "num num ..."
174  */
175 Datum
177 {
178  int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
179  int num,
180  nnums = int2Array->dim1;
181  char *rp;
182  char *result;
183 
184  /* assumes sign, 5 digits, ' ' */
185  rp = result = (char *) palloc(nnums * 7 + 1);
186  for (num = 0; num < nnums; num++)
187  {
188  if (num != 0)
189  *rp++ = ' ';
190  pg_itoa(int2Array->values[num], rp);
191  while (*++rp != '\0')
192  ;
193  }
194  *rp = '\0';
195  PG_RETURN_CSTRING(result);
196 }
197 
198 /*
199  * int2vectorrecv - converts external binary format to int2vector
200  */
201 Datum
203 {
205  FunctionCallInfoData locfcinfo;
206  int2vector *result;
207 
208  /*
209  * Normally one would call array_recv() using DirectFunctionCall3, but
210  * that does not work since array_recv wants to cache some data using
211  * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
212  * parameter.
213  */
214  InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
215  InvalidOid, NULL, NULL);
216 
217  locfcinfo.arg[0] = PointerGetDatum(buf);
218  locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
219  locfcinfo.arg[2] = Int32GetDatum(-1);
220  locfcinfo.argnull[0] = false;
221  locfcinfo.argnull[1] = false;
222  locfcinfo.argnull[2] = false;
223 
224  result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
225 
226  Assert(!locfcinfo.isnull);
227 
228  /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
229  if (ARR_NDIM(result) != 1 ||
230  ARR_HASNULL(result) ||
231  ARR_ELEMTYPE(result) != INT2OID ||
232  ARR_LBOUND(result)[0] != 0)
233  ereport(ERROR,
234  (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
235  errmsg("invalid int2vector data")));
236 
237  /* check length for consistency with int2vectorin() */
238  if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
239  ereport(ERROR,
240  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
241  errmsg("oidvector has too many elements")));
242 
243  PG_RETURN_POINTER(result);
244 }
245 
246 /*
247  * int2vectorsend - converts int2vector to binary format
248  */
249 Datum
251 {
252  return array_send(fcinfo);
253 }
254 
255 
256 /*****************************************************************************
257  * PUBLIC ROUTINES *
258  *****************************************************************************/
259 
260 /*
261  * int4in - converts "num" to int4
262  */
263 Datum
265 {
266  char *num = PG_GETARG_CSTRING(0);
267 
268  PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
269 }
270 
271 /*
272  * int4out - converts int4 to "num"
273  */
274 Datum
276 {
277  int32 arg1 = PG_GETARG_INT32(0);
278  char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
279 
280  pg_ltoa(arg1, result);
281  PG_RETURN_CSTRING(result);
282 }
283 
284 /*
285  * int4recv - converts external binary format to int4
286  */
287 Datum
289 {
291 
292  PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
293 }
294 
295 /*
296  * int4send - converts int4 to binary format
297  */
298 Datum
300 {
301  int32 arg1 = PG_GETARG_INT32(0);
303 
304  pq_begintypsend(&buf);
305  pq_sendint32(&buf, arg1);
307 }
308 
309 
310 /*
311  * ===================
312  * CONVERSION ROUTINES
313  * ===================
314  */
315 
316 Datum
318 {
319  int16 arg1 = PG_GETARG_INT16(0);
320 
321  PG_RETURN_INT32((int32) arg1);
322 }
323 
324 Datum
326 {
327  int32 arg1 = PG_GETARG_INT32(0);
328 
329  if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
330  ereport(ERROR,
331  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
332  errmsg("smallint out of range")));
333 
334  PG_RETURN_INT16((int16) arg1);
335 }
336 
337 /* Cast int4 -> bool */
338 Datum
340 {
341  if (PG_GETARG_INT32(0) == 0)
342  PG_RETURN_BOOL(false);
343  else
344  PG_RETURN_BOOL(true);
345 }
346 
347 /* Cast bool -> int4 */
348 Datum
350 {
351  if (PG_GETARG_BOOL(0) == false)
352  PG_RETURN_INT32(0);
353  else
354  PG_RETURN_INT32(1);
355 }
356 
357 /*
358  * ============================
359  * COMPARISON OPERATOR ROUTINES
360  * ============================
361  */
362 
363 /*
364  * inteq - returns 1 iff arg1 == arg2
365  * intne - returns 1 iff arg1 != arg2
366  * intlt - returns 1 iff arg1 < arg2
367  * intle - returns 1 iff arg1 <= arg2
368  * intgt - returns 1 iff arg1 > arg2
369  * intge - returns 1 iff arg1 >= arg2
370  */
371 
372 Datum
374 {
375  int32 arg1 = PG_GETARG_INT32(0);
376  int32 arg2 = PG_GETARG_INT32(1);
377 
378  PG_RETURN_BOOL(arg1 == arg2);
379 }
380 
381 Datum
383 {
384  int32 arg1 = PG_GETARG_INT32(0);
385  int32 arg2 = PG_GETARG_INT32(1);
386 
387  PG_RETURN_BOOL(arg1 != arg2);
388 }
389 
390 Datum
392 {
393  int32 arg1 = PG_GETARG_INT32(0);
394  int32 arg2 = PG_GETARG_INT32(1);
395 
396  PG_RETURN_BOOL(arg1 < arg2);
397 }
398 
399 Datum
401 {
402  int32 arg1 = PG_GETARG_INT32(0);
403  int32 arg2 = PG_GETARG_INT32(1);
404 
405  PG_RETURN_BOOL(arg1 <= arg2);
406 }
407 
408 Datum
410 {
411  int32 arg1 = PG_GETARG_INT32(0);
412  int32 arg2 = PG_GETARG_INT32(1);
413 
414  PG_RETURN_BOOL(arg1 > arg2);
415 }
416 
417 Datum
419 {
420  int32 arg1 = PG_GETARG_INT32(0);
421  int32 arg2 = PG_GETARG_INT32(1);
422 
423  PG_RETURN_BOOL(arg1 >= arg2);
424 }
425 
426 Datum
428 {
429  int16 arg1 = PG_GETARG_INT16(0);
430  int16 arg2 = PG_GETARG_INT16(1);
431 
432  PG_RETURN_BOOL(arg1 == arg2);
433 }
434 
435 Datum
437 {
438  int16 arg1 = PG_GETARG_INT16(0);
439  int16 arg2 = PG_GETARG_INT16(1);
440 
441  PG_RETURN_BOOL(arg1 != arg2);
442 }
443 
444 Datum
446 {
447  int16 arg1 = PG_GETARG_INT16(0);
448  int16 arg2 = PG_GETARG_INT16(1);
449 
450  PG_RETURN_BOOL(arg1 < arg2);
451 }
452 
453 Datum
455 {
456  int16 arg1 = PG_GETARG_INT16(0);
457  int16 arg2 = PG_GETARG_INT16(1);
458 
459  PG_RETURN_BOOL(arg1 <= arg2);
460 }
461 
462 Datum
464 {
465  int16 arg1 = PG_GETARG_INT16(0);
466  int16 arg2 = PG_GETARG_INT16(1);
467 
468  PG_RETURN_BOOL(arg1 > arg2);
469 }
470 
471 Datum
473 {
474  int16 arg1 = PG_GETARG_INT16(0);
475  int16 arg2 = PG_GETARG_INT16(1);
476 
477  PG_RETURN_BOOL(arg1 >= arg2);
478 }
479 
480 Datum
482 {
483  int16 arg1 = PG_GETARG_INT16(0);
484  int32 arg2 = PG_GETARG_INT32(1);
485 
486  PG_RETURN_BOOL(arg1 == arg2);
487 }
488 
489 Datum
491 {
492  int16 arg1 = PG_GETARG_INT16(0);
493  int32 arg2 = PG_GETARG_INT32(1);
494 
495  PG_RETURN_BOOL(arg1 != arg2);
496 }
497 
498 Datum
500 {
501  int16 arg1 = PG_GETARG_INT16(0);
502  int32 arg2 = PG_GETARG_INT32(1);
503 
504  PG_RETURN_BOOL(arg1 < arg2);
505 }
506 
507 Datum
509 {
510  int16 arg1 = PG_GETARG_INT16(0);
511  int32 arg2 = PG_GETARG_INT32(1);
512 
513  PG_RETURN_BOOL(arg1 <= arg2);
514 }
515 
516 Datum
518 {
519  int16 arg1 = PG_GETARG_INT16(0);
520  int32 arg2 = PG_GETARG_INT32(1);
521 
522  PG_RETURN_BOOL(arg1 > arg2);
523 }
524 
525 Datum
527 {
528  int16 arg1 = PG_GETARG_INT16(0);
529  int32 arg2 = PG_GETARG_INT32(1);
530 
531  PG_RETURN_BOOL(arg1 >= arg2);
532 }
533 
534 Datum
536 {
537  int32 arg1 = PG_GETARG_INT32(0);
538  int16 arg2 = PG_GETARG_INT16(1);
539 
540  PG_RETURN_BOOL(arg1 == arg2);
541 }
542 
543 Datum
545 {
546  int32 arg1 = PG_GETARG_INT32(0);
547  int16 arg2 = PG_GETARG_INT16(1);
548 
549  PG_RETURN_BOOL(arg1 != arg2);
550 }
551 
552 Datum
554 {
555  int32 arg1 = PG_GETARG_INT32(0);
556  int16 arg2 = PG_GETARG_INT16(1);
557 
558  PG_RETURN_BOOL(arg1 < arg2);
559 }
560 
561 Datum
563 {
564  int32 arg1 = PG_GETARG_INT32(0);
565  int16 arg2 = PG_GETARG_INT16(1);
566 
567  PG_RETURN_BOOL(arg1 <= arg2);
568 }
569 
570 Datum
572 {
573  int32 arg1 = PG_GETARG_INT32(0);
574  int16 arg2 = PG_GETARG_INT16(1);
575 
576  PG_RETURN_BOOL(arg1 > arg2);
577 }
578 
579 Datum
581 {
582  int32 arg1 = PG_GETARG_INT32(0);
583  int16 arg2 = PG_GETARG_INT16(1);
584 
585  PG_RETURN_BOOL(arg1 >= arg2);
586 }
587 
588 /*
589  * int[24]pl - returns arg1 + arg2
590  * int[24]mi - returns arg1 - arg2
591  * int[24]mul - returns arg1 * arg2
592  * int[24]div - returns arg1 / arg2
593  */
594 
595 Datum
597 {
599 
600  if (unlikely(arg == PG_INT32_MIN))
601  ereport(ERROR,
602  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
603  errmsg("integer out of range")));
604  PG_RETURN_INT32(-arg);
605 }
606 
607 Datum
609 {
611 
612  PG_RETURN_INT32(arg);
613 }
614 
615 Datum
617 {
618  int32 arg1 = PG_GETARG_INT32(0);
619  int32 arg2 = PG_GETARG_INT32(1);
620  int32 result;
621 
622  if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
623  ereport(ERROR,
624  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
625  errmsg("integer out of range")));
626  PG_RETURN_INT32(result);
627 }
628 
629 Datum
631 {
632  int32 arg1 = PG_GETARG_INT32(0);
633  int32 arg2 = PG_GETARG_INT32(1);
634  int32 result;
635 
636  if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
637  ereport(ERROR,
638  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
639  errmsg("integer out of range")));
640  PG_RETURN_INT32(result);
641 }
642 
643 Datum
645 {
646  int32 arg1 = PG_GETARG_INT32(0);
647  int32 arg2 = PG_GETARG_INT32(1);
648  int32 result;
649 
650  if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
651  ereport(ERROR,
652  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
653  errmsg("integer out of range")));
654  PG_RETURN_INT32(result);
655 }
656 
657 Datum
659 {
660  int32 arg1 = PG_GETARG_INT32(0);
661  int32 arg2 = PG_GETARG_INT32(1);
662  int32 result;
663 
664  if (arg2 == 0)
665  {
666  ereport(ERROR,
667  (errcode(ERRCODE_DIVISION_BY_ZERO),
668  errmsg("division by zero")));
669  /* ensure compiler realizes we mustn't reach the division (gcc bug) */
670  PG_RETURN_NULL();
671  }
672 
673  /*
674  * INT_MIN / -1 is problematic, since the result can't be represented on a
675  * two's-complement machine. Some machines produce INT_MIN, some produce
676  * zero, some throw an exception. We can dodge the problem by recognizing
677  * that division by -1 is the same as negation.
678  */
679  if (arg2 == -1)
680  {
681  if (unlikely(arg1 == PG_INT32_MIN))
682  ereport(ERROR,
683  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
684  errmsg("integer out of range")));
685  result = -arg1;
686  PG_RETURN_INT32(result);
687  }
688 
689  /* No overflow is possible */
690 
691  result = arg1 / arg2;
692 
693  PG_RETURN_INT32(result);
694 }
695 
696 Datum
698 {
700  int32 result;
701 
702  if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
703  ereport(ERROR,
704  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
705  errmsg("integer out of range")));
706 
707  PG_RETURN_INT32(result);
708 }
709 
710 Datum
712 {
714 
715  if (unlikely(arg == PG_INT16_MIN))
716  ereport(ERROR,
717  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
718  errmsg("smallint out of range")));
719  PG_RETURN_INT16(-arg);
720 }
721 
722 Datum
724 {
726 
727  PG_RETURN_INT16(arg);
728 }
729 
730 Datum
732 {
733  int16 arg1 = PG_GETARG_INT16(0);
734  int16 arg2 = PG_GETARG_INT16(1);
735  int16 result;
736 
737  if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
738  ereport(ERROR,
739  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
740  errmsg("smallint out of range")));
741  PG_RETURN_INT16(result);
742 }
743 
744 Datum
746 {
747  int16 arg1 = PG_GETARG_INT16(0);
748  int16 arg2 = PG_GETARG_INT16(1);
749  int16 result;
750 
751  if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
752  ereport(ERROR,
753  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
754  errmsg("smallint out of range")));
755  PG_RETURN_INT16(result);
756 }
757 
758 Datum
760 {
761  int16 arg1 = PG_GETARG_INT16(0);
762  int16 arg2 = PG_GETARG_INT16(1);
763  int16 result;
764 
765  if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
766  ereport(ERROR,
767  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
768  errmsg("smallint out of range")));
769 
770  PG_RETURN_INT16(result);
771 }
772 
773 Datum
775 {
776  int16 arg1 = PG_GETARG_INT16(0);
777  int16 arg2 = PG_GETARG_INT16(1);
778  int16 result;
779 
780  if (arg2 == 0)
781  {
782  ereport(ERROR,
783  (errcode(ERRCODE_DIVISION_BY_ZERO),
784  errmsg("division by zero")));
785  /* ensure compiler realizes we mustn't reach the division (gcc bug) */
786  PG_RETURN_NULL();
787  }
788 
789  /*
790  * SHRT_MIN / -1 is problematic, since the result can't be represented on
791  * a two's-complement machine. Some machines produce SHRT_MIN, some
792  * produce zero, some throw an exception. We can dodge the problem by
793  * recognizing that division by -1 is the same as negation.
794  */
795  if (arg2 == -1)
796  {
797  if (unlikely(arg1 == PG_INT16_MIN))
798  ereport(ERROR,
799  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
800  errmsg("smallint out of range")));
801  result = -arg1;
802  PG_RETURN_INT16(result);
803  }
804 
805  /* No overflow is possible */
806 
807  result = arg1 / arg2;
808 
809  PG_RETURN_INT16(result);
810 }
811 
812 Datum
814 {
815  int16 arg1 = PG_GETARG_INT16(0);
816  int32 arg2 = PG_GETARG_INT32(1);
817  int32 result;
818 
819  if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
820  ereport(ERROR,
821  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
822  errmsg("integer out of range")));
823  PG_RETURN_INT32(result);
824 }
825 
826 Datum
828 {
829  int16 arg1 = PG_GETARG_INT16(0);
830  int32 arg2 = PG_GETARG_INT32(1);
831  int32 result;
832 
833  if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
834  ereport(ERROR,
835  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
836  errmsg("integer out of range")));
837  PG_RETURN_INT32(result);
838 }
839 
840 Datum
842 {
843  int16 arg1 = PG_GETARG_INT16(0);
844  int32 arg2 = PG_GETARG_INT32(1);
845  int32 result;
846 
847  if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
848  ereport(ERROR,
849  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
850  errmsg("integer out of range")));
851  PG_RETURN_INT32(result);
852 }
853 
854 Datum
856 {
857  int16 arg1 = PG_GETARG_INT16(0);
858  int32 arg2 = PG_GETARG_INT32(1);
859 
860  if (unlikely(arg2 == 0))
861  {
862  ereport(ERROR,
863  (errcode(ERRCODE_DIVISION_BY_ZERO),
864  errmsg("division by zero")));
865  /* ensure compiler realizes we mustn't reach the division (gcc bug) */
866  PG_RETURN_NULL();
867  }
868 
869  /* No overflow is possible */
870  PG_RETURN_INT32((int32) arg1 / arg2);
871 }
872 
873 Datum
875 {
876  int32 arg1 = PG_GETARG_INT32(0);
877  int16 arg2 = PG_GETARG_INT16(1);
878  int32 result;
879 
880  if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
881  ereport(ERROR,
882  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
883  errmsg("integer out of range")));
884  PG_RETURN_INT32(result);
885 }
886 
887 Datum
889 {
890  int32 arg1 = PG_GETARG_INT32(0);
891  int16 arg2 = PG_GETARG_INT16(1);
892  int32 result;
893 
894  if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
895  ereport(ERROR,
896  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
897  errmsg("integer out of range")));
898  PG_RETURN_INT32(result);
899 }
900 
901 Datum
903 {
904  int32 arg1 = PG_GETARG_INT32(0);
905  int16 arg2 = PG_GETARG_INT16(1);
906  int32 result;
907 
908  if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
909  ereport(ERROR,
910  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
911  errmsg("integer out of range")));
912  PG_RETURN_INT32(result);
913 }
914 
915 Datum
917 {
918  int32 arg1 = PG_GETARG_INT32(0);
919  int16 arg2 = PG_GETARG_INT16(1);
920  int32 result;
921 
922  if (unlikely(arg2 == 0))
923  {
924  ereport(ERROR,
925  (errcode(ERRCODE_DIVISION_BY_ZERO),
926  errmsg("division by zero")));
927  /* ensure compiler realizes we mustn't reach the division (gcc bug) */
928  PG_RETURN_NULL();
929  }
930 
931  /*
932  * INT_MIN / -1 is problematic, since the result can't be represented on a
933  * two's-complement machine. Some machines produce INT_MIN, some produce
934  * zero, some throw an exception. We can dodge the problem by recognizing
935  * that division by -1 is the same as negation.
936  */
937  if (arg2 == -1)
938  {
939  if (unlikely(arg1 == PG_INT32_MIN))
940  ereport(ERROR,
941  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
942  errmsg("integer out of range")));
943  result = -arg1;
944  PG_RETURN_INT32(result);
945  }
946 
947  /* No overflow is possible */
948 
949  result = arg1 / arg2;
950 
951  PG_RETURN_INT32(result);
952 }
953 
954 Datum
956 {
957  int32 arg1 = PG_GETARG_INT32(0);
958  int32 arg2 = PG_GETARG_INT32(1);
959 
960  if (unlikely(arg2 == 0))
961  {
962  ereport(ERROR,
963  (errcode(ERRCODE_DIVISION_BY_ZERO),
964  errmsg("division by zero")));
965  /* ensure compiler realizes we mustn't reach the division (gcc bug) */
966  PG_RETURN_NULL();
967  }
968 
969  /*
970  * Some machines throw a floating-point exception for INT_MIN % -1, which
971  * is a bit silly since the correct answer is perfectly well-defined,
972  * namely zero.
973  */
974  if (arg2 == -1)
975  PG_RETURN_INT32(0);
976 
977  /* No overflow is possible */
978 
979  PG_RETURN_INT32(arg1 % arg2);
980 }
981 
982 Datum
984 {
985  int16 arg1 = PG_GETARG_INT16(0);
986  int16 arg2 = PG_GETARG_INT16(1);
987 
988  if (unlikely(arg2 == 0))
989  {
990  ereport(ERROR,
991  (errcode(ERRCODE_DIVISION_BY_ZERO),
992  errmsg("division by zero")));
993  /* ensure compiler realizes we mustn't reach the division (gcc bug) */
994  PG_RETURN_NULL();
995  }
996 
997  /*
998  * Some machines throw a floating-point exception for INT_MIN % -1, which
999  * is a bit silly since the correct answer is perfectly well-defined,
1000  * namely zero. (It's not clear this ever happens when dealing with
1001  * int16, but we might as well have the test for safety.)
1002  */
1003  if (arg2 == -1)
1004  PG_RETURN_INT16(0);
1005 
1006  /* No overflow is possible */
1007 
1008  PG_RETURN_INT16(arg1 % arg2);
1009 }
1010 
1011 
1012 /* int[24]abs()
1013  * Absolute value
1014  */
1015 Datum
1017 {
1018  int32 arg1 = PG_GETARG_INT32(0);
1019  int32 result;
1020 
1021  if (unlikely(arg1 == PG_INT32_MIN))
1022  ereport(ERROR,
1023  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1024  errmsg("integer out of range")));
1025  result = (arg1 < 0) ? -arg1 : arg1;
1026  PG_RETURN_INT32(result);
1027 }
1028 
1029 Datum
1031 {
1032  int16 arg1 = PG_GETARG_INT16(0);
1033  int16 result;
1034 
1035  if (unlikely(arg1 == PG_INT16_MIN))
1036  ereport(ERROR,
1037  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1038  errmsg("smallint out of range")));
1039  result = (arg1 < 0) ? -arg1 : arg1;
1040  PG_RETURN_INT16(result);
1041 }
1042 
1043 Datum
1045 {
1046  int16 arg1 = PG_GETARG_INT16(0);
1047  int16 arg2 = PG_GETARG_INT16(1);
1048 
1049  PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1050 }
1051 
1052 Datum
1054 {
1055  int16 arg1 = PG_GETARG_INT16(0);
1056  int16 arg2 = PG_GETARG_INT16(1);
1057 
1058  PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
1059 }
1060 
1061 Datum
1063 {
1064  int32 arg1 = PG_GETARG_INT32(0);
1065  int32 arg2 = PG_GETARG_INT32(1);
1066 
1067  PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1068 }
1069 
1070 Datum
1072 {
1073  int32 arg1 = PG_GETARG_INT32(0);
1074  int32 arg2 = PG_GETARG_INT32(1);
1075 
1076  PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1077 }
1078 
1079 /*
1080  * Bit-pushing operators
1081  *
1082  * int[24]and - returns arg1 & arg2
1083  * int[24]or - returns arg1 | arg2
1084  * int[24]xor - returns arg1 # arg2
1085  * int[24]not - returns ~arg1
1086  * int[24]shl - returns arg1 << arg2
1087  * int[24]shr - returns arg1 >> arg2
1088  */
1089 
1090 Datum
1092 {
1093  int32 arg1 = PG_GETARG_INT32(0);
1094  int32 arg2 = PG_GETARG_INT32(1);
1095 
1096  PG_RETURN_INT32(arg1 & arg2);
1097 }
1098 
1099 Datum
1101 {
1102  int32 arg1 = PG_GETARG_INT32(0);
1103  int32 arg2 = PG_GETARG_INT32(1);
1104 
1105  PG_RETURN_INT32(arg1 | arg2);
1106 }
1107 
1108 Datum
1110 {
1111  int32 arg1 = PG_GETARG_INT32(0);
1112  int32 arg2 = PG_GETARG_INT32(1);
1113 
1114  PG_RETURN_INT32(arg1 ^ arg2);
1115 }
1116 
1117 Datum
1119 {
1120  int32 arg1 = PG_GETARG_INT32(0);
1121  int32 arg2 = PG_GETARG_INT32(1);
1122 
1123  PG_RETURN_INT32(arg1 << arg2);
1124 }
1125 
1126 Datum
1128 {
1129  int32 arg1 = PG_GETARG_INT32(0);
1130  int32 arg2 = PG_GETARG_INT32(1);
1131 
1132  PG_RETURN_INT32(arg1 >> arg2);
1133 }
1134 
1135 Datum
1137 {
1138  int32 arg1 = PG_GETARG_INT32(0);
1139 
1140  PG_RETURN_INT32(~arg1);
1141 }
1142 
1143 Datum
1145 {
1146  int16 arg1 = PG_GETARG_INT16(0);
1147  int16 arg2 = PG_GETARG_INT16(1);
1148 
1149  PG_RETURN_INT16(arg1 & arg2);
1150 }
1151 
1152 Datum
1154 {
1155  int16 arg1 = PG_GETARG_INT16(0);
1156  int16 arg2 = PG_GETARG_INT16(1);
1157 
1158  PG_RETURN_INT16(arg1 | arg2);
1159 }
1160 
1161 Datum
1163 {
1164  int16 arg1 = PG_GETARG_INT16(0);
1165  int16 arg2 = PG_GETARG_INT16(1);
1166 
1167  PG_RETURN_INT16(arg1 ^ arg2);
1168 }
1169 
1170 Datum
1172 {
1173  int16 arg1 = PG_GETARG_INT16(0);
1174 
1175  PG_RETURN_INT16(~arg1);
1176 }
1177 
1178 
1179 Datum
1181 {
1182  int16 arg1 = PG_GETARG_INT16(0);
1183  int32 arg2 = PG_GETARG_INT32(1);
1184 
1185  PG_RETURN_INT16(arg1 << arg2);
1186 }
1187 
1188 Datum
1190 {
1191  int16 arg1 = PG_GETARG_INT16(0);
1192  int32 arg2 = PG_GETARG_INT32(1);
1193 
1194  PG_RETURN_INT16(arg1 >> arg2);
1195 }
1196 
1197 /*
1198  * non-persistent numeric series generator
1199  */
1200 Datum
1202 {
1203  return generate_series_step_int4(fcinfo);
1204 }
1205 
1206 Datum
1208 {
1209  FuncCallContext *funcctx;
1210  generate_series_fctx *fctx;
1211  int32 result;
1212  MemoryContext oldcontext;
1213 
1214  /* stuff done only on the first call of the function */
1215  if (SRF_IS_FIRSTCALL())
1216  {
1217  int32 start = PG_GETARG_INT32(0);
1218  int32 finish = PG_GETARG_INT32(1);
1219  int32 step = 1;
1220 
1221  /* see if we were given an explicit step size */
1222  if (PG_NARGS() == 3)
1223  step = PG_GETARG_INT32(2);
1224  if (step == 0)
1225  ereport(ERROR,
1226  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1227  errmsg("step size cannot equal zero")));
1228 
1229  /* create a function context for cross-call persistence */
1230  funcctx = SRF_FIRSTCALL_INIT();
1231 
1232  /*
1233  * switch to memory context appropriate for multiple function calls
1234  */
1235  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1236 
1237  /* allocate memory for user context */
1238  fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1239 
1240  /*
1241  * Use fctx to keep state from call to call. Seed current with the
1242  * original start value
1243  */
1244  fctx->current = start;
1245  fctx->finish = finish;
1246  fctx->step = step;
1247 
1248  funcctx->user_fctx = fctx;
1249  MemoryContextSwitchTo(oldcontext);
1250  }
1251 
1252  /* stuff done on every call of the function */
1253  funcctx = SRF_PERCALL_SETUP();
1254 
1255  /*
1256  * get the saved state and use current as the result for this iteration
1257  */
1258  fctx = funcctx->user_fctx;
1259  result = fctx->current;
1260 
1261  if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1262  (fctx->step < 0 && fctx->current >= fctx->finish))
1263  {
1264  /*
1265  * Increment current in preparation for next iteration. If next-value
1266  * computation overflows, this is the final result.
1267  */
1268  if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
1269  fctx->step = 0;
1270 
1271  /* do when there is more left to send */
1272  SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1273  }
1274  else
1275  /* do when there is no more left */
1276  SRF_RETURN_DONE(funcctx);
1277 }
Datum int2not(PG_FUNCTION_ARGS)
Definition: int.c:1171
signed short int16
Definition: c.h:293
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
int lbound1
Definition: c.h:532
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
Datum array_send(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:1535
Datum int2shr(PG_FUNCTION_ARGS)
Definition: int.c:1189
Datum int24mi(PG_FUNCTION_ARGS)
Definition: int.c:827
Datum int2mod(PG_FUNCTION_ARGS)
Definition: int.c:983
Datum int2vectorout(PG_FUNCTION_ARGS)
Definition: int.c:176
Datum int4inc(PG_FUNCTION_ARGS)
Definition: int.c:697
Datum int24gt(PG_FUNCTION_ARGS)
Definition: int.c:517
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:129
Datum int42eq(PG_FUNCTION_ARGS)
Definition: int.c:535
Datum int24ge(PG_FUNCTION_ARGS)
Definition: int.c:526
static void pq_sendint32(StringInfo buf, int32 i)
Definition: pqformat.h:148
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
#define PointerGetDatum(X)
Definition: postgres.h:562
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
Datum int2ge(PG_FUNCTION_ARGS)
Definition: int.c:472
Datum int4mod(PG_FUNCTION_ARGS)
Definition: int.c:955
Datum int42lt(PG_FUNCTION_ARGS)
Definition: int.c:553
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:110
Datum int4and(PG_FUNCTION_ARGS)
Definition: int.c:1091
Datum int4in(PG_FUNCTION_ARGS)
Definition: int.c:264
StringInfoData * StringInfo
Definition: stringinfo.h:43
Datum int2and(PG_FUNCTION_ARGS)
Definition: int.c:1144
Datum int24ne(PG_FUNCTION_ARGS)
Definition: int.c:490
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
Datum int24mul(PG_FUNCTION_ARGS)
Definition: int.c:841
#define PG_RETURN_INT16(x)
Definition: fmgr.h:316
Datum generate_series_int4(PG_FUNCTION_ARGS)
Definition: int.c:1201
int errcode(int sqlerrcode)
Definition: elog.c:575
Datum int2xor(PG_FUNCTION_ARGS)
Definition: int.c:1162
Datum int4up(PG_FUNCTION_ARGS)
Definition: int.c:608
Datum int4ne(PG_FUNCTION_ARGS)
Definition: int.c:382
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:29
Oid elemtype
Definition: c.h:530
Datum int2vectorsend(PG_FUNCTION_ARGS)
Definition: int.c:250
Datum array_recv(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:1255
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:330
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
Datum i2toi4(PG_FUNCTION_ARGS)
Definition: int.c:317
Datum int4_bool(PG_FUNCTION_ARGS)
Definition: int.c:339
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:69
Datum int2lt(PG_FUNCTION_ARGS)
Definition: int.c:445
Datum int4pl(PG_FUNCTION_ARGS)
Definition: int.c:616
Datum int24div(PG_FUNCTION_ARGS)
Definition: int.c:855
Datum int4send(PG_FUNCTION_ARGS)
Definition: int.c:299
signed int int32
Definition: c.h:294
Datum int24eq(PG_FUNCTION_ARGS)
Definition: int.c:481
#define ARR_LBOUND(a)
Definition: array.h:281
#define FUNC_MAX_ARGS
Datum int2up(PG_FUNCTION_ARGS)
Definition: int.c:723
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
FmgrInfo * flinfo
Definition: fmgr.h:79
int32 dataoffset
Definition: c.h:529
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Datum int2vectorrecv(PG_FUNCTION_ARGS)
Definition: int.c:202
Datum int4abs(PG_FUNCTION_ARGS)
Definition: int.c:1016
#define ARR_DIMS(a)
Definition: array.h:279
Datum int2send(PG_FUNCTION_ARGS)
Definition: int.c:94
Datum int42gt(PG_FUNCTION_ARGS)
Definition: int.c:571
Datum int4ge(PG_FUNCTION_ARGS)
Definition: int.c:418
Datum int4lt(PG_FUNCTION_ARGS)
Definition: int.c:391
Datum int4mi(PG_FUNCTION_ARGS)
Definition: int.c:630
Datum int2smaller(PG_FUNCTION_ARGS)
Definition: int.c:1053
Datum int4larger(PG_FUNCTION_ARGS)
Definition: int.c:1062
#define INT2OID
Definition: pg_type.h:308
Datum int2mul(PG_FUNCTION_ARGS)
Definition: int.c:759
static char * buf
Definition: pg_test_fsync.c:67
int ndim
Definition: c.h:528
#define ARR_HASNULL(a)
Definition: array.h:276
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:109
Datum int2eq(PG_FUNCTION_ARGS)
Definition: int.c:427
Datum int4out(PG_FUNCTION_ARGS)
Definition: int.c:275
Datum int4not(PG_FUNCTION_ARGS)
Definition: int.c:1136
#define PG_INT16_MIN
Definition: c.h:385
#define PG_INT32_MIN
Definition: c.h:388
Datum int2vectorin(PG_FUNCTION_ARGS)
Definition: int.c:137
#define ereport(elevel, rest)
Definition: elog.h:122
void pg_itoa(int16 i, char *a)
Definition: numutils.c:120
Datum int42mul(PG_FUNCTION_ARGS)
Definition: int.c:902
Datum int4shl(PG_FUNCTION_ARGS)
Definition: int.c:1118
Datum int24lt(PG_FUNCTION_ARGS)
Definition: int.c:499
Datum int4um(PG_FUNCTION_ARGS)
Definition: int.c:596
Definition: c.h:525
void * palloc0(Size size)
Definition: mcxt.c:864
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
uintptr_t Datum
Definition: postgres.h:372
Datum int4or(PG_FUNCTION_ARGS)
Definition: int.c:1100
Datum int4le(PG_FUNCTION_ARGS)
Definition: int.c:400
Datum int4xor(PG_FUNCTION_ARGS)
Definition: int.c:1109
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
int dim1
Definition: c.h:531
Datum bool_int4(PG_FUNCTION_ARGS)
Definition: int.c:349
Datum i4toi2(PG_FUNCTION_ARGS)
Definition: int.c:325
#define InvalidOid
Definition: postgres_ext.h:36
Datum int24le(PG_FUNCTION_ARGS)
Definition: int.c:508
Datum int2larger(PG_FUNCTION_ARGS)
Definition: int.c:1044
int32 current
Definition: int.c:45
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
int32 finish
Definition: int.c:46
Datum int2out(PG_FUNCTION_ARGS)
Definition: int.c:70
Datum int4div(PG_FUNCTION_ARGS)
Definition: int.c:658
Datum int2div(PG_FUNCTION_ARGS)
Definition: int.c:774
Datum int42div(PG_FUNCTION_ARGS)
Definition: int.c:916
#define Assert(condition)
Definition: c.h:680
Datum int2mi(PG_FUNCTION_ARGS)
Definition: int.c:745
Datum int2ne(PG_FUNCTION_ARGS)
Definition: int.c:436
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:49
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:89
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
Datum int2shl(PG_FUNCTION_ARGS)
Definition: int.c:1180
Datum int4mul(PG_FUNCTION_ARGS)
Definition: int.c:644
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:120
Datum int2or(PG_FUNCTION_ARGS)
Definition: int.c:1153
#define PG_NARGS()
Definition: fmgr.h:168
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:533
#define ARR_NDIM(a)
Definition: array.h:275
Datum int2in(PG_FUNCTION_ARGS)
Definition: int.c:59
#define Int2VectorSize(n)
Definition: int.c:41
#define DatumGetPointer(X)
Definition: postgres.h:555
static void pq_sendint16(StringInfo buf, int16 i)
Definition: pqformat.h:140
Datum int42ne(PG_FUNCTION_ARGS)
Definition: int.c:544
Datum int2recv(PG_FUNCTION_ARGS)
Definition: int.c:83
#define Int32GetDatum(X)
Definition: postgres.h:485
Datum int2um(PG_FUNCTION_ARGS)
Definition: int.c:711
Datum int4gt(PG_FUNCTION_ARGS)
Definition: int.c:409
void * user_fctx
Definition: funcapi.h:91
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum int2abs(PG_FUNCTION_ARGS)
Definition: int.c:1030
Datum int42ge(PG_FUNCTION_ARGS)
Definition: int.c:580
Datum int2pl(PG_FUNCTION_ARGS)
Definition: int.c:731
void * arg
#define unlikely(x)
Definition: c.h:200
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
Datum int42pl(PG_FUNCTION_ARGS)
Definition: int.c:874
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
Datum int4shr(PG_FUNCTION_ARGS)
Definition: int.c:1127
Datum int4smaller(PG_FUNCTION_ARGS)
Definition: int.c:1071
Datum generate_series_step_int4(PG_FUNCTION_ARGS)
Definition: int.c:1207
void pg_ltoa(int32 value, char *a)
Definition: numutils.c:132
#define ARR_ELEMTYPE(a)
Definition: array.h:277
Datum int4eq(PG_FUNCTION_ARGS)
Definition: int.c:373
Datum int42mi(PG_FUNCTION_ARGS)
Definition: int.c:888
Datum int24pl(PG_FUNCTION_ARGS)
Definition: int.c:813
#define PG_RETURN_NULL()
Definition: fmgr.h:305
Datum int2gt(PG_FUNCTION_ARGS)
Definition: int.c:463
int32 pg_atoi(const char *s, int size, int c)
Definition: numutils.c:37
Datum int42le(PG_FUNCTION_ARGS)
Definition: int.c:562
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
Datum int2le(PG_FUNCTION_ARGS)
Definition: int.c:454
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295
Datum int4recv(PG_FUNCTION_ARGS)
Definition: int.c:288