PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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
53
54
55/*****************************************************************************
56 * USER I/O ROUTINES *
57 *****************************************************************************/
58
59/*
60 * int2in - converts "num" to short
61 */
64{
65 char *num = PG_GETARG_CSTRING(0);
66
67 PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
68}
69
70/*
71 * int2out - converts short to "num"
72 */
75{
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 */
93
94/*
95 * int2send - converts int2 to binary format
96 */
107
108/*
109 * construct int2vector given a raw array of int2s
110 *
111 * If int2s is NULL then caller must fill values[] afterward
112 */
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 * validate that an array object meets the restrictions of int2vector
139 *
140 * We need this because there are pathways by which a general int2[] array can
141 * be cast to int2vector, allowing the type's restrictions to be violated.
142 * All code that receives an int2vector as a SQL parameter should check this.
143 */
144static void
146{
147 /*
148 * We insist on ndim == 1 and dataoffset == 0 (that is, no nulls) because
149 * otherwise the array's layout will not be what calling code expects. We
150 * needn't be picky about the index lower bound though. Checking elemtype
151 * is just paranoia.
152 */
153 if (int2Array->ndim != 1 ||
154 int2Array->dataoffset != 0 ||
155 int2Array->elemtype != INT2OID)
158 errmsg("array is not a valid int2vector")));
159}
160
161/*
162 * int2vectorin - converts "num num ..." to internal form
163 */
164Datum
166{
167 char *intString = PG_GETARG_CSTRING(0);
168 Node *escontext = fcinfo->context;
169 int2vector *result;
170 int nalloc;
171 int n;
172
173 nalloc = 32; /* arbitrary initial size guess */
175
176 for (n = 0;; n++)
177 {
178 long l;
179 char *endp;
180
181 while (*intString && isspace((unsigned char) *intString))
182 intString++;
183 if (*intString == '\0')
184 break;
185
186 if (n >= nalloc)
187 {
188 nalloc *= 2;
189 result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
190 }
191
192 errno = 0;
193 l = strtol(intString, &endp, 10);
194
195 if (intString == endp)
196 ereturn(escontext, (Datum) 0,
198 errmsg("invalid input syntax for type %s: \"%s\"",
199 "smallint", intString)));
200
202 ereturn(escontext, (Datum) 0,
204 errmsg("value \"%s\" is out of range for type %s", intString,
205 "smallint")));
206
207 if (*endp && *endp != ' ')
208 ereturn(escontext, (Datum) 0,
210 errmsg("invalid input syntax for type %s: \"%s\"",
211 "smallint", intString)));
212
213 result->values[n] = l;
214 intString = endp;
215 }
216
217 SET_VARSIZE(result, Int2VectorSize(n));
218 result->ndim = 1;
219 result->dataoffset = 0; /* never any nulls */
220 result->elemtype = INT2OID;
221 result->dim1 = n;
222 result->lbound1 = 0;
223
224 PG_RETURN_POINTER(result);
225}
226
227/*
228 * int2vectorout - converts internal form to "num num ..."
229 */
230Datum
232{
234 int num,
235 nnums;
236 char *rp;
237 char *result;
238
239 /* validate input before fetching dim1 */
241 nnums = int2Array->dim1;
242
243 /* assumes sign, 5 digits, ' ' */
244 rp = result = (char *) palloc(nnums * 7 + 1);
245 for (num = 0; num < nnums; num++)
246 {
247 if (num != 0)
248 *rp++ = ' ';
249 rp += pg_itoa(int2Array->values[num], rp);
250 }
251 *rp = '\0';
252 PG_RETURN_CSTRING(result);
253}
254
255/*
256 * int2vectorrecv - converts external binary format to int2vector
257 */
258Datum
260{
263 int2vector *result;
264
265 /*
266 * Normally one would call array_recv() using DirectFunctionCall3, but
267 * that does not work since array_recv wants to cache some data using
268 * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
269 * parameter.
270 */
271 InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
273
274 locfcinfo->args[0].value = PointerGetDatum(buf);
275 locfcinfo->args[0].isnull = false;
276 locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID);
277 locfcinfo->args[1].isnull = false;
278 locfcinfo->args[2].value = Int32GetDatum(-1);
279 locfcinfo->args[2].isnull = false;
280
282
283 Assert(!locfcinfo->isnull);
284
285 /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
286 if (ARR_NDIM(result) != 1 ||
287 ARR_HASNULL(result) ||
288 ARR_ELEMTYPE(result) != INT2OID ||
289 ARR_LBOUND(result)[0] != 0)
292 errmsg("invalid int2vector data")));
293
294 PG_RETURN_POINTER(result);
295}
296
297/*
298 * int2vectorsend - converts int2vector to binary format
299 */
300Datum
302{
303 /* We don't do check_valid_int2vector, since array_send won't care */
304 return array_send(fcinfo);
305}
306
307
308/*****************************************************************************
309 * PUBLIC ROUTINES *
310 *****************************************************************************/
311
312/*
313 * int4in - converts "num" to int4
314 */
315Datum
317{
318 char *num = PG_GETARG_CSTRING(0);
319
320 PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
321}
322
323/*
324 * int4out - converts int4 to "num"
325 */
326Datum
328{
330 char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
331
332 pg_ltoa(arg1, result);
333 PG_RETURN_CSTRING(result);
334}
335
336/*
337 * int4recv - converts external binary format to int4
338 */
339Datum
346
347/*
348 * int4send - converts int4 to binary format
349 */
350Datum
360
361
362/*
363 * ===================
364 * CONVERSION ROUTINES
365 * ===================
366 */
367
368Datum
375
376Datum
378{
380
384 errmsg("smallint out of range")));
385
387}
388
389/* Cast int4 -> bool */
390Datum
392{
393 if (PG_GETARG_INT32(0) == 0)
394 PG_RETURN_BOOL(false);
395 else
396 PG_RETURN_BOOL(true);
397}
398
399/* Cast bool -> int4 */
400Datum
402{
403 if (PG_GETARG_BOOL(0) == false)
405 else
407}
408
409/*
410 * ============================
411 * COMPARISON OPERATOR ROUTINES
412 * ============================
413 */
414
415/*
416 * inteq - returns 1 iff arg1 == arg2
417 * intne - returns 1 iff arg1 != arg2
418 * intlt - returns 1 iff arg1 < arg2
419 * intle - returns 1 iff arg1 <= arg2
420 * intgt - returns 1 iff arg1 > arg2
421 * intge - returns 1 iff arg1 >= arg2
422 */
423
424Datum
432
433Datum
441
442Datum
450
451Datum
459
460Datum
468
469Datum
477
478Datum
486
487Datum
495
496Datum
504
505Datum
513
514Datum
522
523Datum
531
532Datum
540
541Datum
549
550Datum
558
559Datum
567
568Datum
576
577Datum
585
586Datum
594
595Datum
603
604Datum
612
613Datum
621
622Datum
630
631Datum
639
640
641/*----------------------------------------------------------
642 * in_range functions for int4 and int2,
643 * including cross-data-type comparisons.
644 *
645 * Note: we provide separate intN_int8 functions for performance
646 * reasons. This forces also providing intN_int2, else cases with a
647 * smallint offset value would fail to resolve which function to use.
648 * But that's an unlikely situation, so don't duplicate code for it.
649 *---------------------------------------------------------*/
650
651Datum
653{
655 int32 base = PG_GETARG_INT32(1);
656 int32 offset = PG_GETARG_INT32(2);
657 bool sub = PG_GETARG_BOOL(3);
658 bool less = PG_GETARG_BOOL(4);
659 int32 sum;
660
661 if (offset < 0)
664 errmsg("invalid preceding or following size in window function")));
665
666 if (sub)
667 offset = -offset; /* cannot overflow */
668
669 if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
670 {
671 /*
672 * If sub is false, the true sum is surely more than val, so correct
673 * answer is the same as "less". If sub is true, the true sum is
674 * surely less than val, so the answer is "!less".
675 */
676 PG_RETURN_BOOL(sub ? !less : less);
677 }
678
679 if (less)
680 PG_RETURN_BOOL(val <= sum);
681 else
682 PG_RETURN_BOOL(val >= sum);
683}
684
685Datum
687{
688 /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
694 PG_GETARG_DATUM(4));
695}
696
697Datum
699{
700 /* We must do all the math in int64 */
702 int64 base = (int64) PG_GETARG_INT32(1);
703 int64 offset = PG_GETARG_INT64(2);
704 bool sub = PG_GETARG_BOOL(3);
705 bool less = PG_GETARG_BOOL(4);
706 int64 sum;
707
708 if (offset < 0)
711 errmsg("invalid preceding or following size in window function")));
712
713 if (sub)
714 offset = -offset; /* cannot overflow */
715
716 if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
717 {
718 /*
719 * If sub is false, the true sum is surely more than val, so correct
720 * answer is the same as "less". If sub is true, the true sum is
721 * surely less than val, so the answer is "!less".
722 */
723 PG_RETURN_BOOL(sub ? !less : less);
724 }
725
726 if (less)
727 PG_RETURN_BOOL(val <= sum);
728 else
729 PG_RETURN_BOOL(val >= sum);
730}
731
732Datum
734{
735 /* We must do all the math in int32 */
737 int32 base = (int32) PG_GETARG_INT16(1);
738 int32 offset = PG_GETARG_INT32(2);
739 bool sub = PG_GETARG_BOOL(3);
740 bool less = PG_GETARG_BOOL(4);
741 int32 sum;
742
743 if (offset < 0)
746 errmsg("invalid preceding or following size in window function")));
747
748 if (sub)
749 offset = -offset; /* cannot overflow */
750
751 if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
752 {
753 /*
754 * If sub is false, the true sum is surely more than val, so correct
755 * answer is the same as "less". If sub is true, the true sum is
756 * surely less than val, so the answer is "!less".
757 */
758 PG_RETURN_BOOL(sub ? !less : less);
759 }
760
761 if (less)
762 PG_RETURN_BOOL(val <= sum);
763 else
764 PG_RETURN_BOOL(val >= sum);
765}
766
767Datum
769{
770 /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
776 PG_GETARG_DATUM(4));
777}
778
779Datum
781{
782 /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
788 PG_GETARG_DATUM(4));
789}
790
791
792/*
793 * int[24]pl - returns arg1 + arg2
794 * int[24]mi - returns arg1 - arg2
795 * int[24]mul - returns arg1 * arg2
796 * int[24]div - returns arg1 / arg2
797 */
798
799Datum
801{
803
804 if (unlikely(arg == PG_INT32_MIN))
807 errmsg("integer out of range")));
809}
810
811Datum
818
819Datum
821{
824 int32 result;
825
826 if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
829 errmsg("integer out of range")));
830 PG_RETURN_INT32(result);
831}
832
833Datum
835{
838 int32 result;
839
840 if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
843 errmsg("integer out of range")));
844 PG_RETURN_INT32(result);
845}
846
847Datum
849{
852 int32 result;
853
854 if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
857 errmsg("integer out of range")));
858 PG_RETURN_INT32(result);
859}
860
861Datum
863{
866 int32 result;
867
868 if (arg2 == 0)
869 {
872 errmsg("division by zero")));
873 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
875 }
876
877 /*
878 * INT_MIN / -1 is problematic, since the result can't be represented on a
879 * two's-complement machine. Some machines produce INT_MIN, some produce
880 * zero, some throw an exception. We can dodge the problem by recognizing
881 * that division by -1 is the same as negation.
882 */
883 if (arg2 == -1)
884 {
885 if (unlikely(arg1 == PG_INT32_MIN))
888 errmsg("integer out of range")));
889 result = -arg1;
890 PG_RETURN_INT32(result);
891 }
892
893 /* No overflow is possible */
894
895 result = arg1 / arg2;
896
897 PG_RETURN_INT32(result);
898}
899
900Datum
902{
904 int32 result;
905
906 if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
909 errmsg("integer out of range")));
910
911 PG_RETURN_INT32(result);
912}
913
914Datum
916{
918
919 if (unlikely(arg == PG_INT16_MIN))
922 errmsg("smallint out of range")));
924}
925
926Datum
933
934Datum
936{
939 int16 result;
940
941 if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
944 errmsg("smallint out of range")));
945 PG_RETURN_INT16(result);
946}
947
948Datum
950{
953 int16 result;
954
955 if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
958 errmsg("smallint out of range")));
959 PG_RETURN_INT16(result);
960}
961
962Datum
964{
967 int16 result;
968
969 if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
972 errmsg("smallint out of range")));
973
974 PG_RETURN_INT16(result);
975}
976
977Datum
979{
982 int16 result;
983
984 if (arg2 == 0)
985 {
988 errmsg("division by zero")));
989 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
991 }
992
993 /*
994 * SHRT_MIN / -1 is problematic, since the result can't be represented on
995 * a two's-complement machine. Some machines produce SHRT_MIN, some
996 * produce zero, some throw an exception. We can dodge the problem by
997 * recognizing that division by -1 is the same as negation.
998 */
999 if (arg2 == -1)
1000 {
1001 if (unlikely(arg1 == PG_INT16_MIN))
1002 ereport(ERROR,
1004 errmsg("smallint out of range")));
1005 result = -arg1;
1006 PG_RETURN_INT16(result);
1007 }
1008
1009 /* No overflow is possible */
1010
1011 result = arg1 / arg2;
1012
1013 PG_RETURN_INT16(result);
1014}
1015
1016Datum
1018{
1021 int32 result;
1022
1023 if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
1024 ereport(ERROR,
1026 errmsg("integer out of range")));
1027 PG_RETURN_INT32(result);
1028}
1029
1030Datum
1032{
1035 int32 result;
1036
1037 if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
1038 ereport(ERROR,
1040 errmsg("integer out of range")));
1041 PG_RETURN_INT32(result);
1042}
1043
1044Datum
1046{
1049 int32 result;
1050
1051 if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
1052 ereport(ERROR,
1054 errmsg("integer out of range")));
1055 PG_RETURN_INT32(result);
1056}
1057
1058Datum
1060{
1063
1064 if (unlikely(arg2 == 0))
1065 {
1066 ereport(ERROR,
1068 errmsg("division by zero")));
1069 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1071 }
1072
1073 /* No overflow is possible */
1075}
1076
1077Datum
1079{
1082 int32 result;
1083
1084 if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
1085 ereport(ERROR,
1087 errmsg("integer out of range")));
1088 PG_RETURN_INT32(result);
1089}
1090
1091Datum
1093{
1096 int32 result;
1097
1098 if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
1099 ereport(ERROR,
1101 errmsg("integer out of range")));
1102 PG_RETURN_INT32(result);
1103}
1104
1105Datum
1107{
1110 int32 result;
1111
1112 if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
1113 ereport(ERROR,
1115 errmsg("integer out of range")));
1116 PG_RETURN_INT32(result);
1117}
1118
1119Datum
1121{
1124 int32 result;
1125
1126 if (unlikely(arg2 == 0))
1127 {
1128 ereport(ERROR,
1130 errmsg("division by zero")));
1131 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1133 }
1134
1135 /*
1136 * INT_MIN / -1 is problematic, since the result can't be represented on a
1137 * two's-complement machine. Some machines produce INT_MIN, some produce
1138 * zero, some throw an exception. We can dodge the problem by recognizing
1139 * that division by -1 is the same as negation.
1140 */
1141 if (arg2 == -1)
1142 {
1143 if (unlikely(arg1 == PG_INT32_MIN))
1144 ereport(ERROR,
1146 errmsg("integer out of range")));
1147 result = -arg1;
1148 PG_RETURN_INT32(result);
1149 }
1150
1151 /* No overflow is possible */
1152
1153 result = arg1 / arg2;
1154
1155 PG_RETURN_INT32(result);
1156}
1157
1158Datum
1160{
1163
1164 if (unlikely(arg2 == 0))
1165 {
1166 ereport(ERROR,
1168 errmsg("division by zero")));
1169 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1171 }
1172
1173 /*
1174 * Some machines throw a floating-point exception for INT_MIN % -1, which
1175 * is a bit silly since the correct answer is perfectly well-defined,
1176 * namely zero.
1177 */
1178 if (arg2 == -1)
1179 PG_RETURN_INT32(0);
1180
1181 /* No overflow is possible */
1182
1184}
1185
1186Datum
1188{
1191
1192 if (unlikely(arg2 == 0))
1193 {
1194 ereport(ERROR,
1196 errmsg("division by zero")));
1197 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1199 }
1200
1201 /*
1202 * Some machines throw a floating-point exception for INT_MIN % -1, which
1203 * is a bit silly since the correct answer is perfectly well-defined,
1204 * namely zero. (It's not clear this ever happens when dealing with
1205 * int16, but we might as well have the test for safety.)
1206 */
1207 if (arg2 == -1)
1208 PG_RETURN_INT16(0);
1209
1210 /* No overflow is possible */
1211
1213}
1214
1215
1216/* int[24]abs()
1217 * Absolute value
1218 */
1219Datum
1221{
1223 int32 result;
1224
1225 if (unlikely(arg1 == PG_INT32_MIN))
1226 ereport(ERROR,
1228 errmsg("integer out of range")));
1229 result = (arg1 < 0) ? -arg1 : arg1;
1230 PG_RETURN_INT32(result);
1231}
1232
1233Datum
1235{
1237 int16 result;
1238
1239 if (unlikely(arg1 == PG_INT16_MIN))
1240 ereport(ERROR,
1242 errmsg("smallint out of range")));
1243 result = (arg1 < 0) ? -arg1 : arg1;
1244 PG_RETURN_INT16(result);
1245}
1246
1247/*
1248 * Greatest Common Divisor
1249 *
1250 * Returns the largest positive integer that exactly divides both inputs.
1251 * Special cases:
1252 * - gcd(x, 0) = gcd(0, x) = abs(x)
1253 * because 0 is divisible by anything
1254 * - gcd(0, 0) = 0
1255 * complies with the previous definition and is a common convention
1256 *
1257 * Special care must be taken if either input is INT_MIN --- gcd(0, INT_MIN),
1258 * gcd(INT_MIN, 0) and gcd(INT_MIN, INT_MIN) are all equal to abs(INT_MIN),
1259 * which cannot be represented as a 32-bit signed integer.
1260 */
1261static int32
1263{
1264 int32 swap;
1265 int32 a1,
1266 a2;
1267
1268 /*
1269 * Put the greater absolute value in arg1.
1270 *
1271 * This would happen automatically in the loop below, but avoids an
1272 * expensive modulo operation, and simplifies the special-case handling
1273 * for INT_MIN below.
1274 *
1275 * We do this in negative space in order to handle INT_MIN.
1276 */
1277 a1 = (arg1 < 0) ? arg1 : -arg1;
1278 a2 = (arg2 < 0) ? arg2 : -arg2;
1279 if (a1 > a2)
1280 {
1281 swap = arg1;
1282 arg1 = arg2;
1283 arg2 = swap;
1284 }
1285
1286 /* Special care needs to be taken with INT_MIN. See comments above. */
1287 if (arg1 == PG_INT32_MIN)
1288 {
1289 if (arg2 == 0 || arg2 == PG_INT32_MIN)
1290 ereport(ERROR,
1292 errmsg("integer out of range")));
1293
1294 /*
1295 * Some machines throw a floating-point exception for INT_MIN % -1,
1296 * which is a bit silly since the correct answer is perfectly
1297 * well-defined, namely zero. Guard against this and just return the
1298 * result, gcd(INT_MIN, -1) = 1.
1299 */
1300 if (arg2 == -1)
1301 return 1;
1302 }
1303
1304 /* Use the Euclidean algorithm to find the GCD */
1305 while (arg2 != 0)
1306 {
1307 swap = arg2;
1308 arg2 = arg1 % arg2;
1309 arg1 = swap;
1310 }
1311
1312 /*
1313 * Make sure the result is positive. (We know we don't have INT_MIN
1314 * anymore).
1315 */
1316 if (arg1 < 0)
1317 arg1 = -arg1;
1318
1319 return arg1;
1320}
1321
1322Datum
1324{
1327 int32 result;
1328
1329 result = int4gcd_internal(arg1, arg2);
1330
1331 PG_RETURN_INT32(result);
1332}
1333
1334/*
1335 * Least Common Multiple
1336 */
1337Datum
1339{
1342 int32 gcd;
1343 int32 result;
1344
1345 /*
1346 * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case. This prevents a
1347 * division-by-zero error below when x is zero, and an overflow error from
1348 * the GCD computation when x = INT_MIN.
1349 */
1350 if (arg1 == 0 || arg2 == 0)
1351 PG_RETURN_INT32(0);
1352
1353 /* lcm(x, y) = abs(x / gcd(x, y) * y) */
1355 arg1 = arg1 / gcd;
1356
1357 if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
1358 ereport(ERROR,
1360 errmsg("integer out of range")));
1361
1362 /* If the result is INT_MIN, it cannot be represented. */
1363 if (unlikely(result == PG_INT32_MIN))
1364 ereport(ERROR,
1366 errmsg("integer out of range")));
1367
1368 if (result < 0)
1369 result = -result;
1370
1371 PG_RETURN_INT32(result);
1372}
1373
1374Datum
1382
1383Datum
1391
1392Datum
1400
1401Datum
1409
1410/*
1411 * Bit-pushing operators
1412 *
1413 * int[24]and - returns arg1 & arg2
1414 * int[24]or - returns arg1 | arg2
1415 * int[24]xor - returns arg1 # arg2
1416 * int[24]not - returns ~arg1
1417 * int[24]shl - returns arg1 << arg2
1418 * int[24]shr - returns arg1 >> arg2
1419 */
1420
1421Datum
1429
1430Datum
1438
1439Datum
1447
1448Datum
1456
1457Datum
1465
1466Datum
1473
1474Datum
1482
1483Datum
1491
1492Datum
1500
1501Datum
1508
1509
1510Datum
1518
1519Datum
1527
1528/*
1529 * non-persistent numeric series generator
1530 */
1531Datum
1536
1537Datum
1539{
1542 int32 result;
1543 MemoryContext oldcontext;
1544
1545 /* stuff done only on the first call of the function */
1546 if (SRF_IS_FIRSTCALL())
1547 {
1549 int32 finish = PG_GETARG_INT32(1);
1550 int32 step = 1;
1551
1552 /* see if we were given an explicit step size */
1553 if (PG_NARGS() == 3)
1554 step = PG_GETARG_INT32(2);
1555 if (step == 0)
1556 ereport(ERROR,
1558 errmsg("step size cannot equal zero")));
1559
1560 /* create a function context for cross-call persistence */
1562
1563 /*
1564 * switch to memory context appropriate for multiple function calls
1565 */
1566 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1567
1568 /* allocate memory for user context */
1570
1571 /*
1572 * Use fctx to keep state from call to call. Seed current with the
1573 * original start value
1574 */
1575 fctx->current = start;
1576 fctx->finish = finish;
1577 fctx->step = step;
1578
1579 funcctx->user_fctx = fctx;
1580 MemoryContextSwitchTo(oldcontext);
1581 }
1582
1583 /* stuff done on every call of the function */
1585
1586 /*
1587 * get the saved state and use current as the result for this iteration
1588 */
1589 fctx = funcctx->user_fctx;
1590 result = fctx->current;
1591
1592 if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1593 (fctx->step < 0 && fctx->current >= fctx->finish))
1594 {
1595 /*
1596 * Increment current in preparation for next iteration. If next-value
1597 * computation overflows, this is the final result.
1598 */
1599 if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
1600 fctx->step = 0;
1601
1602 /* do when there is more left to send */
1604 }
1605 else
1606 /* do when there is no more left */
1608}
1609
1610/*
1611 * Planner support function for generate_series(int4, int4 [, int4])
1612 */
1613Datum
1615{
1617 Node *ret = NULL;
1618
1620 {
1621 /* Try to estimate the number of rows returned */
1623
1624 if (is_funcclause(req->node)) /* be paranoid */
1625 {
1626 List *args = ((FuncExpr *) req->node)->args;
1627 Node *arg1,
1628 *arg2,
1629 *arg3;
1630
1631 /* We can use estimated argument values here */
1633 arg2 = estimate_expression_value(req->root, lsecond(args));
1634 if (list_length(args) >= 3)
1635 arg3 = estimate_expression_value(req->root, lthird(args));
1636 else
1637 arg3 = NULL;
1638
1639 /*
1640 * If any argument is constant NULL, we can safely assume that
1641 * zero rows are returned. Otherwise, if they're all non-NULL
1642 * constants, we can calculate the number of rows that will be
1643 * returned. Use double arithmetic to avoid overflow hazards.
1644 */
1645 if ((IsA(arg1, Const) &&
1646 ((Const *) arg1)->constisnull) ||
1647 (IsA(arg2, Const) &&
1648 ((Const *) arg2)->constisnull) ||
1649 (arg3 != NULL && IsA(arg3, Const) &&
1650 ((Const *) arg3)->constisnull))
1651 {
1652 req->rows = 0;
1653 ret = (Node *) req;
1654 }
1655 else if (IsA(arg1, Const) &&
1656 IsA(arg2, Const) &&
1657 (arg3 == NULL || IsA(arg3, Const)))
1658 {
1659 double start,
1660 finish,
1661 step;
1662
1664 finish = DatumGetInt32(((Const *) arg2)->constvalue);
1665 step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
1666
1667 /* This equation works for either sign of step */
1668 if (step != 0)
1669 {
1670 req->rows = floor((finish - start + step) / step);
1671 ret = (Node *) req;
1672 }
1673 }
1674 }
1675 }
1676
1677 PG_RETURN_POINTER(ret);
1678}
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_HASNULL(a)
Definition array.h:291
#define ARR_LBOUND(a)
Definition array.h:296
Datum array_recv(PG_FUNCTION_ARGS)
Datum array_send(PG_FUNCTION_ARGS)
#define Assert(condition)
Definition c.h:885
int64_t int64
Definition c.h:555
int16_t int16
Definition c.h:553
#define PG_INT16_MIN
Definition c.h:611
int32_t int32
Definition c.h:554
#define unlikely(x)
Definition c.h:424
#define PG_INT32_MIN
Definition c.h:614
Node * estimate_expression_value(PlannerInfo *root, Node *node)
Definition clauses.c:2408
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define ereturn(context, dummy_value,...)
Definition elog.h:278
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition fmgr.h:150
#define PG_RETURN_CSTRING(x)
Definition fmgr.h:364
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define LOCAL_FCINFO(name, nargs)
Definition fmgr.h:110
#define PG_NARGS()
Definition fmgr.h:203
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_RETURN_INT16(x)
Definition fmgr.h:357
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition fmgr.h:692
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define PG_GETARG_INT16(n)
Definition fmgr.h:271
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
return str start
static const FormData_pg_attribute a1
Definition heap.c:144
static const FormData_pg_attribute a2
Definition heap.c:157
long val
Definition informix.c:689
Datum int4div(PG_FUNCTION_ARGS)
Definition int.c:862
Datum int4shl(PG_FUNCTION_ARGS)
Definition int.c:1449
Datum int2vectorrecv(PG_FUNCTION_ARGS)
Definition int.c:259
Datum int2not(PG_FUNCTION_ARGS)
Definition int.c:1502
Datum int4pl(PG_FUNCTION_ARGS)
Definition int.c:820
Datum int2xor(PG_FUNCTION_ARGS)
Definition int.c:1493
Datum generate_series_int4(PG_FUNCTION_ARGS)
Definition int.c:1532
Datum int4recv(PG_FUNCTION_ARGS)
Definition int.c:340
Datum int4um(PG_FUNCTION_ARGS)
Definition int.c:800
Datum int4gt(PG_FUNCTION_ARGS)
Definition int.c:461
Datum int24eq(PG_FUNCTION_ARGS)
Definition int.c:533
Datum int2lt(PG_FUNCTION_ARGS)
Definition int.c:497
Datum int24mi(PG_FUNCTION_ARGS)
Definition int.c:1031
Datum int2out(PG_FUNCTION_ARGS)
Definition int.c:74
Datum int2eq(PG_FUNCTION_ARGS)
Definition int.c:479
Datum int42eq(PG_FUNCTION_ARGS)
Definition int.c:587
Datum int2ge(PG_FUNCTION_ARGS)
Definition int.c:524
Datum int2up(PG_FUNCTION_ARGS)
Definition int.c:927
Datum int4gcd(PG_FUNCTION_ARGS)
Definition int.c:1323
Datum int42ge(PG_FUNCTION_ARGS)
Definition int.c:632
Datum int42mul(PG_FUNCTION_ARGS)
Definition int.c:1106
Datum int24gt(PG_FUNCTION_ARGS)
Definition int.c:569
Datum int2le(PG_FUNCTION_ARGS)
Definition int.c:506
Datum int2abs(PG_FUNCTION_ARGS)
Definition int.c:1234
#define Int2VectorSize(n)
Definition int.c:45
Datum int4lt(PG_FUNCTION_ARGS)
Definition int.c:443
Datum int2um(PG_FUNCTION_ARGS)
Definition int.c:915
Datum int2shl(PG_FUNCTION_ARGS)
Definition int.c:1511
Datum in_range_int2_int8(PG_FUNCTION_ARGS)
Definition int.c:780
Datum int42div(PG_FUNCTION_ARGS)
Definition int.c:1120
static void check_valid_int2vector(const int2vector *int2Array)
Definition int.c:145
Datum int2mi(PG_FUNCTION_ARGS)
Definition int.c:949
Datum int2ne(PG_FUNCTION_ARGS)
Definition int.c:488
Datum int24le(PG_FUNCTION_ARGS)
Definition int.c:560
Datum int2send(PG_FUNCTION_ARGS)
Definition int.c:98
Datum int2mul(PG_FUNCTION_ARGS)
Definition int.c:963
Datum int2smaller(PG_FUNCTION_ARGS)
Definition int.c:1384
Datum int2mod(PG_FUNCTION_ARGS)
Definition int.c:1187
int2vector * buildint2vector(const int16 *int2s, int n)
Definition int.c:114
Datum int2in(PG_FUNCTION_ARGS)
Definition int.c:63
Datum int24mul(PG_FUNCTION_ARGS)
Definition int.c:1045
Datum int42gt(PG_FUNCTION_ARGS)
Definition int.c:623
Datum int4lcm(PG_FUNCTION_ARGS)
Definition int.c:1338
Datum in_range_int4_int8(PG_FUNCTION_ARGS)
Definition int.c:698
Datum int2div(PG_FUNCTION_ARGS)
Definition int.c:978
Datum in_range_int2_int2(PG_FUNCTION_ARGS)
Definition int.c:768
Datum int4in(PG_FUNCTION_ARGS)
Definition int.c:316
Datum int2shr(PG_FUNCTION_ARGS)
Definition int.c:1520
Datum in_range_int2_int4(PG_FUNCTION_ARGS)
Definition int.c:733
static int32 int4gcd_internal(int32 arg1, int32 arg2)
Definition int.c:1262
Datum int2vectorout(PG_FUNCTION_ARGS)
Definition int.c:231
Datum i4toi2(PG_FUNCTION_ARGS)
Definition int.c:377
Datum int4ge(PG_FUNCTION_ARGS)
Definition int.c:470
Datum int4and(PG_FUNCTION_ARGS)
Definition int.c:1422
Datum int4send(PG_FUNCTION_ARGS)
Definition int.c:351
Datum int24ge(PG_FUNCTION_ARGS)
Definition int.c:578
Datum in_range_int4_int2(PG_FUNCTION_ARGS)
Definition int.c:686
Datum int2vectorin(PG_FUNCTION_ARGS)
Definition int.c:165
Datum bool_int4(PG_FUNCTION_ARGS)
Definition int.c:401
Datum int4inc(PG_FUNCTION_ARGS)
Definition int.c:901
Datum int4shr(PG_FUNCTION_ARGS)
Definition int.c:1458
Datum int4larger(PG_FUNCTION_ARGS)
Definition int.c:1393
Datum int24ne(PG_FUNCTION_ARGS)
Definition int.c:542
Datum int2gt(PG_FUNCTION_ARGS)
Definition int.c:515
Datum int24lt(PG_FUNCTION_ARGS)
Definition int.c:551
Datum int42pl(PG_FUNCTION_ARGS)
Definition int.c:1078
Datum in_range_int4_int4(PG_FUNCTION_ARGS)
Definition int.c:652
Datum int4ne(PG_FUNCTION_ARGS)
Definition int.c:434
Datum int42le(PG_FUNCTION_ARGS)
Definition int.c:614
Datum i2toi4(PG_FUNCTION_ARGS)
Definition int.c:369
Datum int4smaller(PG_FUNCTION_ARGS)
Definition int.c:1402
Datum int24pl(PG_FUNCTION_ARGS)
Definition int.c:1017
Datum int4_bool(PG_FUNCTION_ARGS)
Definition int.c:391
Datum int4mod(PG_FUNCTION_ARGS)
Definition int.c:1159
Datum int24div(PG_FUNCTION_ARGS)
Definition int.c:1059
Datum int4xor(PG_FUNCTION_ARGS)
Definition int.c:1440
Datum generate_series_step_int4(PG_FUNCTION_ARGS)
Definition int.c:1538
Datum int2larger(PG_FUNCTION_ARGS)
Definition int.c:1375
Datum int2and(PG_FUNCTION_ARGS)
Definition int.c:1475
Datum int4not(PG_FUNCTION_ARGS)
Definition int.c:1467
Datum int4abs(PG_FUNCTION_ARGS)
Definition int.c:1220
Datum int4out(PG_FUNCTION_ARGS)
Definition int.c:327
Datum generate_series_int4_support(PG_FUNCTION_ARGS)
Definition int.c:1614
Datum int4mul(PG_FUNCTION_ARGS)
Definition int.c:848
Datum int4eq(PG_FUNCTION_ARGS)
Definition int.c:425
Datum int4le(PG_FUNCTION_ARGS)
Definition int.c:452
Datum int42ne(PG_FUNCTION_ARGS)
Definition int.c:596
Datum int4mi(PG_FUNCTION_ARGS)
Definition int.c:834
Datum int42lt(PG_FUNCTION_ARGS)
Definition int.c:605
Datum int2pl(PG_FUNCTION_ARGS)
Definition int.c:935
Datum int4up(PG_FUNCTION_ARGS)
Definition int.c:812
Datum int2vectorsend(PG_FUNCTION_ARGS)
Definition int.c:301
Datum int2recv(PG_FUNCTION_ARGS)
Definition int.c:87
Datum int42mi(PG_FUNCTION_ARGS)
Definition int.c:1092
Datum int4or(PG_FUNCTION_ARGS)
Definition int.c:1431
Datum int2or(PG_FUNCTION_ARGS)
Definition int.c:1484
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
Definition int.h:85
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition int.h:187
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
Definition int.h:103
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition int.h:67
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition int.h:169
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition int.h:235
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition int.h:151
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
void * palloc0(Size size)
Definition mcxt.c:1417
void * palloc(Size size)
Definition mcxt.c:1387
static bool is_funcclause(const void *clause)
Definition nodeFuncs.h:69
#define IsA(nodeptr, _type_)
Definition nodes.h:164
int pg_ltoa(int32 value, char *a)
Definition numutils.c:1119
int32 pg_strtoint32_safe(const char *s, Node *escontext)
Definition numutils.c:388
int pg_itoa(int16 i, char *a)
Definition numutils.c:1041
int16 pg_strtoint16_safe(const char *s, Node *escontext)
Definition numutils.c:127
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static int list_length(const List *l)
Definition pg_list.h:152
#define lthird(l)
Definition pg_list.h:188
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183
static char buf[DEFAULT_XLOG_SEG_SIZE]
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
static int32 DatumGetInt32(Datum X)
Definition postgres.h:212
#define InvalidOid
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition pqformat.c:414
void pq_begintypsend(StringInfo buf)
Definition pqformat.c:325
bytea * pq_endtypsend(StringInfo buf)
Definition pqformat.c:345
static void pq_sendint32(StringInfo buf, uint32 i)
Definition pqformat.h:144
static void pq_sendint16(StringInfo buf, uint16 i)
Definition pqformat.h:136
static int fb(int x)
struct StringInfoData * StringInfo
Definition string.h:15
Definition pg_list.h:54
Definition nodes.h:135
int ndim
Definition c.h:748
int dim1
Definition c.h:751
Oid elemtype
Definition c.h:750
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition c.h:753
int32 dataoffset
Definition c.h:749
int lbound1
Definition c.h:752
static uint32 gcd(uint32 a, uint32 b)
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432