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

Generated by: LCOV version 2.0-1