]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/int8.c
Allow float8, int8, and related datatypes to be passed by value on machines
[postgresql] / src / backend / utils / adt / int8.c
1 /*-------------------------------------------------------------------------
2  *
3  * int8.c
4  *        Internal 64-bit integer operations
5  *
6  * Portions Copyright (c) 1996-2008, 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.69 2008/04/21 00:26:45 tgl 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.  (But that only works if we
579          * really have a 64-bit int64 datatype...)
580          */
581 #ifndef INT64_IS_BUSTED
582         if (arg1 != (int64) ((int32) arg1) || arg2 != (int64) ((int32) arg2))
583 #endif
584         {
585                 if (arg2 != 0 &&
586                         (result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
587                         ereport(ERROR,
588                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
589                                          errmsg("bigint out of range")));
590         }
591         PG_RETURN_INT64(result);
592 }
593
594 Datum
595 int8div(PG_FUNCTION_ARGS)
596 {
597         int64           arg1 = PG_GETARG_INT64(0);
598         int64           arg2 = PG_GETARG_INT64(1);
599         int64           result;
600
601         if (arg2 == 0)
602                 ereport(ERROR,
603                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
604                                  errmsg("division by zero")));
605
606         result = arg1 / arg2;
607
608         /*
609          * Overflow check.      The only possible overflow case is for arg1 =
610          * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
611          * can't be represented on a two's-complement machine.
612          */
613         if (arg2 == -1 && arg1 < 0 && result < 0)
614                 ereport(ERROR,
615                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
616                                  errmsg("bigint out of range")));
617         PG_RETURN_INT64(result);
618 }
619
620 /* int8abs()
621  * Absolute value
622  */
623 Datum
624 int8abs(PG_FUNCTION_ARGS)
625 {
626         int64           arg1 = PG_GETARG_INT64(0);
627         int64           result;
628
629         result = (arg1 < 0) ? -arg1 : arg1;
630         /* overflow check (needed for INT64_MIN) */
631         if (result < 0)
632                 ereport(ERROR,
633                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
634                                  errmsg("bigint out of range")));
635         PG_RETURN_INT64(result);
636 }
637
638 /* int8mod()
639  * Modulo operation.
640  */
641 Datum
642 int8mod(PG_FUNCTION_ARGS)
643 {
644         int64           arg1 = PG_GETARG_INT64(0);
645         int64           arg2 = PG_GETARG_INT64(1);
646
647         if (arg2 == 0)
648                 ereport(ERROR,
649                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
650                                  errmsg("division by zero")));
651         /* No overflow is possible */
652
653         PG_RETURN_INT64(arg1 % arg2);
654 }
655
656
657 Datum
658 int8inc(PG_FUNCTION_ARGS)
659 {
660         /*
661          * When int8 is pass-by-reference, we provide this special case to avoid
662          * palloc overhead for COUNT(): when called from nodeAgg, we know that the
663          * argument is modifiable local storage, so just update it in-place.
664          * (If int8 is pass-by-value, then of course this is useless as well
665          * as incorrect, so just ifdef it out.)
666          */
667 #ifndef USE_FLOAT8_BYVAL                /* controls int8 too */
668         if (fcinfo->context && IsA(fcinfo->context, AggState))
669         {
670                 int64      *arg = (int64 *) PG_GETARG_POINTER(0);
671                 int64           result;
672
673                 result = *arg + 1;
674                 /* Overflow check */
675                 if (result < 0 && *arg > 0)
676                         ereport(ERROR,
677                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
678                                          errmsg("bigint out of range")));
679
680                 *arg = result;
681                 PG_RETURN_POINTER(arg);
682         }
683         else
684 #endif
685         {
686                 /* Not called by nodeAgg, so just do it the dumb way */
687                 int64           arg = PG_GETARG_INT64(0);
688                 int64           result;
689
690                 result = arg + 1;
691                 /* Overflow check */
692                 if (result < 0 && arg > 0)
693                         ereport(ERROR,
694                                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
695                                          errmsg("bigint out of range")));
696
697                 PG_RETURN_INT64(result);
698         }
699 }
700
701 /*
702  * These functions are exactly like int8inc but are used for aggregates that
703  * count only non-null values.  Since the functions are declared strict,
704  * the null checks happen before we ever get here, and all we need do is
705  * increment the state value.  We could actually make these pg_proc entries
706  * point right at int8inc, but then the opr_sanity regression test would
707  * complain about mismatched entries for a built-in function.
708  */
709
710 Datum
711 int8inc_any(PG_FUNCTION_ARGS)
712 {
713         return int8inc(fcinfo);
714 }
715
716 Datum
717 int8inc_float8_float8(PG_FUNCTION_ARGS)
718 {
719         return int8inc(fcinfo);
720 }
721
722
723 Datum
724 int8larger(PG_FUNCTION_ARGS)
725 {
726         int64           arg1 = PG_GETARG_INT64(0);
727         int64           arg2 = PG_GETARG_INT64(1);
728         int64           result;
729
730         result = ((arg1 > arg2) ? arg1 : arg2);
731
732         PG_RETURN_INT64(result);
733 }
734
735 Datum
736 int8smaller(PG_FUNCTION_ARGS)
737 {
738         int64           arg1 = PG_GETARG_INT64(0);
739         int64           arg2 = PG_GETARG_INT64(1);
740         int64           result;
741
742         result = ((arg1 < arg2) ? arg1 : arg2);
743
744         PG_RETURN_INT64(result);
745 }
746
747 Datum
748 int84pl(PG_FUNCTION_ARGS)
749 {
750         int64           arg1 = PG_GETARG_INT64(0);
751         int32           arg2 = PG_GETARG_INT32(1);
752         int64           result;
753
754         result = arg1 + arg2;
755
756         /*
757          * Overflow check.      If the inputs are of different signs then their sum
758          * cannot overflow.  If the inputs are of the same sign, their sum had
759          * better be that sign too.
760          */
761         if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
762                 ereport(ERROR,
763                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
764                                  errmsg("bigint out of range")));
765         PG_RETURN_INT64(result);
766 }
767
768 Datum
769 int84mi(PG_FUNCTION_ARGS)
770 {
771         int64           arg1 = PG_GETARG_INT64(0);
772         int32           arg2 = PG_GETARG_INT32(1);
773         int64           result;
774
775         result = arg1 - arg2;
776
777         /*
778          * Overflow check.      If the inputs are of the same sign then their
779          * difference cannot overflow.  If they are of different signs then the
780          * result should be of the same sign as the first input.
781          */
782         if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
783                 ereport(ERROR,
784                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
785                                  errmsg("bigint out of range")));
786         PG_RETURN_INT64(result);
787 }
788
789 Datum
790 int84mul(PG_FUNCTION_ARGS)
791 {
792         int64           arg1 = PG_GETARG_INT64(0);
793         int32           arg2 = PG_GETARG_INT32(1);
794         int64           result;
795
796         result = arg1 * arg2;
797
798         /*
799          * Overflow check.      We basically check to see if result / arg1 gives arg2
800          * again.  There is one case where this fails: arg1 = 0 (which cannot
801          * overflow).
802          *
803          * Since the division is likely much more expensive than the actual
804          * multiplication, we'd like to skip it where possible.  The best bang for
805          * the buck seems to be to check whether both inputs are in the int32
806          * range; if so, no overflow is possible.
807          */
808         if (arg1 != (int64) ((int32) arg1) &&
809                 result / arg1 != arg2)
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 int84div(PG_FUNCTION_ARGS)
818 {
819         int64           arg1 = PG_GETARG_INT64(0);
820         int32           arg2 = PG_GETARG_INT32(1);
821         int64           result;
822
823         if (arg2 == 0)
824                 ereport(ERROR,
825                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
826                                  errmsg("division by zero")));
827
828         result = arg1 / arg2;
829
830         /*
831          * Overflow check.      The only possible overflow case is for arg1 =
832          * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
833          * can't be represented on a two's-complement machine.
834          */
835         if (arg2 == -1 && arg1 < 0 && result < 0)
836                 ereport(ERROR,
837                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
838                                  errmsg("bigint out of range")));
839         PG_RETURN_INT64(result);
840 }
841
842 Datum
843 int48pl(PG_FUNCTION_ARGS)
844 {
845         int32           arg1 = PG_GETARG_INT32(0);
846         int64           arg2 = PG_GETARG_INT64(1);
847         int64           result;
848
849         result = arg1 + arg2;
850
851         /*
852          * Overflow check.      If the inputs are of different signs then their sum
853          * cannot overflow.  If the inputs are of the same sign, their sum had
854          * better be that sign too.
855          */
856         if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
857                 ereport(ERROR,
858                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
859                                  errmsg("bigint out of range")));
860         PG_RETURN_INT64(result);
861 }
862
863 Datum
864 int48mi(PG_FUNCTION_ARGS)
865 {
866         int32           arg1 = PG_GETARG_INT32(0);
867         int64           arg2 = PG_GETARG_INT64(1);
868         int64           result;
869
870         result = arg1 - arg2;
871
872         /*
873          * Overflow check.      If the inputs are of the same sign then their
874          * difference cannot overflow.  If they are of different signs then the
875          * result should be of the same sign as the first input.
876          */
877         if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
878                 ereport(ERROR,
879                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
880                                  errmsg("bigint out of range")));
881         PG_RETURN_INT64(result);
882 }
883
884 Datum
885 int48mul(PG_FUNCTION_ARGS)
886 {
887         int32           arg1 = PG_GETARG_INT32(0);
888         int64           arg2 = PG_GETARG_INT64(1);
889         int64           result;
890
891         result = arg1 * arg2;
892
893         /*
894          * Overflow check.      We basically check to see if result / arg2 gives arg1
895          * again.  There is one case where this fails: arg2 = 0 (which cannot
896          * overflow).
897          *
898          * Since the division is likely much more expensive than the actual
899          * multiplication, we'd like to skip it where possible.  The best bang for
900          * the buck seems to be to check whether both inputs are in the int32
901          * range; if so, no overflow is possible.
902          */
903         if (arg2 != (int64) ((int32) arg2) &&
904                 result / arg2 != arg1)
905                 ereport(ERROR,
906                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
907                                  errmsg("bigint out of range")));
908         PG_RETURN_INT64(result);
909 }
910
911 Datum
912 int48div(PG_FUNCTION_ARGS)
913 {
914         int32           arg1 = PG_GETARG_INT32(0);
915         int64           arg2 = PG_GETARG_INT64(1);
916
917         if (arg2 == 0)
918                 ereport(ERROR,
919                                 (errcode(ERRCODE_DIVISION_BY_ZERO),
920                                  errmsg("division by zero")));
921         /* No overflow is possible */
922         PG_RETURN_INT64((int64) arg1 / arg2);
923 }
924
925 /* Binary arithmetics
926  *
927  *              int8and         - returns arg1 & arg2
928  *              int8or          - returns arg1 | arg2
929  *              int8xor         - returns arg1 # arg2
930  *              int8not         - returns ~arg1
931  *              int8shl         - returns arg1 << arg2
932  *              int8shr         - returns arg1 >> arg2
933  */
934
935 Datum
936 int8and(PG_FUNCTION_ARGS)
937 {
938         int64           arg1 = PG_GETARG_INT64(0);
939         int64           arg2 = PG_GETARG_INT64(1);
940
941         PG_RETURN_INT64(arg1 & arg2);
942 }
943
944 Datum
945 int8or(PG_FUNCTION_ARGS)
946 {
947         int64           arg1 = PG_GETARG_INT64(0);
948         int64           arg2 = PG_GETARG_INT64(1);
949
950         PG_RETURN_INT64(arg1 | arg2);
951 }
952
953 Datum
954 int8xor(PG_FUNCTION_ARGS)
955 {
956         int64           arg1 = PG_GETARG_INT64(0);
957         int64           arg2 = PG_GETARG_INT64(1);
958
959         PG_RETURN_INT64(arg1 ^ arg2);
960 }
961
962 Datum
963 int8not(PG_FUNCTION_ARGS)
964 {
965         int64           arg1 = PG_GETARG_INT64(0);
966
967         PG_RETURN_INT64(~arg1);
968 }
969
970 Datum
971 int8shl(PG_FUNCTION_ARGS)
972 {
973         int64           arg1 = PG_GETARG_INT64(0);
974         int32           arg2 = PG_GETARG_INT32(1);
975
976         PG_RETURN_INT64(arg1 << arg2);
977 }
978
979 Datum
980 int8shr(PG_FUNCTION_ARGS)
981 {
982         int64           arg1 = PG_GETARG_INT64(0);
983         int32           arg2 = PG_GETARG_INT32(1);
984
985         PG_RETURN_INT64(arg1 >> arg2);
986 }
987
988 /*----------------------------------------------------------
989  *      Conversion operators.
990  *---------------------------------------------------------*/
991
992 Datum
993 int48(PG_FUNCTION_ARGS)
994 {
995         int32           arg = PG_GETARG_INT32(0);
996
997         PG_RETURN_INT64((int64) arg);
998 }
999
1000 Datum
1001 int84(PG_FUNCTION_ARGS)
1002 {
1003         int64           arg = PG_GETARG_INT64(0);
1004         int32           result;
1005
1006         result = (int32) arg;
1007
1008         /* Test for overflow by reverse-conversion. */
1009         if ((int64) result != arg)
1010                 ereport(ERROR,
1011                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1012                                  errmsg("integer out of range")));
1013
1014         PG_RETURN_INT32(result);
1015 }
1016
1017 Datum
1018 int28(PG_FUNCTION_ARGS)
1019 {
1020         int16           arg = PG_GETARG_INT16(0);
1021
1022         PG_RETURN_INT64((int64) arg);
1023 }
1024
1025 Datum
1026 int82(PG_FUNCTION_ARGS)
1027 {
1028         int64           arg = PG_GETARG_INT64(0);
1029         int16           result;
1030
1031         result = (int16) arg;
1032
1033         /* Test for overflow by reverse-conversion. */
1034         if ((int64) result != arg)
1035                 ereport(ERROR,
1036                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1037                                  errmsg("smallint out of range")));
1038
1039         PG_RETURN_INT16(result);
1040 }
1041
1042 Datum
1043 i8tod(PG_FUNCTION_ARGS)
1044 {
1045         int64           arg = PG_GETARG_INT64(0);
1046         float8          result;
1047
1048         result = arg;
1049
1050         PG_RETURN_FLOAT8(result);
1051 }
1052
1053 /* dtoi8()
1054  * Convert float8 to 8-byte integer.
1055  */
1056 Datum
1057 dtoi8(PG_FUNCTION_ARGS)
1058 {
1059         float8          arg = PG_GETARG_FLOAT8(0);
1060         int64           result;
1061
1062         /* Round arg to nearest integer (but it's still in float form) */
1063         arg = rint(arg);
1064
1065         /*
1066          * Does it fit in an int64?  Avoid assuming that we have handy constants
1067          * defined for the range boundaries, instead test for overflow by
1068          * reverse-conversion.
1069          */
1070         result = (int64) arg;
1071
1072         if ((float8) result != arg)
1073                 ereport(ERROR,
1074                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1075                                  errmsg("bigint out of range")));
1076
1077         PG_RETURN_INT64(result);
1078 }
1079
1080 Datum
1081 i8tof(PG_FUNCTION_ARGS)
1082 {
1083         int64           arg = PG_GETARG_INT64(0);
1084         float4          result;
1085
1086         result = arg;
1087
1088         PG_RETURN_FLOAT4(result);
1089 }
1090
1091 /* ftoi8()
1092  * Convert float4 to 8-byte integer.
1093  */
1094 Datum
1095 ftoi8(PG_FUNCTION_ARGS)
1096 {
1097         float4          arg = PG_GETARG_FLOAT4(0);
1098         int64           result;
1099         float8          darg;
1100
1101         /* Round arg to nearest integer (but it's still in float form) */
1102         darg = rint(arg);
1103
1104         /*
1105          * Does it fit in an int64?  Avoid assuming that we have handy constants
1106          * defined for the range boundaries, instead test for overflow by
1107          * reverse-conversion.
1108          */
1109         result = (int64) darg;
1110
1111         if ((float8) result != darg)
1112                 ereport(ERROR,
1113                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1114                                  errmsg("bigint out of range")));
1115
1116         PG_RETURN_INT64(result);
1117 }
1118
1119 Datum
1120 i8tooid(PG_FUNCTION_ARGS)
1121 {
1122         int64           arg = PG_GETARG_INT64(0);
1123         Oid                     result;
1124
1125         result = (Oid) arg;
1126
1127         /* Test for overflow by reverse-conversion. */
1128         if ((int64) result != arg)
1129                 ereport(ERROR,
1130                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1131                                  errmsg("OID out of range")));
1132
1133         PG_RETURN_OID(result);
1134 }
1135
1136 Datum
1137 oidtoi8(PG_FUNCTION_ARGS)
1138 {
1139         Oid                     arg = PG_GETARG_OID(0);
1140
1141         PG_RETURN_INT64((int64) arg);
1142 }
1143
1144 /*
1145  * non-persistent numeric series generator
1146  */
1147 Datum
1148 generate_series_int8(PG_FUNCTION_ARGS)
1149 {
1150         return generate_series_step_int8(fcinfo);
1151 }
1152
1153 Datum
1154 generate_series_step_int8(PG_FUNCTION_ARGS)
1155 {
1156         FuncCallContext *funcctx;
1157         generate_series_fctx *fctx;
1158         int64           result;
1159         MemoryContext oldcontext;
1160
1161         /* stuff done only on the first call of the function */
1162         if (SRF_IS_FIRSTCALL())
1163         {
1164                 int64           start = PG_GETARG_INT64(0);
1165                 int64           finish = PG_GETARG_INT64(1);
1166                 int64           step = 1;
1167
1168                 /* see if we were given an explicit step size */
1169                 if (PG_NARGS() == 3)
1170                         step = PG_GETARG_INT64(2);
1171                 if (step == 0)
1172                         ereport(ERROR,
1173                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1174                                          errmsg("step size cannot equal zero")));
1175
1176                 /* create a function context for cross-call persistence */
1177                 funcctx = SRF_FIRSTCALL_INIT();
1178
1179                 /*
1180                  * switch to memory context appropriate for multiple function calls
1181                  */
1182                 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1183
1184                 /* allocate memory for user context */
1185                 fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1186
1187                 /*
1188                  * Use fctx to keep state from call to call. Seed current with the
1189                  * original start value
1190                  */
1191                 fctx->current = start;
1192                 fctx->finish = finish;
1193                 fctx->step = step;
1194
1195                 funcctx->user_fctx = fctx;
1196                 MemoryContextSwitchTo(oldcontext);
1197         }
1198
1199         /* stuff done on every call of the function */
1200         funcctx = SRF_PERCALL_SETUP();
1201
1202         /*
1203          * get the saved state and use current as the result for this iteration
1204          */
1205         fctx = funcctx->user_fctx;
1206         result = fctx->current;
1207
1208         if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1209                 (fctx->step < 0 && fctx->current >= fctx->finish))
1210         {
1211                 /* increment current in preparation for next iteration */
1212                 fctx->current += fctx->step;
1213
1214                 /* do when there is more left to send */
1215                 SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1216         }
1217         else
1218                 /* do when there is no more left */
1219                 SRF_RETURN_DONE(funcctx);
1220 }