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

Generated by: LCOV version 1.13