LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - int8.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 97.7 % 517 505 12 1 504 1
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 89 89 1 88
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a