]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/int8.c
Tweak int8in to accept -9223372036854775808, per recent discussion in
[postgresql] / src / backend / utils / adt / int8.c
1 /*-------------------------------------------------------------------------
2  *
3  * int8.c
4  *        Internal 64-bit integer operations
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.36 2001/11/24 19:57:06 tgl Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include <ctype.h>
17 #include <time.h>
18 #include <math.h>
19 #include <float.h>
20 #include <limits.h>
21
22 #include "utils/int8.h"
23
24 /* this should be set in pg_config.h, but just in case it wasn't: */
25 #ifndef INT64_FORMAT
26 #define INT64_FORMAT "%ld"
27 #endif
28
29 #ifdef HAVE_LL_CONSTANTS
30 #define INT64CONST(x)  ((int64) x##LL)
31 #else
32 #define INT64CONST(x)  ((int64) x)
33 #endif
34
35 #define MAXINT8LEN              25
36
37 #ifndef INT_MAX
38 #define INT_MAX (0x7FFFFFFFL)
39 #endif
40 #ifndef INT_MIN
41 #define INT_MIN (-INT_MAX-1)
42 #endif
43 #ifndef SHRT_MAX
44 #define SHRT_MAX (0x7FFF)
45 #endif
46 #ifndef SHRT_MIN
47 #define SHRT_MIN (-SHRT_MAX-1)
48 #endif
49
50
51 /***********************************************************************
52  **
53  **             Routines for 64-bit integers.
54  **
55  ***********************************************************************/
56
57 /*----------------------------------------------------------
58  * Formatting and conversion routines.
59  *---------------------------------------------------------*/
60
61 /* int8in()
62  */
63 Datum
64 int8in(PG_FUNCTION_ARGS)
65 {
66         char       *str = PG_GETARG_CSTRING(0);
67         int64           result;
68         char       *ptr = str;
69         int64           tmp = 0;
70         int                     sign = 1;
71
72         /*
73          * Do our own scan, rather than relying on sscanf which might be
74          * broken for long long.
75          */
76         while (*ptr && isspace((unsigned char) *ptr))           /* skip leading spaces */
77                 ptr++;
78         /* handle sign */
79         if (*ptr == '-')
80         {
81                 ptr++;
82                 sign = -1;
83                 /*
84                  * Do an explicit check for INT64_MIN.  Ugly though this is, it's
85                  * cleaner than trying to get the loop below to handle it portably.
86                  */
87 #ifndef INT64_IS_BUSTED
88                 if (strcmp(ptr, "9223372036854775808") == 0)
89                 {
90                         result = - INT64CONST(0x7fffffffffffffff) - 1;
91                         PG_RETURN_INT64(result);
92                 }
93 #endif
94         }
95         else if (*ptr == '+')
96                 ptr++;
97         if (!isdigit((unsigned char) *ptr)) /* require at least one digit */
98                 elog(ERROR, "Bad int8 external representation \"%s\"", str);
99         while (*ptr && isdigit((unsigned char) *ptr))           /* process digits */
100         {
101                 int64           newtmp = tmp * 10 + (*ptr++ - '0');
102
103                 if ((newtmp / 10) != tmp)               /* overflow? */
104                         elog(ERROR, "int8 value out of range: \"%s\"", str);
105                 tmp = newtmp;
106         }
107         if (*ptr)                                       /* trailing junk? */
108                 elog(ERROR, "Bad int8 external representation \"%s\"", str);
109
110         result = (sign < 0) ? -tmp : tmp;
111
112         PG_RETURN_INT64(result);
113 }
114
115
116 /* int8out()
117  */
118 Datum
119 int8out(PG_FUNCTION_ARGS)
120 {
121         int64           val = PG_GETARG_INT64(0);
122         char       *result;
123         int                     len;
124         char            buf[MAXINT8LEN + 1];
125
126         if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0)
127                 elog(ERROR, "Unable to format int8");
128
129         result = pstrdup(buf);
130         PG_RETURN_CSTRING(result);
131 }
132
133
134 /*----------------------------------------------------------
135  *      Relational operators for int8s, including cross-data-type comparisons.
136  *---------------------------------------------------------*/
137
138 /* int8relop()
139  * Is val1 relop val2?
140  */
141 Datum
142 int8eq(PG_FUNCTION_ARGS)
143 {
144         int64           val1 = PG_GETARG_INT64(0);
145         int64           val2 = PG_GETARG_INT64(1);
146
147         PG_RETURN_BOOL(val1 == val2);
148 }
149
150 Datum
151 int8ne(PG_FUNCTION_ARGS)
152 {
153         int64           val1 = PG_GETARG_INT64(0);
154         int64           val2 = PG_GETARG_INT64(1);
155
156         PG_RETURN_BOOL(val1 != val2);
157 }
158
159 Datum
160 int8lt(PG_FUNCTION_ARGS)
161 {
162         int64           val1 = PG_GETARG_INT64(0);
163         int64           val2 = PG_GETARG_INT64(1);
164
165         PG_RETURN_BOOL(val1 < val2);
166 }
167
168 Datum
169 int8gt(PG_FUNCTION_ARGS)
170 {
171         int64           val1 = PG_GETARG_INT64(0);
172         int64           val2 = PG_GETARG_INT64(1);
173
174         PG_RETURN_BOOL(val1 > val2);
175 }
176
177 Datum
178 int8le(PG_FUNCTION_ARGS)
179 {
180         int64           val1 = PG_GETARG_INT64(0);
181         int64           val2 = PG_GETARG_INT64(1);
182
183         PG_RETURN_BOOL(val1 <= val2);
184 }
185
186 Datum
187 int8ge(PG_FUNCTION_ARGS)
188 {
189         int64           val1 = PG_GETARG_INT64(0);
190         int64           val2 = PG_GETARG_INT64(1);
191
192         PG_RETURN_BOOL(val1 >= val2);
193 }
194
195 /* int84relop()
196  * Is 64-bit val1 relop 32-bit val2?
197  */
198 Datum
199 int84eq(PG_FUNCTION_ARGS)
200 {
201         int64           val1 = PG_GETARG_INT64(0);
202         int32           val2 = PG_GETARG_INT32(1);
203
204         PG_RETURN_BOOL(val1 == val2);
205 }
206
207 Datum
208 int84ne(PG_FUNCTION_ARGS)
209 {
210         int64           val1 = PG_GETARG_INT64(0);
211         int32           val2 = PG_GETARG_INT32(1);
212
213         PG_RETURN_BOOL(val1 != val2);
214 }
215
216 Datum
217 int84lt(PG_FUNCTION_ARGS)
218 {
219         int64           val1 = PG_GETARG_INT64(0);
220         int32           val2 = PG_GETARG_INT32(1);
221
222         PG_RETURN_BOOL(val1 < val2);
223 }
224
225 Datum
226 int84gt(PG_FUNCTION_ARGS)
227 {
228         int64           val1 = PG_GETARG_INT64(0);
229         int32           val2 = PG_GETARG_INT32(1);
230
231         PG_RETURN_BOOL(val1 > val2);
232 }
233
234 Datum
235 int84le(PG_FUNCTION_ARGS)
236 {
237         int64           val1 = PG_GETARG_INT64(0);
238         int32           val2 = PG_GETARG_INT32(1);
239
240         PG_RETURN_BOOL(val1 <= val2);
241 }
242
243 Datum
244 int84ge(PG_FUNCTION_ARGS)
245 {
246         int64           val1 = PG_GETARG_INT64(0);
247         int32           val2 = PG_GETARG_INT32(1);
248
249         PG_RETURN_BOOL(val1 >= val2);
250 }
251
252 /* int48relop()
253  * Is 32-bit val1 relop 64-bit val2?
254  */
255 Datum
256 int48eq(PG_FUNCTION_ARGS)
257 {
258         int32           val1 = PG_GETARG_INT32(0);
259         int64           val2 = PG_GETARG_INT64(1);
260
261         PG_RETURN_BOOL(val1 == val2);
262 }
263
264 Datum
265 int48ne(PG_FUNCTION_ARGS)
266 {
267         int32           val1 = PG_GETARG_INT32(0);
268         int64           val2 = PG_GETARG_INT64(1);
269
270         PG_RETURN_BOOL(val1 != val2);
271 }
272
273 Datum
274 int48lt(PG_FUNCTION_ARGS)
275 {
276         int32           val1 = PG_GETARG_INT32(0);
277         int64           val2 = PG_GETARG_INT64(1);
278
279         PG_RETURN_BOOL(val1 < val2);
280 }
281
282 Datum
283 int48gt(PG_FUNCTION_ARGS)
284 {
285         int32           val1 = PG_GETARG_INT32(0);
286         int64           val2 = PG_GETARG_INT64(1);
287
288         PG_RETURN_BOOL(val1 > val2);
289 }
290
291 Datum
292 int48le(PG_FUNCTION_ARGS)
293 {
294         int32           val1 = PG_GETARG_INT32(0);
295         int64           val2 = PG_GETARG_INT64(1);
296
297         PG_RETURN_BOOL(val1 <= val2);
298 }
299
300 Datum
301 int48ge(PG_FUNCTION_ARGS)
302 {
303         int32           val1 = PG_GETARG_INT32(0);
304         int64           val2 = PG_GETARG_INT64(1);
305
306         PG_RETURN_BOOL(val1 >= val2);
307 }
308
309 /* int82relop()
310  * Is 64-bit val1 relop 16-bit val2?
311  */
312 Datum
313 int82eq(PG_FUNCTION_ARGS)
314 {
315         int64           val1 = PG_GETARG_INT64(0);
316         int16           val2 = PG_GETARG_INT16(1);
317
318         PG_RETURN_BOOL(val1 == val2);
319 }
320
321 Datum
322 int82ne(PG_FUNCTION_ARGS)
323 {
324         int64           val1 = PG_GETARG_INT64(0);
325         int16           val2 = PG_GETARG_INT16(1);
326
327         PG_RETURN_BOOL(val1 != val2);
328 }
329
330 Datum
331 int82lt(PG_FUNCTION_ARGS)
332 {
333         int64           val1 = PG_GETARG_INT64(0);
334         int16           val2 = PG_GETARG_INT16(1);
335
336         PG_RETURN_BOOL(val1 < val2);
337 }
338
339 Datum
340 int82gt(PG_FUNCTION_ARGS)
341 {
342         int64           val1 = PG_GETARG_INT64(0);
343         int16           val2 = PG_GETARG_INT16(1);
344
345         PG_RETURN_BOOL(val1 > val2);
346 }
347
348 Datum
349 int82le(PG_FUNCTION_ARGS)
350 {
351         int64           val1 = PG_GETARG_INT64(0);
352         int16           val2 = PG_GETARG_INT16(1);
353
354         PG_RETURN_BOOL(val1 <= val2);
355 }
356
357 Datum
358 int82ge(PG_FUNCTION_ARGS)
359 {
360         int64           val1 = PG_GETARG_INT64(0);
361         int16           val2 = PG_GETARG_INT16(1);
362
363         PG_RETURN_BOOL(val1 >= val2);
364 }
365
366 /* int28relop()
367  * Is 16-bit val1 relop 64-bit val2?
368  */
369 Datum
370 int28eq(PG_FUNCTION_ARGS)
371 {
372         int16           val1 = PG_GETARG_INT16(0);
373         int64           val2 = PG_GETARG_INT64(1);
374
375         PG_RETURN_BOOL(val1 == val2);
376 }
377
378 Datum
379 int28ne(PG_FUNCTION_ARGS)
380 {
381         int16           val1 = PG_GETARG_INT16(0);
382         int64           val2 = PG_GETARG_INT64(1);
383
384         PG_RETURN_BOOL(val1 != val2);
385 }
386
387 Datum
388 int28lt(PG_FUNCTION_ARGS)
389 {
390         int16           val1 = PG_GETARG_INT16(0);
391         int64           val2 = PG_GETARG_INT64(1);
392
393         PG_RETURN_BOOL(val1 < val2);
394 }
395
396 Datum
397 int28gt(PG_FUNCTION_ARGS)
398 {
399         int16           val1 = PG_GETARG_INT16(0);
400         int64           val2 = PG_GETARG_INT64(1);
401
402         PG_RETURN_BOOL(val1 > val2);
403 }
404
405 Datum
406 int28le(PG_FUNCTION_ARGS)
407 {
408         int16           val1 = PG_GETARG_INT16(0);
409         int64           val2 = PG_GETARG_INT64(1);
410
411         PG_RETURN_BOOL(val1 <= val2);
412 }
413
414 Datum
415 int28ge(PG_FUNCTION_ARGS)
416 {
417         int16           val1 = PG_GETARG_INT16(0);
418         int64           val2 = PG_GETARG_INT64(1);
419
420         PG_RETURN_BOOL(val1 >= val2);
421 }
422
423
424 /*----------------------------------------------------------
425  *      Arithmetic operators on 64-bit integers.
426  *---------------------------------------------------------*/
427
428 Datum
429 int8um(PG_FUNCTION_ARGS)
430 {
431         int64           val = PG_GETARG_INT64(0);
432
433         PG_RETURN_INT64(-val);
434 }
435
436 Datum
437 int8up(PG_FUNCTION_ARGS)
438 {
439         int64           val = PG_GETARG_INT64(0);
440
441         PG_RETURN_INT64(val);
442 }
443
444 Datum
445 int8pl(PG_FUNCTION_ARGS)
446 {
447         int64           val1 = PG_GETARG_INT64(0);
448         int64           val2 = PG_GETARG_INT64(1);
449
450         PG_RETURN_INT64(val1 + val2);
451 }
452
453 Datum
454 int8mi(PG_FUNCTION_ARGS)
455 {
456         int64           val1 = PG_GETARG_INT64(0);
457         int64           val2 = PG_GETARG_INT64(1);
458
459         PG_RETURN_INT64(val1 - val2);
460 }
461
462 Datum
463 int8mul(PG_FUNCTION_ARGS)
464 {
465         int64           val1 = PG_GETARG_INT64(0);
466         int64           val2 = PG_GETARG_INT64(1);
467
468         PG_RETURN_INT64(val1 * val2);
469 }
470
471 Datum
472 int8div(PG_FUNCTION_ARGS)
473 {
474         int64           val1 = PG_GETARG_INT64(0);
475         int64           val2 = PG_GETARG_INT64(1);
476
477         PG_RETURN_INT64(val1 / val2);
478 }
479
480 /* int8abs()
481  * Absolute value
482  */
483 Datum
484 int8abs(PG_FUNCTION_ARGS)
485 {
486         int64           arg1 = PG_GETARG_INT64(0);
487
488         PG_RETURN_INT64((arg1 < 0) ? -arg1 : arg1);
489 }
490
491 /* int8mod()
492  * Modulo operation.
493  */
494 Datum
495 int8mod(PG_FUNCTION_ARGS)
496 {
497         int64           val1 = PG_GETARG_INT64(0);
498         int64           val2 = PG_GETARG_INT64(1);
499         int64           result;
500
501         result = val1 / val2;
502         result *= val2;
503         result = val1 - result;
504
505         PG_RETURN_INT64(result);
506 }
507
508 /* int8fac()
509  * Factorial
510  */
511 Datum
512 int8fac(PG_FUNCTION_ARGS)
513 {
514         int64           arg1 = PG_GETARG_INT64(0);
515         int64           result;
516         int64           i;
517
518         if (arg1 < 1)
519                 result = 0;
520         else
521                 for (i = arg1, result = 1; i > 0; --i)
522                         result *= i;
523
524         PG_RETURN_INT64(result);
525 }
526
527 Datum
528 int8inc(PG_FUNCTION_ARGS)
529 {
530         int64           arg = PG_GETARG_INT64(0);
531
532         PG_RETURN_INT64(arg + 1);
533 }
534
535 Datum
536 int8larger(PG_FUNCTION_ARGS)
537 {
538         int64           val1 = PG_GETARG_INT64(0);
539         int64           val2 = PG_GETARG_INT64(1);
540         int64           result;
541
542         result = ((val1 > val2) ? val1 : val2);
543
544         PG_RETURN_INT64(result);
545 }
546
547 Datum
548 int8smaller(PG_FUNCTION_ARGS)
549 {
550         int64           val1 = PG_GETARG_INT64(0);
551         int64           val2 = PG_GETARG_INT64(1);
552         int64           result;
553
554         result = ((val1 < val2) ? val1 : val2);
555
556         PG_RETURN_INT64(result);
557 }
558
559 Datum
560 int84pl(PG_FUNCTION_ARGS)
561 {
562         int64           val1 = PG_GETARG_INT64(0);
563         int32           val2 = PG_GETARG_INT32(1);
564
565         PG_RETURN_INT64(val1 + val2);
566 }
567
568 Datum
569 int84mi(PG_FUNCTION_ARGS)
570 {
571         int64           val1 = PG_GETARG_INT64(0);
572         int32           val2 = PG_GETARG_INT32(1);
573
574         PG_RETURN_INT64(val1 - val2);
575 }
576
577 Datum
578 int84mul(PG_FUNCTION_ARGS)
579 {
580         int64           val1 = PG_GETARG_INT64(0);
581         int32           val2 = PG_GETARG_INT32(1);
582
583         PG_RETURN_INT64(val1 * val2);
584 }
585
586 Datum
587 int84div(PG_FUNCTION_ARGS)
588 {
589         int64           val1 = PG_GETARG_INT64(0);
590         int32           val2 = PG_GETARG_INT32(1);
591
592         PG_RETURN_INT64(val1 / val2);
593 }
594
595 Datum
596 int48pl(PG_FUNCTION_ARGS)
597 {
598         int32           val1 = PG_GETARG_INT32(0);
599         int64           val2 = PG_GETARG_INT64(1);
600
601         PG_RETURN_INT64(val1 + val2);
602 }
603
604 Datum
605 int48mi(PG_FUNCTION_ARGS)
606 {
607         int32           val1 = PG_GETARG_INT32(0);
608         int64           val2 = PG_GETARG_INT64(1);
609
610         PG_RETURN_INT64(val1 - val2);
611 }
612
613 Datum
614 int48mul(PG_FUNCTION_ARGS)
615 {
616         int32           val1 = PG_GETARG_INT32(0);
617         int64           val2 = PG_GETARG_INT64(1);
618
619         PG_RETURN_INT64(val1 * val2);
620 }
621
622 Datum
623 int48div(PG_FUNCTION_ARGS)
624 {
625         int32           val1 = PG_GETARG_INT32(0);
626         int64           val2 = PG_GETARG_INT64(1);
627
628         PG_RETURN_INT64(val1 / val2);
629 }
630
631 /* Binary arithmetics
632  *
633  *              int8and         - returns arg1 & arg2
634  *              int8or          - returns arg1 | arg2
635  *              int8xor         - returns arg1 # arg2
636  *              int8not         - returns ~arg1
637  *              int8shl         - returns arg1 << arg2
638  *              int8shr         - returns arg1 >> arg2
639  */
640
641 Datum
642 int8and(PG_FUNCTION_ARGS)
643 {
644         int64           arg1 = PG_GETARG_INT64(0);
645         int64           arg2 = PG_GETARG_INT64(1);
646
647         PG_RETURN_INT64(arg1 & arg2);
648 }
649
650 Datum
651 int8or(PG_FUNCTION_ARGS)
652 {
653         int64           arg1 = PG_GETARG_INT64(0);
654         int64           arg2 = PG_GETARG_INT64(1);
655
656         PG_RETURN_INT64(arg1 | arg2);
657 }
658
659 Datum
660 int8xor(PG_FUNCTION_ARGS)
661 {
662         int64           arg1 = PG_GETARG_INT64(0);
663         int64           arg2 = PG_GETARG_INT64(1);
664
665         PG_RETURN_INT64(arg1 ^ arg2);
666 }
667
668 Datum
669 int8not(PG_FUNCTION_ARGS)
670 {
671         int64           arg1 = PG_GETARG_INT64(0);
672
673         PG_RETURN_INT64(~arg1);
674 }
675
676 Datum
677 int8shl(PG_FUNCTION_ARGS)
678 {
679         int64           arg1 = PG_GETARG_INT64(0);
680         int32           arg2 = PG_GETARG_INT32(1);
681
682         PG_RETURN_INT64(arg1 << arg2);
683 }
684
685 Datum
686 int8shr(PG_FUNCTION_ARGS)
687 {
688         int64           arg1 = PG_GETARG_INT64(0);
689         int32           arg2 = PG_GETARG_INT32(1);
690
691         PG_RETURN_INT64(arg1 >> arg2);
692 }
693
694 /*----------------------------------------------------------
695  *      Conversion operators.
696  *---------------------------------------------------------*/
697
698 Datum
699 int48(PG_FUNCTION_ARGS)
700 {
701         int32           val = PG_GETARG_INT32(0);
702
703         PG_RETURN_INT64((int64) val);
704 }
705
706 Datum
707 int84(PG_FUNCTION_ARGS)
708 {
709         int64           val = PG_GETARG_INT64(0);
710         int32           result;
711
712         result = (int32) val;
713
714         /* Test for overflow by reverse-conversion. */
715         if ((int64) result != val)
716                 elog(ERROR, "int8 conversion to int4 is out of range");
717
718         PG_RETURN_INT32(result);
719 }
720
721 Datum
722 int28(PG_FUNCTION_ARGS)
723 {
724         int16           val = PG_GETARG_INT16(0);
725
726         PG_RETURN_INT64((int64) val);
727 }
728
729 Datum
730 int82(PG_FUNCTION_ARGS)
731 {
732         int64           val = PG_GETARG_INT64(0);
733         int16           result;
734
735         result = (int16) val;
736
737         /* Test for overflow by reverse-conversion. */
738         if ((int64) result != val)
739                 elog(ERROR, "int8 conversion to int2 is out of range");
740
741         PG_RETURN_INT16(result);
742 }
743
744 Datum
745 i8tod(PG_FUNCTION_ARGS)
746 {
747         int64           val = PG_GETARG_INT64(0);
748         float8          result;
749
750         result = val;
751
752         PG_RETURN_FLOAT8(result);
753 }
754
755 /* dtoi8()
756  * Convert double float to 8-byte integer.
757  */
758 Datum
759 dtoi8(PG_FUNCTION_ARGS)
760 {
761         float8          val = PG_GETARG_FLOAT8(0);
762         int64           result;
763
764         /* Round val to nearest integer (but it's still in float form) */
765         val = rint(val);
766
767         /*
768          * Does it fit in an int64?  Avoid assuming that we have handy
769          * constants defined for the range boundaries, instead test for
770          * overflow by reverse-conversion.
771          */
772         result = (int64) val;
773
774         if ((float8) result != val)
775                 elog(ERROR, "Floating point conversion to int8 is out of range");
776
777         PG_RETURN_INT64(result);
778 }
779
780 /* text_int8()
781  */
782 Datum
783 text_int8(PG_FUNCTION_ARGS)
784 {
785         text       *str = PG_GETARG_TEXT_P(0);
786         int                     len;
787         char       *s;
788         Datum           result;
789
790         len = (VARSIZE(str) - VARHDRSZ);
791         s = palloc(len + 1);
792         memcpy(s, VARDATA(str), len);
793         *(s + len) = '\0';
794
795         result = DirectFunctionCall1(int8in, CStringGetDatum(s));
796
797         pfree(s);
798
799         return result;
800 }
801
802
803 /* int8_text()
804  */
805 Datum
806 int8_text(PG_FUNCTION_ARGS)
807 {
808         /* val is int64, but easier to leave it as Datum */
809         Datum           val = PG_GETARG_DATUM(0);
810         char       *s;
811         int                     len;
812         text       *result;
813
814         s = DatumGetCString(DirectFunctionCall1(int8out, val));
815         len = strlen(s);
816
817         result = (text *) palloc(VARHDRSZ + len);
818
819         VARATT_SIZEP(result) = len + VARHDRSZ;
820         memcpy(VARDATA(result), s, len);
821
822         pfree(s);
823
824         PG_RETURN_TEXT_P(result);
825 }