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