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: 2024-03-29 02:11:11 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-2024, 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      130066 : int8in(PG_FUNCTION_ARGS)
      51             : {
      52      130066 :     char       *num = PG_GETARG_CSTRING(0);
      53             : 
      54      130066 :     PG_RETURN_INT64(pg_strtoint64_safe(num, fcinfo->context));
      55             : }
      56             : 
      57             : 
      58             : /* int8out()
      59             :  */
      60             : Datum
      61      302384 : int8out(PG_FUNCTION_ARGS)
      62             : {
      63      302384 :     int64       val = PG_GETARG_INT64(0);
      64             :     char        buf[MAXINT8LEN + 1];
      65             :     char       *result;
      66             :     int         len;
      67             : 
      68      302384 :     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      302384 :     result = palloc(len);
      75      302384 :     memcpy(result, buf, len);
      76      302384 :     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        4910 : int8send(PG_FUNCTION_ARGS)
      95             : {
      96        4910 :     int64       arg1 = PG_GETARG_INT64(0);
      97             :     StringInfoData buf;
      98             : 
      99        4910 :     pq_begintypsend(&buf);
     100        4910 :     pq_sendint64(&buf, arg1);
     101        4910 :     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      248828 : int8eq(PG_FUNCTION_ARGS)
     114             : {
     115      248828 :     int64       val1 = PG_GETARG_INT64(0);
     116      248828 :     int64       val2 = PG_GETARG_INT64(1);
     117             : 
     118      248828 :     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      422128 : int8lt(PG_FUNCTION_ARGS)
     132             : {
     133      422128 :     int64       val1 = PG_GETARG_INT64(0);
     134      422128 :     int64       val2 = PG_GETARG_INT64(1);
     135             : 
     136      422128 :     PG_RETURN_BOOL(val1 < val2);
     137             : }
     138             : 
     139             : Datum
     140      247014 : int8gt(PG_FUNCTION_ARGS)
     141             : {
     142      247014 :     int64       val1 = PG_GETARG_INT64(0);
     143      247014 :     int64       val2 = PG_GETARG_INT64(1);
     144             : 
     145      247014 :     PG_RETURN_BOOL(val1 > val2);
     146             : }
     147             : 
     148             : Datum
     149        5416 : int8le(PG_FUNCTION_ARGS)
     150             : {
     151        5416 :     int64       val1 = PG_GETARG_INT64(0);
     152        5416 :     int64       val2 = PG_GETARG_INT64(1);
     153             : 
     154        5416 :     PG_RETURN_BOOL(val1 <= val2);
     155             : }
     156             : 
     157             : Datum
     158        5646 : int8ge(PG_FUNCTION_ARGS)
     159             : {
     160        5646 :     int64       val1 = PG_GETARG_INT64(0);
     161        5646 :     int64       val2 = PG_GETARG_INT64(1);
     162             : 
     163        5646 :     PG_RETURN_BOOL(val1 >= val2);
     164             : }
     165             : 
     166             : /* int84relop()
     167             :  * Is 64-bit val1 relop 32-bit val2?
     168             :  */
     169             : Datum
     170      196000 : int84eq(PG_FUNCTION_ARGS)
     171             : {
     172      196000 :     int64       val1 = PG_GETARG_INT64(0);
     173      196000 :     int32       val2 = PG_GETARG_INT32(1);
     174             : 
     175      196000 :     PG_RETURN_BOOL(val1 == val2);
     176             : }
     177             : 
     178             : Datum
     179          76 : int84ne(PG_FUNCTION_ARGS)
     180             : {
     181          76 :     int64       val1 = PG_GETARG_INT64(0);
     182          76 :     int32       val2 = PG_GETARG_INT32(1);
     183             : 
     184          76 :     PG_RETURN_BOOL(val1 != val2);
     185             : }
     186             : 
     187             : Datum
     188      694522 : int84lt(PG_FUNCTION_ARGS)
     189             : {
     190      694522 :     int64       val1 = PG_GETARG_INT64(0);
     191      694522 :     int32       val2 = PG_GETARG_INT32(1);
     192             : 
     193      694522 :     PG_RETURN_BOOL(val1 < val2);
     194             : }
     195             : 
     196             : Datum
     197       80136 : int84gt(PG_FUNCTION_ARGS)
     198             : {
     199       80136 :     int64       val1 = PG_GETARG_INT64(0);
     200       80136 :     int32       val2 = PG_GETARG_INT32(1);
     201             : 
     202       80136 :     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       10024 : int84ge(PG_FUNCTION_ARGS)
     216             : {
     217       10024 :     int64       val1 = PG_GETARG_INT64(0);
     218       10024 :     int32       val2 = PG_GETARG_INT32(1);
     219             : 
     220       10024 :     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        6444 : int48lt(PG_FUNCTION_ARGS)
     246             : {
     247        6444 :     int32       val1 = PG_GETARG_INT32(0);
     248        6444 :     int64       val2 = PG_GETARG_INT64(1);
     249             : 
     250        6444 :     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        1848 : int28eq(PG_FUNCTION_ARGS)
     342             : {
     343        1848 :     int16       val1 = PG_GETARG_INT16(0);
     344        1848 :     int64       val2 = PG_GETARG_INT64(1);
     345             : 
     346        1848 :     PG_RETURN_BOOL(val1 == val2);
     347             : }
     348             : 
     349             : Datum
     350        3228 : int28ne(PG_FUNCTION_ARGS)
     351             : {
     352        3228 :     int16       val1 = PG_GETARG_INT16(0);
     353        3228 :     int64       val2 = PG_GETARG_INT64(1);
     354             : 
     355        3228 :     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         900 : int8um(PG_FUNCTION_ARGS)
     441             : {
     442         900 :     int64       arg = PG_GETARG_INT64(0);
     443             :     int64       result;
     444             : 
     445         900 :     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         894 :     result = -arg;
     450         894 :     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      129108 : int8pl(PG_FUNCTION_ARGS)
     463             : {
     464      129108 :     int64       arg1 = PG_GETARG_INT64(0);
     465      129108 :     int64       arg2 = PG_GETARG_INT64(1);
     466             :     int64       result;
     467             : 
     468      129108 :     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      129096 :     PG_RETURN_INT64(result);
     473             : }
     474             : 
     475             : Datum
     476          96 : int8mi(PG_FUNCTION_ARGS)
     477             : {
     478          96 :     int64       arg1 = PG_GETARG_INT64(0);
     479          96 :     int64       arg2 = PG_GETARG_INT64(1);
     480             :     int64       result;
     481             : 
     482          96 :     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          78 :     PG_RETURN_INT64(result);
     487             : }
     488             : 
     489             : Datum
     490         174 : int8mul(PG_FUNCTION_ARGS)
     491             : {
     492         174 :     int64       arg1 = PG_GETARG_INT64(0);
     493         174 :     int64       arg2 = PG_GETARG_INT64(1);
     494             :     int64       result;
     495             : 
     496         174 :     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         156 :     PG_RETURN_INT64(result);
     501             : }
     502             : 
     503             : Datum
     504         126 : int8div(PG_FUNCTION_ARGS)
     505             : {
     506         126 :     int64       arg1 = PG_GETARG_INT64(0);
     507         126 :     int64       arg2 = PG_GETARG_INT64(1);
     508             :     int64       result;
     509             : 
     510         126 :     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         120 :     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         114 :     result = arg1 / arg2;
     538             : 
     539         114 :     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    17947768 : int8inc(PG_FUNCTION_ARGS)
     720             : {
     721             :     /*
     722             :      * When int8 is pass-by-reference, we provide this special case to avoid
     723             :      * palloc overhead for COUNT(): when called as an aggregate, we know that
     724             :      * the argument is modifiable local storage, so just update it in-place.
     725             :      * (If int8 is pass-by-value, then of course this is useless as well as
     726             :      * incorrect, so just ifdef it out.)
     727             :      */
     728             : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
     729             :     if (AggCheckCallContext(fcinfo, NULL))
     730             :     {
     731             :         int64      *arg = (int64 *) PG_GETARG_POINTER(0);
     732             : 
     733             :         if (unlikely(pg_add_s64_overflow(*arg, 1, arg)))
     734             :             ereport(ERROR,
     735             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     736             :                      errmsg("bigint out of range")));
     737             : 
     738             :         PG_RETURN_POINTER(arg);
     739             :     }
     740             :     else
     741             : #endif
     742             :     {
     743             :         /* Not called as an aggregate, so just do it the dumb way */
     744    17947768 :         int64       arg = PG_GETARG_INT64(0);
     745             :         int64       result;
     746             : 
     747    17947768 :         if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
     748           0 :             ereport(ERROR,
     749             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     750             :                      errmsg("bigint out of range")));
     751             : 
     752    17947768 :         PG_RETURN_INT64(result);
     753             :     }
     754             : }
     755             : 
     756             : Datum
     757          24 : int8dec(PG_FUNCTION_ARGS)
     758             : {
     759             :     /*
     760             :      * When int8 is pass-by-reference, we provide this special case to avoid
     761             :      * palloc overhead for COUNT(): when called as an aggregate, we know that
     762             :      * the argument is modifiable local storage, so just update it in-place.
     763             :      * (If int8 is pass-by-value, then of course this is useless as well as
     764             :      * incorrect, so just ifdef it out.)
     765             :      */
     766             : #ifndef USE_FLOAT8_BYVAL        /* controls int8 too */
     767             :     if (AggCheckCallContext(fcinfo, NULL))
     768             :     {
     769             :         int64      *arg = (int64 *) PG_GETARG_POINTER(0);
     770             : 
     771             :         if (unlikely(pg_sub_s64_overflow(*arg, 1, arg)))
     772             :             ereport(ERROR,
     773             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     774             :                      errmsg("bigint out of range")));
     775             :         PG_RETURN_POINTER(arg);
     776             :     }
     777             :     else
     778             : #endif
     779             :     {
     780             :         /* Not called as an aggregate, so just do it the dumb way */
     781          24 :         int64       arg = PG_GETARG_INT64(0);
     782             :         int64       result;
     783             : 
     784          24 :         if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
     785           0 :             ereport(ERROR,
     786             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     787             :                      errmsg("bigint out of range")));
     788             : 
     789          24 :         PG_RETURN_INT64(result);
     790             :     }
     791             : }
     792             : 
     793             : 
     794             : /*
     795             :  * These functions are exactly like int8inc/int8dec but are used for
     796             :  * aggregates that count only non-null values.  Since the functions are
     797             :  * declared strict, the null checks happen before we ever get here, and all we
     798             :  * need do is increment the state value.  We could actually make these pg_proc
     799             :  * entries point right at int8inc/int8dec, but then the opr_sanity regression
     800             :  * test would complain about mismatched entries for a built-in function.
     801             :  */
     802             : 
     803             : Datum
     804     1187742 : int8inc_any(PG_FUNCTION_ARGS)
     805             : {
     806     1187742 :     return int8inc(fcinfo);
     807             : }
     808             : 
     809             : Datum
     810      240024 : int8inc_float8_float8(PG_FUNCTION_ARGS)
     811             : {
     812      240024 :     return int8inc(fcinfo);
     813             : }
     814             : 
     815             : Datum
     816           6 : int8dec_any(PG_FUNCTION_ARGS)
     817             : {
     818           6 :     return int8dec(fcinfo);
     819             : }
     820             : 
     821             : /*
     822             :  * int8inc_support
     823             :  *      prosupport function for int8inc() and int8inc_any()
     824             :  */
     825             : Datum
     826         584 : int8inc_support(PG_FUNCTION_ARGS)
     827             : {
     828         584 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
     829             : 
     830         584 :     if (IsA(rawreq, SupportRequestWFuncMonotonic))
     831             :     {
     832          78 :         SupportRequestWFuncMonotonic *req = (SupportRequestWFuncMonotonic *) rawreq;
     833          78 :         MonotonicFunction monotonic = MONOTONICFUNC_NONE;
     834          78 :         int         frameOptions = req->window_clause->frameOptions;
     835             : 
     836             :         /* No ORDER BY clause then all rows are peers */
     837          78 :         if (req->window_clause->orderClause == NIL)
     838          24 :             monotonic = MONOTONICFUNC_BOTH;
     839             :         else
     840             :         {
     841             :             /*
     842             :              * Otherwise take into account the frame options.  When the frame
     843             :              * bound is the start of the window then the resulting value can
     844             :              * never decrease, therefore is monotonically increasing
     845             :              */
     846          54 :             if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
     847          42 :                 monotonic |= MONOTONICFUNC_INCREASING;
     848             : 
     849             :             /*
     850             :              * Likewise, if the frame bound is the end of the window then the
     851             :              * resulting value can never decrease.
     852             :              */
     853          54 :             if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
     854          12 :                 monotonic |= MONOTONICFUNC_DECREASING;
     855             :         }
     856             : 
     857          78 :         req->monotonic = monotonic;
     858          78 :         PG_RETURN_POINTER(req);
     859             :     }
     860             : 
     861         506 :     PG_RETURN_POINTER(NULL);
     862             : }
     863             : 
     864             : 
     865             : Datum
     866         642 : int8larger(PG_FUNCTION_ARGS)
     867             : {
     868         642 :     int64       arg1 = PG_GETARG_INT64(0);
     869         642 :     int64       arg2 = PG_GETARG_INT64(1);
     870             :     int64       result;
     871             : 
     872         642 :     result = ((arg1 > arg2) ? arg1 : arg2);
     873             : 
     874         642 :     PG_RETURN_INT64(result);
     875             : }
     876             : 
     877             : Datum
     878        8730 : int8smaller(PG_FUNCTION_ARGS)
     879             : {
     880        8730 :     int64       arg1 = PG_GETARG_INT64(0);
     881        8730 :     int64       arg2 = PG_GETARG_INT64(1);
     882             :     int64       result;
     883             : 
     884        8730 :     result = ((arg1 < arg2) ? arg1 : arg2);
     885             : 
     886        8730 :     PG_RETURN_INT64(result);
     887             : }
     888             : 
     889             : Datum
     890        4842 : int84pl(PG_FUNCTION_ARGS)
     891             : {
     892        4842 :     int64       arg1 = PG_GETARG_INT64(0);
     893        4842 :     int32       arg2 = PG_GETARG_INT32(1);
     894             :     int64       result;
     895             : 
     896        4842 :     if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
     897           6 :         ereport(ERROR,
     898             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     899             :                  errmsg("bigint out of range")));
     900        4836 :     PG_RETURN_INT64(result);
     901             : }
     902             : 
     903             : Datum
     904         122 : int84mi(PG_FUNCTION_ARGS)
     905             : {
     906         122 :     int64       arg1 = PG_GETARG_INT64(0);
     907         122 :     int32       arg2 = PG_GETARG_INT32(1);
     908             :     int64       result;
     909             : 
     910         122 :     if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
     911           6 :         ereport(ERROR,
     912             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     913             :                  errmsg("bigint out of range")));
     914         116 :     PG_RETURN_INT64(result);
     915             : }
     916             : 
     917             : Datum
     918        2186 : int84mul(PG_FUNCTION_ARGS)
     919             : {
     920        2186 :     int64       arg1 = PG_GETARG_INT64(0);
     921        2186 :     int32       arg2 = PG_GETARG_INT32(1);
     922             :     int64       result;
     923             : 
     924        2186 :     if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
     925          12 :         ereport(ERROR,
     926             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     927             :                  errmsg("bigint out of range")));
     928        2174 :     PG_RETURN_INT64(result);
     929             : }
     930             : 
     931             : Datum
     932         180 : int84div(PG_FUNCTION_ARGS)
     933             : {
     934         180 :     int64       arg1 = PG_GETARG_INT64(0);
     935         180 :     int32       arg2 = PG_GETARG_INT32(1);
     936             :     int64       result;
     937             : 
     938         180 :     if (arg2 == 0)
     939             :     {
     940           6 :         ereport(ERROR,
     941             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     942             :                  errmsg("division by zero")));
     943             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     944             :         PG_RETURN_NULL();
     945             :     }
     946             : 
     947             :     /*
     948             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
     949             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
     950             :      * produce zero, some throw an exception.  We can dodge the problem by
     951             :      * recognizing that division by -1 is the same as negation.
     952             :      */
     953         174 :     if (arg2 == -1)
     954             :     {
     955           6 :         if (unlikely(arg1 == PG_INT64_MIN))
     956           6 :             ereport(ERROR,
     957             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     958             :                      errmsg("bigint out of range")));
     959           0 :         result = -arg1;
     960           0 :         PG_RETURN_INT64(result);
     961             :     }
     962             : 
     963             :     /* No overflow is possible */
     964             : 
     965         168 :     result = arg1 / arg2;
     966             : 
     967         168 :     PG_RETURN_INT64(result);
     968             : }
     969             : 
     970             : Datum
     971        1226 : int48pl(PG_FUNCTION_ARGS)
     972             : {
     973        1226 :     int32       arg1 = PG_GETARG_INT32(0);
     974        1226 :     int64       arg2 = PG_GETARG_INT64(1);
     975             :     int64       result;
     976             : 
     977        1226 :     if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
     978           6 :         ereport(ERROR,
     979             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     980             :                  errmsg("bigint out of range")));
     981        1220 :     PG_RETURN_INT64(result);
     982             : }
     983             : 
     984             : Datum
     985          66 : int48mi(PG_FUNCTION_ARGS)
     986             : {
     987          66 :     int32       arg1 = PG_GETARG_INT32(0);
     988          66 :     int64       arg2 = PG_GETARG_INT64(1);
     989             :     int64       result;
     990             : 
     991          66 :     if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
     992           6 :         ereport(ERROR,
     993             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     994             :                  errmsg("bigint out of range")));
     995          60 :     PG_RETURN_INT64(result);
     996             : }
     997             : 
     998             : Datum
     999         222 : int48mul(PG_FUNCTION_ARGS)
    1000             : {
    1001         222 :     int32       arg1 = PG_GETARG_INT32(0);
    1002         222 :     int64       arg2 = PG_GETARG_INT64(1);
    1003             :     int64       result;
    1004             : 
    1005         222 :     if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
    1006           6 :         ereport(ERROR,
    1007             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1008             :                  errmsg("bigint out of range")));
    1009         216 :     PG_RETURN_INT64(result);
    1010             : }
    1011             : 
    1012             : Datum
    1013          36 : int48div(PG_FUNCTION_ARGS)
    1014             : {
    1015          36 :     int32       arg1 = PG_GETARG_INT32(0);
    1016          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1017             : 
    1018          36 :     if (unlikely(arg2 == 0))
    1019             :     {
    1020           6 :         ereport(ERROR,
    1021             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1022             :                  errmsg("division by zero")));
    1023             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1024             :         PG_RETURN_NULL();
    1025             :     }
    1026             : 
    1027             :     /* No overflow is possible */
    1028          30 :     PG_RETURN_INT64((int64) arg1 / arg2);
    1029             : }
    1030             : 
    1031             : Datum
    1032          36 : int82pl(PG_FUNCTION_ARGS)
    1033             : {
    1034          36 :     int64       arg1 = PG_GETARG_INT64(0);
    1035          36 :     int16       arg2 = PG_GETARG_INT16(1);
    1036             :     int64       result;
    1037             : 
    1038          36 :     if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
    1039           6 :         ereport(ERROR,
    1040             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1041             :                  errmsg("bigint out of range")));
    1042          30 :     PG_RETURN_INT64(result);
    1043             : }
    1044             : 
    1045             : Datum
    1046          36 : int82mi(PG_FUNCTION_ARGS)
    1047             : {
    1048          36 :     int64       arg1 = PG_GETARG_INT64(0);
    1049          36 :     int16       arg2 = PG_GETARG_INT16(1);
    1050             :     int64       result;
    1051             : 
    1052          36 :     if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
    1053           6 :         ereport(ERROR,
    1054             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1055             :                  errmsg("bigint out of range")));
    1056          30 :     PG_RETURN_INT64(result);
    1057             : }
    1058             : 
    1059             : Datum
    1060          42 : int82mul(PG_FUNCTION_ARGS)
    1061             : {
    1062          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1063          42 :     int16       arg2 = PG_GETARG_INT16(1);
    1064             :     int64       result;
    1065             : 
    1066          42 :     if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
    1067          12 :         ereport(ERROR,
    1068             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1069             :                  errmsg("bigint out of range")));
    1070          30 :     PG_RETURN_INT64(result);
    1071             : }
    1072             : 
    1073             : Datum
    1074          42 : int82div(PG_FUNCTION_ARGS)
    1075             : {
    1076          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1077          42 :     int16       arg2 = PG_GETARG_INT16(1);
    1078             :     int64       result;
    1079             : 
    1080          42 :     if (unlikely(arg2 == 0))
    1081             :     {
    1082           6 :         ereport(ERROR,
    1083             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1084             :                  errmsg("division by zero")));
    1085             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1086             :         PG_RETURN_NULL();
    1087             :     }
    1088             : 
    1089             :     /*
    1090             :      * INT64_MIN / -1 is problematic, since the result can't be represented on
    1091             :      * a two's-complement machine.  Some machines produce INT64_MIN, some
    1092             :      * produce zero, some throw an exception.  We can dodge the problem by
    1093             :      * recognizing that division by -1 is the same as negation.
    1094             :      */
    1095          36 :     if (arg2 == -1)
    1096             :     {
    1097           6 :         if (unlikely(arg1 == PG_INT64_MIN))
    1098           6 :             ereport(ERROR,
    1099             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1100             :                      errmsg("bigint out of range")));
    1101           0 :         result = -arg1;
    1102           0 :         PG_RETURN_INT64(result);
    1103             :     }
    1104             : 
    1105             :     /* No overflow is possible */
    1106             : 
    1107          30 :     result = arg1 / arg2;
    1108             : 
    1109          30 :     PG_RETURN_INT64(result);
    1110             : }
    1111             : 
    1112             : Datum
    1113          36 : int28pl(PG_FUNCTION_ARGS)
    1114             : {
    1115          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1116          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1117             :     int64       result;
    1118             : 
    1119          36 :     if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
    1120           6 :         ereport(ERROR,
    1121             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1122             :                  errmsg("bigint out of range")));
    1123          30 :     PG_RETURN_INT64(result);
    1124             : }
    1125             : 
    1126             : Datum
    1127          36 : int28mi(PG_FUNCTION_ARGS)
    1128             : {
    1129          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1130          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1131             :     int64       result;
    1132             : 
    1133          36 :     if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
    1134           6 :         ereport(ERROR,
    1135             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1136             :                  errmsg("bigint out of range")));
    1137          30 :     PG_RETURN_INT64(result);
    1138             : }
    1139             : 
    1140             : Datum
    1141          36 : int28mul(PG_FUNCTION_ARGS)
    1142             : {
    1143          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1144          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1145             :     int64       result;
    1146             : 
    1147          36 :     if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
    1148           6 :         ereport(ERROR,
    1149             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1150             :                  errmsg("bigint out of range")));
    1151          30 :     PG_RETURN_INT64(result);
    1152             : }
    1153             : 
    1154             : Datum
    1155          36 : int28div(PG_FUNCTION_ARGS)
    1156             : {
    1157          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1158          36 :     int64       arg2 = PG_GETARG_INT64(1);
    1159             : 
    1160          36 :     if (unlikely(arg2 == 0))
    1161             :     {
    1162           6 :         ereport(ERROR,
    1163             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1164             :                  errmsg("division by zero")));
    1165             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1166             :         PG_RETURN_NULL();
    1167             :     }
    1168             : 
    1169             :     /* No overflow is possible */
    1170          30 :     PG_RETURN_INT64((int64) arg1 / arg2);
    1171             : }
    1172             : 
    1173             : /* Binary arithmetics
    1174             :  *
    1175             :  *      int8and     - returns arg1 & arg2
    1176             :  *      int8or      - returns arg1 | arg2
    1177             :  *      int8xor     - returns arg1 # arg2
    1178             :  *      int8not     - returns ~arg1
    1179             :  *      int8shl     - returns arg1 << arg2
    1180             :  *      int8shr     - returns arg1 >> arg2
    1181             :  */
    1182             : 
    1183             : Datum
    1184          42 : int8and(PG_FUNCTION_ARGS)
    1185             : {
    1186          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1187          42 :     int64       arg2 = PG_GETARG_INT64(1);
    1188             : 
    1189          42 :     PG_RETURN_INT64(arg1 & arg2);
    1190             : }
    1191             : 
    1192             : Datum
    1193          46 : int8or(PG_FUNCTION_ARGS)
    1194             : {
    1195          46 :     int64       arg1 = PG_GETARG_INT64(0);
    1196          46 :     int64       arg2 = PG_GETARG_INT64(1);
    1197             : 
    1198          46 :     PG_RETURN_INT64(arg1 | arg2);
    1199             : }
    1200             : 
    1201             : Datum
    1202          42 : int8xor(PG_FUNCTION_ARGS)
    1203             : {
    1204          42 :     int64       arg1 = PG_GETARG_INT64(0);
    1205          42 :     int64       arg2 = PG_GETARG_INT64(1);
    1206             : 
    1207          42 :     PG_RETURN_INT64(arg1 ^ arg2);
    1208             : }
    1209             : 
    1210             : Datum
    1211          30 : int8not(PG_FUNCTION_ARGS)
    1212             : {
    1213          30 :     int64       arg1 = PG_GETARG_INT64(0);
    1214             : 
    1215          30 :     PG_RETURN_INT64(~arg1);
    1216             : }
    1217             : 
    1218             : Datum
    1219          46 : int8shl(PG_FUNCTION_ARGS)
    1220             : {
    1221          46 :     int64       arg1 = PG_GETARG_INT64(0);
    1222          46 :     int32       arg2 = PG_GETARG_INT32(1);
    1223             : 
    1224          46 :     PG_RETURN_INT64(arg1 << arg2);
    1225             : }
    1226             : 
    1227             : Datum
    1228          30 : int8shr(PG_FUNCTION_ARGS)
    1229             : {
    1230          30 :     int64       arg1 = PG_GETARG_INT64(0);
    1231          30 :     int32       arg2 = PG_GETARG_INT32(1);
    1232             : 
    1233          30 :     PG_RETURN_INT64(arg1 >> arg2);
    1234             : }
    1235             : 
    1236             : /*----------------------------------------------------------
    1237             :  *  Conversion operators.
    1238             :  *---------------------------------------------------------*/
    1239             : 
    1240             : Datum
    1241     2553646 : int48(PG_FUNCTION_ARGS)
    1242             : {
    1243     2553646 :     int32       arg = PG_GETARG_INT32(0);
    1244             : 
    1245     2553646 :     PG_RETURN_INT64((int64) arg);
    1246             : }
    1247             : 
    1248             : Datum
    1249      222694 : int84(PG_FUNCTION_ARGS)
    1250             : {
    1251      222694 :     int64       arg = PG_GETARG_INT64(0);
    1252             : 
    1253      222694 :     if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
    1254           6 :         ereport(ERROR,
    1255             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1256             :                  errmsg("integer out of range")));
    1257             : 
    1258      222688 :     PG_RETURN_INT32((int32) arg);
    1259             : }
    1260             : 
    1261             : Datum
    1262          18 : int28(PG_FUNCTION_ARGS)
    1263             : {
    1264          18 :     int16       arg = PG_GETARG_INT16(0);
    1265             : 
    1266          18 :     PG_RETURN_INT64((int64) arg);
    1267             : }
    1268             : 
    1269             : Datum
    1270          36 : int82(PG_FUNCTION_ARGS)
    1271             : {
    1272          36 :     int64       arg = PG_GETARG_INT64(0);
    1273             : 
    1274          36 :     if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
    1275           6 :         ereport(ERROR,
    1276             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1277             :                  errmsg("smallint out of range")));
    1278             : 
    1279          30 :     PG_RETURN_INT16((int16) arg);
    1280             : }
    1281             : 
    1282             : Datum
    1283       12198 : i8tod(PG_FUNCTION_ARGS)
    1284             : {
    1285       12198 :     int64       arg = PG_GETARG_INT64(0);
    1286             :     float8      result;
    1287             : 
    1288       12198 :     result = arg;
    1289             : 
    1290       12198 :     PG_RETURN_FLOAT8(result);
    1291             : }
    1292             : 
    1293             : /* dtoi8()
    1294             :  * Convert float8 to 8-byte integer.
    1295             :  */
    1296             : Datum
    1297         138 : dtoi8(PG_FUNCTION_ARGS)
    1298             : {
    1299         138 :     float8      num = PG_GETARG_FLOAT8(0);
    1300             : 
    1301             :     /*
    1302             :      * Get rid of any fractional part in the input.  This is so we don't fail
    1303             :      * on just-out-of-range values that would round into range.  Note
    1304             :      * assumption that rint() will pass through a NaN or Inf unchanged.
    1305             :      */
    1306         138 :     num = rint(num);
    1307             : 
    1308             :     /* Range check */
    1309         138 :     if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
    1310          18 :         ereport(ERROR,
    1311             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1312             :                  errmsg("bigint out of range")));
    1313             : 
    1314         120 :     PG_RETURN_INT64((int64) num);
    1315             : }
    1316             : 
    1317             : Datum
    1318         150 : i8tof(PG_FUNCTION_ARGS)
    1319             : {
    1320         150 :     int64       arg = PG_GETARG_INT64(0);
    1321             :     float4      result;
    1322             : 
    1323         150 :     result = arg;
    1324             : 
    1325         150 :     PG_RETURN_FLOAT4(result);
    1326             : }
    1327             : 
    1328             : /* ftoi8()
    1329             :  * Convert float4 to 8-byte integer.
    1330             :  */
    1331             : Datum
    1332          30 : ftoi8(PG_FUNCTION_ARGS)
    1333             : {
    1334          30 :     float4      num = PG_GETARG_FLOAT4(0);
    1335             : 
    1336             :     /*
    1337             :      * Get rid of any fractional part in the input.  This is so we don't fail
    1338             :      * on just-out-of-range values that would round into range.  Note
    1339             :      * assumption that rint() will pass through a NaN or Inf unchanged.
    1340             :      */
    1341          30 :     num = rint(num);
    1342             : 
    1343             :     /* Range check */
    1344          30 :     if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
    1345          12 :         ereport(ERROR,
    1346             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1347             :                  errmsg("bigint out of range")));
    1348             : 
    1349          18 :     PG_RETURN_INT64((int64) num);
    1350             : }
    1351             : 
    1352             : Datum
    1353          20 : i8tooid(PG_FUNCTION_ARGS)
    1354             : {
    1355          20 :     int64       arg = PG_GETARG_INT64(0);
    1356             : 
    1357          20 :     if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
    1358           6 :         ereport(ERROR,
    1359             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1360             :                  errmsg("OID out of range")));
    1361             : 
    1362          14 :     PG_RETURN_OID((Oid) arg);
    1363             : }
    1364             : 
    1365             : Datum
    1366          22 : oidtoi8(PG_FUNCTION_ARGS)
    1367             : {
    1368          22 :     Oid         arg = PG_GETARG_OID(0);
    1369             : 
    1370          22 :     PG_RETURN_INT64((int64) arg);
    1371             : }
    1372             : 
    1373             : /*
    1374             :  * non-persistent numeric series generator
    1375             :  */
    1376             : Datum
    1377     2086648 : generate_series_int8(PG_FUNCTION_ARGS)
    1378             : {
    1379     2086648 :     return generate_series_step_int8(fcinfo);
    1380             : }
    1381             : 
    1382             : Datum
    1383     2086794 : generate_series_step_int8(PG_FUNCTION_ARGS)
    1384             : {
    1385             :     FuncCallContext *funcctx;
    1386             :     generate_series_fctx *fctx;
    1387             :     int64       result;
    1388             :     MemoryContext oldcontext;
    1389             : 
    1390             :     /* stuff done only on the first call of the function */
    1391     2086794 :     if (SRF_IS_FIRSTCALL())
    1392             :     {
    1393          60 :         int64       start = PG_GETARG_INT64(0);
    1394          60 :         int64       finish = PG_GETARG_INT64(1);
    1395          60 :         int64       step = 1;
    1396             : 
    1397             :         /* see if we were given an explicit step size */
    1398          60 :         if (PG_NARGS() == 3)
    1399          14 :             step = PG_GETARG_INT64(2);
    1400          60 :         if (step == 0)
    1401           6 :             ereport(ERROR,
    1402             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1403             :                      errmsg("step size cannot equal zero")));
    1404             : 
    1405             :         /* create a function context for cross-call persistence */
    1406          54 :         funcctx = SRF_FIRSTCALL_INIT();
    1407             : 
    1408             :         /*
    1409             :          * switch to memory context appropriate for multiple function calls
    1410             :          */
    1411          54 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1412             : 
    1413             :         /* allocate memory for user context */
    1414          54 :         fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
    1415             : 
    1416             :         /*
    1417             :          * Use fctx to keep state from call to call. Seed current with the
    1418             :          * original start value
    1419             :          */
    1420          54 :         fctx->current = start;
    1421          54 :         fctx->finish = finish;
    1422          54 :         fctx->step = step;
    1423             : 
    1424          54 :         funcctx->user_fctx = fctx;
    1425          54 :         MemoryContextSwitchTo(oldcontext);
    1426             :     }
    1427             : 
    1428             :     /* stuff done on every call of the function */
    1429     2086788 :     funcctx = SRF_PERCALL_SETUP();
    1430             : 
    1431             :     /*
    1432             :      * get the saved state and use current as the result for this iteration
    1433             :      */
    1434     2086788 :     fctx = funcctx->user_fctx;
    1435     2086788 :     result = fctx->current;
    1436             : 
    1437     2086788 :     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
    1438          52 :         (fctx->step < 0 && fctx->current >= fctx->finish))
    1439             :     {
    1440             :         /*
    1441             :          * Increment current in preparation for next iteration. If next-value
    1442             :          * computation overflows, this is the final result.
    1443             :          */
    1444     2086736 :         if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
    1445           0 :             fctx->step = 0;
    1446             : 
    1447             :         /* do when there is more left to send */
    1448     2086736 :         SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
    1449             :     }
    1450             :     else
    1451             :         /* do when there is no more left */
    1452          52 :         SRF_RETURN_DONE(funcctx);
    1453             : }
    1454             : 
    1455             : /*
    1456             :  * Planner support function for generate_series(int8, int8 [, int8])
    1457             :  */
    1458             : Datum
    1459         150 : generate_series_int8_support(PG_FUNCTION_ARGS)
    1460             : {
    1461         150 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1462         150 :     Node       *ret = NULL;
    1463             : 
    1464         150 :     if (IsA(rawreq, SupportRequestRows))
    1465             :     {
    1466             :         /* Try to estimate the number of rows returned */
    1467          48 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
    1468             : 
    1469          48 :         if (is_funcclause(req->node))    /* be paranoid */
    1470             :         {
    1471          48 :             List       *args = ((FuncExpr *) req->node)->args;
    1472             :             Node       *arg1,
    1473             :                        *arg2,
    1474             :                        *arg3;
    1475             : 
    1476             :             /* We can use estimated argument values here */
    1477          48 :             arg1 = estimate_expression_value(req->root, linitial(args));
    1478          48 :             arg2 = estimate_expression_value(req->root, lsecond(args));
    1479          48 :             if (list_length(args) >= 3)
    1480          14 :                 arg3 = estimate_expression_value(req->root, lthird(args));
    1481             :             else
    1482          34 :                 arg3 = NULL;
    1483             : 
    1484             :             /*
    1485             :              * If any argument is constant NULL, we can safely assume that
    1486             :              * zero rows are returned.  Otherwise, if they're all non-NULL
    1487             :              * constants, we can calculate the number of rows that will be
    1488             :              * returned.  Use double arithmetic to avoid overflow hazards.
    1489             :              */
    1490          48 :             if ((IsA(arg1, Const) &&
    1491          40 :                  ((Const *) arg1)->constisnull) ||
    1492          48 :                 (IsA(arg2, Const) &&
    1493          48 :                  ((Const *) arg2)->constisnull) ||
    1494          14 :                 (arg3 != NULL && IsA(arg3, Const) &&
    1495          14 :                  ((Const *) arg3)->constisnull))
    1496             :             {
    1497           0 :                 req->rows = 0;
    1498           0 :                 ret = (Node *) req;
    1499             :             }
    1500          48 :             else if (IsA(arg1, Const) &&
    1501          40 :                      IsA(arg2, Const) &&
    1502          14 :                      (arg3 == NULL || IsA(arg3, Const)))
    1503             :             {
    1504             :                 double      start,
    1505             :                             finish,
    1506             :                             step;
    1507             : 
    1508          34 :                 start = DatumGetInt64(((Const *) arg1)->constvalue);
    1509          34 :                 finish = DatumGetInt64(((Const *) arg2)->constvalue);
    1510          34 :                 step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
    1511             : 
    1512             :                 /* This equation works for either sign of step */
    1513          34 :                 if (step != 0)
    1514             :                 {
    1515          28 :                     req->rows = floor((finish - start + step) / step);
    1516          28 :                     ret = (Node *) req;
    1517             :                 }
    1518             :             }
    1519             :         }
    1520             :     }
    1521             : 
    1522         150 :     PG_RETURN_POINTER(ret);
    1523             : }

Generated by: LCOV version 1.14