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 "funcapi.h"
36 #include "libpq/pqformat.h"
37 #include "utils/array.h"
38 #include "utils/builtins.h"
39 
40 
41 #define SAMESIGN(a,b)	(((a) < 0) == ((b) < 0))
42 
43 #define Int2VectorSize(n)	(offsetof(int2vector, values) + (n) * sizeof(int16))
44 
45 typedef struct
46 {
47 	int32		current;
48 	int32		finish;
49 	int32		step;
50 } generate_series_fctx;
51 
52 
53 /*****************************************************************************
54  *	 USER I/O ROUTINES														 *
55  *****************************************************************************/
56 
57 /*
58  *		int2in			- converts "num" to short
59  */
60 Datum
int2in(PG_FUNCTION_ARGS)61 int2in(PG_FUNCTION_ARGS)
62 {
63 	char	   *num = PG_GETARG_CSTRING(0);
64 
65 	PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
66 }
67 
68 /*
69  *		int2out			- converts short to "num"
70  */
71 Datum
int2out(PG_FUNCTION_ARGS)72 int2out(PG_FUNCTION_ARGS)
73 {
74 	int16		arg1 = PG_GETARG_INT16(0);
75 	char	   *result = (char *) palloc(7);	/* sign, 5 digits, '\0' */
76 
77 	pg_itoa(arg1, result);
78 	PG_RETURN_CSTRING(result);
79 }
80 
81 /*
82  *		int2recv			- converts external binary format to int2
83  */
84 Datum
int2recv(PG_FUNCTION_ARGS)85 int2recv(PG_FUNCTION_ARGS)
86 {
87 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
88 
89 	PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
90 }
91 
92 /*
93  *		int2send			- converts int2 to binary format
94  */
95 Datum
int2send(PG_FUNCTION_ARGS)96 int2send(PG_FUNCTION_ARGS)
97 {
98 	int16		arg1 = PG_GETARG_INT16(0);
99 	StringInfoData buf;
100 
101 	pq_begintypsend(&buf);
102 	pq_sendint(&buf, arg1, sizeof(int16));
103 	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
104 }
105 
106 /*
107  * construct int2vector given a raw array of int2s
108  *
109  * If int2s is NULL then caller must fill values[] afterward
110  */
111 int2vector *
buildint2vector(const int16 * int2s,int n)112 buildint2vector(const int16 *int2s, int n)
113 {
114 	int2vector *result;
115 
116 	result = (int2vector *) palloc0(Int2VectorSize(n));
117 
118 	if (n > 0 && int2s)
119 		memcpy(result->values, int2s, n * sizeof(int16));
120 
121 	/*
122 	 * Attach standard array header.  For historical reasons, we set the index
123 	 * lower bound to 0 not 1.
124 	 */
125 	SET_VARSIZE(result, Int2VectorSize(n));
126 	result->ndim = 1;
127 	result->dataoffset = 0;		/* never any nulls */
128 	result->elemtype = INT2OID;
129 	result->dim1 = n;
130 	result->lbound1 = 0;
131 
132 	return result;
133 }
134 
135 /*
136  *		int2vectorin			- converts "num num ..." to internal form
137  */
138 Datum
int2vectorin(PG_FUNCTION_ARGS)139 int2vectorin(PG_FUNCTION_ARGS)
140 {
141 	char	   *intString = PG_GETARG_CSTRING(0);
142 	int2vector *result;
143 	int			n;
144 
145 	result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
146 
147 	for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
148 	{
149 		while (*intString && isspace((unsigned char) *intString))
150 			intString++;
151 		if (*intString == '\0')
152 			break;
153 		result->values[n] = pg_atoi(intString, sizeof(int16), ' ');
154 		while (*intString && !isspace((unsigned char) *intString))
155 			intString++;
156 	}
157 	while (*intString && isspace((unsigned char) *intString))
158 		intString++;
159 	if (*intString)
160 		ereport(ERROR,
161 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
162 				 errmsg("int2vector has too many elements")));
163 
164 	SET_VARSIZE(result, Int2VectorSize(n));
165 	result->ndim = 1;
166 	result->dataoffset = 0;		/* never any nulls */
167 	result->elemtype = INT2OID;
168 	result->dim1 = n;
169 	result->lbound1 = 0;
170 
171 	PG_RETURN_POINTER(result);
172 }
173 
174 /*
175  *		int2vectorout		- converts internal form to "num num ..."
176  */
177 Datum
int2vectorout(PG_FUNCTION_ARGS)178 int2vectorout(PG_FUNCTION_ARGS)
179 {
180 	int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
181 	int			num,
182 				nnums = int2Array->dim1;
183 	char	   *rp;
184 	char	   *result;
185 
186 	/* assumes sign, 5 digits, ' ' */
187 	rp = result = (char *) palloc(nnums * 7 + 1);
188 	for (num = 0; num < nnums; num++)
189 	{
190 		if (num != 0)
191 			*rp++ = ' ';
192 		pg_itoa(int2Array->values[num], rp);
193 		while (*++rp != '\0')
194 			;
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 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
207 	FunctionCallInfoData locfcinfo;
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.arg[0] = PointerGetDatum(buf);
220 	locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
221 	locfcinfo.arg[2] = Int32GetDatum(-1);
222 	locfcinfo.argnull[0] = false;
223 	locfcinfo.argnull[1] = false;
224 	locfcinfo.argnull[2] = 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_atoi(num, sizeof(int32), '\0'));
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_sendint(&buf, arg1, sizeof(int32));
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 (arg1 < SHRT_MIN || 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  *		int[24]pl		- returns arg1 + arg2
592  *		int[24]mi		- returns arg1 - arg2
593  *		int[24]mul		- returns arg1 * arg2
594  *		int[24]div		- returns arg1 / arg2
595  */
596 
597 Datum
int4um(PG_FUNCTION_ARGS)598 int4um(PG_FUNCTION_ARGS)
599 {
600 	int32		arg = PG_GETARG_INT32(0);
601 	int32		result;
602 
603 	result = -arg;
604 	/* overflow check (needed for INT_MIN) */
605 	if (arg != 0 && SAMESIGN(result, arg))
606 		ereport(ERROR,
607 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
608 				 errmsg("integer out of range")));
609 	PG_RETURN_INT32(result);
610 }
611 
612 Datum
int4up(PG_FUNCTION_ARGS)613 int4up(PG_FUNCTION_ARGS)
614 {
615 	int32		arg = PG_GETARG_INT32(0);
616 
617 	PG_RETURN_INT32(arg);
618 }
619 
620 Datum
int4pl(PG_FUNCTION_ARGS)621 int4pl(PG_FUNCTION_ARGS)
622 {
623 	int32		arg1 = PG_GETARG_INT32(0);
624 	int32		arg2 = PG_GETARG_INT32(1);
625 	int32		result;
626 
627 	result = arg1 + arg2;
628 
629 	/*
630 	 * Overflow check.  If the inputs are of different signs then their sum
631 	 * cannot overflow.  If the inputs are of the same sign, their sum had
632 	 * better be that sign too.
633 	 */
634 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
635 		ereport(ERROR,
636 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
637 				 errmsg("integer out of range")));
638 	PG_RETURN_INT32(result);
639 }
640 
641 Datum
int4mi(PG_FUNCTION_ARGS)642 int4mi(PG_FUNCTION_ARGS)
643 {
644 	int32		arg1 = PG_GETARG_INT32(0);
645 	int32		arg2 = PG_GETARG_INT32(1);
646 	int32		result;
647 
648 	result = arg1 - arg2;
649 
650 	/*
651 	 * Overflow check.  If the inputs are of the same sign then their
652 	 * difference cannot overflow.  If they are of different signs then the
653 	 * result should be of the same sign as the first input.
654 	 */
655 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
656 		ereport(ERROR,
657 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
658 				 errmsg("integer out of range")));
659 	PG_RETURN_INT32(result);
660 }
661 
662 Datum
int4mul(PG_FUNCTION_ARGS)663 int4mul(PG_FUNCTION_ARGS)
664 {
665 	int32		arg1 = PG_GETARG_INT32(0);
666 	int32		arg2 = PG_GETARG_INT32(1);
667 	int32		result;
668 
669 	result = arg1 * arg2;
670 
671 	/*
672 	 * Overflow check.  We basically check to see if result / arg2 gives arg1
673 	 * again.  There are two cases where this fails: arg2 = 0 (which cannot
674 	 * overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
675 	 * overflow and thus incorrectly match).
676 	 *
677 	 * Since the division is likely much more expensive than the actual
678 	 * multiplication, we'd like to skip it where possible.  The best bang for
679 	 * the buck seems to be to check whether both inputs are in the int16
680 	 * range; if so, no overflow is possible.
681 	 */
682 	if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
683 		  arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
684 		arg2 != 0 &&
685 		((arg2 == -1 && arg1 < 0 && result < 0) ||
686 		 result / arg2 != arg1))
687 		ereport(ERROR,
688 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
689 				 errmsg("integer out of range")));
690 	PG_RETURN_INT32(result);
691 }
692 
693 Datum
int4div(PG_FUNCTION_ARGS)694 int4div(PG_FUNCTION_ARGS)
695 {
696 	int32		arg1 = PG_GETARG_INT32(0);
697 	int32		arg2 = PG_GETARG_INT32(1);
698 	int32		result;
699 
700 	if (arg2 == 0)
701 	{
702 		ereport(ERROR,
703 				(errcode(ERRCODE_DIVISION_BY_ZERO),
704 				 errmsg("division by zero")));
705 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
706 		PG_RETURN_NULL();
707 	}
708 
709 	/*
710 	 * INT_MIN / -1 is problematic, since the result can't be represented on a
711 	 * two's-complement machine.  Some machines produce INT_MIN, some produce
712 	 * zero, some throw an exception.  We can dodge the problem by recognizing
713 	 * that division by -1 is the same as negation.
714 	 */
715 	if (arg2 == -1)
716 	{
717 		result = -arg1;
718 		/* overflow check (needed for INT_MIN) */
719 		if (arg1 != 0 && SAMESIGN(result, arg1))
720 			ereport(ERROR,
721 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
722 					 errmsg("integer out of range")));
723 		PG_RETURN_INT32(result);
724 	}
725 
726 	/* No overflow is possible */
727 
728 	result = arg1 / arg2;
729 
730 	PG_RETURN_INT32(result);
731 }
732 
733 Datum
int4inc(PG_FUNCTION_ARGS)734 int4inc(PG_FUNCTION_ARGS)
735 {
736 	int32		arg = PG_GETARG_INT32(0);
737 	int32		result;
738 
739 	result = arg + 1;
740 	/* Overflow check */
741 	if (arg > 0 && result < 0)
742 		ereport(ERROR,
743 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
744 				 errmsg("integer out of range")));
745 
746 	PG_RETURN_INT32(result);
747 }
748 
749 Datum
int2um(PG_FUNCTION_ARGS)750 int2um(PG_FUNCTION_ARGS)
751 {
752 	int16		arg = PG_GETARG_INT16(0);
753 	int16		result;
754 
755 	result = -arg;
756 	/* overflow check (needed for SHRT_MIN) */
757 	if (arg != 0 && SAMESIGN(result, arg))
758 		ereport(ERROR,
759 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
760 				 errmsg("smallint out of range")));
761 	PG_RETURN_INT16(result);
762 }
763 
764 Datum
int2up(PG_FUNCTION_ARGS)765 int2up(PG_FUNCTION_ARGS)
766 {
767 	int16		arg = PG_GETARG_INT16(0);
768 
769 	PG_RETURN_INT16(arg);
770 }
771 
772 Datum
int2pl(PG_FUNCTION_ARGS)773 int2pl(PG_FUNCTION_ARGS)
774 {
775 	int16		arg1 = PG_GETARG_INT16(0);
776 	int16		arg2 = PG_GETARG_INT16(1);
777 	int16		result;
778 
779 	result = arg1 + arg2;
780 
781 	/*
782 	 * Overflow check.  If the inputs are of different signs then their sum
783 	 * cannot overflow.  If the inputs are of the same sign, their sum had
784 	 * better be that sign too.
785 	 */
786 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
787 		ereport(ERROR,
788 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
789 				 errmsg("smallint out of range")));
790 	PG_RETURN_INT16(result);
791 }
792 
793 Datum
int2mi(PG_FUNCTION_ARGS)794 int2mi(PG_FUNCTION_ARGS)
795 {
796 	int16		arg1 = PG_GETARG_INT16(0);
797 	int16		arg2 = PG_GETARG_INT16(1);
798 	int16		result;
799 
800 	result = arg1 - arg2;
801 
802 	/*
803 	 * Overflow check.  If the inputs are of the same sign then their
804 	 * difference cannot overflow.  If they are of different signs then the
805 	 * result should be of the same sign as the first input.
806 	 */
807 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
808 		ereport(ERROR,
809 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
810 				 errmsg("smallint out of range")));
811 	PG_RETURN_INT16(result);
812 }
813 
814 Datum
int2mul(PG_FUNCTION_ARGS)815 int2mul(PG_FUNCTION_ARGS)
816 {
817 	int16		arg1 = PG_GETARG_INT16(0);
818 	int16		arg2 = PG_GETARG_INT16(1);
819 	int32		result32;
820 
821 	/*
822 	 * The most practical way to detect overflow is to do the arithmetic in
823 	 * int32 (so that the result can't overflow) and then do a range check.
824 	 */
825 	result32 = (int32) arg1 * (int32) arg2;
826 
827 	if (result32 < SHRT_MIN || result32 > SHRT_MAX)
828 		ereport(ERROR,
829 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
830 				 errmsg("smallint out of range")));
831 
832 	PG_RETURN_INT16((int16) result32);
833 }
834 
835 Datum
int2div(PG_FUNCTION_ARGS)836 int2div(PG_FUNCTION_ARGS)
837 {
838 	int16		arg1 = PG_GETARG_INT16(0);
839 	int16		arg2 = PG_GETARG_INT16(1);
840 	int16		result;
841 
842 	if (arg2 == 0)
843 	{
844 		ereport(ERROR,
845 				(errcode(ERRCODE_DIVISION_BY_ZERO),
846 				 errmsg("division by zero")));
847 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
848 		PG_RETURN_NULL();
849 	}
850 
851 	/*
852 	 * SHRT_MIN / -1 is problematic, since the result can't be represented on
853 	 * a two's-complement machine.  Some machines produce SHRT_MIN, some
854 	 * produce zero, some throw an exception.  We can dodge the problem by
855 	 * recognizing that division by -1 is the same as negation.
856 	 */
857 	if (arg2 == -1)
858 	{
859 		result = -arg1;
860 		/* overflow check (needed for SHRT_MIN) */
861 		if (arg1 != 0 && SAMESIGN(result, arg1))
862 			ereport(ERROR,
863 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
864 					 errmsg("smallint out of range")));
865 		PG_RETURN_INT16(result);
866 	}
867 
868 	/* No overflow is possible */
869 
870 	result = arg1 / arg2;
871 
872 	PG_RETURN_INT16(result);
873 }
874 
875 Datum
int24pl(PG_FUNCTION_ARGS)876 int24pl(PG_FUNCTION_ARGS)
877 {
878 	int16		arg1 = PG_GETARG_INT16(0);
879 	int32		arg2 = PG_GETARG_INT32(1);
880 	int32		result;
881 
882 	result = arg1 + arg2;
883 
884 	/*
885 	 * Overflow check.  If the inputs are of different signs then their sum
886 	 * cannot overflow.  If the inputs are of the same sign, their sum had
887 	 * better be that sign too.
888 	 */
889 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
890 		ereport(ERROR,
891 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
892 				 errmsg("integer out of range")));
893 	PG_RETURN_INT32(result);
894 }
895 
896 Datum
int24mi(PG_FUNCTION_ARGS)897 int24mi(PG_FUNCTION_ARGS)
898 {
899 	int16		arg1 = PG_GETARG_INT16(0);
900 	int32		arg2 = PG_GETARG_INT32(1);
901 	int32		result;
902 
903 	result = arg1 - arg2;
904 
905 	/*
906 	 * Overflow check.  If the inputs are of the same sign then their
907 	 * difference cannot overflow.  If they are of different signs then the
908 	 * result should be of the same sign as the first input.
909 	 */
910 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
911 		ereport(ERROR,
912 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
913 				 errmsg("integer out of range")));
914 	PG_RETURN_INT32(result);
915 }
916 
917 Datum
int24mul(PG_FUNCTION_ARGS)918 int24mul(PG_FUNCTION_ARGS)
919 {
920 	int16		arg1 = PG_GETARG_INT16(0);
921 	int32		arg2 = PG_GETARG_INT32(1);
922 	int32		result;
923 
924 	result = arg1 * arg2;
925 
926 	/*
927 	 * Overflow check.  We basically check to see if result / arg2 gives arg1
928 	 * again.  There is one case where this fails: arg2 = 0 (which cannot
929 	 * overflow).
930 	 *
931 	 * Since the division is likely much more expensive than the actual
932 	 * multiplication, we'd like to skip it where possible.  The best bang for
933 	 * the buck seems to be to check whether both inputs are in the int16
934 	 * range; if so, no overflow is possible.
935 	 */
936 	if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
937 		result / arg2 != arg1)
938 		ereport(ERROR,
939 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
940 				 errmsg("integer out of range")));
941 	PG_RETURN_INT32(result);
942 }
943 
944 Datum
int24div(PG_FUNCTION_ARGS)945 int24div(PG_FUNCTION_ARGS)
946 {
947 	int16		arg1 = PG_GETARG_INT16(0);
948 	int32		arg2 = PG_GETARG_INT32(1);
949 
950 	if (arg2 == 0)
951 	{
952 		ereport(ERROR,
953 				(errcode(ERRCODE_DIVISION_BY_ZERO),
954 				 errmsg("division by zero")));
955 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
956 		PG_RETURN_NULL();
957 	}
958 
959 	/* No overflow is possible */
960 	PG_RETURN_INT32((int32) arg1 / arg2);
961 }
962 
963 Datum
int42pl(PG_FUNCTION_ARGS)964 int42pl(PG_FUNCTION_ARGS)
965 {
966 	int32		arg1 = PG_GETARG_INT32(0);
967 	int16		arg2 = PG_GETARG_INT16(1);
968 	int32		result;
969 
970 	result = arg1 + arg2;
971 
972 	/*
973 	 * Overflow check.  If the inputs are of different signs then their sum
974 	 * cannot overflow.  If the inputs are of the same sign, their sum had
975 	 * better be that sign too.
976 	 */
977 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
978 		ereport(ERROR,
979 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
980 				 errmsg("integer out of range")));
981 	PG_RETURN_INT32(result);
982 }
983 
984 Datum
int42mi(PG_FUNCTION_ARGS)985 int42mi(PG_FUNCTION_ARGS)
986 {
987 	int32		arg1 = PG_GETARG_INT32(0);
988 	int16		arg2 = PG_GETARG_INT16(1);
989 	int32		result;
990 
991 	result = arg1 - arg2;
992 
993 	/*
994 	 * Overflow check.  If the inputs are of the same sign then their
995 	 * difference cannot overflow.  If they are of different signs then the
996 	 * result should be of the same sign as the first input.
997 	 */
998 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
999 		ereport(ERROR,
1000 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1001 				 errmsg("integer out of range")));
1002 	PG_RETURN_INT32(result);
1003 }
1004 
1005 Datum
int42mul(PG_FUNCTION_ARGS)1006 int42mul(PG_FUNCTION_ARGS)
1007 {
1008 	int32		arg1 = PG_GETARG_INT32(0);
1009 	int16		arg2 = PG_GETARG_INT16(1);
1010 	int32		result;
1011 
1012 	result = arg1 * arg2;
1013 
1014 	/*
1015 	 * Overflow check.  We basically check to see if result / arg1 gives arg2
1016 	 * again.  There is one case where this fails: arg1 = 0 (which cannot
1017 	 * overflow).
1018 	 *
1019 	 * Since the division is likely much more expensive than the actual
1020 	 * multiplication, we'd like to skip it where possible.  The best bang for
1021 	 * the buck seems to be to check whether both inputs are in the int16
1022 	 * range; if so, no overflow is possible.
1023 	 */
1024 	if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
1025 		result / arg1 != arg2)
1026 		ereport(ERROR,
1027 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1028 				 errmsg("integer out of range")));
1029 	PG_RETURN_INT32(result);
1030 }
1031 
1032 Datum
int42div(PG_FUNCTION_ARGS)1033 int42div(PG_FUNCTION_ARGS)
1034 {
1035 	int32		arg1 = PG_GETARG_INT32(0);
1036 	int16		arg2 = PG_GETARG_INT16(1);
1037 	int32		result;
1038 
1039 	if (arg2 == 0)
1040 	{
1041 		ereport(ERROR,
1042 				(errcode(ERRCODE_DIVISION_BY_ZERO),
1043 				 errmsg("division by zero")));
1044 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
1045 		PG_RETURN_NULL();
1046 	}
1047 
1048 	/*
1049 	 * INT_MIN / -1 is problematic, since the result can't be represented on a
1050 	 * two's-complement machine.  Some machines produce INT_MIN, some produce
1051 	 * zero, some throw an exception.  We can dodge the problem by recognizing
1052 	 * that division by -1 is the same as negation.
1053 	 */
1054 	if (arg2 == -1)
1055 	{
1056 		result = -arg1;
1057 		/* overflow check (needed for INT_MIN) */
1058 		if (arg1 != 0 && SAMESIGN(result, arg1))
1059 			ereport(ERROR,
1060 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1061 					 errmsg("integer out of range")));
1062 		PG_RETURN_INT32(result);
1063 	}
1064 
1065 	/* No overflow is possible */
1066 
1067 	result = arg1 / arg2;
1068 
1069 	PG_RETURN_INT32(result);
1070 }
1071 
1072 Datum
int4mod(PG_FUNCTION_ARGS)1073 int4mod(PG_FUNCTION_ARGS)
1074 {
1075 	int32		arg1 = PG_GETARG_INT32(0);
1076 	int32		arg2 = PG_GETARG_INT32(1);
1077 
1078 	if (arg2 == 0)
1079 	{
1080 		ereport(ERROR,
1081 				(errcode(ERRCODE_DIVISION_BY_ZERO),
1082 				 errmsg("division by zero")));
1083 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
1084 		PG_RETURN_NULL();
1085 	}
1086 
1087 	/*
1088 	 * Some machines throw a floating-point exception for INT_MIN % -1, which
1089 	 * is a bit silly since the correct answer is perfectly well-defined,
1090 	 * namely zero.
1091 	 */
1092 	if (arg2 == -1)
1093 		PG_RETURN_INT32(0);
1094 
1095 	/* No overflow is possible */
1096 
1097 	PG_RETURN_INT32(arg1 % arg2);
1098 }
1099 
1100 Datum
int2mod(PG_FUNCTION_ARGS)1101 int2mod(PG_FUNCTION_ARGS)
1102 {
1103 	int16		arg1 = PG_GETARG_INT16(0);
1104 	int16		arg2 = PG_GETARG_INT16(1);
1105 
1106 	if (arg2 == 0)
1107 	{
1108 		ereport(ERROR,
1109 				(errcode(ERRCODE_DIVISION_BY_ZERO),
1110 				 errmsg("division by zero")));
1111 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
1112 		PG_RETURN_NULL();
1113 	}
1114 
1115 	/*
1116 	 * Some machines throw a floating-point exception for INT_MIN % -1, which
1117 	 * is a bit silly since the correct answer is perfectly well-defined,
1118 	 * namely zero.  (It's not clear this ever happens when dealing with
1119 	 * int16, but we might as well have the test for safety.)
1120 	 */
1121 	if (arg2 == -1)
1122 		PG_RETURN_INT16(0);
1123 
1124 	/* No overflow is possible */
1125 
1126 	PG_RETURN_INT16(arg1 % arg2);
1127 }
1128 
1129 
1130 /* int[24]abs()
1131  * Absolute value
1132  */
1133 Datum
int4abs(PG_FUNCTION_ARGS)1134 int4abs(PG_FUNCTION_ARGS)
1135 {
1136 	int32		arg1 = PG_GETARG_INT32(0);
1137 	int32		result;
1138 
1139 	result = (arg1 < 0) ? -arg1 : arg1;
1140 	/* overflow check (needed for INT_MIN) */
1141 	if (result < 0)
1142 		ereport(ERROR,
1143 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1144 				 errmsg("integer out of range")));
1145 	PG_RETURN_INT32(result);
1146 }
1147 
1148 Datum
int2abs(PG_FUNCTION_ARGS)1149 int2abs(PG_FUNCTION_ARGS)
1150 {
1151 	int16		arg1 = PG_GETARG_INT16(0);
1152 	int16		result;
1153 
1154 	result = (arg1 < 0) ? -arg1 : arg1;
1155 	/* overflow check (needed for SHRT_MIN) */
1156 	if (result < 0)
1157 		ereport(ERROR,
1158 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1159 				 errmsg("smallint out of range")));
1160 	PG_RETURN_INT16(result);
1161 }
1162 
1163 Datum
int2larger(PG_FUNCTION_ARGS)1164 int2larger(PG_FUNCTION_ARGS)
1165 {
1166 	int16		arg1 = PG_GETARG_INT16(0);
1167 	int16		arg2 = PG_GETARG_INT16(1);
1168 
1169 	PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1170 }
1171 
1172 Datum
int2smaller(PG_FUNCTION_ARGS)1173 int2smaller(PG_FUNCTION_ARGS)
1174 {
1175 	int16		arg1 = PG_GETARG_INT16(0);
1176 	int16		arg2 = PG_GETARG_INT16(1);
1177 
1178 	PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
1179 }
1180 
1181 Datum
int4larger(PG_FUNCTION_ARGS)1182 int4larger(PG_FUNCTION_ARGS)
1183 {
1184 	int32		arg1 = PG_GETARG_INT32(0);
1185 	int32		arg2 = PG_GETARG_INT32(1);
1186 
1187 	PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1188 }
1189 
1190 Datum
int4smaller(PG_FUNCTION_ARGS)1191 int4smaller(PG_FUNCTION_ARGS)
1192 {
1193 	int32		arg1 = PG_GETARG_INT32(0);
1194 	int32		arg2 = PG_GETARG_INT32(1);
1195 
1196 	PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1197 }
1198 
1199 /*
1200  * Bit-pushing operators
1201  *
1202  *		int[24]and		- returns arg1 & arg2
1203  *		int[24]or		- returns arg1 | arg2
1204  *		int[24]xor		- returns arg1 # arg2
1205  *		int[24]not		- returns ~arg1
1206  *		int[24]shl		- returns arg1 << arg2
1207  *		int[24]shr		- returns arg1 >> arg2
1208  */
1209 
1210 Datum
int4and(PG_FUNCTION_ARGS)1211 int4and(PG_FUNCTION_ARGS)
1212 {
1213 	int32		arg1 = PG_GETARG_INT32(0);
1214 	int32		arg2 = PG_GETARG_INT32(1);
1215 
1216 	PG_RETURN_INT32(arg1 & arg2);
1217 }
1218 
1219 Datum
int4or(PG_FUNCTION_ARGS)1220 int4or(PG_FUNCTION_ARGS)
1221 {
1222 	int32		arg1 = PG_GETARG_INT32(0);
1223 	int32		arg2 = PG_GETARG_INT32(1);
1224 
1225 	PG_RETURN_INT32(arg1 | arg2);
1226 }
1227 
1228 Datum
int4xor(PG_FUNCTION_ARGS)1229 int4xor(PG_FUNCTION_ARGS)
1230 {
1231 	int32		arg1 = PG_GETARG_INT32(0);
1232 	int32		arg2 = PG_GETARG_INT32(1);
1233 
1234 	PG_RETURN_INT32(arg1 ^ arg2);
1235 }
1236 
1237 Datum
int4shl(PG_FUNCTION_ARGS)1238 int4shl(PG_FUNCTION_ARGS)
1239 {
1240 	int32		arg1 = PG_GETARG_INT32(0);
1241 	int32		arg2 = PG_GETARG_INT32(1);
1242 
1243 	PG_RETURN_INT32(arg1 << arg2);
1244 }
1245 
1246 Datum
int4shr(PG_FUNCTION_ARGS)1247 int4shr(PG_FUNCTION_ARGS)
1248 {
1249 	int32		arg1 = PG_GETARG_INT32(0);
1250 	int32		arg2 = PG_GETARG_INT32(1);
1251 
1252 	PG_RETURN_INT32(arg1 >> arg2);
1253 }
1254 
1255 Datum
int4not(PG_FUNCTION_ARGS)1256 int4not(PG_FUNCTION_ARGS)
1257 {
1258 	int32		arg1 = PG_GETARG_INT32(0);
1259 
1260 	PG_RETURN_INT32(~arg1);
1261 }
1262 
1263 Datum
int2and(PG_FUNCTION_ARGS)1264 int2and(PG_FUNCTION_ARGS)
1265 {
1266 	int16		arg1 = PG_GETARG_INT16(0);
1267 	int16		arg2 = PG_GETARG_INT16(1);
1268 
1269 	PG_RETURN_INT16(arg1 & arg2);
1270 }
1271 
1272 Datum
int2or(PG_FUNCTION_ARGS)1273 int2or(PG_FUNCTION_ARGS)
1274 {
1275 	int16		arg1 = PG_GETARG_INT16(0);
1276 	int16		arg2 = PG_GETARG_INT16(1);
1277 
1278 	PG_RETURN_INT16(arg1 | arg2);
1279 }
1280 
1281 Datum
int2xor(PG_FUNCTION_ARGS)1282 int2xor(PG_FUNCTION_ARGS)
1283 {
1284 	int16		arg1 = PG_GETARG_INT16(0);
1285 	int16		arg2 = PG_GETARG_INT16(1);
1286 
1287 	PG_RETURN_INT16(arg1 ^ arg2);
1288 }
1289 
1290 Datum
int2not(PG_FUNCTION_ARGS)1291 int2not(PG_FUNCTION_ARGS)
1292 {
1293 	int16		arg1 = PG_GETARG_INT16(0);
1294 
1295 	PG_RETURN_INT16(~arg1);
1296 }
1297 
1298 
1299 Datum
int2shl(PG_FUNCTION_ARGS)1300 int2shl(PG_FUNCTION_ARGS)
1301 {
1302 	int16		arg1 = PG_GETARG_INT16(0);
1303 	int32		arg2 = PG_GETARG_INT32(1);
1304 
1305 	PG_RETURN_INT16(arg1 << arg2);
1306 }
1307 
1308 Datum
int2shr(PG_FUNCTION_ARGS)1309 int2shr(PG_FUNCTION_ARGS)
1310 {
1311 	int16		arg1 = PG_GETARG_INT16(0);
1312 	int32		arg2 = PG_GETARG_INT32(1);
1313 
1314 	PG_RETURN_INT16(arg1 >> arg2);
1315 }
1316 
1317 /*
1318  * non-persistent numeric series generator
1319  */
1320 Datum
generate_series_int4(PG_FUNCTION_ARGS)1321 generate_series_int4(PG_FUNCTION_ARGS)
1322 {
1323 	return generate_series_step_int4(fcinfo);
1324 }
1325 
1326 Datum
generate_series_step_int4(PG_FUNCTION_ARGS)1327 generate_series_step_int4(PG_FUNCTION_ARGS)
1328 {
1329 	FuncCallContext *funcctx;
1330 	generate_series_fctx *fctx;
1331 	int32		result;
1332 	MemoryContext oldcontext;
1333 
1334 	/* stuff done only on the first call of the function */
1335 	if (SRF_IS_FIRSTCALL())
1336 	{
1337 		int32		start = PG_GETARG_INT32(0);
1338 		int32		finish = PG_GETARG_INT32(1);
1339 		int32		step = 1;
1340 
1341 		/* see if we were given an explicit step size */
1342 		if (PG_NARGS() == 3)
1343 			step = PG_GETARG_INT32(2);
1344 		if (step == 0)
1345 			ereport(ERROR,
1346 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1347 					 errmsg("step size cannot equal zero")));
1348 
1349 		/* create a function context for cross-call persistence */
1350 		funcctx = SRF_FIRSTCALL_INIT();
1351 
1352 		/*
1353 		 * switch to memory context appropriate for multiple function calls
1354 		 */
1355 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1356 
1357 		/* allocate memory for user context */
1358 		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1359 
1360 		/*
1361 		 * Use fctx to keep state from call to call. Seed current with the
1362 		 * original start value
1363 		 */
1364 		fctx->current = start;
1365 		fctx->finish = finish;
1366 		fctx->step = step;
1367 
1368 		funcctx->user_fctx = fctx;
1369 		MemoryContextSwitchTo(oldcontext);
1370 	}
1371 
1372 	/* stuff done on every call of the function */
1373 	funcctx = SRF_PERCALL_SETUP();
1374 
1375 	/*
1376 	 * get the saved state and use current as the result for this iteration
1377 	 */
1378 	fctx = funcctx->user_fctx;
1379 	result = fctx->current;
1380 
1381 	if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1382 		(fctx->step < 0 && fctx->current >= fctx->finish))
1383 	{
1384 		/* increment current in preparation for next iteration */
1385 		fctx->current += fctx->step;
1386 
1387 		/* if next-value computation overflows, this is the final result */
1388 		if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
1389 			fctx->step = 0;
1390 
1391 		/* do when there is more left to send */
1392 		SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1393 	}
1394 	else
1395 		/* do when there is no more left */
1396 		SRF_RETURN_DONE(funcctx);
1397 }
1398