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-04-07 14:16:30 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        80672 : int8in(PG_FUNCTION_ARGS)
      51              : {
      52        80672 :     char       *num = PG_GETARG_CSTRING(0);
      53              : 
      54        80672 :     PG_RETURN_INT64(pg_strtoint64_safe(num, fcinfo->context));
      55              : }
      56              : 
      57              : 
      58              : /* int8out()
      59              :  */
      60              : Datum
      61       173609 : int8out(PG_FUNCTION_ARGS)
      62              : {
      63       173609 :     int64       val = PG_GETARG_INT64(0);
      64              :     char        buf[MAXINT8LEN + 1];
      65              :     char       *result;
      66              :     int         len;
      67              : 
      68       173609 :     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       173609 :     result = palloc(len);
      75       173609 :     memcpy(result, buf, len);
      76       173609 :     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         2428 : int8send(PG_FUNCTION_ARGS)
      95              : {
      96         2428 :     int64       arg1 = PG_GETARG_INT64(0);
      97              :     StringInfoData buf;
      98              : 
      99         2428 :     pq_begintypsend(&buf);
     100         2428 :     pq_sendint64(&buf, arg1);
     101         2428 :     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       231215 : int8eq(PG_FUNCTION_ARGS)
     114              : {
     115       231215 :     int64       val1 = PG_GETARG_INT64(0);
     116       231215 :     int64       val2 = PG_GETARG_INT64(1);
     117              : 
     118       231215 :     PG_RETURN_BOOL(val1 == val2);
     119              : }
     120              : 
     121              : Datum
     122        40033 : int8ne(PG_FUNCTION_ARGS)
     123              : {
     124        40033 :     int64       val1 = PG_GETARG_INT64(0);
     125        40033 :     int64       val2 = PG_GETARG_INT64(1);
     126              : 
     127        40033 :     PG_RETURN_BOOL(val1 != val2);
     128              : }
     129              : 
     130              : Datum
     131       349904 : int8lt(PG_FUNCTION_ARGS)
     132              : {
     133       349904 :     int64       val1 = PG_GETARG_INT64(0);
     134       349904 :     int64       val2 = PG_GETARG_INT64(1);
     135              : 
     136       349904 :     PG_RETURN_BOOL(val1 < val2);
     137              : }
     138              : 
     139              : Datum
     140       130359 : int8gt(PG_FUNCTION_ARGS)
     141              : {
     142       130359 :     int64       val1 = PG_GETARG_INT64(0);
     143       130359 :     int64       val2 = PG_GETARG_INT64(1);
     144              : 
     145       130359 :     PG_RETURN_BOOL(val1 > val2);
     146              : }
     147              : 
     148              : Datum
     149         3153 : int8le(PG_FUNCTION_ARGS)
     150              : {
     151         3153 :     int64       val1 = PG_GETARG_INT64(0);
     152         3153 :     int64       val2 = PG_GETARG_INT64(1);
     153              : 
     154         3153 :     PG_RETURN_BOOL(val1 <= val2);
     155              : }
     156              : 
     157              : Datum
     158         3496 : int8ge(PG_FUNCTION_ARGS)
     159              : {
     160         3496 :     int64       val1 = PG_GETARG_INT64(0);
     161         3496 :     int64       val2 = PG_GETARG_INT64(1);
     162              : 
     163         3496 :     PG_RETURN_BOOL(val1 >= val2);
     164              : }
     165              : 
     166              : /* int84relop()
     167              :  * Is 64-bit val1 relop 32-bit val2?
     168              :  */
     169              : Datum
     170       117373 : int84eq(PG_FUNCTION_ARGS)
     171              : {
     172       117373 :     int64       val1 = PG_GETARG_INT64(0);
     173       117373 :     int32       val2 = PG_GETARG_INT32(1);
     174              : 
     175       117373 :     PG_RETURN_BOOL(val1 == val2);
     176              : }
     177              : 
     178              : Datum
     179           71 : int84ne(PG_FUNCTION_ARGS)
     180              : {
     181           71 :     int64       val1 = PG_GETARG_INT64(0);
     182           71 :     int32       val2 = PG_GETARG_INT32(1);
     183              : 
     184           71 :     PG_RETURN_BOOL(val1 != val2);
     185              : }
     186              : 
     187              : Datum
     188       436401 : int84lt(PG_FUNCTION_ARGS)
     189              : {
     190       436401 :     int64       val1 = PG_GETARG_INT64(0);
     191       436401 :     int32       val2 = PG_GETARG_INT32(1);
     192              : 
     193       436401 :     PG_RETURN_BOOL(val1 < val2);
     194              : }
     195              : 
     196              : Datum
     197        93609 : int84gt(PG_FUNCTION_ARGS)
     198              : {
     199        93609 :     int64       val1 = PG_GETARG_INT64(0);
     200        93609 :     int32       val2 = PG_GETARG_INT32(1);
     201              : 
     202        93609 :     PG_RETURN_BOOL(val1 > val2);
     203              : }
     204              : 
     205              : Datum
     206        14785 : int84le(PG_FUNCTION_ARGS)
     207              : {
     208        14785 :     int64       val1 = PG_GETARG_INT64(0);
     209        14785 :     int32       val2 = PG_GETARG_INT32(1);
     210              : 
     211        14785 :     PG_RETURN_BOOL(val1 <= val2);
     212              : }
     213              : 
     214              : Datum
     215         6687 : int84ge(PG_FUNCTION_ARGS)
     216              : {
     217         6687 :     int64       val1 = PG_GETARG_INT64(0);
     218         6687 :     int32       val2 = PG_GETARG_INT32(1);
     219              : 
     220         6687 :     PG_RETURN_BOOL(val1 >= val2);
     221              : }
     222              : 
     223              : /* int48relop()
     224              :  * Is 32-bit val1 relop 64-bit val2?
     225              :  */
     226              : Datum
     227        77606 : int48eq(PG_FUNCTION_ARGS)
     228              : {
     229        77606 :     int32       val1 = PG_GETARG_INT32(0);
     230        77606 :     int64       val2 = PG_GETARG_INT64(1);
     231              : 
     232        77606 :     PG_RETURN_BOOL(val1 == val2);
     233              : }
     234              : 
     235              : Datum
     236           24 : int48ne(PG_FUNCTION_ARGS)
     237              : {
     238           24 :     int32       val1 = PG_GETARG_INT32(0);
     239           24 :     int64       val2 = PG_GETARG_INT64(1);
     240              : 
     241           24 :     PG_RETURN_BOOL(val1 != val2);
     242              : }
     243              : 
     244              : Datum
     245         4440 : int48lt(PG_FUNCTION_ARGS)
     246              : {
     247         4440 :     int32       val1 = PG_GETARG_INT32(0);
     248         4440 :     int64       val2 = PG_GETARG_INT64(1);
     249              : 
     250         4440 :     PG_RETURN_BOOL(val1 < val2);
     251              : }
     252              : 
     253              : Datum
     254         2180 : int48gt(PG_FUNCTION_ARGS)
     255              : {
     256         2180 :     int32       val1 = PG_GETARG_INT32(0);
     257         2180 :     int64       val2 = PG_GETARG_INT64(1);
     258              : 
     259         2180 :     PG_RETURN_BOOL(val1 > val2);
     260              : }
     261              : 
     262              : Datum
     263         2552 : int48le(PG_FUNCTION_ARGS)
     264              : {
     265         2552 :     int32       val1 = PG_GETARG_INT32(0);
     266         2552 :     int64       val2 = PG_GETARG_INT64(1);
     267              : 
     268         2552 :     PG_RETURN_BOOL(val1 <= val2);
     269              : }
     270              : 
     271              : Datum
     272         2316 : int48ge(PG_FUNCTION_ARGS)
     273              : {
     274         2316 :     int32       val1 = PG_GETARG_INT32(0);
     275         2316 :     int64       val2 = PG_GETARG_INT64(1);
     276              : 
     277         2316 :     PG_RETURN_BOOL(val1 >= val2);
     278              : }
     279              : 
     280              : /* int82relop()
     281              :  * Is 64-bit val1 relop 16-bit val2?
     282              :  */
     283              : Datum
     284           20 : int82eq(PG_FUNCTION_ARGS)
     285              : {
     286           20 :     int64       val1 = PG_GETARG_INT64(0);
     287           20 :     int16       val2 = PG_GETARG_INT16(1);
     288              : 
     289           20 :     PG_RETURN_BOOL(val1 == val2);
     290              : }
     291              : 
     292              : Datum
     293           20 : int82ne(PG_FUNCTION_ARGS)
     294              : {
     295           20 :     int64       val1 = PG_GETARG_INT64(0);
     296           20 :     int16       val2 = PG_GETARG_INT16(1);
     297              : 
     298           20 :     PG_RETURN_BOOL(val1 != val2);
     299              : }
     300              : 
     301              : Datum
     302           20 : int82lt(PG_FUNCTION_ARGS)
     303              : {
     304           20 :     int64       val1 = PG_GETARG_INT64(0);
     305           20 :     int16       val2 = PG_GETARG_INT16(1);
     306              : 
     307           20 :     PG_RETURN_BOOL(val1 < val2);
     308              : }
     309              : 
     310              : Datum
     311         2152 : int82gt(PG_FUNCTION_ARGS)
     312              : {
     313         2152 :     int64       val1 = PG_GETARG_INT64(0);
     314         2152 :     int16       val2 = PG_GETARG_INT16(1);
     315              : 
     316         2152 :     PG_RETURN_BOOL(val1 > val2);
     317              : }
     318              : 
     319              : Datum
     320           20 : int82le(PG_FUNCTION_ARGS)
     321              : {
     322           20 :     int64       val1 = PG_GETARG_INT64(0);
     323           20 :     int16       val2 = PG_GETARG_INT16(1);
     324              : 
     325           20 :     PG_RETURN_BOOL(val1 <= val2);
     326              : }
     327              : 
     328              : Datum
     329         2152 : int82ge(PG_FUNCTION_ARGS)
     330              : {
     331         2152 :     int64       val1 = PG_GETARG_INT64(0);
     332         2152 :     int16       val2 = PG_GETARG_INT16(1);
     333              : 
     334         2152 :     PG_RETURN_BOOL(val1 >= val2);
     335              : }
     336              : 
     337              : /* int28relop()
     338              :  * Is 16-bit val1 relop 64-bit val2?
     339              :  */
     340              : Datum
     341         1237 : int28eq(PG_FUNCTION_ARGS)
     342              : {
     343         1237 :     int16       val1 = PG_GETARG_INT16(0);
     344         1237 :     int64       val2 = PG_GETARG_INT64(1);
     345              : 
     346         1237 :     PG_RETURN_BOOL(val1 == val2);
     347              : }
     348              : 
     349              : Datum
     350         2345 : int28ne(PG_FUNCTION_ARGS)
     351              : {
     352         2345 :     int16       val1 = PG_GETARG_INT16(0);
     353         2345 :     int64       val2 = PG_GETARG_INT64(1);
     354              : 
     355         2345 :     PG_RETURN_BOOL(val1 != val2);
     356              : }
     357              : 
     358              : Datum
     359         2152 : int28lt(PG_FUNCTION_ARGS)
     360              : {
     361         2152 :     int16       val1 = PG_GETARG_INT16(0);
     362         2152 :     int64       val2 = PG_GETARG_INT64(1);
     363              : 
     364         2152 :     PG_RETURN_BOOL(val1 < val2);
     365              : }
     366              : 
     367              : Datum
     368         2152 : int28gt(PG_FUNCTION_ARGS)
     369              : {
     370         2152 :     int16       val1 = PG_GETARG_INT16(0);
     371         2152 :     int64       val2 = PG_GETARG_INT64(1);
     372              : 
     373         2152 :     PG_RETURN_BOOL(val1 > val2);
     374              : }
     375              : 
     376              : Datum
     377         2552 : int28le(PG_FUNCTION_ARGS)
     378              : {
     379         2552 :     int16       val1 = PG_GETARG_INT16(0);
     380         2552 :     int64       val2 = PG_GETARG_INT64(1);
     381              : 
     382         2552 :     PG_RETURN_BOOL(val1 <= val2);
     383              : }
     384              : 
     385              : Datum
     386         2476 : int28ge(PG_FUNCTION_ARGS)
     387              : {
     388         2476 :     int16       val1 = PG_GETARG_INT16(0);
     389         2476 :     int64       val2 = PG_GETARG_INT64(1);
     390              : 
     391         2476 :     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           72 : in_range_int8_int8(PG_FUNCTION_ARGS)
     402              : {
     403           72 :     int64       val = PG_GETARG_INT64(0);
     404           72 :     int64       base = PG_GETARG_INT64(1);
     405           72 :     int64       offset = PG_GETARG_INT64(2);
     406           72 :     bool        sub = PG_GETARG_BOOL(3);
     407           72 :     bool        less = PG_GETARG_BOOL(4);
     408              :     int64       sum;
     409              : 
     410           72 :     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           72 :     if (sub)
     416           36 :         offset = -offset;       /* cannot overflow */
     417              : 
     418           72 :     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           24 :         PG_RETURN_BOOL(sub ? !less : less);
     426              :     }
     427              : 
     428           48 :     if (less)
     429           24 :         PG_RETURN_BOOL(val <= sum);
     430              :     else
     431           24 :         PG_RETURN_BOOL(val >= sum);
     432              : }
     433              : 
     434              : 
     435              : /*----------------------------------------------------------
     436              :  *  Arithmetic operators on 64-bit integers.
     437              :  *---------------------------------------------------------*/
     438              : 
     439              : Datum
     440          633 : int8um(PG_FUNCTION_ARGS)
     441              : {
     442          633 :     int64       arg = PG_GETARG_INT64(0);
     443              :     int64       result;
     444              : 
     445          633 :     if (unlikely(arg == PG_INT64_MIN))
     446            4 :         ereport(ERROR,
     447              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     448              :                  errmsg("bigint out of range")));
     449          629 :     result = -arg;
     450          629 :     PG_RETURN_INT64(result);
     451              : }
     452              : 
     453              : Datum
     454            5 : int8up(PG_FUNCTION_ARGS)
     455              : {
     456            5 :     int64       arg = PG_GETARG_INT64(0);
     457              : 
     458            5 :     PG_RETURN_INT64(arg);
     459              : }
     460              : 
     461              : Datum
     462       169793 : int8pl(PG_FUNCTION_ARGS)
     463              : {
     464       169793 :     int64       arg1 = PG_GETARG_INT64(0);
     465       169793 :     int64       arg2 = PG_GETARG_INT64(1);
     466              :     int64       result;
     467              : 
     468       169793 :     if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
     469            8 :         ereport(ERROR,
     470              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     471              :                  errmsg("bigint out of range")));
     472       169785 :     PG_RETURN_INT64(result);
     473              : }
     474              : 
     475              : Datum
     476          160 : int8mi(PG_FUNCTION_ARGS)
     477              : {
     478          160 :     int64       arg1 = PG_GETARG_INT64(0);
     479          160 :     int64       arg2 = PG_GETARG_INT64(1);
     480              :     int64       result;
     481              : 
     482          160 :     if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
     483           12 :         ereport(ERROR,
     484              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     485              :                  errmsg("bigint out of range")));
     486          148 :     PG_RETURN_INT64(result);
     487              : }
     488              : 
     489              : Datum
     490           88 : int8mul(PG_FUNCTION_ARGS)
     491              : {
     492           88 :     int64       arg1 = PG_GETARG_INT64(0);
     493           88 :     int64       arg2 = PG_GETARG_INT64(1);
     494              :     int64       result;
     495              : 
     496           88 :     if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
     497           13 :         ereport(ERROR,
     498              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     499              :                  errmsg("bigint out of range")));
     500           75 :     PG_RETURN_INT64(result);
     501              : }
     502              : 
     503              : Datum
     504           83 : int8div(PG_FUNCTION_ARGS)
     505              : {
     506           83 :     int64       arg1 = PG_GETARG_INT64(0);
     507           83 :     int64       arg2 = PG_GETARG_INT64(1);
     508              :     int64       result;
     509              : 
     510           83 :     if (arg2 == 0)
     511              :     {
     512            4 :         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           79 :     if (arg2 == -1)
     526              :     {
     527            4 :         if (unlikely(arg1 == PG_INT64_MIN))
     528            4 :             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           75 :     result = arg1 / arg2;
     538              : 
     539           75 :     PG_RETURN_INT64(result);
     540              : }
     541              : 
     542              : /* int8abs()
     543              :  * Absolute value
     544              :  */
     545              : Datum
     546           24 : int8abs(PG_FUNCTION_ARGS)
     547              : {
     548           24 :     int64       arg1 = PG_GETARG_INT64(0);
     549              :     int64       result;
     550              : 
     551           24 :     if (unlikely(arg1 == PG_INT64_MIN))
     552            4 :         ereport(ERROR,
     553              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     554              :                  errmsg("bigint out of range")));
     555           20 :     result = (arg1 < 0) ? -arg1 : arg1;
     556           20 :     PG_RETURN_INT64(result);
     557              : }
     558              : 
     559              : /* int8mod()
     560              :  * Modulo operation.
     561              :  */
     562              : Datum
     563           39 : int8mod(PG_FUNCTION_ARGS)
     564              : {
     565           39 :     int64       arg1 = PG_GETARG_INT64(0);
     566           39 :     int64       arg2 = PG_GETARG_INT64(1);
     567              : 
     568           39 :     if (unlikely(arg2 == 0))
     569              :     {
     570            4 :         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           35 :     if (arg2 == -1)
     583           15 :         PG_RETURN_INT64(0);
     584              : 
     585              :     /* No overflow is possible */
     586              : 
     587           20 :     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          176 : 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          176 :     a1 = (arg1 < 0) ? arg1 : -arg1;
     622          176 :     a2 = (arg2 < 0) ? arg2 : -arg2;
     623          176 :     if (a1 > a2)
     624              :     {
     625           64 :         swap = arg1;
     626           64 :         arg1 = arg2;
     627           64 :         arg2 = swap;
     628              :     }
     629              : 
     630              :     /* Special care needs to be taken with INT64_MIN.  See comments above. */
     631          176 :     if (arg1 == PG_INT64_MIN)
     632              :     {
     633           60 :         if (arg2 == 0 || arg2 == PG_INT64_MIN)
     634            8 :             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           52 :         if (arg2 == -1)
     645            8 :             return 1;
     646              :     }
     647              : 
     648              :     /* Use the Euclidean algorithm to find the GCD */
     649          820 :     while (arg2 != 0)
     650              :     {
     651          660 :         swap = arg2;
     652          660 :         arg2 = arg1 % arg2;
     653          660 :         arg1 = swap;
     654              :     }
     655              : 
     656              :     /*
     657              :      * Make sure the result is positive. (We know we don't have INT64_MIN
     658              :      * anymore).
     659              :      */
     660          160 :     if (arg1 < 0)
     661           68 :         arg1 = -arg1;
     662              : 
     663          160 :     return arg1;
     664              : }
     665              : 
     666              : Datum
     667          120 : int8gcd(PG_FUNCTION_ARGS)
     668              : {
     669          120 :     int64       arg1 = PG_GETARG_INT64(0);
     670          120 :     int64       arg2 = PG_GETARG_INT64(1);
     671              :     int64       result;
     672              : 
     673          120 :     result = int8gcd_internal(arg1, arg2);
     674              : 
     675          112 :     PG_RETURN_INT64(result);
     676              : }
     677              : 
     678              : /*
     679              :  * Least Common Multiple
     680              :  */
     681              : Datum
     682          104 : int8lcm(PG_FUNCTION_ARGS)
     683              : {
     684          104 :     int64       arg1 = PG_GETARG_INT64(0);
     685          104 :     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          104 :     if (arg1 == 0 || arg2 == 0)
     695           48 :         PG_RETURN_INT64(0);
     696              : 
     697              :     /* lcm(x, y) = abs(x / gcd(x, y) * y) */
     698           56 :     gcd = int8gcd_internal(arg1, arg2);
     699           56 :     arg1 = arg1 / gcd;
     700              : 
     701           56 :     if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
     702            4 :         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           52 :     if (unlikely(result == PG_INT64_MIN))
     708            4 :         ereport(ERROR,
     709              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     710              :                  errmsg("bigint out of range")));
     711              : 
     712           48 :     if (result < 0)
     713           24 :         result = -result;
     714              : 
     715           48 :     PG_RETURN_INT64(result);
     716              : }
     717              : 
     718              : Datum
     719     14536187 : int8inc(PG_FUNCTION_ARGS)
     720              : {
     721     14536187 :     int64       arg = PG_GETARG_INT64(0);
     722              :     int64       result;
     723              : 
     724     14536187 :     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     14536187 :     PG_RETURN_INT64(result);
     730              : }
     731              : 
     732              : Datum
     733           16 : int8dec(PG_FUNCTION_ARGS)
     734              : {
     735           16 :     int64       arg = PG_GETARG_INT64(0);
     736              :     int64       result;
     737              : 
     738           16 :     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           16 :     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       796601 : int8inc_any(PG_FUNCTION_ARGS)
     758              : {
     759       796601 :     return int8inc(fcinfo);
     760              : }
     761              : 
     762              : Datum
     763       160016 : int8inc_float8_float8(PG_FUNCTION_ARGS)
     764              : {
     765       160016 :     return int8inc(fcinfo);
     766              : }
     767              : 
     768              : Datum
     769            4 : int8dec_any(PG_FUNCTION_ARGS)
     770              : {
     771            4 :     return int8dec(fcinfo);
     772              : }
     773              : 
     774              : /*
     775              :  * int8inc_support
     776              :  *      prosupport function for int8inc() and int8inc_any()
     777              :  */
     778              : Datum
     779        14387 : int8inc_support(PG_FUNCTION_ARGS)
     780              : {
     781        14387 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     782              : 
     783        14387 :     if (IsA(rawreq, SupportRequestWFuncMonotonic))
     784              :     {
     785           65 :         SupportRequestWFuncMonotonic *req = (SupportRequestWFuncMonotonic *) rawreq;
     786           65 :         MonotonicFunction monotonic = MONOTONICFUNC_NONE;
     787           65 :         int         frameOptions = req->window_clause->frameOptions;
     788              : 
     789              :         /* No ORDER BY clause then all rows are peers */
     790           65 :         if (req->window_clause->orderClause == NIL)
     791           20 :             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           45 :             if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
     800           35 :                 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           45 :             if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
     807           10 :                 monotonic |= MONOTONICFUNC_DECREASING;
     808              :         }
     809              : 
     810           65 :         req->monotonic = monotonic;
     811           65 :         PG_RETURN_POINTER(req);
     812              :     }
     813              : 
     814        14322 :     if (IsA(rawreq, SupportRequestSimplifyAggref))
     815              :     {
     816        13892 :         SupportRequestSimplifyAggref *req = (SupportRequestSimplifyAggref *) rawreq;
     817        13892 :         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        13892 :         if (agg->aggfnoid == F_COUNT_ANY && list_length(agg->args) == 1)
     827              :         {
     828         1183 :             TargetEntry *tle = (TargetEntry *) linitial(agg->args);
     829         1183 :             Expr       *arg = tle->expr;
     830              : 
     831              :             /* Check for unsupported cases */
     832         1183 :             if (agg->aggdistinct != NIL || agg->aggorder != NIL ||
     833          943 :                 agg->agglevelsup != 0)
     834          250 :                 PG_RETURN_POINTER(NULL);
     835              : 
     836              :             /* If the arg isn't NULLable, do the conversion */
     837          933 :             if (expr_is_nonnullable(req->root, arg, NOTNULL_SOURCE_HASHTABLE))
     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          274 :                 newagg = makeNode(Aggref);
     847          274 :                 memcpy(newagg, agg, sizeof(Aggref));
     848          274 :                 newagg->aggfnoid = F_COUNT_;
     849              : 
     850              :                 /* count(*) has no args */
     851          274 :                 newagg->aggargtypes = NULL;
     852          274 :                 newagg->args = NULL;
     853          274 :                 newagg->aggstar = true;
     854          274 :                 newagg->location = -1;
     855              : 
     856          274 :                 PG_RETURN_POINTER(newagg);
     857              :             }
     858              :         }
     859              :     }
     860              : 
     861        13798 :     PG_RETURN_POINTER(NULL);
     862              : }
     863              : 
     864              : 
     865              : Datum
     866          572 : int8larger(PG_FUNCTION_ARGS)
     867              : {
     868          572 :     int64       arg1 = PG_GETARG_INT64(0);
     869          572 :     int64       arg2 = PG_GETARG_INT64(1);
     870              :     int64       result;
     871              : 
     872          572 :     result = ((arg1 > arg2) ? arg1 : arg2);
     873              : 
     874          572 :     PG_RETURN_INT64(result);
     875              : }
     876              : 
     877              : Datum
     878         4489 : int8smaller(PG_FUNCTION_ARGS)
     879              : {
     880         4489 :     int64       arg1 = PG_GETARG_INT64(0);
     881         4489 :     int64       arg2 = PG_GETARG_INT64(1);
     882              :     int64       result;
     883              : 
     884         4489 :     result = ((arg1 < arg2) ? arg1 : arg2);
     885              : 
     886         4489 :     PG_RETURN_INT64(result);
     887              : }
     888              : 
     889              : Datum
     890         2747 : int84pl(PG_FUNCTION_ARGS)
     891              : {
     892         2747 :     int64       arg1 = PG_GETARG_INT64(0);
     893         2747 :     int32       arg2 = PG_GETARG_INT32(1);
     894              :     int64       result;
     895              : 
     896         2747 :     if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
     897            4 :         ereport(ERROR,
     898              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     899              :                  errmsg("bigint out of range")));
     900         2743 :     PG_RETURN_INT64(result);
     901              : }
     902              : 
     903              : Datum
     904           88 : int84mi(PG_FUNCTION_ARGS)
     905              : {
     906           88 :     int64       arg1 = PG_GETARG_INT64(0);
     907           88 :     int32       arg2 = PG_GETARG_INT32(1);
     908              :     int64       result;
     909              : 
     910           88 :     if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
     911            4 :         ereport(ERROR,
     912              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     913              :                  errmsg("bigint out of range")));
     914           84 :     PG_RETURN_INT64(result);
     915              : }
     916              : 
     917              : Datum
     918         1631 : int84mul(PG_FUNCTION_ARGS)
     919              : {
     920         1631 :     int64       arg1 = PG_GETARG_INT64(0);
     921         1631 :     int32       arg2 = PG_GETARG_INT32(1);
     922              :     int64       result;
     923              : 
     924         1631 :     if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
     925            8 :         ereport(ERROR,
     926              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     927              :                  errmsg("bigint out of range")));
     928         1623 :     PG_RETURN_INT64(result);
     929              : }
     930              : 
     931              : Datum
     932          112 : int84div(PG_FUNCTION_ARGS)
     933              : {
     934          112 :     int64       arg1 = PG_GETARG_INT64(0);
     935          112 :     int32       arg2 = PG_GETARG_INT32(1);
     936              :     int64       result;
     937              : 
     938          112 :     if (arg2 == 0)
     939              :     {
     940            4 :         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          108 :     if (arg2 == -1)
     954              :     {
     955            4 :         if (unlikely(arg1 == PG_INT64_MIN))
     956            4 :             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          104 :     result = arg1 / arg2;
     966              : 
     967          104 :     PG_RETURN_INT64(result);
     968              : }
     969              : 
     970              : Datum
     971         1055 : int48pl(PG_FUNCTION_ARGS)
     972              : {
     973         1055 :     int32       arg1 = PG_GETARG_INT32(0);
     974         1055 :     int64       arg2 = PG_GETARG_INT64(1);
     975              :     int64       result;
     976              : 
     977         1055 :     if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
     978            4 :         ereport(ERROR,
     979              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     980              :                  errmsg("bigint out of range")));
     981         1051 :     PG_RETURN_INT64(result);
     982              : }
     983              : 
     984              : Datum
     985           44 : int48mi(PG_FUNCTION_ARGS)
     986              : {
     987           44 :     int32       arg1 = PG_GETARG_INT32(0);
     988           44 :     int64       arg2 = PG_GETARG_INT64(1);
     989              :     int64       result;
     990              : 
     991           44 :     if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
     992            4 :         ereport(ERROR,
     993              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     994              :                  errmsg("bigint out of range")));
     995           40 :     PG_RETURN_INT64(result);
     996              : }
     997              : 
     998              : Datum
     999          148 : int48mul(PG_FUNCTION_ARGS)
    1000              : {
    1001          148 :     int32       arg1 = PG_GETARG_INT32(0);
    1002          148 :     int64       arg2 = PG_GETARG_INT64(1);
    1003              :     int64       result;
    1004              : 
    1005          148 :     if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
    1006            4 :         ereport(ERROR,
    1007              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1008              :                  errmsg("bigint out of range")));
    1009          144 :     PG_RETURN_INT64(result);
    1010              : }
    1011              : 
    1012              : Datum
    1013           24 : int48div(PG_FUNCTION_ARGS)
    1014              : {
    1015           24 :     int32       arg1 = PG_GETARG_INT32(0);
    1016           24 :     int64       arg2 = PG_GETARG_INT64(1);
    1017              : 
    1018           24 :     if (unlikely(arg2 == 0))
    1019              :     {
    1020            4 :         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           20 :     PG_RETURN_INT64((int64) arg1 / arg2);
    1029              : }
    1030              : 
    1031              : Datum
    1032           24 : int82pl(PG_FUNCTION_ARGS)
    1033              : {
    1034           24 :     int64       arg1 = PG_GETARG_INT64(0);
    1035           24 :     int16       arg2 = PG_GETARG_INT16(1);
    1036              :     int64       result;
    1037              : 
    1038           24 :     if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
    1039            4 :         ereport(ERROR,
    1040              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1041              :                  errmsg("bigint out of range")));
    1042           20 :     PG_RETURN_INT64(result);
    1043              : }
    1044              : 
    1045              : Datum
    1046           24 : int82mi(PG_FUNCTION_ARGS)
    1047              : {
    1048           24 :     int64       arg1 = PG_GETARG_INT64(0);
    1049           24 :     int16       arg2 = PG_GETARG_INT16(1);
    1050              :     int64       result;
    1051              : 
    1052           24 :     if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
    1053            4 :         ereport(ERROR,
    1054              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1055              :                  errmsg("bigint out of range")));
    1056           20 :     PG_RETURN_INT64(result);
    1057              : }
    1058              : 
    1059              : Datum
    1060           28 : int82mul(PG_FUNCTION_ARGS)
    1061              : {
    1062           28 :     int64       arg1 = PG_GETARG_INT64(0);
    1063           28 :     int16       arg2 = PG_GETARG_INT16(1);
    1064              :     int64       result;
    1065              : 
    1066           28 :     if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
    1067            8 :         ereport(ERROR,
    1068              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1069              :                  errmsg("bigint out of range")));
    1070           20 :     PG_RETURN_INT64(result);
    1071              : }
    1072              : 
    1073              : Datum
    1074           28 : int82div(PG_FUNCTION_ARGS)
    1075              : {
    1076           28 :     int64       arg1 = PG_GETARG_INT64(0);
    1077           28 :     int16       arg2 = PG_GETARG_INT16(1);
    1078              :     int64       result;
    1079              : 
    1080           28 :     if (unlikely(arg2 == 0))
    1081              :     {
    1082            4 :         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           24 :     if (arg2 == -1)
    1096              :     {
    1097            4 :         if (unlikely(arg1 == PG_INT64_MIN))
    1098            4 :             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           20 :     result = arg1 / arg2;
    1108              : 
    1109           20 :     PG_RETURN_INT64(result);
    1110              : }
    1111              : 
    1112              : Datum
    1113           24 : int28pl(PG_FUNCTION_ARGS)
    1114              : {
    1115           24 :     int16       arg1 = PG_GETARG_INT16(0);
    1116           24 :     int64       arg2 = PG_GETARG_INT64(1);
    1117              :     int64       result;
    1118              : 
    1119           24 :     if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
    1120            4 :         ereport(ERROR,
    1121              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1122              :                  errmsg("bigint out of range")));
    1123           20 :     PG_RETURN_INT64(result);
    1124              : }
    1125              : 
    1126              : Datum
    1127           24 : int28mi(PG_FUNCTION_ARGS)
    1128              : {
    1129           24 :     int16       arg1 = PG_GETARG_INT16(0);
    1130           24 :     int64       arg2 = PG_GETARG_INT64(1);
    1131              :     int64       result;
    1132              : 
    1133           24 :     if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
    1134            4 :         ereport(ERROR,
    1135              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1136              :                  errmsg("bigint out of range")));
    1137           20 :     PG_RETURN_INT64(result);
    1138              : }
    1139              : 
    1140              : Datum
    1141           24 : int28mul(PG_FUNCTION_ARGS)
    1142              : {
    1143           24 :     int16       arg1 = PG_GETARG_INT16(0);
    1144           24 :     int64       arg2 = PG_GETARG_INT64(1);
    1145              :     int64       result;
    1146              : 
    1147           24 :     if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
    1148            4 :         ereport(ERROR,
    1149              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1150              :                  errmsg("bigint out of range")));
    1151           20 :     PG_RETURN_INT64(result);
    1152              : }
    1153              : 
    1154              : Datum
    1155           24 : int28div(PG_FUNCTION_ARGS)
    1156              : {
    1157           24 :     int16       arg1 = PG_GETARG_INT16(0);
    1158           24 :     int64       arg2 = PG_GETARG_INT64(1);
    1159              : 
    1160           24 :     if (unlikely(arg2 == 0))
    1161              :     {
    1162            4 :         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           20 :     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           28 : int8and(PG_FUNCTION_ARGS)
    1185              : {
    1186           28 :     int64       arg1 = PG_GETARG_INT64(0);
    1187           28 :     int64       arg2 = PG_GETARG_INT64(1);
    1188              : 
    1189           28 :     PG_RETURN_INT64(arg1 & arg2);
    1190              : }
    1191              : 
    1192              : Datum
    1193           30 : int8or(PG_FUNCTION_ARGS)
    1194              : {
    1195           30 :     int64       arg1 = PG_GETARG_INT64(0);
    1196           30 :     int64       arg2 = PG_GETARG_INT64(1);
    1197              : 
    1198           30 :     PG_RETURN_INT64(arg1 | arg2);
    1199              : }
    1200              : 
    1201              : Datum
    1202           28 : int8xor(PG_FUNCTION_ARGS)
    1203              : {
    1204           28 :     int64       arg1 = PG_GETARG_INT64(0);
    1205           28 :     int64       arg2 = PG_GETARG_INT64(1);
    1206              : 
    1207           28 :     PG_RETURN_INT64(arg1 ^ arg2);
    1208              : }
    1209              : 
    1210              : Datum
    1211           20 : int8not(PG_FUNCTION_ARGS)
    1212              : {
    1213           20 :     int64       arg1 = PG_GETARG_INT64(0);
    1214              : 
    1215           20 :     PG_RETURN_INT64(~arg1);
    1216              : }
    1217              : 
    1218              : Datum
    1219           32 : int8shl(PG_FUNCTION_ARGS)
    1220              : {
    1221           32 :     int64       arg1 = PG_GETARG_INT64(0);
    1222           32 :     int32       arg2 = PG_GETARG_INT32(1);
    1223              : 
    1224           32 :     PG_RETURN_INT64(arg1 << arg2);
    1225              : }
    1226              : 
    1227              : Datum
    1228           20 : int8shr(PG_FUNCTION_ARGS)
    1229              : {
    1230           20 :     int64       arg1 = PG_GETARG_INT64(0);
    1231           20 :     int32       arg2 = PG_GETARG_INT32(1);
    1232              : 
    1233           20 :     PG_RETURN_INT64(arg1 >> arg2);
    1234              : }
    1235              : 
    1236              : /*----------------------------------------------------------
    1237              :  *  Conversion operators.
    1238              :  *---------------------------------------------------------*/
    1239              : 
    1240              : Datum
    1241      1442944 : int48(PG_FUNCTION_ARGS)
    1242              : {
    1243      1442944 :     int32       arg = PG_GETARG_INT32(0);
    1244              : 
    1245      1442944 :     PG_RETURN_INT64((int64) arg);
    1246              : }
    1247              : 
    1248              : Datum
    1249       257545 : int84(PG_FUNCTION_ARGS)
    1250              : {
    1251       257545 :     int64       arg = PG_GETARG_INT64(0);
    1252              : 
    1253       257545 :     if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
    1254            5 :         ereturn(fcinfo->context, (Datum) 0,
    1255              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1256              :                  errmsg("integer out of range")));
    1257              : 
    1258       257540 :     PG_RETURN_INT32((int32) arg);
    1259              : }
    1260              : 
    1261              : Datum
    1262           20 : int28(PG_FUNCTION_ARGS)
    1263              : {
    1264           20 :     int16       arg = PG_GETARG_INT16(0);
    1265              : 
    1266           20 :     PG_RETURN_INT64((int64) arg);
    1267              : }
    1268              : 
    1269              : Datum
    1270           24 : int82(PG_FUNCTION_ARGS)
    1271              : {
    1272           24 :     int64       arg = PG_GETARG_INT64(0);
    1273              : 
    1274           24 :     if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
    1275            4 :         ereturn(fcinfo->context, (Datum) 0,
    1276              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1277              :                  errmsg("smallint out of range")));
    1278              : 
    1279           20 :     PG_RETURN_INT16((int16) arg);
    1280              : }
    1281              : 
    1282              : Datum
    1283         8131 : i8tod(PG_FUNCTION_ARGS)
    1284              : {
    1285         8131 :     int64       arg = PG_GETARG_INT64(0);
    1286              :     float8      result;
    1287              : 
    1288         8131 :     result = arg;
    1289              : 
    1290         8131 :     PG_RETURN_FLOAT8(result);
    1291              : }
    1292              : 
    1293              : /* dtoi8()
    1294              :  * Convert float8 to 8-byte integer.
    1295              :  */
    1296              : Datum
    1297          101 : dtoi8(PG_FUNCTION_ARGS)
    1298              : {
    1299          101 :     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          101 :     num = rint(num);
    1307              : 
    1308              :     /* Range check */
    1309          101 :     if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
    1310           12 :         ereturn(fcinfo->context, (Datum) 0,
    1311              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1312              :                  errmsg("bigint out of range")));
    1313              : 
    1314           89 :     PG_RETURN_INT64((int64) num);
    1315              : }
    1316              : 
    1317              : Datum
    1318          100 : i8tof(PG_FUNCTION_ARGS)
    1319              : {
    1320          100 :     int64       arg = PG_GETARG_INT64(0);
    1321              :     float4      result;
    1322              : 
    1323          100 :     result = arg;
    1324              : 
    1325          100 :     PG_RETURN_FLOAT4(result);
    1326              : }
    1327              : 
    1328              : /* ftoi8()
    1329              :  * Convert float4 to 8-byte integer.
    1330              :  */
    1331              : Datum
    1332           23 : ftoi8(PG_FUNCTION_ARGS)
    1333              : {
    1334           23 :     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           23 :     num = rint(num);
    1342              : 
    1343              :     /* Range check */
    1344           23 :     if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
    1345            8 :         ereturn(fcinfo->context, (Datum) 0,
    1346              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1347              :                  errmsg("bigint out of range")));
    1348              : 
    1349           15 :     PG_RETURN_INT64((int64) num);
    1350              : }
    1351              : 
    1352              : Datum
    1353           13 : i8tooid(PG_FUNCTION_ARGS)
    1354              : {
    1355           13 :     int64       arg = PG_GETARG_INT64(0);
    1356              : 
    1357           13 :     if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
    1358            4 :         ereturn(fcinfo->context, (Datum) 0,
    1359              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1360              :                  errmsg("OID out of range")));
    1361              : 
    1362            9 :     PG_RETURN_OID((Oid) arg);
    1363              : }
    1364              : 
    1365              : Datum
    1366           12 : oidtoi8(PG_FUNCTION_ARGS)
    1367              : {
    1368           12 :     Oid         arg = PG_GETARG_OID(0);
    1369              : 
    1370           12 :     PG_RETURN_INT64((int64) arg);
    1371              : }
    1372              : 
    1373              : Datum
    1374            5 : oidtooid8(PG_FUNCTION_ARGS)
    1375              : {
    1376            5 :     Oid         arg = PG_GETARG_OID(0);
    1377              : 
    1378            5 :     PG_RETURN_OID8((Oid8) arg);
    1379              : }
    1380              : 
    1381              : /*
    1382              :  * non-persistent numeric series generator
    1383              :  */
    1384              : Datum
    1385      2582301 : generate_series_int8(PG_FUNCTION_ARGS)
    1386              : {
    1387      2582301 :     return generate_series_step_int8(fcinfo);
    1388              : }
    1389              : 
    1390              : Datum
    1391      2582382 : 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      2582382 :     if (SRF_IS_FIRSTCALL())
    1400              :     {
    1401           35 :         int64       start = PG_GETARG_INT64(0);
    1402           35 :         int64       finish = PG_GETARG_INT64(1);
    1403           35 :         int64       step = 1;
    1404              : 
    1405              :         /* see if we were given an explicit step size */
    1406           35 :         if (PG_NARGS() == 3)
    1407            9 :             step = PG_GETARG_INT64(2);
    1408           35 :         if (step == 0)
    1409            4 :             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           31 :         funcctx = SRF_FIRSTCALL_INIT();
    1415              : 
    1416              :         /*
    1417              :          * switch to memory context appropriate for multiple function calls
    1418              :          */
    1419           31 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1420              : 
    1421              :         /* allocate memory for user context */
    1422           31 :         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           31 :         fctx->current = start;
    1429           31 :         fctx->finish = finish;
    1430           31 :         fctx->step = step;
    1431              : 
    1432           31 :         funcctx->user_fctx = fctx;
    1433           31 :         MemoryContextSwitchTo(oldcontext);
    1434              :     }
    1435              : 
    1436              :     /* stuff done on every call of the function */
    1437      2582378 :     funcctx = SRF_PERCALL_SETUP();
    1438              : 
    1439              :     /*
    1440              :      * get the saved state and use current as the result for this iteration
    1441              :      */
    1442      2582378 :     fctx = funcctx->user_fctx;
    1443      2582378 :     result = fctx->current;
    1444              : 
    1445      2582378 :     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
    1446           30 :         (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      2582348 :         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      2582348 :         SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
    1457              :     }
    1458              :     else
    1459              :         /* do when there is no more left */
    1460           30 :         SRF_RETURN_DONE(funcctx);
    1461              : }
    1462              : 
    1463              : /*
    1464              :  * Planner support function for generate_series(int8, int8 [, int8])
    1465              :  */
    1466              : Datum
    1467          154 : generate_series_int8_support(PG_FUNCTION_ARGS)
    1468              : {
    1469          154 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1470          154 :     Node       *ret = NULL;
    1471              : 
    1472          154 :     if (IsA(rawreq, SupportRequestRows))
    1473              :     {
    1474              :         /* Try to estimate the number of rows returned */
    1475           39 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
    1476              : 
    1477           39 :         if (is_funcclause(req->node))    /* be paranoid */
    1478              :         {
    1479           39 :             List       *args = ((FuncExpr *) req->node)->args;
    1480              :             Node       *arg1,
    1481              :                        *arg2,
    1482              :                        *arg3;
    1483              : 
    1484              :             /* We can use estimated argument values here */
    1485           39 :             arg1 = estimate_expression_value(req->root, linitial(args));
    1486           39 :             arg2 = estimate_expression_value(req->root, lsecond(args));
    1487           39 :             if (list_length(args) >= 3)
    1488           11 :                 arg3 = estimate_expression_value(req->root, lthird(args));
    1489              :             else
    1490           28 :                 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           39 :             if ((IsA(arg1, Const) &&
    1499           33 :                  ((Const *) arg1)->constisnull) ||
    1500           39 :                 (IsA(arg2, Const) &&
    1501           39 :                  ((Const *) arg2)->constisnull) ||
    1502           11 :                 (arg3 != NULL && IsA(arg3, Const) &&
    1503           11 :                  ((Const *) arg3)->constisnull))
    1504              :             {
    1505            0 :                 req->rows = 0;
    1506            0 :                 ret = (Node *) req;
    1507              :             }
    1508           39 :             else if (IsA(arg1, Const) &&
    1509           33 :                      IsA(arg2, Const) &&
    1510           11 :                      (arg3 == NULL || IsA(arg3, Const)))
    1511              :             {
    1512              :                 double      start,
    1513              :                             finish,
    1514              :                             step;
    1515              : 
    1516           27 :                 start = DatumGetInt64(((Const *) arg1)->constvalue);
    1517           27 :                 finish = DatumGetInt64(((Const *) arg2)->constvalue);
    1518           27 :                 step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
    1519              : 
    1520              :                 /* This equation works for either sign of step */
    1521           27 :                 if (step != 0)
    1522              :                 {
    1523           22 :                     req->rows = floor((finish - start + step) / step);
    1524           22 :                     ret = (Node *) req;
    1525              :                 }
    1526              :             }
    1527              :         }
    1528              :     }
    1529              : 
    1530          154 :     PG_RETURN_POINTER(ret);
    1531              : }
        

Generated by: LCOV version 2.0-1