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