LCOV - code coverage report
Current view: top level - src/backend/utils/adt - int8.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 472 497 95.0 %
Date: 2017-09-29 13:40:31 Functions: 82 84 97.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * int8.c
       4             :  *    Internal 64-bit integer operations
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/backend/utils/adt/int8.c
      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 "utils/int8.h"
      23             : #include "utils/builtins.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        1978 : scanint8(const char *str, bool errorOK, int64 *result)
      56             : {
      57        1978 :     const char *ptr = str;
      58        1978 :     int64       tmp = 0;
      59        1978 :     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        3968 :     while (*ptr && isspace((unsigned char) *ptr))
      68          12 :         ptr++;
      69             : 
      70             :     /* handle sign */
      71        1978 :     if (*ptr == '-')
      72             :     {
      73          76 :         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          76 :         if (strncmp(ptr, "9223372036854775808", 19) == 0)
      80             :         {
      81          15 :             tmp = PG_INT64_MIN;
      82          15 :             ptr += 19;
      83          15 :             goto gotdigits;
      84             :         }
      85          61 :         sign = -1;
      86             :     }
      87        1902 :     else if (*ptr == '+')
      88           7 :         ptr++;
      89             : 
      90             :     /* require at least one digit */
      91        1963 :     if (!isdigit((unsigned char) *ptr))
      92             :     {
      93           8 :         if (errorOK)
      94           4 :             return false;
      95             :         else
      96           4 :             ereport(ERROR,
      97             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      98             :                      errmsg("invalid input syntax for %s: \"%s\"",
      99             :                             "integer", str)));
     100             :     }
     101             : 
     102             :     /* process digits */
     103        8213 :     while (*ptr && isdigit((unsigned char) *ptr))
     104             :     {
     105        4339 :         int64       newtmp = tmp * 10 + (*ptr++ - '0');
     106             : 
     107        4339 :         if ((newtmp / 10) != tmp)   /* overflow? */
     108             :         {
     109          36 :             if (errorOK)
     110          32 :                 return false;
     111             :             else
     112           4 :                 ereport(ERROR,
     113             :                         (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     114             :                          errmsg("value \"%s\" is out of range for type %s",
     115             :                                 str, "bigint")));
     116             :         }
     117        4303 :         tmp = newtmp;
     118             :     }
     119             : 
     120             : gotdigits:
     121             : 
     122             :     /* allow trailing whitespace, but not other trailing chars */
     123        3879 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
     124          11 :         ptr++;
     125             : 
     126        1934 :     if (*ptr != '\0')
     127             :     {
     128         736 :         if (errorOK)
     129         735 :             return false;
     130             :         else
     131           1 :             ereport(ERROR,
     132             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     133             :                      errmsg("invalid input syntax for %s: \"%s\"",
     134             :                             "integer", str)));
     135             :     }
     136             : 
     137        1198 :     *result = (sign < 0) ? -tmp : tmp;
     138             : 
     139        1198 :     return true;
     140             : }
     141             : 
     142             : /* int8in()
     143             :  */
     144             : Datum
     145        1155 : int8in(PG_FUNCTION_ARGS)
     146             : {
     147        1155 :     char       *str = PG_GETARG_CSTRING(0);
     148             :     int64       result;
     149             : 
     150        1155 :     (void) scanint8(str, false, &result);
     151        1146 :     PG_RETURN_INT64(result);
     152             : }
     153             : 
     154             : 
     155             : /* int8out()
     156             :  */
     157             : Datum
     158        5306 : int8out(PG_FUNCTION_ARGS)
     159             : {
     160        5306 :     int64       val = PG_GETARG_INT64(0);
     161             :     char        buf[MAXINT8LEN + 1];
     162             :     char       *result;
     163             : 
     164        5306 :     pg_lltoa(val, buf);
     165        5306 :     result = pstrdup(buf);
     166        5306 :     PG_RETURN_CSTRING(result);
     167             : }
     168             : 
     169             : /*
     170             :  *      int8recv            - converts external binary format to int8
     171             :  */
     172             : Datum
     173           0 : int8recv(PG_FUNCTION_ARGS)
     174             : {
     175           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     176             : 
     177           0 :     PG_RETURN_INT64(pq_getmsgint64(buf));
     178             : }
     179             : 
     180             : /*
     181             :  *      int8send            - converts int8 to binary format
     182             :  */
     183             : Datum
     184           0 : int8send(PG_FUNCTION_ARGS)
     185             : {
     186           0 :     int64       arg1 = PG_GETARG_INT64(0);
     187             :     StringInfoData buf;
     188             : 
     189           0 :     pq_begintypsend(&buf);
     190           0 :     pq_sendint64(&buf, arg1);
     191           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     192             : }
     193             : 
     194             : 
     195             : /*----------------------------------------------------------
     196             :  *  Relational operators for int8s, including cross-data-type comparisons.
     197             :  *---------------------------------------------------------*/
     198             : 
     199             : /* int8relop()
     200             :  * Is val1 relop val2?
     201             :  */
     202             : Datum
     203         797 : int8eq(PG_FUNCTION_ARGS)
     204             : {
     205         797 :     int64       val1 = PG_GETARG_INT64(0);
     206         797 :     int64       val2 = PG_GETARG_INT64(1);
     207             : 
     208         797 :     PG_RETURN_BOOL(val1 == val2);
     209             : }
     210             : 
     211             : Datum
     212       10005 : int8ne(PG_FUNCTION_ARGS)
     213             : {
     214       10005 :     int64       val1 = PG_GETARG_INT64(0);
     215       10005 :     int64       val2 = PG_GETARG_INT64(1);
     216             : 
     217       10005 :     PG_RETURN_BOOL(val1 != val2);
     218             : }
     219             : 
     220             : Datum
     221         520 : int8lt(PG_FUNCTION_ARGS)
     222             : {
     223         520 :     int64       val1 = PG_GETARG_INT64(0);
     224         520 :     int64       val2 = PG_GETARG_INT64(1);
     225             : 
     226         520 :     PG_RETURN_BOOL(val1 < val2);
     227             : }
     228             : 
     229             : Datum
     230         520 : int8gt(PG_FUNCTION_ARGS)
     231             : {
     232         520 :     int64       val1 = PG_GETARG_INT64(0);
     233         520 :     int64       val2 = PG_GETARG_INT64(1);
     234             : 
     235         520 :     PG_RETURN_BOOL(val1 > val2);
     236             : }
     237             : 
     238             : Datum
     239         408 : int8le(PG_FUNCTION_ARGS)
     240             : {
     241         408 :     int64       val1 = PG_GETARG_INT64(0);
     242         408 :     int64       val2 = PG_GETARG_INT64(1);
     243             : 
     244         408 :     PG_RETURN_BOOL(val1 <= val2);
     245             : }
     246             : 
     247             : Datum
     248         411 : int8ge(PG_FUNCTION_ARGS)
     249             : {
     250         411 :     int64       val1 = PG_GETARG_INT64(0);
     251         411 :     int64       val2 = PG_GETARG_INT64(1);
     252             : 
     253         411 :     PG_RETURN_BOOL(val1 >= val2);
     254             : }
     255             : 
     256             : /* int84relop()
     257             :  * Is 64-bit val1 relop 32-bit val2?
     258             :  */
     259             : Datum
     260       15563 : int84eq(PG_FUNCTION_ARGS)
     261             : {
     262       15563 :     int64       val1 = PG_GETARG_INT64(0);
     263       15563 :     int32       val2 = PG_GETARG_INT32(1);
     264             : 
     265       15563 :     PG_RETURN_BOOL(val1 == val2);
     266             : }
     267             : 
     268             : Datum
     269          11 : int84ne(PG_FUNCTION_ARGS)
     270             : {
     271          11 :     int64       val1 = PG_GETARG_INT64(0);
     272          11 :     int32       val2 = PG_GETARG_INT32(1);
     273             : 
     274          11 :     PG_RETURN_BOOL(val1 != val2);
     275             : }
     276             : 
     277             : Datum
     278          14 : int84lt(PG_FUNCTION_ARGS)
     279             : {
     280          14 :     int64       val1 = PG_GETARG_INT64(0);
     281          14 :     int32       val2 = PG_GETARG_INT32(1);
     282             : 
     283          14 :     PG_RETURN_BOOL(val1 < val2);
     284             : }
     285             : 
     286             : Datum
     287         352 : int84gt(PG_FUNCTION_ARGS)
     288             : {
     289         352 :     int64       val1 = PG_GETARG_INT64(0);
     290         352 :     int32       val2 = PG_GETARG_INT32(1);
     291             : 
     292         352 :     PG_RETURN_BOOL(val1 > val2);
     293             : }
     294             : 
     295             : Datum
     296           7 : int84le(PG_FUNCTION_ARGS)
     297             : {
     298           7 :     int64       val1 = PG_GETARG_INT64(0);
     299           7 :     int32       val2 = PG_GETARG_INT32(1);
     300             : 
     301           7 :     PG_RETURN_BOOL(val1 <= val2);
     302             : }
     303             : 
     304             : Datum
     305         313 : int84ge(PG_FUNCTION_ARGS)
     306             : {
     307         313 :     int64       val1 = PG_GETARG_INT64(0);
     308         313 :     int32       val2 = PG_GETARG_INT32(1);
     309             : 
     310         313 :     PG_RETURN_BOOL(val1 >= val2);
     311             : }
     312             : 
     313             : /* int48relop()
     314             :  * Is 32-bit val1 relop 64-bit val2?
     315             :  */
     316             : Datum
     317        3695 : int48eq(PG_FUNCTION_ARGS)
     318             : {
     319        3695 :     int32       val1 = PG_GETARG_INT32(0);
     320        3695 :     int64       val2 = PG_GETARG_INT64(1);
     321             : 
     322        3695 :     PG_RETURN_BOOL(val1 == val2);
     323             : }
     324             : 
     325             : Datum
     326           5 : int48ne(PG_FUNCTION_ARGS)
     327             : {
     328           5 :     int32       val1 = PG_GETARG_INT32(0);
     329           5 :     int64       val2 = PG_GETARG_INT64(1);
     330             : 
     331           5 :     PG_RETURN_BOOL(val1 != val2);
     332             : }
     333             : 
     334             : Datum
     335         841 : int48lt(PG_FUNCTION_ARGS)
     336             : {
     337         841 :     int32       val1 = PG_GETARG_INT32(0);
     338         841 :     int64       val2 = PG_GETARG_INT64(1);
     339             : 
     340         841 :     PG_RETURN_BOOL(val1 < val2);
     341             : }
     342             : 
     343             : Datum
     344         309 : int48gt(PG_FUNCTION_ARGS)
     345             : {
     346         309 :     int32       val1 = PG_GETARG_INT32(0);
     347         309 :     int64       val2 = PG_GETARG_INT64(1);
     348             : 
     349         309 :     PG_RETURN_BOOL(val1 > val2);
     350             : }
     351             : 
     352             : Datum
     353         405 : int48le(PG_FUNCTION_ARGS)
     354             : {
     355         405 :     int32       val1 = PG_GETARG_INT32(0);
     356         405 :     int64       val2 = PG_GETARG_INT64(1);
     357             : 
     358         405 :     PG_RETURN_BOOL(val1 <= val2);
     359             : }
     360             : 
     361             : Datum
     362         343 : int48ge(PG_FUNCTION_ARGS)
     363             : {
     364         343 :     int32       val1 = PG_GETARG_INT32(0);
     365         343 :     int64       val2 = PG_GETARG_INT64(1);
     366             : 
     367         343 :     PG_RETURN_BOOL(val1 >= val2);
     368             : }
     369             : 
     370             : /* int82relop()
     371             :  * Is 64-bit val1 relop 16-bit val2?
     372             :  */
     373             : Datum
     374           5 : int82eq(PG_FUNCTION_ARGS)
     375             : {
     376           5 :     int64       val1 = PG_GETARG_INT64(0);
     377           5 :     int16       val2 = PG_GETARG_INT16(1);
     378             : 
     379           5 :     PG_RETURN_BOOL(val1 == val2);
     380             : }
     381             : 
     382             : Datum
     383           5 : int82ne(PG_FUNCTION_ARGS)
     384             : {
     385           5 :     int64       val1 = PG_GETARG_INT64(0);
     386           5 :     int16       val2 = PG_GETARG_INT16(1);
     387             : 
     388           5 :     PG_RETURN_BOOL(val1 != val2);
     389             : }
     390             : 
     391             : Datum
     392           5 : int82lt(PG_FUNCTION_ARGS)
     393             : {
     394           5 :     int64       val1 = PG_GETARG_INT64(0);
     395           5 :     int16       val2 = PG_GETARG_INT16(1);
     396             : 
     397           5 :     PG_RETURN_BOOL(val1 < val2);
     398             : }
     399             : 
     400             : Datum
     401         305 : int82gt(PG_FUNCTION_ARGS)
     402             : {
     403         305 :     int64       val1 = PG_GETARG_INT64(0);
     404         305 :     int16       val2 = PG_GETARG_INT16(1);
     405             : 
     406         305 :     PG_RETURN_BOOL(val1 > val2);
     407             : }
     408             : 
     409             : Datum
     410           5 : int82le(PG_FUNCTION_ARGS)
     411             : {
     412           5 :     int64       val1 = PG_GETARG_INT64(0);
     413           5 :     int16       val2 = PG_GETARG_INT16(1);
     414             : 
     415           5 :     PG_RETURN_BOOL(val1 <= val2);
     416             : }
     417             : 
     418             : Datum
     419         305 : int82ge(PG_FUNCTION_ARGS)
     420             : {
     421         305 :     int64       val1 = PG_GETARG_INT64(0);
     422         305 :     int16       val2 = PG_GETARG_INT16(1);
     423             : 
     424         305 :     PG_RETURN_BOOL(val1 >= val2);
     425             : }
     426             : 
     427             : /* int28relop()
     428             :  * Is 16-bit val1 relop 64-bit val2?
     429             :  */
     430             : Datum
     431         106 : int28eq(PG_FUNCTION_ARGS)
     432             : {
     433         106 :     int16       val1 = PG_GETARG_INT16(0);
     434         106 :     int64       val2 = PG_GETARG_INT64(1);
     435             : 
     436         106 :     PG_RETURN_BOOL(val1 == val2);
     437             : }
     438             : 
     439             : Datum
     440         416 : int28ne(PG_FUNCTION_ARGS)
     441             : {
     442         416 :     int16       val1 = PG_GETARG_INT16(0);
     443         416 :     int64       val2 = PG_GETARG_INT64(1);
     444             : 
     445         416 :     PG_RETURN_BOOL(val1 != val2);
     446             : }
     447             : 
     448             : Datum
     449         305 : int28lt(PG_FUNCTION_ARGS)
     450             : {
     451         305 :     int16       val1 = PG_GETARG_INT16(0);
     452         305 :     int64       val2 = PG_GETARG_INT64(1);
     453             : 
     454         305 :     PG_RETURN_BOOL(val1 < val2);
     455             : }
     456             : 
     457             : Datum
     458         305 : int28gt(PG_FUNCTION_ARGS)
     459             : {
     460         305 :     int16       val1 = PG_GETARG_INT16(0);
     461         305 :     int64       val2 = PG_GETARG_INT64(1);
     462             : 
     463         305 :     PG_RETURN_BOOL(val1 > val2);
     464             : }
     465             : 
     466             : Datum
     467         405 : int28le(PG_FUNCTION_ARGS)
     468             : {
     469         405 :     int16       val1 = PG_GETARG_INT16(0);
     470         405 :     int64       val2 = PG_GETARG_INT64(1);
     471             : 
     472         405 :     PG_RETURN_BOOL(val1 <= val2);
     473             : }
     474             : 
     475             : Datum
     476         386 : int28ge(PG_FUNCTION_ARGS)
     477             : {
     478         386 :     int16       val1 = PG_GETARG_INT16(0);
     479         386 :     int64       val2 = PG_GETARG_INT64(1);
     480             : 
     481         386 :     PG_RETURN_BOOL(val1 >= val2);
     482             : }
     483             : 
     484             : 
     485             : /*----------------------------------------------------------
     486             :  *  Arithmetic operators on 64-bit integers.
     487             :  *---------------------------------------------------------*/
     488             : 
     489             : Datum
     490         109 : int8um(PG_FUNCTION_ARGS)
     491             : {
     492         109 :     int64       arg = PG_GETARG_INT64(0);
     493             :     int64       result;
     494             : 
     495         109 :     result = -arg;
     496             :     /* overflow check (needed for INT64_MIN) */
     497         109 :     if (arg != 0 && SAMESIGN(result, arg))
     498           1 :         ereport(ERROR,
     499             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     500             :                  errmsg("bigint out of range")));
     501         108 :     PG_RETURN_INT64(result);
     502             : }
     503             : 
     504             : Datum
     505           1 : int8up(PG_FUNCTION_ARGS)
     506             : {
     507           1 :     int64       arg = PG_GETARG_INT64(0);
     508             : 
     509           1 :     PG_RETURN_INT64(arg);
     510             : }
     511             : 
     512             : Datum
     513       20135 : int8pl(PG_FUNCTION_ARGS)
     514             : {
     515       20135 :     int64       arg1 = PG_GETARG_INT64(0);
     516       20135 :     int64       arg2 = PG_GETARG_INT64(1);
     517             :     int64       result;
     518             : 
     519       20135 :     result = arg1 + arg2;
     520             : 
     521             :     /*
     522             :      * Overflow check.  If the inputs are of different signs then their sum
     523             :      * cannot overflow.  If the inputs are of the same sign, their sum had
     524             :      * better be that sign too.
     525             :      */
     526       20135 :     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
     527           2 :         ereport(ERROR,
     528             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     529             :                  errmsg("bigint out of range")));
     530       20133 :     PG_RETURN_INT64(result);
     531             : }
     532             : 
     533             : Datum
     534          15 : int8mi(PG_FUNCTION_ARGS)
     535             : {
     536          15 :     int64       arg1 = PG_GETARG_INT64(0);
     537          15 :     int64       arg2 = PG_GETARG_INT64(1);
     538             :     int64       result;
     539             : 
     540          15 :     result = arg1 - arg2;
     541             : 
     542             :     /*
     543             :      * Overflow check.  If the inputs are of the same sign then their
     544             :      * difference cannot overflow.  If they are of different signs then the
     545             :      * result should be of the same sign as the first input.
     546             :      */
     547          15 :     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
     548           2 :         ereport(ERROR,
     549             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     550             :                  errmsg("bigint out of range")));
     551          13 :     PG_RETURN_INT64(result);
     552             : }
     553             : 
     554             : Datum
     555       40021 : int8mul(PG_FUNCTION_ARGS)
     556             : {
     557       40021 :     int64       arg1 = PG_GETARG_INT64(0);
     558       40021 :     int64       arg2 = PG_GETARG_INT64(1);
     559             :     int64       result;
     560             : 
     561       40021 :     result = arg1 * arg2;
     562             : 
     563             :     /*
     564             :      * Overflow check.  We basically check to see if result / arg2 gives arg1
     565             :      * again.  There are two cases where this fails: arg2 = 0 (which cannot
     566             :      * overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division itself
     567             :      * will overflow and thus incorrectly match).
     568             :      *
     569             :      * Since the division is likely much more expensive than the actual
     570             :      * multiplication, we'd like to skip it where possible.  The best bang for
     571             :      * the buck seems to be to check whether both inputs are in the int32
     572             :      * range; if so, no overflow is possible.
     573             :      */
     574       40021 :     if (arg1 != (int64) ((int32) arg1) || arg2 != (int64) ((int32) arg2))
     575             :     {
     576          11 :         if (arg2 != 0 &&
     577          11 :             ((arg2 == -1 && arg1 < 0 && result < 0) ||
     578          10 :              result / arg2 != arg1))
     579           3 :             ereport(ERROR,
     580             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     581             :                      errmsg("bigint out of range")));
     582             :     }
     583       40018 :     PG_RETURN_INT64(result);
     584             : }
     585             : 
     586             : Datum
     587          15 : int8div(PG_FUNCTION_ARGS)
     588             : {
     589          15 :     int64       arg1 = PG_GETARG_INT64(0);
     590          15 :     int64       arg2 = PG_GETARG_INT64(1);
     591             :     int64       result;
     592             : 
     593          15 :     if (arg2 == 0)
     594             :     {
     595           1 :         ereport(ERROR,
     596             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     597             :                  errmsg("division by zero")));
     598             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     599             :         PG_RETURN_NULL();
     600             :     }
     601             : 
     602             :     /*
     603             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
     604             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
     605             :      * produce zero, some throw an exception.  We can dodge the problem by
     606             :      * recognizing that division by -1 is the same as negation.
     607             :      */
     608          14 :     if (arg2 == -1)
     609             :     {
     610           1 :         result = -arg1;
     611             :         /* overflow check (needed for INT64_MIN) */
     612           1 :         if (arg1 != 0 && SAMESIGN(result, arg1))
     613           1 :             ereport(ERROR,
     614             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     615             :                      errmsg("bigint out of range")));
     616           0 :         PG_RETURN_INT64(result);
     617             :     }
     618             : 
     619             :     /* No overflow is possible */
     620             : 
     621          13 :     result = arg1 / arg2;
     622             : 
     623          13 :     PG_RETURN_INT64(result);
     624             : }
     625             : 
     626             : /* int8abs()
     627             :  * Absolute value
     628             :  */
     629             : Datum
     630           6 : int8abs(PG_FUNCTION_ARGS)
     631             : {
     632           6 :     int64       arg1 = PG_GETARG_INT64(0);
     633             :     int64       result;
     634             : 
     635           6 :     result = (arg1 < 0) ? -arg1 : arg1;
     636             :     /* overflow check (needed for INT64_MIN) */
     637           6 :     if (result < 0)
     638           1 :         ereport(ERROR,
     639             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     640             :                  errmsg("bigint out of range")));
     641           5 :     PG_RETURN_INT64(result);
     642             : }
     643             : 
     644             : /* int8mod()
     645             :  * Modulo operation.
     646             :  */
     647             : Datum
     648           9 : int8mod(PG_FUNCTION_ARGS)
     649             : {
     650           9 :     int64       arg1 = PG_GETARG_INT64(0);
     651           9 :     int64       arg2 = PG_GETARG_INT64(1);
     652             : 
     653           9 :     if (arg2 == 0)
     654             :     {
     655           1 :         ereport(ERROR,
     656             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     657             :                  errmsg("division by zero")));
     658             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     659             :         PG_RETURN_NULL();
     660             :     }
     661             : 
     662             :     /*
     663             :      * Some machines throw a floating-point exception for INT64_MIN % -1,
     664             :      * which is a bit silly since the correct answer is perfectly
     665             :      * well-defined, namely zero.
     666             :      */
     667           8 :     if (arg2 == -1)
     668           3 :         PG_RETURN_INT64(0);
     669             : 
     670             :     /* No overflow is possible */
     671             : 
     672           5 :     PG_RETURN_INT64(arg1 % arg2);
     673             : }
     674             : 
     675             : 
     676             : Datum
     677     8177943 : int8inc(PG_FUNCTION_ARGS)
     678             : {
     679             :     /*
     680             :      * When int8 is pass-by-reference, we provide this special case to avoid
     681             :      * palloc overhead for COUNT(): when called as an aggregate, we know that
     682             :      * the argument is modifiable local storage, so just update it in-place.
     683             :      * (If int8 is pass-by-value, then of course this is useless as well as
     684             :      * incorrect, so just ifdef it out.)
     685             :      */
     686             : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
     687     8177943 :     if (AggCheckCallContext(fcinfo, NULL))
     688             :     {
     689     8177943 :         int64      *arg = (int64 *) PG_GETARG_POINTER(0);
     690             :         int64       result;
     691             : 
     692     8177943 :         result = *arg + 1;
     693             :         /* Overflow check */
     694     8177943 :         if (result < 0 && *arg > 0)
     695           0 :             ereport(ERROR,
     696             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     697             :                      errmsg("bigint out of range")));
     698             : 
     699     8177943 :         *arg = result;
     700     8177943 :         PG_RETURN_POINTER(arg);
     701             :     }
     702             :     else
     703             : #endif
     704             :     {
     705             :         /* Not called as an aggregate, so just do it the dumb way */
     706           0 :         int64       arg = PG_GETARG_INT64(0);
     707             :         int64       result;
     708             : 
     709           0 :         result = arg + 1;
     710             :         /* Overflow check */
     711           0 :         if (result < 0 && arg > 0)
     712           0 :             ereport(ERROR,
     713             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     714             :                      errmsg("bigint out of range")));
     715             : 
     716           0 :         PG_RETURN_INT64(result);
     717             :     }
     718             : }
     719             : 
     720             : Datum
     721           4 : int8dec(PG_FUNCTION_ARGS)
     722             : {
     723             :     /*
     724             :      * When int8 is pass-by-reference, we provide this special case to avoid
     725             :      * palloc overhead for COUNT(): when called as an aggregate, we know that
     726             :      * the argument is modifiable local storage, so just update it in-place.
     727             :      * (If int8 is pass-by-value, then of course this is useless as well as
     728             :      * incorrect, so just ifdef it out.)
     729             :      */
     730             : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
     731           4 :     if (AggCheckCallContext(fcinfo, NULL))
     732             :     {
     733           4 :         int64      *arg = (int64 *) PG_GETARG_POINTER(0);
     734             :         int64       result;
     735             : 
     736           4 :         result = *arg - 1;
     737             :         /* Overflow check */
     738           4 :         if (result > 0 && *arg < 0)
     739           0 :             ereport(ERROR,
     740             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     741             :                      errmsg("bigint out of range")));
     742             : 
     743           4 :         *arg = result;
     744           4 :         PG_RETURN_POINTER(arg);
     745             :     }
     746             :     else
     747             : #endif
     748             :     {
     749             :         /* Not called as an aggregate, so just do it the dumb way */
     750           0 :         int64       arg = PG_GETARG_INT64(0);
     751             :         int64       result;
     752             : 
     753           0 :         result = arg - 1;
     754             :         /* Overflow check */
     755           0 :         if (result > 0 && arg < 0)
     756           0 :             ereport(ERROR,
     757             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     758             :                      errmsg("bigint out of range")));
     759             : 
     760           0 :         PG_RETURN_INT64(result);
     761             :     }
     762             : }
     763             : 
     764             : 
     765             : /*
     766             :  * These functions are exactly like int8inc/int8dec but are used for
     767             :  * aggregates that count only non-null values.  Since the functions are
     768             :  * declared strict, the null checks happen before we ever get here, and all we
     769             :  * need do is increment the state value.  We could actually make these pg_proc
     770             :  * entries point right at int8inc/int8dec, but then the opr_sanity regression
     771             :  * test would complain about mismatched entries for a built-in function.
     772             :  */
     773             : 
     774             : Datum
     775       99865 : int8inc_any(PG_FUNCTION_ARGS)
     776             : {
     777       99865 :     return int8inc(fcinfo);
     778             : }
     779             : 
     780             : Datum
     781           4 : int8inc_float8_float8(PG_FUNCTION_ARGS)
     782             : {
     783           4 :     return int8inc(fcinfo);
     784             : }
     785             : 
     786             : Datum
     787           1 : int8dec_any(PG_FUNCTION_ARGS)
     788             : {
     789           1 :     return int8dec(fcinfo);
     790             : }
     791             : 
     792             : 
     793             : Datum
     794           8 : int8larger(PG_FUNCTION_ARGS)
     795             : {
     796           8 :     int64       arg1 = PG_GETARG_INT64(0);
     797           8 :     int64       arg2 = PG_GETARG_INT64(1);
     798             :     int64       result;
     799             : 
     800           8 :     result = ((arg1 > arg2) ? arg1 : arg2);
     801             : 
     802           8 :     PG_RETURN_INT64(result);
     803             : }
     804             : 
     805             : Datum
     806          18 : int8smaller(PG_FUNCTION_ARGS)
     807             : {
     808          18 :     int64       arg1 = PG_GETARG_INT64(0);
     809          18 :     int64       arg2 = PG_GETARG_INT64(1);
     810             :     int64       result;
     811             : 
     812          18 :     result = ((arg1 < arg2) ? arg1 : arg2);
     813             : 
     814          18 :     PG_RETURN_INT64(result);
     815             : }
     816             : 
     817             : Datum
     818          52 : int84pl(PG_FUNCTION_ARGS)
     819             : {
     820          52 :     int64       arg1 = PG_GETARG_INT64(0);
     821          52 :     int32       arg2 = PG_GETARG_INT32(1);
     822             :     int64       result;
     823             : 
     824          52 :     result = arg1 + arg2;
     825             : 
     826             :     /*
     827             :      * Overflow check.  If the inputs are of different signs then their sum
     828             :      * cannot overflow.  If the inputs are of the same sign, their sum had
     829             :      * better be that sign too.
     830             :      */
     831          52 :     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
     832           1 :         ereport(ERROR,
     833             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     834             :                  errmsg("bigint out of range")));
     835          51 :     PG_RETURN_INT64(result);
     836             : }
     837             : 
     838             : Datum
     839           7 : int84mi(PG_FUNCTION_ARGS)
     840             : {
     841           7 :     int64       arg1 = PG_GETARG_INT64(0);
     842           7 :     int32       arg2 = PG_GETARG_INT32(1);
     843             :     int64       result;
     844             : 
     845           7 :     result = arg1 - arg2;
     846             : 
     847             :     /*
     848             :      * Overflow check.  If the inputs are of the same sign then their
     849             :      * difference cannot overflow.  If they are of different signs then the
     850             :      * result should be of the same sign as the first input.
     851             :      */
     852           7 :     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
     853           1 :         ereport(ERROR,
     854             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     855             :                  errmsg("bigint out of range")));
     856           6 :     PG_RETURN_INT64(result);
     857             : }
     858             : 
     859             : Datum
     860         137 : int84mul(PG_FUNCTION_ARGS)
     861             : {
     862         137 :     int64       arg1 = PG_GETARG_INT64(0);
     863         137 :     int32       arg2 = PG_GETARG_INT32(1);
     864             :     int64       result;
     865             : 
     866         137 :     result = arg1 * arg2;
     867             : 
     868             :     /*
     869             :      * Overflow check.  We basically check to see if result / arg1 gives arg2
     870             :      * again.  There is one case where this fails: arg1 = 0 (which cannot
     871             :      * overflow).
     872             :      *
     873             :      * Since the division is likely much more expensive than the actual
     874             :      * multiplication, we'd like to skip it where possible.  The best bang for
     875             :      * the buck seems to be to check whether both inputs are in the int32
     876             :      * range; if so, no overflow is possible.
     877             :      */
     878         157 :     if (arg1 != (int64) ((int32) arg1) &&
     879          20 :         result / arg1 != arg2)
     880           2 :         ereport(ERROR,
     881             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     882             :                  errmsg("bigint out of range")));
     883         135 :     PG_RETURN_INT64(result);
     884             : }
     885             : 
     886             : Datum
     887          12 : int84div(PG_FUNCTION_ARGS)
     888             : {
     889          12 :     int64       arg1 = PG_GETARG_INT64(0);
     890          12 :     int32       arg2 = PG_GETARG_INT32(1);
     891             :     int64       result;
     892             : 
     893          12 :     if (arg2 == 0)
     894             :     {
     895           1 :         ereport(ERROR,
     896             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     897             :                  errmsg("division by zero")));
     898             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     899             :         PG_RETURN_NULL();
     900             :     }
     901             : 
     902             :     /*
     903             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
     904             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
     905             :      * produce zero, some throw an exception.  We can dodge the problem by
     906             :      * recognizing that division by -1 is the same as negation.
     907             :      */
     908          11 :     if (arg2 == -1)
     909             :     {
     910           1 :         result = -arg1;
     911             :         /* overflow check (needed for INT64_MIN) */
     912           1 :         if (arg1 != 0 && SAMESIGN(result, arg1))
     913           1 :             ereport(ERROR,
     914             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     915             :                      errmsg("bigint out of range")));
     916           0 :         PG_RETURN_INT64(result);
     917             :     }
     918             : 
     919             :     /* No overflow is possible */
     920             : 
     921          10 :     result = arg1 / arg2;
     922             : 
     923          10 :     PG_RETURN_INT64(result);
     924             : }
     925             : 
     926             : Datum
     927          32 : int48pl(PG_FUNCTION_ARGS)
     928             : {
     929          32 :     int32       arg1 = PG_GETARG_INT32(0);
     930          32 :     int64       arg2 = PG_GETARG_INT64(1);
     931             :     int64       result;
     932             : 
     933          32 :     result = arg1 + arg2;
     934             : 
     935             :     /*
     936             :      * Overflow check.  If the inputs are of different signs then their sum
     937             :      * cannot overflow.  If the inputs are of the same sign, their sum had
     938             :      * better be that sign too.
     939             :      */
     940          32 :     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
     941           1 :         ereport(ERROR,
     942             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     943             :                  errmsg("bigint out of range")));
     944          31 :     PG_RETURN_INT64(result);
     945             : }
     946             : 
     947             : Datum
     948          11 : int48mi(PG_FUNCTION_ARGS)
     949             : {
     950          11 :     int32       arg1 = PG_GETARG_INT32(0);
     951          11 :     int64       arg2 = PG_GETARG_INT64(1);
     952             :     int64       result;
     953             : 
     954          11 :     result = arg1 - arg2;
     955             : 
     956             :     /*
     957             :      * Overflow check.  If the inputs are of the same sign then their
     958             :      * difference cannot overflow.  If they are of different signs then the
     959             :      * result should be of the same sign as the first input.
     960             :      */
     961          11 :     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
     962           1 :         ereport(ERROR,
     963             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     964             :                  errmsg("bigint out of range")));
     965          10 :     PG_RETURN_INT64(result);
     966             : }
     967             : 
     968             : Datum
     969          27 : int48mul(PG_FUNCTION_ARGS)
     970             : {
     971          27 :     int32       arg1 = PG_GETARG_INT32(0);
     972          27 :     int64       arg2 = PG_GETARG_INT64(1);
     973             :     int64       result;
     974             : 
     975          27 :     result = arg1 * arg2;
     976             : 
     977             :     /*
     978             :      * Overflow check.  We basically check to see if result / arg2 gives arg1
     979             :      * again.  There is one case where this fails: arg2 = 0 (which cannot
     980             :      * overflow).
     981             :      *
     982             :      * Since the division is likely much more expensive than the actual
     983             :      * multiplication, we'd like to skip it where possible.  The best bang for
     984             :      * the buck seems to be to check whether both inputs are in the int32
     985             :      * range; if so, no overflow is possible.
     986             :      */
     987          36 :     if (arg2 != (int64) ((int32) arg2) &&
     988           9 :         result / arg2 != arg1)
     989           1 :         ereport(ERROR,
     990             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     991             :                  errmsg("bigint out of range")));
     992          26 :     PG_RETURN_INT64(result);
     993             : }
     994             : 
     995             : Datum
     996           6 : int48div(PG_FUNCTION_ARGS)
     997             : {
     998           6 :     int32       arg1 = PG_GETARG_INT32(0);
     999           6 :     int64       arg2 = PG_GETARG_INT64(1);
    1000             : 
    1001           6 :     if (arg2 == 0)
    1002             :     {
    1003           1 :         ereport(ERROR,
    1004             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1005             :                  errmsg("division by zero")));
    1006             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1007             :         PG_RETURN_NULL();
    1008             :     }
    1009             : 
    1010             :     /* No overflow is possible */
    1011           5 :     PG_RETURN_INT64((int64) arg1 / arg2);
    1012             : }
    1013             : 
    1014             : Datum
    1015           6 : int82pl(PG_FUNCTION_ARGS)
    1016             : {
    1017           6 :     int64       arg1 = PG_GETARG_INT64(0);
    1018           6 :     int16       arg2 = PG_GETARG_INT16(1);
    1019             :     int64       result;
    1020             : 
    1021           6 :     result = arg1 + arg2;
    1022             : 
    1023             :     /*
    1024             :      * Overflow check.  If the inputs are of different signs then their sum
    1025             :      * cannot overflow.  If the inputs are of the same sign, their sum had
    1026             :      * better be that sign too.
    1027             :      */
    1028           6 :     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
    1029           1 :         ereport(ERROR,
    1030             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1031             :                  errmsg("bigint out of range")));
    1032           5 :     PG_RETURN_INT64(result);
    1033             : }
    1034             : 
    1035             : Datum
    1036           6 : int82mi(PG_FUNCTION_ARGS)
    1037             : {
    1038           6 :     int64       arg1 = PG_GETARG_INT64(0);
    1039           6 :     int16       arg2 = PG_GETARG_INT16(1);
    1040             :     int64       result;
    1041             : 
    1042           6 :     result = arg1 - arg2;
    1043             : 
    1044             :     /*
    1045             :      * Overflow check.  If the inputs are of the same sign then their
    1046             :      * difference cannot overflow.  If they are of different signs then the
    1047             :      * result should be of the same sign as the first input.
    1048             :      */
    1049           6 :     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
    1050           1 :         ereport(ERROR,
    1051             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1052             :                  errmsg("bigint out of range")));
    1053           5 :     PG_RETURN_INT64(result);
    1054             : }
    1055             : 
    1056             : Datum
    1057           7 : int82mul(PG_FUNCTION_ARGS)
    1058             : {
    1059           7 :     int64       arg1 = PG_GETARG_INT64(0);
    1060           7 :     int16       arg2 = PG_GETARG_INT16(1);
    1061             :     int64       result;
    1062             : 
    1063           7 :     result = arg1 * arg2;
    1064             : 
    1065             :     /*
    1066             :      * Overflow check.  We basically check to see if result / arg1 gives arg2
    1067             :      * again.  There is one case where this fails: arg1 = 0 (which cannot
    1068             :      * overflow).
    1069             :      *
    1070             :      * Since the division is likely much more expensive than the actual
    1071             :      * multiplication, we'd like to skip it where possible.  The best bang for
    1072             :      * the buck seems to be to check whether both inputs are in the int32
    1073             :      * range; if so, no overflow is possible.
    1074             :      */
    1075          12 :     if (arg1 != (int64) ((int32) arg1) &&
    1076           5 :         result / arg1 != arg2)
    1077           2 :         ereport(ERROR,
    1078             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1079             :                  errmsg("bigint out of range")));
    1080           5 :     PG_RETURN_INT64(result);
    1081             : }
    1082             : 
    1083             : Datum
    1084           7 : int82div(PG_FUNCTION_ARGS)
    1085             : {
    1086           7 :     int64       arg1 = PG_GETARG_INT64(0);
    1087           7 :     int16       arg2 = PG_GETARG_INT16(1);
    1088             :     int64       result;
    1089             : 
    1090           7 :     if (arg2 == 0)
    1091             :     {
    1092           1 :         ereport(ERROR,
    1093             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1094             :                  errmsg("division by zero")));
    1095             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1096             :         PG_RETURN_NULL();
    1097             :     }
    1098             : 
    1099             :     /*
    1100             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
    1101             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
    1102             :      * produce zero, some throw an exception.  We can dodge the problem by
    1103             :      * recognizing that division by -1 is the same as negation.
    1104             :      */
    1105           6 :     if (arg2 == -1)
    1106             :     {
    1107           1 :         result = -arg1;
    1108             :         /* overflow check (needed for INT64_MIN) */
    1109           1 :         if (arg1 != 0 && SAMESIGN(result, arg1))
    1110           1 :             ereport(ERROR,
    1111             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1112             :                      errmsg("bigint out of range")));
    1113           0 :         PG_RETURN_INT64(result);
    1114             :     }
    1115             : 
    1116             :     /* No overflow is possible */
    1117             : 
    1118           5 :     result = arg1 / arg2;
    1119             : 
    1120           5 :     PG_RETURN_INT64(result);
    1121             : }
    1122             : 
    1123             : Datum
    1124           6 : int28pl(PG_FUNCTION_ARGS)
    1125             : {
    1126           6 :     int16       arg1 = PG_GETARG_INT16(0);
    1127           6 :     int64       arg2 = PG_GETARG_INT64(1);
    1128             :     int64       result;
    1129             : 
    1130           6 :     result = arg1 + arg2;
    1131             : 
    1132             :     /*
    1133             :      * Overflow check.  If the inputs are of different signs then their sum
    1134             :      * cannot overflow.  If the inputs are of the same sign, their sum had
    1135             :      * better be that sign too.
    1136             :      */
    1137           6 :     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
    1138           1 :         ereport(ERROR,
    1139             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1140             :                  errmsg("bigint out of range")));
    1141           5 :     PG_RETURN_INT64(result);
    1142             : }
    1143             : 
    1144             : Datum
    1145           6 : int28mi(PG_FUNCTION_ARGS)
    1146             : {
    1147           6 :     int16       arg1 = PG_GETARG_INT16(0);
    1148           6 :     int64       arg2 = PG_GETARG_INT64(1);
    1149             :     int64       result;
    1150             : 
    1151           6 :     result = arg1 - arg2;
    1152             : 
    1153             :     /*
    1154             :      * Overflow check.  If the inputs are of the same sign then their
    1155             :      * difference cannot overflow.  If they are of different signs then the
    1156             :      * result should be of the same sign as the first input.
    1157             :      */
    1158           6 :     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
    1159           1 :         ereport(ERROR,
    1160             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1161             :                  errmsg("bigint out of range")));
    1162           5 :     PG_RETURN_INT64(result);
    1163             : }
    1164             : 
    1165             : Datum
    1166           6 : int28mul(PG_FUNCTION_ARGS)
    1167             : {
    1168           6 :     int16       arg1 = PG_GETARG_INT16(0);
    1169           6 :     int64       arg2 = PG_GETARG_INT64(1);
    1170             :     int64       result;
    1171             : 
    1172           6 :     result = arg1 * arg2;
    1173             : 
    1174             :     /*
    1175             :      * Overflow check.  We basically check to see if result / arg2 gives arg1
    1176             :      * again.  There is one case where this fails: arg2 = 0 (which cannot
    1177             :      * overflow).
    1178             :      *
    1179             :      * Since the division is likely much more expensive than the actual
    1180             :      * multiplication, we'd like to skip it where possible.  The best bang for
    1181             :      * the buck seems to be to check whether both inputs are in the int32
    1182             :      * range; if so, no overflow is possible.
    1183             :      */
    1184          10 :     if (arg2 != (int64) ((int32) arg2) &&
    1185           4 :         result / arg2 != arg1)
    1186           1 :         ereport(ERROR,
    1187             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1188             :                  errmsg("bigint out of range")));
    1189           5 :     PG_RETURN_INT64(result);
    1190             : }
    1191             : 
    1192             : Datum
    1193           6 : int28div(PG_FUNCTION_ARGS)
    1194             : {
    1195           6 :     int16       arg1 = PG_GETARG_INT16(0);
    1196           6 :     int64       arg2 = PG_GETARG_INT64(1);
    1197             : 
    1198           6 :     if (arg2 == 0)
    1199             :     {
    1200           1 :         ereport(ERROR,
    1201             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1202             :                  errmsg("division by zero")));
    1203             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1204             :         PG_RETURN_NULL();
    1205             :     }
    1206             : 
    1207             :     /* No overflow is possible */
    1208           5 :     PG_RETURN_INT64((int64) arg1 / arg2);
    1209             : }
    1210             : 
    1211             : /* Binary arithmetics
    1212             :  *
    1213             :  *      int8and     - returns arg1 & arg2
    1214             :  *      int8or      - returns arg1 | arg2
    1215             :  *      int8xor     - returns arg1 # arg2
    1216             :  *      int8not     - returns ~arg1
    1217             :  *      int8shl     - returns arg1 << arg2
    1218             :  *      int8shr     - returns arg1 >> arg2
    1219             :  */
    1220             : 
    1221             : Datum
    1222           7 : int8and(PG_FUNCTION_ARGS)
    1223             : {
    1224           7 :     int64       arg1 = PG_GETARG_INT64(0);
    1225           7 :     int64       arg2 = PG_GETARG_INT64(1);
    1226             : 
    1227           7 :     PG_RETURN_INT64(arg1 & arg2);
    1228             : }
    1229             : 
    1230             : Datum
    1231           7 : int8or(PG_FUNCTION_ARGS)
    1232             : {
    1233           7 :     int64       arg1 = PG_GETARG_INT64(0);
    1234           7 :     int64       arg2 = PG_GETARG_INT64(1);
    1235             : 
    1236           7 :     PG_RETURN_INT64(arg1 | arg2);
    1237             : }
    1238             : 
    1239             : Datum
    1240           5 : int8xor(PG_FUNCTION_ARGS)
    1241             : {
    1242           5 :     int64       arg1 = PG_GETARG_INT64(0);
    1243           5 :     int64       arg2 = PG_GETARG_INT64(1);
    1244             : 
    1245           5 :     PG_RETURN_INT64(arg1 ^ arg2);
    1246             : }
    1247             : 
    1248             : Datum
    1249           5 : int8not(PG_FUNCTION_ARGS)
    1250             : {
    1251           5 :     int64       arg1 = PG_GETARG_INT64(0);
    1252             : 
    1253           5 :     PG_RETURN_INT64(~arg1);
    1254             : }
    1255             : 
    1256             : Datum
    1257           7 : int8shl(PG_FUNCTION_ARGS)
    1258             : {
    1259           7 :     int64       arg1 = PG_GETARG_INT64(0);
    1260           7 :     int32       arg2 = PG_GETARG_INT32(1);
    1261             : 
    1262           7 :     PG_RETURN_INT64(arg1 << arg2);
    1263             : }
    1264             : 
    1265             : Datum
    1266           5 : int8shr(PG_FUNCTION_ARGS)
    1267             : {
    1268           5 :     int64       arg1 = PG_GETARG_INT64(0);
    1269           5 :     int32       arg2 = PG_GETARG_INT32(1);
    1270             : 
    1271           5 :     PG_RETURN_INT64(arg1 >> arg2);
    1272             : }
    1273             : 
    1274             : /*----------------------------------------------------------
    1275             :  *  Conversion operators.
    1276             :  *---------------------------------------------------------*/
    1277             : 
    1278             : Datum
    1279        1262 : int48(PG_FUNCTION_ARGS)
    1280             : {
    1281        1262 :     int32       arg = PG_GETARG_INT32(0);
    1282             : 
    1283        1262 :     PG_RETURN_INT64((int64) arg);
    1284             : }
    1285             : 
    1286             : Datum
    1287        1069 : int84(PG_FUNCTION_ARGS)
    1288             : {
    1289        1069 :     int64       arg = PG_GETARG_INT64(0);
    1290             :     int32       result;
    1291             : 
    1292        1069 :     result = (int32) arg;
    1293             : 
    1294             :     /* Test for overflow by reverse-conversion. */
    1295        1069 :     if ((int64) result != arg)
    1296           1 :         ereport(ERROR,
    1297             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1298             :                  errmsg("integer out of range")));
    1299             : 
    1300        1068 :     PG_RETURN_INT32(result);
    1301             : }
    1302             : 
    1303             : Datum
    1304           3 : int28(PG_FUNCTION_ARGS)
    1305             : {
    1306           3 :     int16       arg = PG_GETARG_INT16(0);
    1307             : 
    1308           3 :     PG_RETURN_INT64((int64) arg);
    1309             : }
    1310             : 
    1311             : Datum
    1312           6 : int82(PG_FUNCTION_ARGS)
    1313             : {
    1314           6 :     int64       arg = PG_GETARG_INT64(0);
    1315             :     int16       result;
    1316             : 
    1317           6 :     result = (int16) arg;
    1318             : 
    1319             :     /* Test for overflow by reverse-conversion. */
    1320           6 :     if ((int64) result != arg)
    1321           1 :         ereport(ERROR,
    1322             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1323             :                  errmsg("smallint out of range")));
    1324             : 
    1325           5 :     PG_RETURN_INT16(result);
    1326             : }
    1327             : 
    1328             : Datum
    1329          25 : i8tod(PG_FUNCTION_ARGS)
    1330             : {
    1331          25 :     int64       arg = PG_GETARG_INT64(0);
    1332             :     float8      result;
    1333             : 
    1334          25 :     result = arg;
    1335             : 
    1336          25 :     PG_RETURN_FLOAT8(result);
    1337             : }
    1338             : 
    1339             : /* dtoi8()
    1340             :  * Convert float8 to 8-byte integer.
    1341             :  */
    1342             : Datum
    1343           9 : dtoi8(PG_FUNCTION_ARGS)
    1344             : {
    1345           9 :     float8      arg = PG_GETARG_FLOAT8(0);
    1346             :     int64       result;
    1347             : 
    1348             :     /* Round arg to nearest integer (but it's still in float form) */
    1349           9 :     arg = rint(arg);
    1350             : 
    1351             :     /*
    1352             :      * Does it fit in an int64?  Avoid assuming that we have handy constants
    1353             :      * defined for the range boundaries, instead test for overflow by
    1354             :      * reverse-conversion.
    1355             :      */
    1356           9 :     result = (int64) arg;
    1357             : 
    1358           9 :     if ((float8) result != arg)
    1359           1 :         ereport(ERROR,
    1360             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1361             :                  errmsg("bigint out of range")));
    1362             : 
    1363           8 :     PG_RETURN_INT64(result);
    1364             : }
    1365             : 
    1366             : Datum
    1367           5 : i8tof(PG_FUNCTION_ARGS)
    1368             : {
    1369           5 :     int64       arg = PG_GETARG_INT64(0);
    1370             :     float4      result;
    1371             : 
    1372           5 :     result = arg;
    1373             : 
    1374           5 :     PG_RETURN_FLOAT4(result);
    1375             : }
    1376             : 
    1377             : /* ftoi8()
    1378             :  * Convert float4 to 8-byte integer.
    1379             :  */
    1380             : Datum
    1381           1 : ftoi8(PG_FUNCTION_ARGS)
    1382             : {
    1383           1 :     float4      arg = PG_GETARG_FLOAT4(0);
    1384             :     int64       result;
    1385             :     float8      darg;
    1386             : 
    1387             :     /* Round arg to nearest integer (but it's still in float form) */
    1388           1 :     darg = rint(arg);
    1389             : 
    1390             :     /*
    1391             :      * Does it fit in an int64?  Avoid assuming that we have handy constants
    1392             :      * defined for the range boundaries, instead test for overflow by
    1393             :      * reverse-conversion.
    1394             :      */
    1395           1 :     result = (int64) darg;
    1396             : 
    1397           1 :     if ((float8) result != darg)
    1398           0 :         ereport(ERROR,
    1399             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1400             :                  errmsg("bigint out of range")));
    1401             : 
    1402           1 :     PG_RETURN_INT64(result);
    1403             : }
    1404             : 
    1405             : Datum
    1406           3 : i8tooid(PG_FUNCTION_ARGS)
    1407             : {
    1408           3 :     int64       arg = PG_GETARG_INT64(0);
    1409             :     Oid         result;
    1410             : 
    1411           3 :     result = (Oid) arg;
    1412             : 
    1413             :     /* Test for overflow by reverse-conversion. */
    1414           3 :     if ((int64) result != arg)
    1415           1 :         ereport(ERROR,
    1416             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1417             :                  errmsg("OID out of range")));
    1418             : 
    1419           2 :     PG_RETURN_OID(result);
    1420             : }
    1421             : 
    1422             : Datum
    1423           1 : oidtoi8(PG_FUNCTION_ARGS)
    1424             : {
    1425           1 :     Oid         arg = PG_GETARG_OID(0);
    1426             : 
    1427           1 :     PG_RETURN_INT64((int64) arg);
    1428             : }
    1429             : 
    1430             : /*
    1431             :  * non-persistent numeric series generator
    1432             :  */
    1433             : Datum
    1434          12 : generate_series_int8(PG_FUNCTION_ARGS)
    1435             : {
    1436          12 :     return generate_series_step_int8(fcinfo);
    1437             : }
    1438             : 
    1439             : Datum
    1440          20 : generate_series_step_int8(PG_FUNCTION_ARGS)
    1441             : {
    1442             :     FuncCallContext *funcctx;
    1443             :     generate_series_fctx *fctx;
    1444             :     int64       result;
    1445             :     MemoryContext oldcontext;
    1446             : 
    1447             :     /* stuff done only on the first call of the function */
    1448          20 :     if (SRF_IS_FIRSTCALL())
    1449             :     {
    1450           3 :         int64       start = PG_GETARG_INT64(0);
    1451           3 :         int64       finish = PG_GETARG_INT64(1);
    1452           3 :         int64       step = 1;
    1453             : 
    1454             :         /* see if we were given an explicit step size */
    1455           3 :         if (PG_NARGS() == 3)
    1456           2 :             step = PG_GETARG_INT64(2);
    1457           3 :         if (step == 0)
    1458           1 :             ereport(ERROR,
    1459             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1460             :                      errmsg("step size cannot equal zero")));
    1461             : 
    1462             :         /* create a function context for cross-call persistence */
    1463           2 :         funcctx = SRF_FIRSTCALL_INIT();
    1464             : 
    1465             :         /*
    1466             :          * switch to memory context appropriate for multiple function calls
    1467             :          */
    1468           2 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1469             : 
    1470             :         /* allocate memory for user context */
    1471           2 :         fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
    1472             : 
    1473             :         /*
    1474             :          * Use fctx to keep state from call to call. Seed current with the
    1475             :          * original start value
    1476             :          */
    1477           2 :         fctx->current = start;
    1478           2 :         fctx->finish = finish;
    1479           2 :         fctx->step = step;
    1480             : 
    1481           2 :         funcctx->user_fctx = fctx;
    1482           2 :         MemoryContextSwitchTo(oldcontext);
    1483             :     }
    1484             : 
    1485             :     /* stuff done on every call of the function */
    1486          19 :     funcctx = SRF_PERCALL_SETUP();
    1487             : 
    1488             :     /*
    1489             :      * get the saved state and use current as the result for this iteration
    1490             :      */
    1491          19 :     fctx = funcctx->user_fctx;
    1492          19 :     result = fctx->current;
    1493             : 
    1494          21 :     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
    1495           2 :         (fctx->step < 0 && fctx->current >= fctx->finish))
    1496             :     {
    1497             :         /* increment current in preparation for next iteration */
    1498          17 :         fctx->current += fctx->step;
    1499             : 
    1500             :         /* if next-value computation overflows, this is the final result */
    1501          17 :         if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
    1502           0 :             fctx->step = 0;
    1503             : 
    1504             :         /* do when there is more left to send */
    1505          17 :         SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
    1506             :     }
    1507             :     else
    1508             :         /* do when there is no more left */
    1509           2 :         SRF_RETURN_DONE(funcctx);
    1510             : }

Generated by: LCOV version 1.11