LCOV - code coverage report
Current view: top level - src/backend/utils/adt - int8.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 505 517 97.7 %
Date: 2023-12-02 15:10:53 Functions: 89 89 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14