]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/int8.c
6418da312e03e0377d514e7d4aebd14f86237b6e
[postgresql] / src / backend / utils / adt / int8.c
1 /*-------------------------------------------------------------------------
2  *
3  * int8.c
4  *        Internal 64-bit integer operations
5  *
6  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.59 2005/10/15 02:49:28 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include <ctype.h>
17 #include <limits.h>
18 #include <math.h>
19
20 #include "funcapi.h"
21 #include "libpq/pqformat.h"
22 #include "nodes/nodes.h"
23 #include "utils/int8.h"
24
25
26 #define MAXINT8LEN              25
27
28 #define SAMESIGN(a,b)   (((a) < 0) == ((b) < 0))
29
30 typedef struct
31 {
32         int64           current;
33         int64           finish;
34         int64           step;
35 } generate_series_fctx;
36
37
38 /***********************************************************************
39  **
40  **             Routines for 64-bit integers.
41  **
42  ***********************************************************************/
43
44 /*----------------------------------------------------------
45  * Formatting and conversion routines.
46  *---------------------------------------------------------*/
47
48 /*
49  * scanint8 --- try to parse a string into an int8.
50  *
51  * If errorOK is false, ereport a useful error message if the string is bad.
52  * If errorOK is true, just return "false" for bad input.
53  */
54 bool
55 scanint8(const char *str, bool errorOK, int64 *result)
56 {
57         const char *ptr = str;
58         int64           tmp = 0;
59         int                     sign = 1;
60
61         /*
62          * Do our own scan, rather than relying on sscanf which might be broken
63          * for long long.
64          */
65
66         /* skip leading spaces */
67         while (*ptr && isspace((unsigned char) *ptr))
68                 ptr++;
69
70         /* handle sign */
71         if (*ptr == '-')
72         {
73                 ptr++;
74
75                 /*
76                  * Do an explicit check for INT64_MIN.  Ugly though this is, it's
77                  * cleaner than trying to get the loop below to handle it portably.
78                  */
79 #ifndef INT64_IS_BUSTED
80                 if (strncmp(ptr, "9223372036854775808", 19) == 0)
81                 {
82                         tmp = -INT64CONST(0x7fffffffffffffff) - 1;
83                         ptr += 19;
84                         goto gotdigits;
85                 }
86 #endif
87
88                 sign = -1;
89         }
90         else if (*ptr == '+')
91                 ptr++;
92
93         /* require at least one digit */
94         if (!isdigit((unsigned char) *ptr))
95         {
96                 if (errorOK)
97                         return false;
98                 else
99                         ereport(ERROR,
100                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
101                                          errmsg("invalid input syntax for integer: \"%s\"",
102                                                         str)));
103         }
104
105         /* process digits */
106         while (*ptr && isdigit((unsigned char) *ptr))
107         {
108                 int64           newtmp = tmp * 10 + (*ptr++ - '0');
109
110                 if ((newtmp / 10) != tmp)               /* overflow? */
111                 {
112                         if (errorOK)
113                                 return false;
114                         else
115                                 ereport(ERROR,
116                                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
117                                            errmsg("value \"%s\" is out of range for type bigint",
118                                                           str)));
119                 }
120                 tmp = newtmp;
121         }
122
123 gotdigits:
124
125         /* allow trailing whitespace, but not other trailing chars */
126         while (*ptr != '\0' && isspace((unsigned char) *ptr))
127                 ptr++;
128
129         if (*ptr != '\0')
130         {
131                 if (errorOK)
132                         return false;
133                 else
134                         ereport(ERROR,
135                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
136                                          errmsg("invalid input syntax for integer: \"%s\"",
137                                                         str)));
138         }
139
140         *result = (sign < 0) ? -tmp : tmp;
141
142         return true;
143 }
144
145 /* int8in()
146  */
147 Datum
148 int8in(PG_FUNCTION_ARGS)
149 {
150         char       *str = PG_GETARG_CSTRING(0);
151         int64           result;
152
153         (void) scanint8(str, false, &result);
154         PG_RETURN_INT64(result);
155 }
156
157
158 /* int8out()
159  */
160 Datum
161 int8out(PG_FUNCTION_ARGS)
162 {
163         int64           val = PG_GETARG_INT64(0);
164         char       *result;
165         int                     len;
166         char            buf[MAXINT8LEN + 1];
167
168         if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0)
169                 elog(ERROR, "could not format int8");
170
171         result = pstrdup(buf);
172         PG_RETURN_CSTRING(result);
173 }
174
175 /*
176  *              int8recv                        - converts external binary format to int8
177  */
178 Datum
179 int8recv(PG_FUNCTION_ARGS)
180 {
181         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
182
183         PG_RETURN_INT64(pq_getmsgint64(buf));
184 }
185
186 /*
187  *              int8send                        - converts int8 to binary format
188  */
189 Datum
190 int8send(PG_FUNCTION_ARGS)
191 {
192         int64           arg1 = PG_GETARG_INT64(0);
193         StringInfoData buf;
194
195         pq_begintypsend(&buf);
196         pq_sendint64(&buf, arg1);
197         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
198 }
199
200
201 /*----------------------------------------------------------
202  *      Relational operators for int8s, including cross-data-type comparisons.
203  *---------------------------------------------------------*/
204
205 /* int8relop()
206  * Is val1 relop val2?
207  */
208 Datum
209 int8eq(PG_FUNCTION_ARGS)
210 {
211         int64           val1 = PG_GETARG_INT64(0);
212         int64           val2 = PG_GETARG_INT64(1);
213
214         PG_RETURN_BOOL(val1 == val2);
215 }
216
217 Datum
218 int8ne(PG_FUNCTION_ARGS)
219 {
220         int64           val1 = PG_GETARG_INT64(0);
221         int64           val2 = PG_GETARG_INT64(1);
222
223         PG_RETURN_BOOL(val1 != val2);
224 }
225
226 Datum
227 int8lt(PG_FUNCTION_ARGS)
228 {
229         int64           val1 = PG_GETARG_INT64(0);
230         int64           val2 = PG_GETARG_INT64(1);
231
232         PG_RETURN_BOOL(val1 < val2);
233 }
234
235 Datum
236 int8gt(PG_FUNCTION_ARGS)
237 {
238         int64           val1 = PG_GETARG_INT64(0);
239         int64           val2 = PG_GETARG_INT64(1);
240
241         PG_RETURN_BOOL(val1 > val2);
242 }
243
244 Datum
245 int8le(PG_FUNCTION_ARGS)
246 {
247         int64           val1 = PG_GETARG_INT64(0);
248         int64           val2 = PG_GETARG_INT64(1);
249
250         PG_RETURN_BOOL(val1 <= val2);
251 }
252
253 Datum
254 int8ge(PG_FUNCTION_ARGS)
255 {
256         int64           val1 = PG_GETARG_INT64(0);
257         int64           val2 = PG_GETARG_INT64(1);
258
259         PG_RETURN_BOOL(val1 >= val2);
260 }
261
262 /* int84relop()
263  * Is 64-bit val1 relop 32-bit val2?
264  */
265 Datum
266 int84eq(PG_FUNCTION_ARGS)
267 {
268         int64           val1 = PG_GETARG_INT64(0);
269         int32           val2 = PG_GETARG_INT32(1);
270
271         PG_RETURN_BOOL(val1 == val2);
272 }
273
274 Datum
275 int84ne(PG_FUNCTION_ARGS)
276 {
277         int64           val1 = PG_GETARG_INT64(0);
278         int32           val2 = PG_GETARG_INT32(1);
279
280         PG_RETURN_BOOL(val1 != val2);
281 }
282
283 Datum
284 int84lt(PG_FUNCTION_ARGS)
285 {
286         int64           val1 = PG_GETARG_INT64(0);
287         int32           val2 = PG_GETARG_INT32(1);
288
289         PG_RETURN_BOOL(val1 < val2);
290 }
291
292 Datum
293 int84gt(PG_FUNCTION_ARGS)
294 {
295         int64           val1 = PG_GETARG_INT64(0);
296         int32           val2 = PG_GETARG_INT32(1);
297
298         PG_RETURN_BOOL(val1 > val2);
299 }
300
301 Datum
302 int84le(PG_FUNCTION_ARGS)
303 {
304         int64           val1 = PG_GETARG_INT64(0);
305         int32           val2 = PG_GETARG_INT32(1);
306
307         PG_RETURN_BOOL(val1 <= val2);
308 }
309
310 Datum
311 int84ge(PG_FUNCTION_ARGS)
312 {
313         int64           val1 = PG_GETARG_INT64(0);
314         int32           val2 = PG_GETARG_INT32(1);
315
316         PG_RETURN_BOOL(val1 >= val2);
317 }
318
319 /* int48relop()
320  * Is 32-bit val1 relop 64-bit val2?
321  */
322 Datum
323 int48eq(PG_FUNCTION_ARGS)
324 {
325         int32           val1 = PG_GETARG_INT32(0);
326         int64           val2 = PG_GETARG_INT64(1);
327
328         PG_RETURN_BOOL(val1 == val2);
329 }
330
331 Datum
332 int48ne(PG_FUNCTION_ARGS)
333 {
334         int32           val1 = PG_GETARG_INT32(0);
335         int64           val2 = PG_GETARG_INT64(1);
336
337         PG_RETURN_BOOL(val1 != val2);
338 }
339
340 Datum
341 int48lt(PG_FUNCTION_ARGS)
342 {
343         int32           val1 = PG_GETARG_INT32(0);
344         int64           val2 = PG_GETARG_INT64(1);
345
346         PG_RETURN_BOOL(val1 < val2);
347 }
348
349 Datum
350 int48gt(PG_FUNCTION_ARGS)
351 {
352         int32           val1 = PG_GETARG_INT32(0);
353         int64           val2 = PG_GETARG_INT64(1);
354
355         PG_RETURN_BOOL(val1 > val2);
356 }
357
358 Datum
359 int48le(PG_FUNCTION_ARGS)
360 {
361         int32           val1 = PG_GETARG_INT32(0);
362         int64           val2 = PG_GETARG_INT64(1);
363
364         PG_RETURN_BOOL(val1 <= val2);
365 }
366
367 Datum
368 int48ge(PG_FUNCTION_ARGS)
369 {
370         int32           val1 = PG_GETARG_INT32(0);
371         int64           val2 = PG_GETARG_INT64(1);
372
373         PG_RETURN_BOOL(val1 >= val2);
374 }
375
376 /* int82relop()
377  * Is 64-bit val1 relop 16-bit val2?
378  */
379 Datum
380 int82eq(PG_FUNCTION_ARGS)
381 {
382         int64           val1 = PG_GETARG_INT64(0);
383         int16           val2 = PG_GETARG_INT16(1);
384
385         PG_RETURN_BOOL(val1 == val2);
386 }
387
388 Datum
389 int82ne(PG_FUNCTION_ARGS)
390 {
391         int64           val1 = PG_GETARG_INT64(0);
392         int16           val2 = PG_GETARG_INT16(1);
393
394         PG_RETURN_BOOL(val1 != val2);
395 }
396
397 Datum
398 int82lt(PG_FUNCTION_ARGS)
399 {
400         int64           val1 = PG_GETARG_INT64(0);
401         int16           val2 = PG_GETARG_INT16(1);
402
403         PG_RETURN_BOOL(val1 < val2);
404 }
405
406 Datum
407 int82gt(PG_FUNCTION_ARGS)
408 {
409         int64           val1 = PG_GETARG_INT64(0);
410         int16           val2 = PG_GETARG_INT16(1);
411
412         PG_RETURN_BOOL(val1 > val2);
413 }
414
415 Datum
416 int82le(PG_FUNCTION_ARGS)
417 {
418         int64           val1 = PG_GETARG_INT64(0);
419         int16           val2 = PG_GETARG_INT16(1);
420
421         PG_RETURN_BOOL(val1 <= val2);
422 }
423
424 Datum
425 int82ge(PG_FUNCTION_ARGS)
426 {
427         int64           val1 = PG_GETARG_INT64(0);
428         int16           val2 = PG_GETARG_INT16(1);
429
430         PG_RETURN_BOOL(val1 >= val2);
431 }
432
433 /* int28relop()
434  * Is 16-bit val1 relop 64-bit val2?
435  */
436 Datum
437 int28eq(PG_FUNCTION_ARGS)
438 {
439         int16           val1 = PG_GETARG_INT16(0);
440         int64           val2 = PG_GETARG_INT64(1);
441
442         PG_RETURN_BOOL(val1 == val2);
443 }
444
445 Datum
446 int28ne(PG_FUNCTION_ARGS)
447 {
448         int16           val1 = PG_GETARG_INT16(0);
449         int64           val2 = PG_GETARG_INT64(1);
450
451         PG_RETURN_BOOL(val1 != val2);
452 }
453
454 Datum
455 int28lt(PG_FUNCTION_ARGS)
456 {
457         int16           val1 = PG_GETARG_INT16(0);
458         int64           val2 = PG_GETARG_INT64(1);
459
460         PG_RETURN_BOOL(val1 < val2);
461 }
462
463 Datum
464 int28gt(PG_FUNCTION_ARGS)
465 {
466         int16           val1 = PG_GETARG_INT16(0);
467         int64           val2 = PG_GETARG_INT64(1);
468
469         PG_RETURN_BOOL(val1 > val2);
470 }
471
472 Datum
473 int28le(PG_FUNCTION_ARGS)
474 {
475         int16           val1 = PG_GETARG_INT16(0);
476         int64           val2 = PG_GETARG_INT64(1);
477
478         PG_RETURN_BOOL(val1 <= val2);
479 }
480
481 Datum
482 int28ge(PG_FUNCTION_ARGS)
483 {
484         int16           val1 = PG_GETARG_INT16(0);
485         int64           val2 = PG_GETARG_INT64(1);
486
487         PG_RETURN_BOOL(val1 >= val2);
488 }
489
490
491 /*----------------------------------------------------------
492  *      Arithmetic operators on 64-bit integers.
493  *---------------------------------------------------------*/
494
495 Datum
496 int8um(PG_FUNCTION_ARGS)
497 {
498         int64           arg = PG_GETARG_INT64(0);
499         int64           result;
500
501         result = -arg;
502         /* overflow check (needed for INT64_MIN) */
503         if (arg != 0 && SAMESIGN(result, arg))
504                 ereport(ERROR,
505                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
506                                  errmsg("bigint out of range")));
507         PG_RETURN_INT64(result);
508 }
509
510 Datum
511 int8up(PG_FUNCTION_ARGS)
512 {
513         int64           arg = PG_GETARG_INT64(0);
514
515         PG_RETURN_INT64(arg);
516 }
517
518 Datum
519 int8pl(PG_FUNCTION_ARGS)
520 {
521         int64           arg1 = PG_GETARG_INT64(0);
522         int64           arg2 = PG_GETARG_INT64(1);
523         int64           result;
524
525         result = arg1 + arg2;
526
527         /*
528          * Overflow check.      If the inputs are of different signs then their sum
529          * cannot overflow.  If the inputs are of the same sign, their sum had
530          * better be that sign too.
531          */
532         if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
533                 ereport(ERROR,
534                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
535                                  errmsg("bigint out of range")));
536         PG_RETURN_INT64(result);
537 }
538
539 Datum
540 int8mi(PG_FUNCTION_ARGS)
541 {
542         int64           arg1 = PG_GETARG_INT64(0);
543         int64           arg2 = PG_GETARG_INT64(1);
544         int64           result;
545
546         result = arg1 - arg2;
547
548         /*
549          * Overflow check.      If the inputs are of the same sign then their
550          * difference cannot overflow.  If they are of different signs then the
551          * result should be of the same sign as the first input.
552          */
553         if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
554                 ereport(ERROR,
555                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
556                                  errmsg("bigint out of range")));
557         PG_RETURN_INT64(result);
558 }
559
560 Datum
561 int8mul(PG_FUNCTION_ARGS)
562 {
563         int64           arg1 = PG_GETARG_INT64(0);
564         int64           arg2 = PG_GETARG_INT64(1);
565         int64           result;
566
567         result = arg1 * arg2;
568
569         /*
570          * Overflow check.      We basically check to see if result / arg2 gives arg1
571          * again.  There are two cases where this fails: arg2 = 0 (which cannot
572          * overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division itself
573          * will overflow and thus incorrectly match).
574          *
575          * Since the division is likely much more expensive than the actual
576          * multiplication, we'd like to skip it where possible.  The best bang for
577          * the buck seems to be to check whether both inputs are in the int32
578          * range; if so, no overflow is possible.
579          */
580         if (!(arg1 == (int64) ((int32) arg1) &&
581                   arg2 == (int64) ((int32) arg2)) &&
582                 arg2 != 0 &&
583                 (result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
584                 ereport(ERROR,
585                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
586                                  errmsg("bigint out of range")));
587         PG_RETURN_INT64(result);
588 }
589
590 Datum
591 int8div(PG_FUNCTION_ARGS)
592 {
593         int64           arg1 = PG_GETARG_INT64(0);
594         int64           arg2 = PG_GETARG_INT64(1);
595         int64           result;
596
597         if (arg2 == 0)
598                 ereport(ERROR,
599                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
600                                  errmsg("division by zero")));
601
602         result = arg1 / arg2;
603
604         /*
605          * Overflow check.      The only possible overflow case is for arg1 =
606          * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
607          * can't be represented on a two's-complement machine.
608          */
609         if (arg2 == -1 && arg1 < 0 && result < 0)
610                 ereport(ERROR,
611                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
612                                  errmsg("bigint out of range")));
613         PG_RETURN_INT64(result);
614 }
615
616 /* int8abs()
617  * Absolute value
618  */
619 Datum
620 int8abs(PG_FUNCTION_ARGS)
621 {
622         int64           arg1 = PG_GETARG_INT64(0);
623         int64           result;
624
625         result = (arg1 < 0) ? -arg1 : arg1;
626         /* overflow check (needed for INT64_MIN) */
627         if (result < 0)
628                 ereport(ERROR,
629                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
630                                  errmsg("bigint out of range")));
631         PG_RETURN_INT64(result);
632 }
633
634 /* int8mod()
635  * Modulo operation.
636  */
637 Datum
638 int8mod(PG_FUNCTION_ARGS)
639 {
640         int64           arg1 = PG_GETARG_INT64(0);
641         int64           arg2 = PG_GETARG_INT64(1);
642
643         if (arg2 == 0)
644                 ereport(ERROR,
645                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
646                                  errmsg("division by zero")));
647         /* No overflow is possible */
648
649         PG_RETURN_INT64(arg1 % arg2);
650 }
651
652
653 Datum
654 int8inc(PG_FUNCTION_ARGS)
655 {
656         if (fcinfo->context && IsA(fcinfo->context, AggState))
657         {
658                 /*
659                  * Special case to avoid palloc overhead for COUNT(): when called from
660                  * nodeAgg, we know that the argument is modifiable local storage, so
661                  * just update it in-place.
662                  *
663                  * Note: this assumes int8 is a pass-by-ref type; if we ever support
664                  * pass-by-val int8, this should be ifdef'd out when int8 is
665                  * pass-by-val.
666                  */
667                 int64      *arg = (int64 *) PG_GETARG_POINTER(0);
668                 int64           result;
669
670                 result = *arg + 1;
671                 /* Overflow check */
672                 if (result < 0 && *arg > 0)
673                         ereport(ERROR,
674                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
675                                          errmsg("bigint out of range")));
676
677                 *arg = result;
678                 PG_RETURN_POINTER(arg);
679         }
680         else
681         {
682                 /* Not called by nodeAgg, so just do it the dumb way */
683                 int64           arg = PG_GETARG_INT64(0);
684                 int64           result;
685
686                 result = arg + 1;
687                 /* Overflow check */
688                 if (result < 0 && arg > 0)
689                         ereport(ERROR,
690                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
691                                          errmsg("bigint out of range")));
692
693                 PG_RETURN_INT64(result);
694         }
695 }
696
697 Datum
698 int8larger(PG_FUNCTION_ARGS)
699 {
700         int64           arg1 = PG_GETARG_INT64(0);
701         int64           arg2 = PG_GETARG_INT64(1);
702         int64           result;
703
704         result = ((arg1 > arg2) ? arg1 : arg2);
705
706         PG_RETURN_INT64(result);
707 }
708
709 Datum
710 int8smaller(PG_FUNCTION_ARGS)
711 {
712         int64           arg1 = PG_GETARG_INT64(0);
713         int64           arg2 = PG_GETARG_INT64(1);
714         int64           result;
715
716         result = ((arg1 < arg2) ? arg1 : arg2);
717
718         PG_RETURN_INT64(result);
719 }
720
721 Datum
722 int84pl(PG_FUNCTION_ARGS)
723 {
724         int64           arg1 = PG_GETARG_INT64(0);
725         int32           arg2 = PG_GETARG_INT32(1);
726         int64           result;
727
728         result = arg1 + arg2;
729
730         /*
731          * Overflow check.      If the inputs are of different signs then their sum
732          * cannot overflow.  If the inputs are of the same sign, their sum had
733          * better be that sign too.
734          */
735         if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
736                 ereport(ERROR,
737                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
738                                  errmsg("bigint out of range")));
739         PG_RETURN_INT64(result);
740 }
741
742 Datum
743 int84mi(PG_FUNCTION_ARGS)
744 {
745         int64           arg1 = PG_GETARG_INT64(0);
746         int32           arg2 = PG_GETARG_INT32(1);
747         int64           result;
748
749         result = arg1 - arg2;
750
751         /*
752          * Overflow check.      If the inputs are of the same sign then their
753          * difference cannot overflow.  If they are of different signs then the
754          * result should be of the same sign as the first input.
755          */
756         if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
757                 ereport(ERROR,
758                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
759                                  errmsg("bigint out of range")));
760         PG_RETURN_INT64(result);
761 }
762
763 Datum
764 int84mul(PG_FUNCTION_ARGS)
765 {
766         int64           arg1 = PG_GETARG_INT64(0);
767         int32           arg2 = PG_GETARG_INT32(1);
768         int64           result;
769
770         result = arg1 * arg2;
771
772         /*
773          * Overflow check.      We basically check to see if result / arg1 gives arg2
774          * again.  There is one case where this fails: arg1 = 0 (which cannot
775          * overflow).
776          *
777          * Since the division is likely much more expensive than the actual
778          * multiplication, we'd like to skip it where possible.  The best bang for
779          * the buck seems to be to check whether both inputs are in the int32
780          * range; if so, no overflow is possible.
781          */
782         if (arg1 != (int64) ((int32) arg1) &&
783                 result / arg1 != arg2)
784                 ereport(ERROR,
785                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
786                                  errmsg("bigint out of range")));
787         PG_RETURN_INT64(result);
788 }
789
790 Datum
791 int84div(PG_FUNCTION_ARGS)
792 {
793         int64           arg1 = PG_GETARG_INT64(0);
794         int32           arg2 = PG_GETARG_INT32(1);
795         int64           result;
796
797         if (arg2 == 0)
798                 ereport(ERROR,
799                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
800                                  errmsg("division by zero")));
801
802         result = arg1 / arg2;
803
804         /*
805          * Overflow check.      The only possible overflow case is for arg1 =
806          * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
807          * can't be represented on a two's-complement machine.
808          */
809         if (arg2 == -1 && arg1 < 0 && result < 0)
810                 ereport(ERROR,
811                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
812                                  errmsg("bigint out of range")));
813         PG_RETURN_INT64(result);
814 }
815
816 Datum
817 int48pl(PG_FUNCTION_ARGS)
818 {
819         int32           arg1 = PG_GETARG_INT32(0);
820         int64           arg2 = PG_GETARG_INT64(1);
821         int64           result;
822
823         result = arg1 + arg2;
824
825         /*
826          * Overflow check.      If the inputs are of different signs then their sum
827          * cannot overflow.  If the inputs are of the same sign, their sum had
828          * better be that sign too.
829          */
830         if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
831                 ereport(ERROR,
832                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
833                                  errmsg("bigint out of range")));
834         PG_RETURN_INT64(result);
835 }
836
837 Datum
838 int48mi(PG_FUNCTION_ARGS)
839 {
840         int32           arg1 = PG_GETARG_INT32(0);
841         int64           arg2 = PG_GETARG_INT64(1);
842         int64           result;
843
844         result = arg1 - arg2;
845
846         /*
847          * Overflow check.      If the inputs are of the same sign then their
848          * difference cannot overflow.  If they are of different signs then the
849          * result should be of the same sign as the first input.
850          */
851         if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
852                 ereport(ERROR,
853                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
854                                  errmsg("bigint out of range")));
855         PG_RETURN_INT64(result);
856 }
857
858 Datum
859 int48mul(PG_FUNCTION_ARGS)
860 {
861         int32           arg1 = PG_GETARG_INT32(0);
862         int64           arg2 = PG_GETARG_INT64(1);
863         int64           result;
864
865         result = arg1 * arg2;
866
867         /*
868          * Overflow check.      We basically check to see if result / arg2 gives arg1
869          * again.  There is one case where this fails: arg2 = 0 (which cannot
870          * overflow).
871          *
872          * Since the division is likely much more expensive than the actual
873          * multiplication, we'd like to skip it where possible.  The best bang for
874          * the buck seems to be to check whether both inputs are in the int32
875          * range; if so, no overflow is possible.
876          */
877         if (arg2 != (int64) ((int32) arg2) &&
878                 result / arg2 != arg1)
879                 ereport(ERROR,
880                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
881                                  errmsg("bigint out of range")));
882         PG_RETURN_INT64(result);
883 }
884
885 Datum
886 int48div(PG_FUNCTION_ARGS)
887 {
888         int32           arg1 = PG_GETARG_INT32(0);
889         int64           arg2 = PG_GETARG_INT64(1);
890
891         if (arg2 == 0)
892                 ereport(ERROR,
893                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
894                                  errmsg("division by zero")));
895         /* No overflow is possible */
896         PG_RETURN_INT64((int64) arg1 / arg2);
897 }
898
899 /* Binary arithmetics
900  *
901  *              int8and         - returns arg1 & arg2
902  *              int8or          - returns arg1 | arg2
903  *              int8xor         - returns arg1 # arg2
904  *              int8not         - returns ~arg1
905  *              int8shl         - returns arg1 << arg2
906  *              int8shr         - returns arg1 >> arg2
907  */
908
909 Datum
910 int8and(PG_FUNCTION_ARGS)
911 {
912         int64           arg1 = PG_GETARG_INT64(0);
913         int64           arg2 = PG_GETARG_INT64(1);
914
915         PG_RETURN_INT64(arg1 & arg2);
916 }
917
918 Datum
919 int8or(PG_FUNCTION_ARGS)
920 {
921         int64           arg1 = PG_GETARG_INT64(0);
922         int64           arg2 = PG_GETARG_INT64(1);
923
924         PG_RETURN_INT64(arg1 | arg2);
925 }
926
927 Datum
928 int8xor(PG_FUNCTION_ARGS)
929 {
930         int64           arg1 = PG_GETARG_INT64(0);
931         int64           arg2 = PG_GETARG_INT64(1);
932
933         PG_RETURN_INT64(arg1 ^ arg2);
934 }
935
936 Datum
937 int8not(PG_FUNCTION_ARGS)
938 {
939         int64           arg1 = PG_GETARG_INT64(0);
940
941         PG_RETURN_INT64(~arg1);
942 }
943
944 Datum
945 int8shl(PG_FUNCTION_ARGS)
946 {
947         int64           arg1 = PG_GETARG_INT64(0);
948         int32           arg2 = PG_GETARG_INT32(1);
949
950         PG_RETURN_INT64(arg1 << arg2);
951 }
952
953 Datum
954 int8shr(PG_FUNCTION_ARGS)
955 {
956         int64           arg1 = PG_GETARG_INT64(0);
957         int32           arg2 = PG_GETARG_INT32(1);
958
959         PG_RETURN_INT64(arg1 >> arg2);
960 }
961
962 /*----------------------------------------------------------
963  *      Conversion operators.
964  *---------------------------------------------------------*/
965
966 Datum
967 int48(PG_FUNCTION_ARGS)
968 {
969         int32           arg = PG_GETARG_INT32(0);
970
971         PG_RETURN_INT64((int64) arg);
972 }
973
974 Datum
975 int84(PG_FUNCTION_ARGS)
976 {
977         int64           arg = PG_GETARG_INT64(0);
978         int32           result;
979
980         result = (int32) arg;
981
982         /* Test for overflow by reverse-conversion. */
983         if ((int64) result != arg)
984                 ereport(ERROR,
985                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
986                                  errmsg("integer out of range")));
987
988         PG_RETURN_INT32(result);
989 }
990
991 Datum
992 int28(PG_FUNCTION_ARGS)
993 {
994         int16           arg = PG_GETARG_INT16(0);
995
996         PG_RETURN_INT64((int64) arg);
997 }
998
999 Datum
1000 int82(PG_FUNCTION_ARGS)
1001 {
1002         int64           arg = PG_GETARG_INT64(0);
1003         int16           result;
1004
1005         result = (int16) arg;
1006
1007         /* Test for overflow by reverse-conversion. */
1008         if ((int64) result != arg)
1009                 ereport(ERROR,
1010                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1011                                  errmsg("smallint out of range")));
1012
1013         PG_RETURN_INT16(result);
1014 }
1015
1016 Datum
1017 i8tod(PG_FUNCTION_ARGS)
1018 {
1019         int64           arg = PG_GETARG_INT64(0);
1020         float8          result;
1021
1022         result = arg;
1023
1024         PG_RETURN_FLOAT8(result);
1025 }
1026
1027 /* dtoi8()
1028  * Convert float8 to 8-byte integer.
1029  */
1030 Datum
1031 dtoi8(PG_FUNCTION_ARGS)
1032 {
1033         float8          arg = PG_GETARG_FLOAT8(0);
1034         int64           result;
1035
1036         /* Round arg to nearest integer (but it's still in float form) */
1037         arg = rint(arg);
1038
1039         /*
1040          * Does it fit in an int64?  Avoid assuming that we have handy constants
1041          * defined for the range boundaries, instead test for overflow by
1042          * reverse-conversion.
1043          */
1044         result = (int64) arg;
1045
1046         if ((float8) result != arg)
1047                 ereport(ERROR,
1048                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1049                                  errmsg("bigint out of range")));
1050
1051         PG_RETURN_INT64(result);
1052 }
1053
1054 Datum
1055 i8tof(PG_FUNCTION_ARGS)
1056 {
1057         int64           arg = PG_GETARG_INT64(0);
1058         float4          result;
1059
1060         result = arg;
1061
1062         PG_RETURN_FLOAT4(result);
1063 }
1064
1065 /* ftoi8()
1066  * Convert float4 to 8-byte integer.
1067  */
1068 Datum
1069 ftoi8(PG_FUNCTION_ARGS)
1070 {
1071         float4          arg = PG_GETARG_FLOAT4(0);
1072         int64           result;
1073         float8          darg;
1074
1075         /* Round arg to nearest integer (but it's still in float form) */
1076         darg = rint(arg);
1077
1078         /*
1079          * Does it fit in an int64?  Avoid assuming that we have handy constants
1080          * defined for the range boundaries, instead test for overflow by
1081          * reverse-conversion.
1082          */
1083         result = (int64) darg;
1084
1085         if ((float8) result != darg)
1086                 ereport(ERROR,
1087                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1088                                  errmsg("bigint out of range")));
1089
1090         PG_RETURN_INT64(result);
1091 }
1092
1093 Datum
1094 i8tooid(PG_FUNCTION_ARGS)
1095 {
1096         int64           arg = PG_GETARG_INT64(0);
1097         Oid                     result;
1098
1099         result = (Oid) arg;
1100
1101         /* Test for overflow by reverse-conversion. */
1102         if ((int64) result != arg)
1103                 ereport(ERROR,
1104                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1105                                  errmsg("OID out of range")));
1106
1107         PG_RETURN_OID(result);
1108 }
1109
1110 Datum
1111 oidtoi8(PG_FUNCTION_ARGS)
1112 {
1113         Oid                     arg = PG_GETARG_OID(0);
1114
1115         PG_RETURN_INT64((int64) arg);
1116 }
1117
1118 Datum
1119 text_int8(PG_FUNCTION_ARGS)
1120 {
1121         text       *str = PG_GETARG_TEXT_P(0);
1122         int                     len;
1123         char       *s;
1124         Datum           result;
1125
1126         len = (VARSIZE(str) - VARHDRSZ);
1127         s = palloc(len + 1);
1128         memcpy(s, VARDATA(str), len);
1129         *(s + len) = '\0';
1130
1131         result = DirectFunctionCall1(int8in, CStringGetDatum(s));
1132
1133         pfree(s);
1134
1135         return result;
1136 }
1137
1138 Datum
1139 int8_text(PG_FUNCTION_ARGS)
1140 {
1141         /* arg is int64, but easier to leave it as Datum */
1142         Datum           arg = PG_GETARG_DATUM(0);
1143         char       *s;
1144         int                     len;
1145         text       *result;
1146
1147         s = DatumGetCString(DirectFunctionCall1(int8out, arg));
1148         len = strlen(s);
1149
1150         result = (text *) palloc(VARHDRSZ + len);
1151
1152         VARATT_SIZEP(result) = len + VARHDRSZ;
1153         memcpy(VARDATA(result), s, len);
1154
1155         pfree(s);
1156
1157         PG_RETURN_TEXT_P(result);
1158 }
1159
1160 /*
1161  * non-persistent numeric series generator
1162  */
1163 Datum
1164 generate_series_int8(PG_FUNCTION_ARGS)
1165 {
1166         return generate_series_step_int8(fcinfo);
1167 }
1168
1169 Datum
1170 generate_series_step_int8(PG_FUNCTION_ARGS)
1171 {
1172         FuncCallContext *funcctx;
1173         generate_series_fctx *fctx;
1174         int64           result;
1175         MemoryContext oldcontext;
1176
1177         /* stuff done only on the first call of the function */
1178         if (SRF_IS_FIRSTCALL())
1179         {
1180                 int64           start = PG_GETARG_INT64(0);
1181                 int64           finish = PG_GETARG_INT64(1);
1182                 int64           step = 1;
1183
1184                 /* see if we were given an explicit step size */
1185                 if (PG_NARGS() == 3)
1186                         step = PG_GETARG_INT64(2);
1187                 if (step == 0)
1188                         ereport(ERROR,
1189                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1190                                          errmsg("step size may not equal zero")));
1191
1192                 /* create a function context for cross-call persistence */
1193                 funcctx = SRF_FIRSTCALL_INIT();
1194
1195                 /*
1196                  * switch to memory context appropriate for multiple function calls
1197                  */
1198                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1199
1200                 /* allocate memory for user context */
1201                 fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1202
1203                 /*
1204                  * Use fctx to keep state from call to call. Seed current with the
1205                  * original start value
1206                  */
1207                 fctx->current = start;
1208                 fctx->finish = finish;
1209                 fctx->step = step;
1210
1211                 funcctx->user_fctx = fctx;
1212                 MemoryContextSwitchTo(oldcontext);
1213         }
1214
1215         /* stuff done on every call of the function */
1216         funcctx = SRF_PERCALL_SETUP();
1217
1218         /*
1219          * get the saved state and use current as the result for this iteration
1220          */
1221         fctx = funcctx->user_fctx;
1222         result = fctx->current;
1223
1224         if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1225                 (fctx->step < 0 && fctx->current >= fctx->finish))
1226         {
1227                 /* increment current in preparation for next iteration */
1228                 fctx->current += fctx->step;
1229
1230                 /* do when there is more left to send */
1231                 SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1232         }
1233         else
1234                 /* do when there is no more left */
1235                 SRF_RETURN_DONE(funcctx);
1236 }