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