LCOV - code coverage report
Current view: top level - src/backend/utils/adt - int8.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 505 517 97.7 %
Date: 2025-08-19 14:18:13 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-2025, 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             : 
      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      133530 : int8in(PG_FUNCTION_ARGS)
      51             : {
      52      133530 :     char       *num = PG_GETARG_CSTRING(0);
      53             : 
      54      133530 :     PG_RETURN_INT64(pg_strtoint64_safe(num, fcinfo->context));
      55             : }
      56             : 
      57             : 
      58             : /* int8out()
      59             :  */
      60             : Datum
      61      318030 : int8out(PG_FUNCTION_ARGS)
      62             : {
      63      318030 :     int64       val = PG_GETARG_INT64(0);
      64             :     char        buf[MAXINT8LEN + 1];
      65             :     char       *result;
      66             :     int         len;
      67             : 
      68      318030 :     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      318030 :     result = palloc(len);
      75      318030 :     memcpy(result, buf, len);
      76      318030 :     PG_RETURN_CSTRING(result);
      77             : }
      78             : 
      79             : /*
      80             :  *      int8recv            - converts external binary format to int8
      81             :  */
      82             : Datum
      83          24 : int8recv(PG_FUNCTION_ARGS)
      84             : {
      85          24 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      86             : 
      87          24 :     PG_RETURN_INT64(pq_getmsgint64(buf));
      88             : }
      89             : 
      90             : /*
      91             :  *      int8send            - converts int8 to binary format
      92             :  */
      93             : Datum
      94        5000 : int8send(PG_FUNCTION_ARGS)
      95             : {
      96        5000 :     int64       arg1 = PG_GETARG_INT64(0);
      97             :     StringInfoData buf;
      98             : 
      99        5000 :     pq_begintypsend(&buf);
     100        5000 :     pq_sendint64(&buf, arg1);
     101        5000 :     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      354442 : int8eq(PG_FUNCTION_ARGS)
     114             : {
     115      354442 :     int64       val1 = PG_GETARG_INT64(0);
     116      354442 :     int64       val2 = PG_GETARG_INT64(1);
     117             : 
     118      354442 :     PG_RETURN_BOOL(val1 == val2);
     119             : }
     120             : 
     121             : Datum
     122       60050 : int8ne(PG_FUNCTION_ARGS)
     123             : {
     124       60050 :     int64       val1 = PG_GETARG_INT64(0);
     125       60050 :     int64       val2 = PG_GETARG_INT64(1);
     126             : 
     127       60050 :     PG_RETURN_BOOL(val1 != val2);
     128             : }
     129             : 
     130             : Datum
     131      627038 : int8lt(PG_FUNCTION_ARGS)
     132             : {
     133      627038 :     int64       val1 = PG_GETARG_INT64(0);
     134      627038 :     int64       val2 = PG_GETARG_INT64(1);
     135             : 
     136      627038 :     PG_RETURN_BOOL(val1 < val2);
     137             : }
     138             : 
     139             : Datum
     140      247242 : int8gt(PG_FUNCTION_ARGS)
     141             : {
     142      247242 :     int64       val1 = PG_GETARG_INT64(0);
     143      247242 :     int64       val2 = PG_GETARG_INT64(1);
     144             : 
     145      247242 :     PG_RETURN_BOOL(val1 > val2);
     146             : }
     147             : 
     148             : Datum
     149        5656 : int8le(PG_FUNCTION_ARGS)
     150             : {
     151        5656 :     int64       val1 = PG_GETARG_INT64(0);
     152        5656 :     int64       val2 = PG_GETARG_INT64(1);
     153             : 
     154        5656 :     PG_RETURN_BOOL(val1 <= val2);
     155             : }
     156             : 
     157             : Datum
     158        6006 : int8ge(PG_FUNCTION_ARGS)
     159             : {
     160        6006 :     int64       val1 = PG_GETARG_INT64(0);
     161        6006 :     int64       val2 = PG_GETARG_INT64(1);
     162             : 
     163        6006 :     PG_RETURN_BOOL(val1 >= val2);
     164             : }
     165             : 
     166             : /* int84relop()
     167             :  * Is 64-bit val1 relop 32-bit val2?
     168             :  */
     169             : Datum
     170      196342 : int84eq(PG_FUNCTION_ARGS)
     171             : {
     172      196342 :     int64       val1 = PG_GETARG_INT64(0);
     173      196342 :     int32       val2 = PG_GETARG_INT32(1);
     174             : 
     175      196342 :     PG_RETURN_BOOL(val1 == val2);
     176             : }
     177             : 
     178             : Datum
     179          94 : int84ne(PG_FUNCTION_ARGS)
     180             : {
     181          94 :     int64       val1 = PG_GETARG_INT64(0);
     182          94 :     int32       val2 = PG_GETARG_INT32(1);
     183             : 
     184          94 :     PG_RETURN_BOOL(val1 != val2);
     185             : }
     186             : 
     187             : Datum
     188      694576 : int84lt(PG_FUNCTION_ARGS)
     189             : {
     190      694576 :     int64       val1 = PG_GETARG_INT64(0);
     191      694576 :     int32       val2 = PG_GETARG_INT32(1);
     192             : 
     193      694576 :     PG_RETURN_BOOL(val1 < val2);
     194             : }
     195             : 
     196             : Datum
     197      140350 : int84gt(PG_FUNCTION_ARGS)
     198             : {
     199      140350 :     int64       val1 = PG_GETARG_INT64(0);
     200      140350 :     int32       val2 = PG_GETARG_INT32(1);
     201             : 
     202      140350 :     PG_RETURN_BOOL(val1 > val2);
     203             : }
     204             : 
     205             : Datum
     206       22178 : int84le(PG_FUNCTION_ARGS)
     207             : {
     208       22178 :     int64       val1 = PG_GETARG_INT64(0);
     209       22178 :     int32       val2 = PG_GETARG_INT32(1);
     210             : 
     211       22178 :     PG_RETURN_BOOL(val1 <= val2);
     212             : }
     213             : 
     214             : Datum
     215       10038 : int84ge(PG_FUNCTION_ARGS)
     216             : {
     217       10038 :     int64       val1 = PG_GETARG_INT64(0);
     218       10038 :     int32       val2 = PG_GETARG_INT32(1);
     219             : 
     220       10038 :     PG_RETURN_BOOL(val1 >= val2);
     221             : }
     222             : 
     223             : /* int48relop()
     224             :  * Is 32-bit val1 relop 64-bit val2?
     225             :  */
     226             : Datum
     227       92002 : int48eq(PG_FUNCTION_ARGS)
     228             : {
     229       92002 :     int32       val1 = PG_GETARG_INT32(0);
     230       92002 :     int64       val2 = PG_GETARG_INT64(1);
     231             : 
     232       92002 :     PG_RETURN_BOOL(val1 == val2);
     233             : }
     234             : 
     235             : Datum
     236          36 : int48ne(PG_FUNCTION_ARGS)
     237             : {
     238          36 :     int32       val1 = PG_GETARG_INT32(0);
     239          36 :     int64       val2 = PG_GETARG_INT64(1);
     240             : 
     241          36 :     PG_RETURN_BOOL(val1 != val2);
     242             : }
     243             : 
     244             : Datum
     245        6618 : int48lt(PG_FUNCTION_ARGS)
     246             : {
     247        6618 :     int32       val1 = PG_GETARG_INT32(0);
     248        6618 :     int64       val2 = PG_GETARG_INT64(1);
     249             : 
     250        6618 :     PG_RETURN_BOOL(val1 < val2);
     251             : }
     252             : 
     253             : Datum
     254        3270 : int48gt(PG_FUNCTION_ARGS)
     255             : {
     256        3270 :     int32       val1 = PG_GETARG_INT32(0);
     257        3270 :     int64       val2 = PG_GETARG_INT64(1);
     258             : 
     259        3270 :     PG_RETURN_BOOL(val1 > val2);
     260             : }
     261             : 
     262             : Datum
     263        3828 : int48le(PG_FUNCTION_ARGS)
     264             : {
     265        3828 :     int32       val1 = PG_GETARG_INT32(0);
     266        3828 :     int64       val2 = PG_GETARG_INT64(1);
     267             : 
     268        3828 :     PG_RETURN_BOOL(val1 <= val2);
     269             : }
     270             : 
     271             : Datum
     272        3474 : int48ge(PG_FUNCTION_ARGS)
     273             : {
     274        3474 :     int32       val1 = PG_GETARG_INT32(0);
     275        3474 :     int64       val2 = PG_GETARG_INT64(1);
     276             : 
     277        3474 :     PG_RETURN_BOOL(val1 >= val2);
     278             : }
     279             : 
     280             : /* int82relop()
     281             :  * Is 64-bit val1 relop 16-bit val2?
     282             :  */
     283             : Datum
     284          30 : int82eq(PG_FUNCTION_ARGS)
     285             : {
     286          30 :     int64       val1 = PG_GETARG_INT64(0);
     287          30 :     int16       val2 = PG_GETARG_INT16(1);
     288             : 
     289          30 :     PG_RETURN_BOOL(val1 == val2);
     290             : }
     291             : 
     292             : Datum
     293          30 : int82ne(PG_FUNCTION_ARGS)
     294             : {
     295          30 :     int64       val1 = PG_GETARG_INT64(0);
     296          30 :     int16       val2 = PG_GETARG_INT16(1);
     297             : 
     298          30 :     PG_RETURN_BOOL(val1 != val2);
     299             : }
     300             : 
     301             : Datum
     302          30 : int82lt(PG_FUNCTION_ARGS)
     303             : {
     304          30 :     int64       val1 = PG_GETARG_INT64(0);
     305          30 :     int16       val2 = PG_GETARG_INT16(1);
     306             : 
     307          30 :     PG_RETURN_BOOL(val1 < val2);
     308             : }
     309             : 
     310             : Datum
     311        3228 : int82gt(PG_FUNCTION_ARGS)
     312             : {
     313        3228 :     int64       val1 = PG_GETARG_INT64(0);
     314        3228 :     int16       val2 = PG_GETARG_INT16(1);
     315             : 
     316        3228 :     PG_RETURN_BOOL(val1 > val2);
     317             : }
     318             : 
     319             : Datum
     320          30 : int82le(PG_FUNCTION_ARGS)
     321             : {
     322          30 :     int64       val1 = PG_GETARG_INT64(0);
     323          30 :     int16       val2 = PG_GETARG_INT16(1);
     324             : 
     325          30 :     PG_RETURN_BOOL(val1 <= val2);
     326             : }
     327             : 
     328             : Datum
     329        3228 : int82ge(PG_FUNCTION_ARGS)
     330             : {
     331        3228 :     int64       val1 = PG_GETARG_INT64(0);
     332        3228 :     int16       val2 = PG_GETARG_INT16(1);
     333             : 
     334        3228 :     PG_RETURN_BOOL(val1 >= val2);
     335             : }
     336             : 
     337             : /* int28relop()
     338             :  * Is 16-bit val1 relop 64-bit val2?
     339             :  */
     340             : Datum
     341        1854 : int28eq(PG_FUNCTION_ARGS)
     342             : {
     343        1854 :     int16       val1 = PG_GETARG_INT16(0);
     344        1854 :     int64       val2 = PG_GETARG_INT64(1);
     345             : 
     346        1854 :     PG_RETURN_BOOL(val1 == val2);
     347             : }
     348             : 
     349             : Datum
     350        3312 : int28ne(PG_FUNCTION_ARGS)
     351             : {
     352        3312 :     int16       val1 = PG_GETARG_INT16(0);
     353        3312 :     int64       val2 = PG_GETARG_INT64(1);
     354             : 
     355        3312 :     PG_RETURN_BOOL(val1 != val2);
     356             : }
     357             : 
     358             : Datum
     359        3228 : int28lt(PG_FUNCTION_ARGS)
     360             : {
     361        3228 :     int16       val1 = PG_GETARG_INT16(0);
     362        3228 :     int64       val2 = PG_GETARG_INT64(1);
     363             : 
     364        3228 :     PG_RETURN_BOOL(val1 < val2);
     365             : }
     366             : 
     367             : Datum
     368        3228 : int28gt(PG_FUNCTION_ARGS)
     369             : {
     370        3228 :     int16       val1 = PG_GETARG_INT16(0);
     371        3228 :     int64       val2 = PG_GETARG_INT64(1);
     372             : 
     373        3228 :     PG_RETURN_BOOL(val1 > val2);
     374             : }
     375             : 
     376             : Datum
     377        3828 : int28le(PG_FUNCTION_ARGS)
     378             : {
     379        3828 :     int16       val1 = PG_GETARG_INT16(0);
     380        3828 :     int64       val2 = PG_GETARG_INT64(1);
     381             : 
     382        3828 :     PG_RETURN_BOOL(val1 <= val2);
     383             : }
     384             : 
     385             : Datum
     386        3714 : int28ge(PG_FUNCTION_ARGS)
     387             : {
     388        3714 :     int16       val1 = PG_GETARG_INT16(0);
     389        3714 :     int64       val2 = PG_GETARG_INT64(1);
     390             : 
     391        3714 :     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         108 : in_range_int8_int8(PG_FUNCTION_ARGS)
     402             : {
     403         108 :     int64       val = PG_GETARG_INT64(0);
     404         108 :     int64       base = PG_GETARG_INT64(1);
     405         108 :     int64       offset = PG_GETARG_INT64(2);
     406         108 :     bool        sub = PG_GETARG_BOOL(3);
     407         108 :     bool        less = PG_GETARG_BOOL(4);
     408             :     int64       sum;
     409             : 
     410         108 :     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         108 :     if (sub)
     416          54 :         offset = -offset;       /* cannot overflow */
     417             : 
     418         108 :     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          36 :         PG_RETURN_BOOL(sub ? !less : less);
     426             :     }
     427             : 
     428          72 :     if (less)
     429          36 :         PG_RETURN_BOOL(val <= sum);
     430             :     else
     431          36 :         PG_RETURN_BOOL(val >= sum);
     432             : }
     433             : 
     434             : 
     435             : /*----------------------------------------------------------
     436             :  *  Arithmetic operators on 64-bit integers.
     437             :  *---------------------------------------------------------*/
     438             : 
     439             : Datum
     440         936 : int8um(PG_FUNCTION_ARGS)
     441             : {
     442         936 :     int64       arg = PG_GETARG_INT64(0);
     443             :     int64       result;
     444             : 
     445         936 :     if (unlikely(arg == PG_INT64_MIN))
     446           6 :         ereport(ERROR,
     447             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     448             :                  errmsg("bigint out of range")));
     449         930 :     result = -arg;
     450         930 :     PG_RETURN_INT64(result);
     451             : }
     452             : 
     453             : Datum
     454           6 : int8up(PG_FUNCTION_ARGS)
     455             : {
     456           6 :     int64       arg = PG_GETARG_INT64(0);
     457             : 
     458           6 :     PG_RETURN_INT64(arg);
     459             : }
     460             : 
     461             : Datum
     462      130504 : int8pl(PG_FUNCTION_ARGS)
     463             : {
     464      130504 :     int64       arg1 = PG_GETARG_INT64(0);
     465      130504 :     int64       arg2 = PG_GETARG_INT64(1);
     466             :     int64       result;
     467             : 
     468      130504 :     if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
     469          12 :         ereport(ERROR,
     470             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     471             :                  errmsg("bigint out of range")));
     472      130492 :     PG_RETURN_INT64(result);
     473             : }
     474             : 
     475             : Datum
     476         252 : int8mi(PG_FUNCTION_ARGS)
     477             : {
     478         252 :     int64       arg1 = PG_GETARG_INT64(0);
     479         252 :     int64       arg2 = PG_GETARG_INT64(1);
     480             :     int64       result;
     481             : 
     482         252 :     if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
     483          18 :         ereport(ERROR,
     484             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     485             :                  errmsg("bigint out of range")));
     486         234 :     PG_RETURN_INT64(result);
     487             : }
     488             : 
     489             : Datum
     490         180 : int8mul(PG_FUNCTION_ARGS)
     491             : {
     492         180 :     int64       arg1 = PG_GETARG_INT64(0);
     493         180 :     int64       arg2 = PG_GETARG_INT64(1);
     494             :     int64       result;
     495             : 
     496         180 :     if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
     497          18 :         ereport(ERROR,
     498             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     499             :                  errmsg("bigint out of range")));
     500         162 :     PG_RETURN_INT64(result);
     501             : }
     502             : 
     503             : Datum
     504         132 : int8div(PG_FUNCTION_ARGS)
     505             : {
     506         132 :     int64       arg1 = PG_GETARG_INT64(0);
     507         132 :     int64       arg2 = PG_GETARG_INT64(1);
     508             :     int64       result;
     509             : 
     510         132 :     if (arg2 == 0)
     511             :     {
     512           6 :         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         126 :     if (arg2 == -1)
     526             :     {
     527           6 :         if (unlikely(arg1 == PG_INT64_MIN))
     528           6 :             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         120 :     result = arg1 / arg2;
     538             : 
     539         120 :     PG_RETURN_INT64(result);
     540             : }
     541             : 
     542             : /* int8abs()
     543             :  * Absolute value
     544             :  */
     545             : Datum
     546          36 : int8abs(PG_FUNCTION_ARGS)
     547             : {
     548          36 :     int64       arg1 = PG_GETARG_INT64(0);
     549             :     int64       result;
     550             : 
     551          36 :     if (unlikely(arg1 == PG_INT64_MIN))
     552           6 :         ereport(ERROR,
     553             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     554             :                  errmsg("bigint out of range")));
     555          30 :     result = (arg1 < 0) ? -arg1 : arg1;
     556          30 :     PG_RETURN_INT64(result);
     557             : }
     558             : 
     559             : /* int8mod()
     560             :  * Modulo operation.
     561             :  */
     562             : Datum
     563          54 : int8mod(PG_FUNCTION_ARGS)
     564             : {
     565          54 :     int64       arg1 = PG_GETARG_INT64(0);
     566          54 :     int64       arg2 = PG_GETARG_INT64(1);
     567             : 
     568          54 :     if (unlikely(arg2 == 0))
     569             :     {
     570           6 :         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          48 :     if (arg2 == -1)
     583          18 :         PG_RETURN_INT64(0);
     584             : 
     585             :     /* No overflow is possible */
     586             : 
     587          30 :     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         264 : 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         264 :     a1 = (arg1 < 0) ? arg1 : -arg1;
     622         264 :     a2 = (arg2 < 0) ? arg2 : -arg2;
     623         264 :     if (a1 > a2)
     624             :     {
     625          96 :         swap = arg1;
     626          96 :         arg1 = arg2;
     627          96 :         arg2 = swap;
     628             :     }
     629             : 
     630             :     /* Special care needs to be taken with INT64_MIN.  See comments above. */
     631         264 :     if (arg1 == PG_INT64_MIN)
     632             :     {
     633          90 :         if (arg2 == 0 || arg2 == PG_INT64_MIN)
     634          12 :             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          78 :         if (arg2 == -1)
     645          12 :             return 1;
     646             :     }
     647             : 
     648             :     /* Use the Euclidean algorithm to find the GCD */
     649        1230 :     while (arg2 != 0)
     650             :     {
     651         990 :         swap = arg2;
     652         990 :         arg2 = arg1 % arg2;
     653         990 :         arg1 = swap;
     654             :     }
     655             : 
     656             :     /*
     657             :      * Make sure the result is positive. (We know we don't have INT64_MIN
     658             :      * anymore).
     659             :      */
     660         240 :     if (arg1 < 0)
     661         102 :         arg1 = -arg1;
     662             : 
     663         240 :     return arg1;
     664             : }
     665             : 
     666             : Datum
     667         180 : int8gcd(PG_FUNCTION_ARGS)
     668             : {
     669         180 :     int64       arg1 = PG_GETARG_INT64(0);
     670         180 :     int64       arg2 = PG_GETARG_INT64(1);
     671             :     int64       result;
     672             : 
     673         180 :     result = int8gcd_internal(arg1, arg2);
     674             : 
     675         168 :     PG_RETURN_INT64(result);
     676             : }
     677             : 
     678             : /*
     679             :  * Least Common Multiple
     680             :  */
     681             : Datum
     682         156 : int8lcm(PG_FUNCTION_ARGS)
     683             : {
     684         156 :     int64       arg1 = PG_GETARG_INT64(0);
     685         156 :     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         156 :     if (arg1 == 0 || arg2 == 0)
     695          72 :         PG_RETURN_INT64(0);
     696             : 
     697             :     /* lcm(x, y) = abs(x / gcd(x, y) * y) */
     698          84 :     gcd = int8gcd_internal(arg1, arg2);
     699          84 :     arg1 = arg1 / gcd;
     700             : 
     701          84 :     if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
     702           6 :         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          78 :     if (unlikely(result == PG_INT64_MIN))
     708           6 :         ereport(ERROR,
     709             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     710             :                  errmsg("bigint out of range")));
     711             : 
     712          72 :     if (result < 0)
     713          36 :         result = -result;
     714             : 
     715          72 :     PG_RETURN_INT64(result);
     716             : }
     717             : 
     718             : Datum
     719    19539592 : int8inc(PG_FUNCTION_ARGS)
     720             : {
     721    19539592 :     int64       arg = PG_GETARG_INT64(0);
     722             :     int64       result;
     723             : 
     724    19539592 :     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    19539592 :     PG_RETURN_INT64(result);
     730             : }
     731             : 
     732             : Datum
     733          24 : int8dec(PG_FUNCTION_ARGS)
     734             : {
     735          24 :     int64       arg = PG_GETARG_INT64(0);
     736             :     int64       result;
     737             : 
     738          24 :     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          24 :     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     1200492 : int8inc_any(PG_FUNCTION_ARGS)
     758             : {
     759     1200492 :     return int8inc(fcinfo);
     760             : }
     761             : 
     762             : Datum
     763      240024 : int8inc_float8_float8(PG_FUNCTION_ARGS)
     764             : {
     765      240024 :     return int8inc(fcinfo);
     766             : }
     767             : 
     768             : Datum
     769           6 : int8dec_any(PG_FUNCTION_ARGS)
     770             : {
     771           6 :     return int8dec(fcinfo);
     772             : }
     773             : 
     774             : /*
     775             :  * int8inc_support
     776             :  *      prosupport function for int8inc() and int8inc_any()
     777             :  */
     778             : Datum
     779         584 : int8inc_support(PG_FUNCTION_ARGS)
     780             : {
     781         584 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     782             : 
     783         584 :     if (IsA(rawreq, SupportRequestWFuncMonotonic))
     784             :     {
     785          78 :         SupportRequestWFuncMonotonic *req = (SupportRequestWFuncMonotonic *) rawreq;
     786          78 :         MonotonicFunction monotonic = MONOTONICFUNC_NONE;
     787          78 :         int         frameOptions = req->window_clause->frameOptions;
     788             : 
     789             :         /* No ORDER BY clause then all rows are peers */
     790          78 :         if (req->window_clause->orderClause == NIL)
     791          24 :             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          54 :             if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
     800          42 :                 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          54 :             if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
     807          12 :                 monotonic |= MONOTONICFUNC_DECREASING;
     808             :         }
     809             : 
     810          78 :         req->monotonic = monotonic;
     811          78 :         PG_RETURN_POINTER(req);
     812             :     }
     813             : 
     814         506 :     PG_RETURN_POINTER(NULL);
     815             : }
     816             : 
     817             : 
     818             : Datum
     819         858 : int8larger(PG_FUNCTION_ARGS)
     820             : {
     821         858 :     int64       arg1 = PG_GETARG_INT64(0);
     822         858 :     int64       arg2 = PG_GETARG_INT64(1);
     823             :     int64       result;
     824             : 
     825         858 :     result = ((arg1 > arg2) ? arg1 : arg2);
     826             : 
     827         858 :     PG_RETURN_INT64(result);
     828             : }
     829             : 
     830             : Datum
     831        8730 : int8smaller(PG_FUNCTION_ARGS)
     832             : {
     833        8730 :     int64       arg1 = PG_GETARG_INT64(0);
     834        8730 :     int64       arg2 = PG_GETARG_INT64(1);
     835             :     int64       result;
     836             : 
     837        8730 :     result = ((arg1 < arg2) ? arg1 : arg2);
     838             : 
     839        8730 :     PG_RETURN_INT64(result);
     840             : }
     841             : 
     842             : Datum
     843        5216 : int84pl(PG_FUNCTION_ARGS)
     844             : {
     845        5216 :     int64       arg1 = PG_GETARG_INT64(0);
     846        5216 :     int32       arg2 = PG_GETARG_INT32(1);
     847             :     int64       result;
     848             : 
     849        5216 :     if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
     850           6 :         ereport(ERROR,
     851             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     852             :                  errmsg("bigint out of range")));
     853        5210 :     PG_RETURN_INT64(result);
     854             : }
     855             : 
     856             : Datum
     857         134 : int84mi(PG_FUNCTION_ARGS)
     858             : {
     859         134 :     int64       arg1 = PG_GETARG_INT64(0);
     860         134 :     int32       arg2 = PG_GETARG_INT32(1);
     861             :     int64       result;
     862             : 
     863         134 :     if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
     864           6 :         ereport(ERROR,
     865             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     866             :                  errmsg("bigint out of range")));
     867         128 :     PG_RETURN_INT64(result);
     868             : }
     869             : 
     870             : Datum
     871        2390 : int84mul(PG_FUNCTION_ARGS)
     872             : {
     873        2390 :     int64       arg1 = PG_GETARG_INT64(0);
     874        2390 :     int32       arg2 = PG_GETARG_INT32(1);
     875             :     int64       result;
     876             : 
     877        2390 :     if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
     878          12 :         ereport(ERROR,
     879             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     880             :                  errmsg("bigint out of range")));
     881        2378 :     PG_RETURN_INT64(result);
     882             : }
     883             : 
     884             : Datum
     885         194 : int84div(PG_FUNCTION_ARGS)
     886             : {
     887         194 :     int64       arg1 = PG_GETARG_INT64(0);
     888         194 :     int32       arg2 = PG_GETARG_INT32(1);
     889             :     int64       result;
     890             : 
     891         194 :     if (arg2 == 0)
     892             :     {
     893           6 :         ereport(ERROR,
     894             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     895             :                  errmsg("division by zero")));
     896             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     897             :         PG_RETURN_NULL();
     898             :     }
     899             : 
     900             :     /*
     901             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
     902             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
     903             :      * produce zero, some throw an exception.  We can dodge the problem by
     904             :      * recognizing that division by -1 is the same as negation.
     905             :      */
     906         188 :     if (arg2 == -1)
     907             :     {
     908           6 :         if (unlikely(arg1 == PG_INT64_MIN))
     909           6 :             ereport(ERROR,
     910             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     911             :                      errmsg("bigint out of range")));
     912           0 :         result = -arg1;
     913           0 :         PG_RETURN_INT64(result);
     914             :     }
     915             : 
     916             :     /* No overflow is possible */
     917             : 
     918         182 :     result = arg1 / arg2;
     919             : 
     920         182 :     PG_RETURN_INT64(result);
     921             : }
     922             : 
     923             : Datum
     924        1370 : int48pl(PG_FUNCTION_ARGS)
     925             : {
     926        1370 :     int32       arg1 = PG_GETARG_INT32(0);
     927        1370 :     int64       arg2 = PG_GETARG_INT64(1);
     928             :     int64       result;
     929             : 
     930        1370 :     if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
     931           6 :         ereport(ERROR,
     932             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     933             :                  errmsg("bigint out of range")));
     934        1364 :     PG_RETURN_INT64(result);
     935             : }
     936             : 
     937             : Datum
     938          66 : int48mi(PG_FUNCTION_ARGS)
     939             : {
     940          66 :     int32       arg1 = PG_GETARG_INT32(0);
     941          66 :     int64       arg2 = PG_GETARG_INT64(1);
     942             :     int64       result;
     943             : 
     944          66 :     if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
     945           6 :         ereport(ERROR,
     946             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     947             :                  errmsg("bigint out of range")));
     948          60 :     PG_RETURN_INT64(result);
     949             : }
     950             : 
     951             : Datum
     952         222 : int48mul(PG_FUNCTION_ARGS)
     953             : {
     954         222 :     int32       arg1 = PG_GETARG_INT32(0);
     955         222 :     int64       arg2 = PG_GETARG_INT64(1);
     956             :     int64       result;
     957             : 
     958         222 :     if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
     959           6 :         ereport(ERROR,
     960             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     961             :                  errmsg("bigint out of range")));
     962         216 :     PG_RETURN_INT64(result);
     963             : }
     964             : 
     965             : Datum
     966          36 : int48div(PG_FUNCTION_ARGS)
     967             : {
     968          36 :     int32       arg1 = PG_GETARG_INT32(0);
     969          36 :     int64       arg2 = PG_GETARG_INT64(1);
     970             : 
     971          36 :     if (unlikely(arg2 == 0))
     972             :     {
     973           6 :         ereport(ERROR,
     974             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     975             :                  errmsg("division by zero")));
     976             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     977             :         PG_RETURN_NULL();
     978             :     }
     979             : 
     980             :     /* No overflow is possible */
     981          30 :     PG_RETURN_INT64((int64) arg1 / arg2);
     982             : }
     983             : 
     984             : Datum
     985          36 : int82pl(PG_FUNCTION_ARGS)
     986             : {
     987          36 :     int64       arg1 = PG_GETARG_INT64(0);
     988          36 :     int16       arg2 = PG_GETARG_INT16(1);
     989             :     int64       result;
     990             : 
     991          36 :     if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
     992           6 :         ereport(ERROR,
     993             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     994             :                  errmsg("bigint out of range")));
     995          30 :     PG_RETURN_INT64(result);
     996             : }
     997             : 
     998             : Datum
     999          36 : int82mi(PG_FUNCTION_ARGS)
    1000             : {
    1001          36 :     int64       arg1 = PG_GETARG_INT64(0);
    1002          36 :     int16       arg2 = PG_GETARG_INT16(1);
    1003             :     int64       result;
    1004             : 
    1005          36 :     if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
    1006           6 :         ereport(ERROR,
    1007             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1008             :                  errmsg("bigint out of range")));
    1009          30 :     PG_RETURN_INT64(result);
    1010             : }
    1011             : 
    1012             : Datum
    1013          42 : int82mul(PG_FUNCTION_ARGS)
    1014             : {
    1015          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1016          42 :     int16       arg2 = PG_GETARG_INT16(1);
    1017             :     int64       result;
    1018             : 
    1019          42 :     if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
    1020          12 :         ereport(ERROR,
    1021             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1022             :                  errmsg("bigint out of range")));
    1023          30 :     PG_RETURN_INT64(result);
    1024             : }
    1025             : 
    1026             : Datum
    1027          42 : int82div(PG_FUNCTION_ARGS)
    1028             : {
    1029          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1030          42 :     int16       arg2 = PG_GETARG_INT16(1);
    1031             :     int64       result;
    1032             : 
    1033          42 :     if (unlikely(arg2 == 0))
    1034             :     {
    1035           6 :         ereport(ERROR,
    1036             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1037             :                  errmsg("division by zero")));
    1038             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1039             :         PG_RETURN_NULL();
    1040             :     }
    1041             : 
    1042             :     /*
    1043             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
    1044             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
    1045             :      * produce zero, some throw an exception.  We can dodge the problem by
    1046             :      * recognizing that division by -1 is the same as negation.
    1047             :      */
    1048          36 :     if (arg2 == -1)
    1049             :     {
    1050           6 :         if (unlikely(arg1 == PG_INT64_MIN))
    1051           6 :             ereport(ERROR,
    1052             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1053             :                      errmsg("bigint out of range")));
    1054           0 :         result = -arg1;
    1055           0 :         PG_RETURN_INT64(result);
    1056             :     }
    1057             : 
    1058             :     /* No overflow is possible */
    1059             : 
    1060          30 :     result = arg1 / arg2;
    1061             : 
    1062          30 :     PG_RETURN_INT64(result);
    1063             : }
    1064             : 
    1065             : Datum
    1066          36 : int28pl(PG_FUNCTION_ARGS)
    1067             : {
    1068          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1069          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1070             :     int64       result;
    1071             : 
    1072          36 :     if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
    1073           6 :         ereport(ERROR,
    1074             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1075             :                  errmsg("bigint out of range")));
    1076          30 :     PG_RETURN_INT64(result);
    1077             : }
    1078             : 
    1079             : Datum
    1080          36 : int28mi(PG_FUNCTION_ARGS)
    1081             : {
    1082          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1083          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1084             :     int64       result;
    1085             : 
    1086          36 :     if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
    1087           6 :         ereport(ERROR,
    1088             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1089             :                  errmsg("bigint out of range")));
    1090          30 :     PG_RETURN_INT64(result);
    1091             : }
    1092             : 
    1093             : Datum
    1094          36 : int28mul(PG_FUNCTION_ARGS)
    1095             : {
    1096          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1097          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1098             :     int64       result;
    1099             : 
    1100          36 :     if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
    1101           6 :         ereport(ERROR,
    1102             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1103             :                  errmsg("bigint out of range")));
    1104          30 :     PG_RETURN_INT64(result);
    1105             : }
    1106             : 
    1107             : Datum
    1108          36 : int28div(PG_FUNCTION_ARGS)
    1109             : {
    1110          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1111          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1112             : 
    1113          36 :     if (unlikely(arg2 == 0))
    1114             :     {
    1115           6 :         ereport(ERROR,
    1116             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1117             :                  errmsg("division by zero")));
    1118             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1119             :         PG_RETURN_NULL();
    1120             :     }
    1121             : 
    1122             :     /* No overflow is possible */
    1123          30 :     PG_RETURN_INT64((int64) arg1 / arg2);
    1124             : }
    1125             : 
    1126             : /* Binary arithmetics
    1127             :  *
    1128             :  *      int8and     - returns arg1 & arg2
    1129             :  *      int8or      - returns arg1 | arg2
    1130             :  *      int8xor     - returns arg1 # arg2
    1131             :  *      int8not     - returns ~arg1
    1132             :  *      int8shl     - returns arg1 << arg2
    1133             :  *      int8shr     - returns arg1 >> arg2
    1134             :  */
    1135             : 
    1136             : Datum
    1137          42 : int8and(PG_FUNCTION_ARGS)
    1138             : {
    1139          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1140          42 :     int64       arg2 = PG_GETARG_INT64(1);
    1141             : 
    1142          42 :     PG_RETURN_INT64(arg1 & arg2);
    1143             : }
    1144             : 
    1145             : Datum
    1146          46 : int8or(PG_FUNCTION_ARGS)
    1147             : {
    1148          46 :     int64       arg1 = PG_GETARG_INT64(0);
    1149          46 :     int64       arg2 = PG_GETARG_INT64(1);
    1150             : 
    1151          46 :     PG_RETURN_INT64(arg1 | arg2);
    1152             : }
    1153             : 
    1154             : Datum
    1155          42 : int8xor(PG_FUNCTION_ARGS)
    1156             : {
    1157          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1158          42 :     int64       arg2 = PG_GETARG_INT64(1);
    1159             : 
    1160          42 :     PG_RETURN_INT64(arg1 ^ arg2);
    1161             : }
    1162             : 
    1163             : Datum
    1164          30 : int8not(PG_FUNCTION_ARGS)
    1165             : {
    1166          30 :     int64       arg1 = PG_GETARG_INT64(0);
    1167             : 
    1168          30 :     PG_RETURN_INT64(~arg1);
    1169             : }
    1170             : 
    1171             : Datum
    1172          46 : int8shl(PG_FUNCTION_ARGS)
    1173             : {
    1174          46 :     int64       arg1 = PG_GETARG_INT64(0);
    1175          46 :     int32       arg2 = PG_GETARG_INT32(1);
    1176             : 
    1177          46 :     PG_RETURN_INT64(arg1 << arg2);
    1178             : }
    1179             : 
    1180             : Datum
    1181          30 : int8shr(PG_FUNCTION_ARGS)
    1182             : {
    1183          30 :     int64       arg1 = PG_GETARG_INT64(0);
    1184          30 :     int32       arg2 = PG_GETARG_INT32(1);
    1185             : 
    1186          30 :     PG_RETURN_INT64(arg1 >> arg2);
    1187             : }
    1188             : 
    1189             : /*----------------------------------------------------------
    1190             :  *  Conversion operators.
    1191             :  *---------------------------------------------------------*/
    1192             : 
    1193             : Datum
    1194     2524814 : int48(PG_FUNCTION_ARGS)
    1195             : {
    1196     2524814 :     int32       arg = PG_GETARG_INT32(0);
    1197             : 
    1198     2524814 :     PG_RETURN_INT64((int64) arg);
    1199             : }
    1200             : 
    1201             : Datum
    1202      390686 : int84(PG_FUNCTION_ARGS)
    1203             : {
    1204      390686 :     int64       arg = PG_GETARG_INT64(0);
    1205             : 
    1206      390686 :     if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
    1207           6 :         ereport(ERROR,
    1208             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1209             :                  errmsg("integer out of range")));
    1210             : 
    1211      390680 :     PG_RETURN_INT32((int32) arg);
    1212             : }
    1213             : 
    1214             : Datum
    1215          18 : int28(PG_FUNCTION_ARGS)
    1216             : {
    1217          18 :     int16       arg = PG_GETARG_INT16(0);
    1218             : 
    1219          18 :     PG_RETURN_INT64((int64) arg);
    1220             : }
    1221             : 
    1222             : Datum
    1223          36 : int82(PG_FUNCTION_ARGS)
    1224             : {
    1225          36 :     int64       arg = PG_GETARG_INT64(0);
    1226             : 
    1227          36 :     if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
    1228           6 :         ereport(ERROR,
    1229             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1230             :                  errmsg("smallint out of range")));
    1231             : 
    1232          30 :     PG_RETURN_INT16((int16) arg);
    1233             : }
    1234             : 
    1235             : Datum
    1236       12198 : i8tod(PG_FUNCTION_ARGS)
    1237             : {
    1238       12198 :     int64       arg = PG_GETARG_INT64(0);
    1239             :     float8      result;
    1240             : 
    1241       12198 :     result = arg;
    1242             : 
    1243       12198 :     PG_RETURN_FLOAT8(result);
    1244             : }
    1245             : 
    1246             : /* dtoi8()
    1247             :  * Convert float8 to 8-byte integer.
    1248             :  */
    1249             : Datum
    1250         144 : dtoi8(PG_FUNCTION_ARGS)
    1251             : {
    1252         144 :     float8      num = PG_GETARG_FLOAT8(0);
    1253             : 
    1254             :     /*
    1255             :      * Get rid of any fractional part in the input.  This is so we don't fail
    1256             :      * on just-out-of-range values that would round into range.  Note
    1257             :      * assumption that rint() will pass through a NaN or Inf unchanged.
    1258             :      */
    1259         144 :     num = rint(num);
    1260             : 
    1261             :     /* Range check */
    1262         144 :     if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
    1263          18 :         ereport(ERROR,
    1264             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1265             :                  errmsg("bigint out of range")));
    1266             : 
    1267         126 :     PG_RETURN_INT64((int64) num);
    1268             : }
    1269             : 
    1270             : Datum
    1271         150 : i8tof(PG_FUNCTION_ARGS)
    1272             : {
    1273         150 :     int64       arg = PG_GETARG_INT64(0);
    1274             :     float4      result;
    1275             : 
    1276         150 :     result = arg;
    1277             : 
    1278         150 :     PG_RETURN_FLOAT4(result);
    1279             : }
    1280             : 
    1281             : /* ftoi8()
    1282             :  * Convert float4 to 8-byte integer.
    1283             :  */
    1284             : Datum
    1285          30 : ftoi8(PG_FUNCTION_ARGS)
    1286             : {
    1287          30 :     float4      num = PG_GETARG_FLOAT4(0);
    1288             : 
    1289             :     /*
    1290             :      * Get rid of any fractional part in the input.  This is so we don't fail
    1291             :      * on just-out-of-range values that would round into range.  Note
    1292             :      * assumption that rint() will pass through a NaN or Inf unchanged.
    1293             :      */
    1294          30 :     num = rint(num);
    1295             : 
    1296             :     /* Range check */
    1297          30 :     if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
    1298          12 :         ereport(ERROR,
    1299             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1300             :                  errmsg("bigint out of range")));
    1301             : 
    1302          18 :     PG_RETURN_INT64((int64) num);
    1303             : }
    1304             : 
    1305             : Datum
    1306          20 : i8tooid(PG_FUNCTION_ARGS)
    1307             : {
    1308          20 :     int64       arg = PG_GETARG_INT64(0);
    1309             : 
    1310          20 :     if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
    1311           6 :         ereport(ERROR,
    1312             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1313             :                  errmsg("OID out of range")));
    1314             : 
    1315          14 :     PG_RETURN_OID((Oid) arg);
    1316             : }
    1317             : 
    1318             : Datum
    1319          22 : oidtoi8(PG_FUNCTION_ARGS)
    1320             : {
    1321          22 :     Oid         arg = PG_GETARG_OID(0);
    1322             : 
    1323          22 :     PG_RETURN_INT64((int64) arg);
    1324             : }
    1325             : 
    1326             : /*
    1327             :  * non-persistent numeric series generator
    1328             :  */
    1329             : Datum
    1330     3382834 : generate_series_int8(PG_FUNCTION_ARGS)
    1331             : {
    1332     3382834 :     return generate_series_step_int8(fcinfo);
    1333             : }
    1334             : 
    1335             : Datum
    1336     3382980 : generate_series_step_int8(PG_FUNCTION_ARGS)
    1337             : {
    1338             :     FuncCallContext *funcctx;
    1339             :     generate_series_fctx *fctx;
    1340             :     int64       result;
    1341             :     MemoryContext oldcontext;
    1342             : 
    1343             :     /* stuff done only on the first call of the function */
    1344     3382980 :     if (SRF_IS_FIRSTCALL())
    1345             :     {
    1346          60 :         int64       start = PG_GETARG_INT64(0);
    1347          60 :         int64       finish = PG_GETARG_INT64(1);
    1348          60 :         int64       step = 1;
    1349             : 
    1350             :         /* see if we were given an explicit step size */
    1351          60 :         if (PG_NARGS() == 3)
    1352          14 :             step = PG_GETARG_INT64(2);
    1353          60 :         if (step == 0)
    1354           6 :             ereport(ERROR,
    1355             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1356             :                      errmsg("step size cannot equal zero")));
    1357             : 
    1358             :         /* create a function context for cross-call persistence */
    1359          54 :         funcctx = SRF_FIRSTCALL_INIT();
    1360             : 
    1361             :         /*
    1362             :          * switch to memory context appropriate for multiple function calls
    1363             :          */
    1364          54 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1365             : 
    1366             :         /* allocate memory for user context */
    1367          54 :         fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
    1368             : 
    1369             :         /*
    1370             :          * Use fctx to keep state from call to call. Seed current with the
    1371             :          * original start value
    1372             :          */
    1373          54 :         fctx->current = start;
    1374          54 :         fctx->finish = finish;
    1375          54 :         fctx->step = step;
    1376             : 
    1377          54 :         funcctx->user_fctx = fctx;
    1378          54 :         MemoryContextSwitchTo(oldcontext);
    1379             :     }
    1380             : 
    1381             :     /* stuff done on every call of the function */
    1382     3382974 :     funcctx = SRF_PERCALL_SETUP();
    1383             : 
    1384             :     /*
    1385             :      * get the saved state and use current as the result for this iteration
    1386             :      */
    1387     3382974 :     fctx = funcctx->user_fctx;
    1388     3382974 :     result = fctx->current;
    1389             : 
    1390     3382974 :     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
    1391          52 :         (fctx->step < 0 && fctx->current >= fctx->finish))
    1392             :     {
    1393             :         /*
    1394             :          * Increment current in preparation for next iteration. If next-value
    1395             :          * computation overflows, this is the final result.
    1396             :          */
    1397     3382922 :         if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
    1398           0 :             fctx->step = 0;
    1399             : 
    1400             :         /* do when there is more left to send */
    1401     3382922 :         SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
    1402             :     }
    1403             :     else
    1404             :         /* do when there is no more left */
    1405          52 :         SRF_RETURN_DONE(funcctx);
    1406             : }
    1407             : 
    1408             : /*
    1409             :  * Planner support function for generate_series(int8, int8 [, int8])
    1410             :  */
    1411             : Datum
    1412         168 : generate_series_int8_support(PG_FUNCTION_ARGS)
    1413             : {
    1414         168 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1415         168 :     Node       *ret = NULL;
    1416             : 
    1417         168 :     if (IsA(rawreq, SupportRequestRows))
    1418             :     {
    1419             :         /* Try to estimate the number of rows returned */
    1420          54 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
    1421             : 
    1422          54 :         if (is_funcclause(req->node))    /* be paranoid */
    1423             :         {
    1424          54 :             List       *args = ((FuncExpr *) req->node)->args;
    1425             :             Node       *arg1,
    1426             :                        *arg2,
    1427             :                        *arg3;
    1428             : 
    1429             :             /* We can use estimated argument values here */
    1430          54 :             arg1 = estimate_expression_value(req->root, linitial(args));
    1431          54 :             arg2 = estimate_expression_value(req->root, lsecond(args));
    1432          54 :             if (list_length(args) >= 3)
    1433          14 :                 arg3 = estimate_expression_value(req->root, lthird(args));
    1434             :             else
    1435          40 :                 arg3 = NULL;
    1436             : 
    1437             :             /*
    1438             :              * If any argument is constant NULL, we can safely assume that
    1439             :              * zero rows are returned.  Otherwise, if they're all non-NULL
    1440             :              * constants, we can calculate the number of rows that will be
    1441             :              * returned.  Use double arithmetic to avoid overflow hazards.
    1442             :              */
    1443          54 :             if ((IsA(arg1, Const) &&
    1444          46 :                  ((Const *) arg1)->constisnull) ||
    1445          54 :                 (IsA(arg2, Const) &&
    1446          54 :                  ((Const *) arg2)->constisnull) ||
    1447          14 :                 (arg3 != NULL && IsA(arg3, Const) &&
    1448          14 :                  ((Const *) arg3)->constisnull))
    1449             :             {
    1450           0 :                 req->rows = 0;
    1451           0 :                 ret = (Node *) req;
    1452             :             }
    1453          54 :             else if (IsA(arg1, Const) &&
    1454          46 :                      IsA(arg2, Const) &&
    1455          14 :                      (arg3 == NULL || IsA(arg3, Const)))
    1456             :             {
    1457             :                 double      start,
    1458             :                             finish,
    1459             :                             step;
    1460             : 
    1461          34 :                 start = DatumGetInt64(((Const *) arg1)->constvalue);
    1462          34 :                 finish = DatumGetInt64(((Const *) arg2)->constvalue);
    1463          34 :                 step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
    1464             : 
    1465             :                 /* This equation works for either sign of step */
    1466          34 :                 if (step != 0)
    1467             :                 {
    1468          28 :                     req->rows = floor((finish - start + step) / step);
    1469          28 :                     ret = (Node *) req;
    1470             :                 }
    1471             :             }
    1472             :         }
    1473             :     }
    1474             : 
    1475         168 :     PG_RETURN_POINTER(ret);
    1476             : }

Generated by: LCOV version 1.16