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

Generated by: LCOV version 1.13