LCOV - code coverage report
Current view: top level - src/backend/utils/adt - int.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 86.7 % 594 515
Test Date: 2026-02-17 17:20:33 Functions: 87.4 % 95 83
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * int.c
       4              :  *    Functions for the built-in integer types (except int8).
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  *
      10              :  * IDENTIFICATION
      11              :  *    src/backend/utils/adt/int.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : /*
      16              :  * OLD COMMENTS
      17              :  *      I/O routines:
      18              :  *       int2in, int2out, int2recv, int2send
      19              :  *       int4in, int4out, int4recv, int4send
      20              :  *       int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
      21              :  *      Boolean operators:
      22              :  *       inteq, intne, intlt, intle, intgt, intge
      23              :  *      Arithmetic operators:
      24              :  *       intpl, intmi, int4mul, intdiv
      25              :  *
      26              :  *      Arithmetic operators:
      27              :  *       intmod
      28              :  */
      29              : #include "postgres.h"
      30              : 
      31              : #include <ctype.h>
      32              : #include <limits.h>
      33              : #include <math.h>
      34              : 
      35              : #include "catalog/pg_type.h"
      36              : #include "common/int.h"
      37              : #include "funcapi.h"
      38              : #include "libpq/pqformat.h"
      39              : #include "nodes/nodeFuncs.h"
      40              : #include "nodes/supportnodes.h"
      41              : #include "optimizer/optimizer.h"
      42              : #include "utils/array.h"
      43              : #include "utils/builtins.h"
      44              : 
      45              : #define Int2VectorSize(n)   (offsetof(int2vector, values) + (n) * sizeof(int16))
      46              : 
      47              : typedef struct
      48              : {
      49              :     int32       current;
      50              :     int32       finish;
      51              :     int32       step;
      52              : } generate_series_fctx;
      53              : 
      54              : 
      55              : /*****************************************************************************
      56              :  *   USER I/O ROUTINES                                                       *
      57              :  *****************************************************************************/
      58              : 
      59              : /*
      60              :  *      int2in          - converts "num" to short
      61              :  */
      62              : Datum
      63       486029 : int2in(PG_FUNCTION_ARGS)
      64              : {
      65       486029 :     char       *num = PG_GETARG_CSTRING(0);
      66              : 
      67       486029 :     PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
      68              : }
      69              : 
      70              : /*
      71              :  *      int2out         - converts short to "num"
      72              :  */
      73              : Datum
      74       336989 : int2out(PG_FUNCTION_ARGS)
      75              : {
      76       336989 :     int16       arg1 = PG_GETARG_INT16(0);
      77       336989 :     char       *result = (char *) palloc(7);    /* sign, 5 digits, '\0' */
      78              : 
      79       336989 :     pg_itoa(arg1, result);
      80       336989 :     PG_RETURN_CSTRING(result);
      81              : }
      82              : 
      83              : /*
      84              :  *      int2recv            - converts external binary format to int2
      85              :  */
      86              : Datum
      87            0 : int2recv(PG_FUNCTION_ARGS)
      88              : {
      89            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      90              : 
      91            0 :     PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
      92              : }
      93              : 
      94              : /*
      95              :  *      int2send            - converts int2 to binary format
      96              :  */
      97              : Datum
      98            9 : int2send(PG_FUNCTION_ARGS)
      99              : {
     100            9 :     int16       arg1 = PG_GETARG_INT16(0);
     101              :     StringInfoData buf;
     102              : 
     103            9 :     pq_begintypsend(&buf);
     104            9 :     pq_sendint16(&buf, arg1);
     105            9 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     106              : }
     107              : 
     108              : /*
     109              :  * construct int2vector given a raw array of int2s
     110              :  *
     111              :  * If int2s is NULL then caller must fill values[] afterward
     112              :  */
     113              : int2vector *
     114        63519 : buildint2vector(const int16 *int2s, int n)
     115              : {
     116              :     int2vector *result;
     117              : 
     118        63519 :     result = (int2vector *) palloc0(Int2VectorSize(n));
     119              : 
     120        63519 :     if (n > 0 && int2s)
     121        29867 :         memcpy(result->values, int2s, n * sizeof(int16));
     122              : 
     123              :     /*
     124              :      * Attach standard array header.  For historical reasons, we set the index
     125              :      * lower bound to 0 not 1.
     126              :      */
     127        63519 :     SET_VARSIZE(result, Int2VectorSize(n));
     128        63519 :     result->ndim = 1;
     129        63519 :     result->dataoffset = 0;      /* never any nulls */
     130        63519 :     result->elemtype = INT2OID;
     131        63519 :     result->dim1 = n;
     132        63519 :     result->lbound1 = 0;
     133              : 
     134        63519 :     return result;
     135              : }
     136              : 
     137              : /*
     138              :  * validate that an array object meets the restrictions of int2vector
     139              :  *
     140              :  * We need this because there are pathways by which a general int2[] array can
     141              :  * be cast to int2vector, allowing the type's restrictions to be violated.
     142              :  * All code that receives an int2vector as a SQL parameter should check this.
     143              :  */
     144              : static void
     145         7094 : check_valid_int2vector(const int2vector *int2Array)
     146              : {
     147              :     /*
     148              :      * We insist on ndim == 1 and dataoffset == 0 (that is, no nulls) because
     149              :      * otherwise the array's layout will not be what calling code expects.  We
     150              :      * needn't be picky about the index lower bound though.  Checking elemtype
     151              :      * is just paranoia.
     152              :      */
     153         7094 :     if (int2Array->ndim != 1 ||
     154         7091 :         int2Array->dataoffset != 0 ||
     155         7091 :         int2Array->elemtype != INT2OID)
     156            3 :         ereport(ERROR,
     157              :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     158              :                  errmsg("array is not a valid int2vector")));
     159         7091 : }
     160              : 
     161              : /*
     162              :  *      int2vectorin            - converts "num num ..." to internal form
     163              :  */
     164              : Datum
     165          369 : int2vectorin(PG_FUNCTION_ARGS)
     166              : {
     167          369 :     char       *intString = PG_GETARG_CSTRING(0);
     168          369 :     Node       *escontext = fcinfo->context;
     169              :     int2vector *result;
     170              :     int         nalloc;
     171              :     int         n;
     172              : 
     173          369 :     nalloc = 32;                /* arbitrary initial size guess */
     174          369 :     result = (int2vector *) palloc0(Int2VectorSize(nalloc));
     175              : 
     176          369 :     for (n = 0;; n++)
     177          679 :     {
     178              :         long        l;
     179              :         char       *endp;
     180              : 
     181         1373 :         while (*intString && isspace((unsigned char) *intString))
     182          325 :             intString++;
     183         1048 :         if (*intString == '\0')
     184          363 :             break;
     185              : 
     186          685 :         if (n >= nalloc)
     187              :         {
     188            0 :             nalloc *= 2;
     189            0 :             result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
     190              :         }
     191              : 
     192          685 :         errno = 0;
     193          685 :         l = strtol(intString, &endp, 10);
     194              : 
     195          685 :         if (intString == endp)
     196            6 :             ereturn(escontext, (Datum) 0,
     197              :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     198              :                      errmsg("invalid input syntax for type %s: \"%s\"",
     199              :                             "smallint", intString)));
     200              : 
     201          682 :         if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
     202            3 :             ereturn(escontext, (Datum) 0,
     203              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     204              :                      errmsg("value \"%s\" is out of range for type %s", intString,
     205              :                             "smallint")));
     206              : 
     207          679 :         if (*endp && *endp != ' ')
     208            0 :             ereturn(escontext, (Datum) 0,
     209              :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     210              :                      errmsg("invalid input syntax for type %s: \"%s\"",
     211              :                             "smallint", intString)));
     212              : 
     213          679 :         result->values[n] = l;
     214          679 :         intString = endp;
     215              :     }
     216              : 
     217          363 :     SET_VARSIZE(result, Int2VectorSize(n));
     218          363 :     result->ndim = 1;
     219          363 :     result->dataoffset = 0;      /* never any nulls */
     220          363 :     result->elemtype = INT2OID;
     221          363 :     result->dim1 = n;
     222          363 :     result->lbound1 = 0;
     223              : 
     224          363 :     PG_RETURN_POINTER(result);
     225              : }
     226              : 
     227              : /*
     228              :  *      int2vectorout       - converts internal form to "num num ..."
     229              :  */
     230              : Datum
     231         7094 : int2vectorout(PG_FUNCTION_ARGS)
     232              : {
     233         7094 :     int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
     234              :     int         num,
     235              :                 nnums;
     236              :     char       *rp;
     237              :     char       *result;
     238              : 
     239              :     /* validate input before fetching dim1 */
     240         7094 :     check_valid_int2vector(int2Array);
     241         7091 :     nnums = int2Array->dim1;
     242              : 
     243              :     /* assumes sign, 5 digits, ' ' */
     244         7091 :     rp = result = (char *) palloc(nnums * 7 + 1);
     245        18423 :     for (num = 0; num < nnums; num++)
     246              :     {
     247        11332 :         if (num != 0)
     248         4736 :             *rp++ = ' ';
     249        11332 :         rp += pg_itoa(int2Array->values[num], rp);
     250              :     }
     251         7091 :     *rp = '\0';
     252         7091 :     PG_RETURN_CSTRING(result);
     253              : }
     254              : 
     255              : /*
     256              :  *      int2vectorrecv          - converts external binary format to int2vector
     257              :  */
     258              : Datum
     259            0 : int2vectorrecv(PG_FUNCTION_ARGS)
     260              : {
     261            0 :     LOCAL_FCINFO(locfcinfo, 3);
     262            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     263              :     int2vector *result;
     264              : 
     265              :     /*
     266              :      * Normally one would call array_recv() using DirectFunctionCall3, but
     267              :      * that does not work since array_recv wants to cache some data using
     268              :      * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
     269              :      * parameter.
     270              :      */
     271            0 :     InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
     272              :                              InvalidOid, NULL, NULL);
     273              : 
     274            0 :     locfcinfo->args[0].value = PointerGetDatum(buf);
     275            0 :     locfcinfo->args[0].isnull = false;
     276            0 :     locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID);
     277            0 :     locfcinfo->args[1].isnull = false;
     278            0 :     locfcinfo->args[2].value = Int32GetDatum(-1);
     279            0 :     locfcinfo->args[2].isnull = false;
     280              : 
     281            0 :     result = (int2vector *) DatumGetPointer(array_recv(locfcinfo));
     282              : 
     283              :     Assert(!locfcinfo->isnull);
     284              : 
     285              :     /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
     286            0 :     if (ARR_NDIM(result) != 1 ||
     287            0 :         ARR_HASNULL(result) ||
     288            0 :         ARR_ELEMTYPE(result) != INT2OID ||
     289            0 :         ARR_LBOUND(result)[0] != 0)
     290            0 :         ereport(ERROR,
     291              :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     292              :                  errmsg("invalid int2vector data")));
     293              : 
     294            0 :     PG_RETURN_POINTER(result);
     295              : }
     296              : 
     297              : /*
     298              :  *      int2vectorsend          - converts int2vector to binary format
     299              :  */
     300              : Datum
     301            0 : int2vectorsend(PG_FUNCTION_ARGS)
     302              : {
     303              :     /* We don't do check_valid_int2vector, since array_send won't care */
     304            0 :     return array_send(fcinfo);
     305              : }
     306              : 
     307              : 
     308              : /*****************************************************************************
     309              :  *   PUBLIC ROUTINES                                                         *
     310              :  *****************************************************************************/
     311              : 
     312              : /*
     313              :  *      int4in          - converts "num" to int4
     314              :  */
     315              : Datum
     316      2229989 : int4in(PG_FUNCTION_ARGS)
     317              : {
     318      2229989 :     char       *num = PG_GETARG_CSTRING(0);
     319              : 
     320      2229989 :     PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
     321              : }
     322              : 
     323              : /*
     324              :  *      int4out         - converts int4 to "num"
     325              :  */
     326              : Datum
     327      8851159 : int4out(PG_FUNCTION_ARGS)
     328              : {
     329      8851159 :     int32       arg1 = PG_GETARG_INT32(0);
     330      8851159 :     char       *result = (char *) palloc(12);   /* sign, 10 digits, '\0' */
     331              : 
     332      8851159 :     pg_ltoa(arg1, result);
     333      8851159 :     PG_RETURN_CSTRING(result);
     334              : }
     335              : 
     336              : /*
     337              :  *      int4recv            - converts external binary format to int4
     338              :  */
     339              : Datum
     340       101646 : int4recv(PG_FUNCTION_ARGS)
     341              : {
     342       101646 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     343              : 
     344       101646 :     PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
     345              : }
     346              : 
     347              : /*
     348              :  *      int4send            - converts int4 to binary format
     349              :  */
     350              : Datum
     351       104560 : int4send(PG_FUNCTION_ARGS)
     352              : {
     353       104560 :     int32       arg1 = PG_GETARG_INT32(0);
     354              :     StringInfoData buf;
     355              : 
     356       104560 :     pq_begintypsend(&buf);
     357       104560 :     pq_sendint32(&buf, arg1);
     358       104560 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     359              : }
     360              : 
     361              : 
     362              : /*
     363              :  *      ===================
     364              :  *      CONVERSION ROUTINES
     365              :  *      ===================
     366              :  */
     367              : 
     368              : Datum
     369        18112 : i2toi4(PG_FUNCTION_ARGS)
     370              : {
     371        18112 :     int16       arg1 = PG_GETARG_INT16(0);
     372              : 
     373        18112 :     PG_RETURN_INT32((int32) arg1);
     374              : }
     375              : 
     376              : Datum
     377        11628 : i4toi2(PG_FUNCTION_ARGS)
     378              : {
     379        11628 :     int32       arg1 = PG_GETARG_INT32(0);
     380              : 
     381        11628 :     if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
     382           14 :         ereport(ERROR,
     383              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     384              :                  errmsg("smallint out of range")));
     385              : 
     386        11614 :     PG_RETURN_INT16((int16) arg1);
     387              : }
     388              : 
     389              : /* Cast int4 -> bool */
     390              : Datum
     391           15 : int4_bool(PG_FUNCTION_ARGS)
     392              : {
     393           15 :     if (PG_GETARG_INT32(0) == 0)
     394            6 :         PG_RETURN_BOOL(false);
     395              :     else
     396            9 :         PG_RETURN_BOOL(true);
     397              : }
     398              : 
     399              : /* Cast bool -> int4 */
     400              : Datum
     401          897 : bool_int4(PG_FUNCTION_ARGS)
     402              : {
     403          897 :     if (PG_GETARG_BOOL(0) == false)
     404          519 :         PG_RETURN_INT32(0);
     405              :     else
     406          378 :         PG_RETURN_INT32(1);
     407              : }
     408              : 
     409              : /*
     410              :  *      ============================
     411              :  *      COMPARISON OPERATOR ROUTINES
     412              :  *      ============================
     413              :  */
     414              : 
     415              : /*
     416              :  *      inteq           - returns 1 iff arg1 == arg2
     417              :  *      intne           - returns 1 iff arg1 != arg2
     418              :  *      intlt           - returns 1 iff arg1 < arg2
     419              :  *      intle           - returns 1 iff arg1 <= arg2
     420              :  *      intgt           - returns 1 iff arg1 > arg2
     421              :  *      intge           - returns 1 iff arg1 >= arg2
     422              :  */
     423              : 
     424              : Datum
     425     18966060 : int4eq(PG_FUNCTION_ARGS)
     426              : {
     427     18966060 :     int32       arg1 = PG_GETARG_INT32(0);
     428     18966060 :     int32       arg2 = PG_GETARG_INT32(1);
     429              : 
     430     18966060 :     PG_RETURN_BOOL(arg1 == arg2);
     431              : }
     432              : 
     433              : Datum
     434       203135 : int4ne(PG_FUNCTION_ARGS)
     435              : {
     436       203135 :     int32       arg1 = PG_GETARG_INT32(0);
     437       203135 :     int32       arg2 = PG_GETARG_INT32(1);
     438              : 
     439       203135 :     PG_RETURN_BOOL(arg1 != arg2);
     440              : }
     441              : 
     442              : Datum
     443      4334386 : int4lt(PG_FUNCTION_ARGS)
     444              : {
     445      4334386 :     int32       arg1 = PG_GETARG_INT32(0);
     446      4334386 :     int32       arg2 = PG_GETARG_INT32(1);
     447              : 
     448      4334386 :     PG_RETURN_BOOL(arg1 < arg2);
     449              : }
     450              : 
     451              : Datum
     452       694369 : int4le(PG_FUNCTION_ARGS)
     453              : {
     454       694369 :     int32       arg1 = PG_GETARG_INT32(0);
     455       694369 :     int32       arg2 = PG_GETARG_INT32(1);
     456              : 
     457       694369 :     PG_RETURN_BOOL(arg1 <= arg2);
     458              : }
     459              : 
     460              : Datum
     461      1933263 : int4gt(PG_FUNCTION_ARGS)
     462              : {
     463      1933263 :     int32       arg1 = PG_GETARG_INT32(0);
     464      1933263 :     int32       arg2 = PG_GETARG_INT32(1);
     465              : 
     466      1933263 :     PG_RETURN_BOOL(arg1 > arg2);
     467              : }
     468              : 
     469              : Datum
     470       367262 : int4ge(PG_FUNCTION_ARGS)
     471              : {
     472       367262 :     int32       arg1 = PG_GETARG_INT32(0);
     473       367262 :     int32       arg2 = PG_GETARG_INT32(1);
     474              : 
     475       367262 :     PG_RETURN_BOOL(arg1 >= arg2);
     476              : }
     477              : 
     478              : Datum
     479      1582620 : int2eq(PG_FUNCTION_ARGS)
     480              : {
     481      1582620 :     int16       arg1 = PG_GETARG_INT16(0);
     482      1582620 :     int16       arg2 = PG_GETARG_INT16(1);
     483              : 
     484      1582620 :     PG_RETURN_BOOL(arg1 == arg2);
     485              : }
     486              : 
     487              : Datum
     488        15901 : int2ne(PG_FUNCTION_ARGS)
     489              : {
     490        15901 :     int16       arg1 = PG_GETARG_INT16(0);
     491        15901 :     int16       arg2 = PG_GETARG_INT16(1);
     492              : 
     493        15901 :     PG_RETURN_BOOL(arg1 != arg2);
     494              : }
     495              : 
     496              : Datum
     497       362689 : int2lt(PG_FUNCTION_ARGS)
     498              : {
     499       362689 :     int16       arg1 = PG_GETARG_INT16(0);
     500       362689 :     int16       arg2 = PG_GETARG_INT16(1);
     501              : 
     502       362689 :     PG_RETURN_BOOL(arg1 < arg2);
     503              : }
     504              : 
     505              : Datum
     506         2401 : int2le(PG_FUNCTION_ARGS)
     507              : {
     508         2401 :     int16       arg1 = PG_GETARG_INT16(0);
     509         2401 :     int16       arg2 = PG_GETARG_INT16(1);
     510              : 
     511         2401 :     PG_RETURN_BOOL(arg1 <= arg2);
     512              : }
     513              : 
     514              : Datum
     515      3417117 : int2gt(PG_FUNCTION_ARGS)
     516              : {
     517      3417117 :     int16       arg1 = PG_GETARG_INT16(0);
     518      3417117 :     int16       arg2 = PG_GETARG_INT16(1);
     519              : 
     520      3417117 :     PG_RETURN_BOOL(arg1 > arg2);
     521              : }
     522              : 
     523              : Datum
     524         1857 : int2ge(PG_FUNCTION_ARGS)
     525              : {
     526         1857 :     int16       arg1 = PG_GETARG_INT16(0);
     527         1857 :     int16       arg2 = PG_GETARG_INT16(1);
     528              : 
     529         1857 :     PG_RETURN_BOOL(arg1 >= arg2);
     530              : }
     531              : 
     532              : Datum
     533       109308 : int24eq(PG_FUNCTION_ARGS)
     534              : {
     535       109308 :     int16       arg1 = PG_GETARG_INT16(0);
     536       109308 :     int32       arg2 = PG_GETARG_INT32(1);
     537              : 
     538       109308 :     PG_RETURN_BOOL(arg1 == arg2);
     539              : }
     540              : 
     541              : Datum
     542        37605 : int24ne(PG_FUNCTION_ARGS)
     543              : {
     544        37605 :     int16       arg1 = PG_GETARG_INT16(0);
     545        37605 :     int32       arg2 = PG_GETARG_INT32(1);
     546              : 
     547        37605 :     PG_RETURN_BOOL(arg1 != arg2);
     548              : }
     549              : 
     550              : Datum
     551        70985 : int24lt(PG_FUNCTION_ARGS)
     552              : {
     553        70985 :     int16       arg1 = PG_GETARG_INT16(0);
     554        70985 :     int32       arg2 = PG_GETARG_INT32(1);
     555              : 
     556        70985 :     PG_RETURN_BOOL(arg1 < arg2);
     557              : }
     558              : 
     559              : Datum
     560        32397 : int24le(PG_FUNCTION_ARGS)
     561              : {
     562        32397 :     int16       arg1 = PG_GETARG_INT16(0);
     563        32397 :     int32       arg2 = PG_GETARG_INT32(1);
     564              : 
     565        32397 :     PG_RETURN_BOOL(arg1 <= arg2);
     566              : }
     567              : 
     568              : Datum
     569       302058 : int24gt(PG_FUNCTION_ARGS)
     570              : {
     571       302058 :     int16       arg1 = PG_GETARG_INT16(0);
     572       302058 :     int32       arg2 = PG_GETARG_INT32(1);
     573              : 
     574       302058 :     PG_RETURN_BOOL(arg1 > arg2);
     575              : }
     576              : 
     577              : Datum
     578         4992 : int24ge(PG_FUNCTION_ARGS)
     579              : {
     580         4992 :     int16       arg1 = PG_GETARG_INT16(0);
     581         4992 :     int32       arg2 = PG_GETARG_INT32(1);
     582              : 
     583         4992 :     PG_RETURN_BOOL(arg1 >= arg2);
     584              : }
     585              : 
     586              : Datum
     587        93421 : int42eq(PG_FUNCTION_ARGS)
     588              : {
     589        93421 :     int32       arg1 = PG_GETARG_INT32(0);
     590        93421 :     int16       arg2 = PG_GETARG_INT16(1);
     591              : 
     592        93421 :     PG_RETURN_BOOL(arg1 == arg2);
     593              : }
     594              : 
     595              : Datum
     596           15 : int42ne(PG_FUNCTION_ARGS)
     597              : {
     598           15 :     int32       arg1 = PG_GETARG_INT32(0);
     599           15 :     int16       arg2 = PG_GETARG_INT16(1);
     600              : 
     601           15 :     PG_RETURN_BOOL(arg1 != arg2);
     602              : }
     603              : 
     604              : Datum
     605         9152 : int42lt(PG_FUNCTION_ARGS)
     606              : {
     607         9152 :     int32       arg1 = PG_GETARG_INT32(0);
     608         9152 :     int16       arg2 = PG_GETARG_INT16(1);
     609              : 
     610         9152 :     PG_RETURN_BOOL(arg1 < arg2);
     611              : }
     612              : 
     613              : Datum
     614         8998 : int42le(PG_FUNCTION_ARGS)
     615              : {
     616         8998 :     int32       arg1 = PG_GETARG_INT32(0);
     617         8998 :     int16       arg2 = PG_GETARG_INT16(1);
     618              : 
     619         8998 :     PG_RETURN_BOOL(arg1 <= arg2);
     620              : }
     621              : 
     622              : Datum
     623         1614 : int42gt(PG_FUNCTION_ARGS)
     624              : {
     625         1614 :     int32       arg1 = PG_GETARG_INT32(0);
     626         1614 :     int16       arg2 = PG_GETARG_INT16(1);
     627              : 
     628         1614 :     PG_RETURN_BOOL(arg1 > arg2);
     629              : }
     630              : 
     631              : Datum
     632         1728 : int42ge(PG_FUNCTION_ARGS)
     633              : {
     634         1728 :     int32       arg1 = PG_GETARG_INT32(0);
     635         1728 :     int16       arg2 = PG_GETARG_INT16(1);
     636              : 
     637         1728 :     PG_RETURN_BOOL(arg1 >= arg2);
     638              : }
     639              : 
     640              : 
     641              : /*----------------------------------------------------------
     642              :  *  in_range functions for int4 and int2,
     643              :  *  including cross-data-type comparisons.
     644              :  *
     645              :  *  Note: we provide separate intN_int8 functions for performance
     646              :  *  reasons.  This forces also providing intN_int2, else cases with a
     647              :  *  smallint offset value would fail to resolve which function to use.
     648              :  *  But that's an unlikely situation, so don't duplicate code for it.
     649              :  *---------------------------------------------------------*/
     650              : 
     651              : Datum
     652         1599 : in_range_int4_int4(PG_FUNCTION_ARGS)
     653              : {
     654         1599 :     int32       val = PG_GETARG_INT32(0);
     655         1599 :     int32       base = PG_GETARG_INT32(1);
     656         1599 :     int32       offset = PG_GETARG_INT32(2);
     657         1599 :     bool        sub = PG_GETARG_BOOL(3);
     658         1599 :     bool        less = PG_GETARG_BOOL(4);
     659              :     int32       sum;
     660              : 
     661         1599 :     if (offset < 0)
     662            6 :         ereport(ERROR,
     663              :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
     664              :                  errmsg("invalid preceding or following size in window function")));
     665              : 
     666         1593 :     if (sub)
     667          720 :         offset = -offset;       /* cannot overflow */
     668              : 
     669         1593 :     if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
     670              :     {
     671              :         /*
     672              :          * If sub is false, the true sum is surely more than val, so correct
     673              :          * answer is the same as "less".  If sub is true, the true sum is
     674              :          * surely less than val, so the answer is "!less".
     675              :          */
     676           18 :         PG_RETURN_BOOL(sub ? !less : less);
     677              :     }
     678              : 
     679         1575 :     if (less)
     680          930 :         PG_RETURN_BOOL(val <= sum);
     681              :     else
     682          645 :         PG_RETURN_BOOL(val >= sum);
     683              : }
     684              : 
     685              : Datum
     686          453 : in_range_int4_int2(PG_FUNCTION_ARGS)
     687              : {
     688              :     /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
     689          453 :     return DirectFunctionCall5(in_range_int4_int4,
     690              :                                PG_GETARG_DATUM(0),
     691              :                                PG_GETARG_DATUM(1),
     692              :                                Int32GetDatum((int32) PG_GETARG_INT16(2)),
     693              :                                PG_GETARG_DATUM(3),
     694              :                                PG_GETARG_DATUM(4));
     695              : }
     696              : 
     697              : Datum
     698          381 : in_range_int4_int8(PG_FUNCTION_ARGS)
     699              : {
     700              :     /* We must do all the math in int64 */
     701          381 :     int64       val = (int64) PG_GETARG_INT32(0);
     702          381 :     int64       base = (int64) PG_GETARG_INT32(1);
     703          381 :     int64       offset = PG_GETARG_INT64(2);
     704          381 :     bool        sub = PG_GETARG_BOOL(3);
     705          381 :     bool        less = PG_GETARG_BOOL(4);
     706              :     int64       sum;
     707              : 
     708          381 :     if (offset < 0)
     709            0 :         ereport(ERROR,
     710              :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
     711              :                  errmsg("invalid preceding or following size in window function")));
     712              : 
     713          381 :     if (sub)
     714          345 :         offset = -offset;       /* cannot overflow */
     715              : 
     716          381 :     if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
     717              :     {
     718              :         /*
     719              :          * If sub is false, the true sum is surely more than val, so correct
     720              :          * answer is the same as "less".  If sub is true, the true sum is
     721              :          * surely less than val, so the answer is "!less".
     722              :          */
     723            0 :         PG_RETURN_BOOL(sub ? !less : less);
     724              :     }
     725              : 
     726          381 :     if (less)
     727           36 :         PG_RETURN_BOOL(val <= sum);
     728              :     else
     729          345 :         PG_RETURN_BOOL(val >= sum);
     730              : }
     731              : 
     732              : Datum
     733           18 : in_range_int2_int4(PG_FUNCTION_ARGS)
     734              : {
     735              :     /* We must do all the math in int32 */
     736           18 :     int32       val = (int32) PG_GETARG_INT16(0);
     737           18 :     int32       base = (int32) PG_GETARG_INT16(1);
     738           18 :     int32       offset = PG_GETARG_INT32(2);
     739           18 :     bool        sub = PG_GETARG_BOOL(3);
     740           18 :     bool        less = PG_GETARG_BOOL(4);
     741              :     int32       sum;
     742              : 
     743           18 :     if (offset < 0)
     744            0 :         ereport(ERROR,
     745              :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
     746              :                  errmsg("invalid preceding or following size in window function")));
     747              : 
     748           18 :     if (sub)
     749            9 :         offset = -offset;       /* cannot overflow */
     750              : 
     751           18 :     if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
     752              :     {
     753              :         /*
     754              :          * If sub is false, the true sum is surely more than val, so correct
     755              :          * answer is the same as "less".  If sub is true, the true sum is
     756              :          * surely less than val, so the answer is "!less".
     757              :          */
     758           18 :         PG_RETURN_BOOL(sub ? !less : less);
     759              :     }
     760              : 
     761            0 :     if (less)
     762            0 :         PG_RETURN_BOOL(val <= sum);
     763              :     else
     764            0 :         PG_RETURN_BOOL(val >= sum);
     765              : }
     766              : 
     767              : Datum
     768            0 : in_range_int2_int2(PG_FUNCTION_ARGS)
     769              : {
     770              :     /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
     771            0 :     return DirectFunctionCall5(in_range_int2_int4,
     772              :                                PG_GETARG_DATUM(0),
     773              :                                PG_GETARG_DATUM(1),
     774              :                                Int32GetDatum((int32) PG_GETARG_INT16(2)),
     775              :                                PG_GETARG_DATUM(3),
     776              :                                PG_GETARG_DATUM(4));
     777              : }
     778              : 
     779              : Datum
     780            0 : in_range_int2_int8(PG_FUNCTION_ARGS)
     781              : {
     782              :     /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
     783            0 :     return DirectFunctionCall5(in_range_int4_int8,
     784              :                                Int32GetDatum((int32) PG_GETARG_INT16(0)),
     785              :                                Int32GetDatum((int32) PG_GETARG_INT16(1)),
     786              :                                PG_GETARG_DATUM(2),
     787              :                                PG_GETARG_DATUM(3),
     788              :                                PG_GETARG_DATUM(4));
     789              : }
     790              : 
     791              : 
     792              : /*
     793              :  *      int[24]pl       - returns arg1 + arg2
     794              :  *      int[24]mi       - returns arg1 - arg2
     795              :  *      int[24]mul      - returns arg1 * arg2
     796              :  *      int[24]div      - returns arg1 / arg2
     797              :  */
     798              : 
     799              : Datum
     800        26012 : int4um(PG_FUNCTION_ARGS)
     801              : {
     802        26012 :     int32       arg = PG_GETARG_INT32(0);
     803              : 
     804        26012 :     if (unlikely(arg == PG_INT32_MIN))
     805            0 :         ereport(ERROR,
     806              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     807              :                  errmsg("integer out of range")));
     808        26012 :     PG_RETURN_INT32(-arg);
     809              : }
     810              : 
     811              : Datum
     812            3 : int4up(PG_FUNCTION_ARGS)
     813              : {
     814            3 :     int32       arg = PG_GETARG_INT32(0);
     815              : 
     816            3 :     PG_RETURN_INT32(arg);
     817              : }
     818              : 
     819              : Datum
     820      3224377 : int4pl(PG_FUNCTION_ARGS)
     821              : {
     822      3224377 :     int32       arg1 = PG_GETARG_INT32(0);
     823      3224377 :     int32       arg2 = PG_GETARG_INT32(1);
     824              :     int32       result;
     825              : 
     826      3224377 :     if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
     827            3 :         ereport(ERROR,
     828              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     829              :                  errmsg("integer out of range")));
     830      3224374 :     PG_RETURN_INT32(result);
     831              : }
     832              : 
     833              : Datum
     834      1446251 : int4mi(PG_FUNCTION_ARGS)
     835              : {
     836      1446251 :     int32       arg1 = PG_GETARG_INT32(0);
     837      1446251 :     int32       arg2 = PG_GETARG_INT32(1);
     838              :     int32       result;
     839              : 
     840      1446251 :     if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
     841            3 :         ereport(ERROR,
     842              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     843              :                  errmsg("integer out of range")));
     844      1446248 :     PG_RETURN_INT32(result);
     845              : }
     846              : 
     847              : Datum
     848      1427254 : int4mul(PG_FUNCTION_ARGS)
     849              : {
     850      1427254 :     int32       arg1 = PG_GETARG_INT32(0);
     851      1427254 :     int32       arg2 = PG_GETARG_INT32(1);
     852              :     int32       result;
     853              : 
     854      1427254 :     if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
     855           12 :         ereport(ERROR,
     856              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     857              :                  errmsg("integer out of range")));
     858      1427242 :     PG_RETURN_INT32(result);
     859              : }
     860              : 
     861              : Datum
     862       753655 : int4div(PG_FUNCTION_ARGS)
     863              : {
     864       753655 :     int32       arg1 = PG_GETARG_INT32(0);
     865       753655 :     int32       arg2 = PG_GETARG_INT32(1);
     866              :     int32       result;
     867              : 
     868       753655 :     if (arg2 == 0)
     869              :     {
     870          151 :         ereport(ERROR,
     871              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     872              :                  errmsg("division by zero")));
     873              :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     874              :         PG_RETURN_NULL();
     875              :     }
     876              : 
     877              :     /*
     878              :      * INT_MIN / -1 is problematic, since the result can't be represented on a
     879              :      * two's-complement machine.  Some machines produce INT_MIN, some produce
     880              :      * zero, some throw an exception.  We can dodge the problem by recognizing
     881              :      * that division by -1 is the same as negation.
     882              :      */
     883       753504 :     if (arg2 == -1)
     884              :     {
     885            8 :         if (unlikely(arg1 == PG_INT32_MIN))
     886            3 :             ereport(ERROR,
     887              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     888              :                      errmsg("integer out of range")));
     889            5 :         result = -arg1;
     890            5 :         PG_RETURN_INT32(result);
     891              :     }
     892              : 
     893              :     /* No overflow is possible */
     894              : 
     895       753496 :     result = arg1 / arg2;
     896              : 
     897       753496 :     PG_RETURN_INT32(result);
     898              : }
     899              : 
     900              : Datum
     901            0 : int4inc(PG_FUNCTION_ARGS)
     902              : {
     903            0 :     int32       arg = PG_GETARG_INT32(0);
     904              :     int32       result;
     905              : 
     906            0 :     if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
     907            0 :         ereport(ERROR,
     908              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     909              :                  errmsg("integer out of range")));
     910              : 
     911            0 :     PG_RETURN_INT32(result);
     912              : }
     913              : 
     914              : Datum
     915            9 : int2um(PG_FUNCTION_ARGS)
     916              : {
     917            9 :     int16       arg = PG_GETARG_INT16(0);
     918              : 
     919            9 :     if (unlikely(arg == PG_INT16_MIN))
     920            0 :         ereport(ERROR,
     921              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     922              :                  errmsg("smallint out of range")));
     923            9 :     PG_RETURN_INT16(-arg);
     924              : }
     925              : 
     926              : Datum
     927            0 : int2up(PG_FUNCTION_ARGS)
     928              : {
     929            0 :     int16       arg = PG_GETARG_INT16(0);
     930              : 
     931            0 :     PG_RETURN_INT16(arg);
     932              : }
     933              : 
     934              : Datum
     935           27 : int2pl(PG_FUNCTION_ARGS)
     936              : {
     937           27 :     int16       arg1 = PG_GETARG_INT16(0);
     938           27 :     int16       arg2 = PG_GETARG_INT16(1);
     939              :     int16       result;
     940              : 
     941           27 :     if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
     942            3 :         ereport(ERROR,
     943              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     944              :                  errmsg("smallint out of range")));
     945           24 :     PG_RETURN_INT16(result);
     946              : }
     947              : 
     948              : Datum
     949           65 : int2mi(PG_FUNCTION_ARGS)
     950              : {
     951           65 :     int16       arg1 = PG_GETARG_INT16(0);
     952           65 :     int16       arg2 = PG_GETARG_INT16(1);
     953              :     int16       result;
     954              : 
     955           65 :     if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
     956            3 :         ereport(ERROR,
     957              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     958              :                  errmsg("smallint out of range")));
     959           62 :     PG_RETURN_INT16(result);
     960              : }
     961              : 
     962              : Datum
     963           27 : int2mul(PG_FUNCTION_ARGS)
     964              : {
     965           27 :     int16       arg1 = PG_GETARG_INT16(0);
     966           27 :     int16       arg2 = PG_GETARG_INT16(1);
     967              :     int16       result;
     968              : 
     969           27 :     if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
     970            6 :         ereport(ERROR,
     971              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     972              :                  errmsg("smallint out of range")));
     973              : 
     974           21 :     PG_RETURN_INT16(result);
     975              : }
     976              : 
     977              : Datum
     978           21 : int2div(PG_FUNCTION_ARGS)
     979              : {
     980           21 :     int16       arg1 = PG_GETARG_INT16(0);
     981           21 :     int16       arg2 = PG_GETARG_INT16(1);
     982              :     int16       result;
     983              : 
     984           21 :     if (arg2 == 0)
     985              :     {
     986            0 :         ereport(ERROR,
     987              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     988              :                  errmsg("division by zero")));
     989              :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     990              :         PG_RETURN_NULL();
     991              :     }
     992              : 
     993              :     /*
     994              :      * SHRT_MIN / -1 is problematic, since the result can't be represented on
     995              :      * a two's-complement machine.  Some machines produce SHRT_MIN, some
     996              :      * produce zero, some throw an exception.  We can dodge the problem by
     997              :      * recognizing that division by -1 is the same as negation.
     998              :      */
     999           21 :     if (arg2 == -1)
    1000              :     {
    1001            3 :         if (unlikely(arg1 == PG_INT16_MIN))
    1002            3 :             ereport(ERROR,
    1003              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1004              :                      errmsg("smallint out of range")));
    1005            0 :         result = -arg1;
    1006            0 :         PG_RETURN_INT16(result);
    1007              :     }
    1008              : 
    1009              :     /* No overflow is possible */
    1010              : 
    1011           18 :     result = arg1 / arg2;
    1012              : 
    1013           18 :     PG_RETURN_INT16(result);
    1014              : }
    1015              : 
    1016              : Datum
    1017         1128 : int24pl(PG_FUNCTION_ARGS)
    1018              : {
    1019         1128 :     int16       arg1 = PG_GETARG_INT16(0);
    1020         1128 :     int32       arg2 = PG_GETARG_INT32(1);
    1021              :     int32       result;
    1022              : 
    1023         1128 :     if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
    1024            0 :         ereport(ERROR,
    1025              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1026              :                  errmsg("integer out of range")));
    1027         1128 :     PG_RETURN_INT32(result);
    1028              : }
    1029              : 
    1030              : Datum
    1031        13022 : int24mi(PG_FUNCTION_ARGS)
    1032              : {
    1033        13022 :     int16       arg1 = PG_GETARG_INT16(0);
    1034        13022 :     int32       arg2 = PG_GETARG_INT32(1);
    1035              :     int32       result;
    1036              : 
    1037        13022 :     if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
    1038            0 :         ereport(ERROR,
    1039              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1040              :                  errmsg("integer out of range")));
    1041        13022 :     PG_RETURN_INT32(result);
    1042              : }
    1043              : 
    1044              : Datum
    1045           18 : int24mul(PG_FUNCTION_ARGS)
    1046              : {
    1047           18 :     int16       arg1 = PG_GETARG_INT16(0);
    1048           18 :     int32       arg2 = PG_GETARG_INT32(1);
    1049              :     int32       result;
    1050              : 
    1051           18 :     if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
    1052            0 :         ereport(ERROR,
    1053              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1054              :                  errmsg("integer out of range")));
    1055           18 :     PG_RETURN_INT32(result);
    1056              : }
    1057              : 
    1058              : Datum
    1059           21 : int24div(PG_FUNCTION_ARGS)
    1060              : {
    1061           21 :     int16       arg1 = PG_GETARG_INT16(0);
    1062           21 :     int32       arg2 = PG_GETARG_INT32(1);
    1063              : 
    1064           21 :     if (unlikely(arg2 == 0))
    1065              :     {
    1066            3 :         ereport(ERROR,
    1067              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1068              :                  errmsg("division by zero")));
    1069              :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1070              :         PG_RETURN_NULL();
    1071              :     }
    1072              : 
    1073              :     /* No overflow is possible */
    1074           18 :     PG_RETURN_INT32((int32) arg1 / arg2);
    1075              : }
    1076              : 
    1077              : Datum
    1078           24 : int42pl(PG_FUNCTION_ARGS)
    1079              : {
    1080           24 :     int32       arg1 = PG_GETARG_INT32(0);
    1081           24 :     int16       arg2 = PG_GETARG_INT16(1);
    1082              :     int32       result;
    1083              : 
    1084           24 :     if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
    1085            3 :         ereport(ERROR,
    1086              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1087              :                  errmsg("integer out of range")));
    1088           21 :     PG_RETURN_INT32(result);
    1089              : }
    1090              : 
    1091              : Datum
    1092           27 : int42mi(PG_FUNCTION_ARGS)
    1093              : {
    1094           27 :     int32       arg1 = PG_GETARG_INT32(0);
    1095           27 :     int16       arg2 = PG_GETARG_INT16(1);
    1096              :     int32       result;
    1097              : 
    1098           27 :     if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
    1099            3 :         ereport(ERROR,
    1100              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1101              :                  errmsg("integer out of range")));
    1102           24 :     PG_RETURN_INT32(result);
    1103              : }
    1104              : 
    1105              : Datum
    1106           27 : int42mul(PG_FUNCTION_ARGS)
    1107              : {
    1108           27 :     int32       arg1 = PG_GETARG_INT32(0);
    1109           27 :     int16       arg2 = PG_GETARG_INT16(1);
    1110              :     int32       result;
    1111              : 
    1112           27 :     if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
    1113            6 :         ereport(ERROR,
    1114              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1115              :                  errmsg("integer out of range")));
    1116           21 :     PG_RETURN_INT32(result);
    1117              : }
    1118              : 
    1119              : Datum
    1120           24 : int42div(PG_FUNCTION_ARGS)
    1121              : {
    1122           24 :     int32       arg1 = PG_GETARG_INT32(0);
    1123           24 :     int16       arg2 = PG_GETARG_INT16(1);
    1124              :     int32       result;
    1125              : 
    1126           24 :     if (unlikely(arg2 == 0))
    1127              :     {
    1128            3 :         ereport(ERROR,
    1129              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1130              :                  errmsg("division by zero")));
    1131              :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1132              :         PG_RETURN_NULL();
    1133              :     }
    1134              : 
    1135              :     /*
    1136              :      * INT_MIN / -1 is problematic, since the result can't be represented on a
    1137              :      * two's-complement machine.  Some machines produce INT_MIN, some produce
    1138              :      * zero, some throw an exception.  We can dodge the problem by recognizing
    1139              :      * that division by -1 is the same as negation.
    1140              :      */
    1141           21 :     if (arg2 == -1)
    1142              :     {
    1143            3 :         if (unlikely(arg1 == PG_INT32_MIN))
    1144            3 :             ereport(ERROR,
    1145              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1146              :                      errmsg("integer out of range")));
    1147            0 :         result = -arg1;
    1148            0 :         PG_RETURN_INT32(result);
    1149              :     }
    1150              : 
    1151              :     /* No overflow is possible */
    1152              : 
    1153           18 :     result = arg1 / arg2;
    1154              : 
    1155           18 :     PG_RETURN_INT32(result);
    1156              : }
    1157              : 
    1158              : Datum
    1159      3980806 : int4mod(PG_FUNCTION_ARGS)
    1160              : {
    1161      3980806 :     int32       arg1 = PG_GETARG_INT32(0);
    1162      3980806 :     int32       arg2 = PG_GETARG_INT32(1);
    1163              : 
    1164      3980806 :     if (unlikely(arg2 == 0))
    1165              :     {
    1166            0 :         ereport(ERROR,
    1167              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1168              :                  errmsg("division by zero")));
    1169              :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1170              :         PG_RETURN_NULL();
    1171              :     }
    1172              : 
    1173              :     /*
    1174              :      * Some machines throw a floating-point exception for INT_MIN % -1, which
    1175              :      * is a bit silly since the correct answer is perfectly well-defined,
    1176              :      * namely zero.
    1177              :      */
    1178      3980806 :     if (arg2 == -1)
    1179            6 :         PG_RETURN_INT32(0);
    1180              : 
    1181              :     /* No overflow is possible */
    1182              : 
    1183      3980800 :     PG_RETURN_INT32(arg1 % arg2);
    1184              : }
    1185              : 
    1186              : Datum
    1187           18 : int2mod(PG_FUNCTION_ARGS)
    1188              : {
    1189           18 :     int16       arg1 = PG_GETARG_INT16(0);
    1190           18 :     int16       arg2 = PG_GETARG_INT16(1);
    1191              : 
    1192           18 :     if (unlikely(arg2 == 0))
    1193              :     {
    1194            0 :         ereport(ERROR,
    1195              :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1196              :                  errmsg("division by zero")));
    1197              :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1198              :         PG_RETURN_NULL();
    1199              :     }
    1200              : 
    1201              :     /*
    1202              :      * Some machines throw a floating-point exception for INT_MIN % -1, which
    1203              :      * is a bit silly since the correct answer is perfectly well-defined,
    1204              :      * namely zero.  (It's not clear this ever happens when dealing with
    1205              :      * int16, but we might as well have the test for safety.)
    1206              :      */
    1207           18 :     if (arg2 == -1)
    1208            3 :         PG_RETURN_INT16(0);
    1209              : 
    1210              :     /* No overflow is possible */
    1211              : 
    1212           15 :     PG_RETURN_INT16(arg1 % arg2);
    1213              : }
    1214              : 
    1215              : 
    1216              : /* int[24]abs()
    1217              :  * Absolute value
    1218              :  */
    1219              : Datum
    1220        64521 : int4abs(PG_FUNCTION_ARGS)
    1221              : {
    1222        64521 :     int32       arg1 = PG_GETARG_INT32(0);
    1223              :     int32       result;
    1224              : 
    1225        64521 :     if (unlikely(arg1 == PG_INT32_MIN))
    1226            0 :         ereport(ERROR,
    1227              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1228              :                  errmsg("integer out of range")));
    1229        64521 :     result = (arg1 < 0) ? -arg1 : arg1;
    1230        64521 :     PG_RETURN_INT32(result);
    1231              : }
    1232              : 
    1233              : Datum
    1234           15 : int2abs(PG_FUNCTION_ARGS)
    1235              : {
    1236           15 :     int16       arg1 = PG_GETARG_INT16(0);
    1237              :     int16       result;
    1238              : 
    1239           15 :     if (unlikely(arg1 == PG_INT16_MIN))
    1240            0 :         ereport(ERROR,
    1241              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1242              :                  errmsg("smallint out of range")));
    1243           15 :     result = (arg1 < 0) ? -arg1 : arg1;
    1244           15 :     PG_RETURN_INT16(result);
    1245              : }
    1246              : 
    1247              : /*
    1248              :  * Greatest Common Divisor
    1249              :  *
    1250              :  * Returns the largest positive integer that exactly divides both inputs.
    1251              :  * Special cases:
    1252              :  *   - gcd(x, 0) = gcd(0, x) = abs(x)
    1253              :  *          because 0 is divisible by anything
    1254              :  *   - gcd(0, 0) = 0
    1255              :  *          complies with the previous definition and is a common convention
    1256              :  *
    1257              :  * Special care must be taken if either input is INT_MIN --- gcd(0, INT_MIN),
    1258              :  * gcd(INT_MIN, 0) and gcd(INT_MIN, INT_MIN) are all equal to abs(INT_MIN),
    1259              :  * which cannot be represented as a 32-bit signed integer.
    1260              :  */
    1261              : static int32
    1262          132 : int4gcd_internal(int32 arg1, int32 arg2)
    1263              : {
    1264              :     int32       swap;
    1265              :     int32       a1,
    1266              :                 a2;
    1267              : 
    1268              :     /*
    1269              :      * Put the greater absolute value in arg1.
    1270              :      *
    1271              :      * This would happen automatically in the loop below, but avoids an
    1272              :      * expensive modulo operation, and simplifies the special-case handling
    1273              :      * for INT_MIN below.
    1274              :      *
    1275              :      * We do this in negative space in order to handle INT_MIN.
    1276              :      */
    1277          132 :     a1 = (arg1 < 0) ? arg1 : -arg1;
    1278          132 :     a2 = (arg2 < 0) ? arg2 : -arg2;
    1279          132 :     if (a1 > a2)
    1280              :     {
    1281           48 :         swap = arg1;
    1282           48 :         arg1 = arg2;
    1283           48 :         arg2 = swap;
    1284              :     }
    1285              : 
    1286              :     /* Special care needs to be taken with INT_MIN.  See comments above. */
    1287          132 :     if (arg1 == PG_INT32_MIN)
    1288              :     {
    1289           45 :         if (arg2 == 0 || arg2 == PG_INT32_MIN)
    1290            6 :             ereport(ERROR,
    1291              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1292              :                      errmsg("integer out of range")));
    1293              : 
    1294              :         /*
    1295              :          * Some machines throw a floating-point exception for INT_MIN % -1,
    1296              :          * which is a bit silly since the correct answer is perfectly
    1297              :          * well-defined, namely zero.  Guard against this and just return the
    1298              :          * result, gcd(INT_MIN, -1) = 1.
    1299              :          */
    1300           39 :         if (arg2 == -1)
    1301            6 :             return 1;
    1302              :     }
    1303              : 
    1304              :     /* Use the Euclidean algorithm to find the GCD */
    1305          471 :     while (arg2 != 0)
    1306              :     {
    1307          351 :         swap = arg2;
    1308          351 :         arg2 = arg1 % arg2;
    1309          351 :         arg1 = swap;
    1310              :     }
    1311              : 
    1312              :     /*
    1313              :      * Make sure the result is positive. (We know we don't have INT_MIN
    1314              :      * anymore).
    1315              :      */
    1316          120 :     if (arg1 < 0)
    1317           51 :         arg1 = -arg1;
    1318              : 
    1319          120 :     return arg1;
    1320              : }
    1321              : 
    1322              : Datum
    1323           90 : int4gcd(PG_FUNCTION_ARGS)
    1324              : {
    1325           90 :     int32       arg1 = PG_GETARG_INT32(0);
    1326           90 :     int32       arg2 = PG_GETARG_INT32(1);
    1327              :     int32       result;
    1328              : 
    1329           90 :     result = int4gcd_internal(arg1, arg2);
    1330              : 
    1331           84 :     PG_RETURN_INT32(result);
    1332              : }
    1333              : 
    1334              : /*
    1335              :  * Least Common Multiple
    1336              :  */
    1337              : Datum
    1338           78 : int4lcm(PG_FUNCTION_ARGS)
    1339              : {
    1340           78 :     int32       arg1 = PG_GETARG_INT32(0);
    1341           78 :     int32       arg2 = PG_GETARG_INT32(1);
    1342              :     int32       gcd;
    1343              :     int32       result;
    1344              : 
    1345              :     /*
    1346              :      * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case.  This prevents a
    1347              :      * division-by-zero error below when x is zero, and an overflow error from
    1348              :      * the GCD computation when x = INT_MIN.
    1349              :      */
    1350           78 :     if (arg1 == 0 || arg2 == 0)
    1351           36 :         PG_RETURN_INT32(0);
    1352              : 
    1353              :     /* lcm(x, y) = abs(x / gcd(x, y) * y) */
    1354           42 :     gcd = int4gcd_internal(arg1, arg2);
    1355           42 :     arg1 = arg1 / gcd;
    1356              : 
    1357           42 :     if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
    1358            3 :         ereport(ERROR,
    1359              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1360              :                  errmsg("integer out of range")));
    1361              : 
    1362              :     /* If the result is INT_MIN, it cannot be represented. */
    1363           39 :     if (unlikely(result == PG_INT32_MIN))
    1364            3 :         ereport(ERROR,
    1365              :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1366              :                  errmsg("integer out of range")));
    1367              : 
    1368           36 :     if (result < 0)
    1369           18 :         result = -result;
    1370              : 
    1371           36 :     PG_RETURN_INT32(result);
    1372              : }
    1373              : 
    1374              : Datum
    1375          201 : int2larger(PG_FUNCTION_ARGS)
    1376              : {
    1377          201 :     int16       arg1 = PG_GETARG_INT16(0);
    1378          201 :     int16       arg2 = PG_GETARG_INT16(1);
    1379              : 
    1380          201 :     PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
    1381              : }
    1382              : 
    1383              : Datum
    1384            0 : int2smaller(PG_FUNCTION_ARGS)
    1385              : {
    1386            0 :     int16       arg1 = PG_GETARG_INT16(0);
    1387            0 :     int16       arg2 = PG_GETARG_INT16(1);
    1388              : 
    1389            0 :     PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
    1390              : }
    1391              : 
    1392              : Datum
    1393       460998 : int4larger(PG_FUNCTION_ARGS)
    1394              : {
    1395       460998 :     int32       arg1 = PG_GETARG_INT32(0);
    1396       460998 :     int32       arg2 = PG_GETARG_INT32(1);
    1397              : 
    1398       460998 :     PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
    1399              : }
    1400              : 
    1401              : Datum
    1402       275973 : int4smaller(PG_FUNCTION_ARGS)
    1403              : {
    1404       275973 :     int32       arg1 = PG_GETARG_INT32(0);
    1405       275973 :     int32       arg2 = PG_GETARG_INT32(1);
    1406              : 
    1407       275973 :     PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
    1408              : }
    1409              : 
    1410              : /*
    1411              :  * Bit-pushing operators
    1412              :  *
    1413              :  *      int[24]and      - returns arg1 & arg2
    1414              :  *      int[24]or       - returns arg1 | arg2
    1415              :  *      int[24]xor      - returns arg1 # arg2
    1416              :  *      int[24]not      - returns ~arg1
    1417              :  *      int[24]shl      - returns arg1 << arg2
    1418              :  *      int[24]shr      - returns arg1 >> arg2
    1419              :  */
    1420              : 
    1421              : Datum
    1422         2583 : int4and(PG_FUNCTION_ARGS)
    1423              : {
    1424         2583 :     int32       arg1 = PG_GETARG_INT32(0);
    1425         2583 :     int32       arg2 = PG_GETARG_INT32(1);
    1426              : 
    1427         2583 :     PG_RETURN_INT32(arg1 & arg2);
    1428              : }
    1429              : 
    1430              : Datum
    1431            9 : int4or(PG_FUNCTION_ARGS)
    1432              : {
    1433            9 :     int32       arg1 = PG_GETARG_INT32(0);
    1434            9 :     int32       arg2 = PG_GETARG_INT32(1);
    1435              : 
    1436            9 :     PG_RETURN_INT32(arg1 | arg2);
    1437              : }
    1438              : 
    1439              : Datum
    1440            9 : int4xor(PG_FUNCTION_ARGS)
    1441              : {
    1442            9 :     int32       arg1 = PG_GETARG_INT32(0);
    1443            9 :     int32       arg2 = PG_GETARG_INT32(1);
    1444              : 
    1445            9 :     PG_RETURN_INT32(arg1 ^ arg2);
    1446              : }
    1447              : 
    1448              : Datum
    1449          774 : int4shl(PG_FUNCTION_ARGS)
    1450              : {
    1451          774 :     int32       arg1 = PG_GETARG_INT32(0);
    1452          774 :     int32       arg2 = PG_GETARG_INT32(1);
    1453              : 
    1454          774 :     PG_RETURN_INT32(arg1 << arg2);
    1455              : }
    1456              : 
    1457              : Datum
    1458            0 : int4shr(PG_FUNCTION_ARGS)
    1459              : {
    1460            0 :     int32       arg1 = PG_GETARG_INT32(0);
    1461            0 :     int32       arg2 = PG_GETARG_INT32(1);
    1462              : 
    1463            0 :     PG_RETURN_INT32(arg1 >> arg2);
    1464              : }
    1465              : 
    1466              : Datum
    1467            0 : int4not(PG_FUNCTION_ARGS)
    1468              : {
    1469            0 :     int32       arg1 = PG_GETARG_INT32(0);
    1470              : 
    1471            0 :     PG_RETURN_INT32(~arg1);
    1472              : }
    1473              : 
    1474              : Datum
    1475           12 : int2and(PG_FUNCTION_ARGS)
    1476              : {
    1477           12 :     int16       arg1 = PG_GETARG_INT16(0);
    1478           12 :     int16       arg2 = PG_GETARG_INT16(1);
    1479              : 
    1480           12 :     PG_RETURN_INT16(arg1 & arg2);
    1481              : }
    1482              : 
    1483              : Datum
    1484           12 : int2or(PG_FUNCTION_ARGS)
    1485              : {
    1486           12 :     int16       arg1 = PG_GETARG_INT16(0);
    1487           12 :     int16       arg2 = PG_GETARG_INT16(1);
    1488              : 
    1489           12 :     PG_RETURN_INT16(arg1 | arg2);
    1490              : }
    1491              : 
    1492              : Datum
    1493           12 : int2xor(PG_FUNCTION_ARGS)
    1494              : {
    1495           12 :     int16       arg1 = PG_GETARG_INT16(0);
    1496           12 :     int16       arg2 = PG_GETARG_INT16(1);
    1497              : 
    1498           12 :     PG_RETURN_INT16(arg1 ^ arg2);
    1499              : }
    1500              : 
    1501              : Datum
    1502            0 : int2not(PG_FUNCTION_ARGS)
    1503              : {
    1504            0 :     int16       arg1 = PG_GETARG_INT16(0);
    1505              : 
    1506            0 :     PG_RETURN_INT16(~arg1);
    1507              : }
    1508              : 
    1509              : 
    1510              : Datum
    1511            6 : int2shl(PG_FUNCTION_ARGS)
    1512              : {
    1513            6 :     int16       arg1 = PG_GETARG_INT16(0);
    1514            6 :     int32       arg2 = PG_GETARG_INT32(1);
    1515              : 
    1516            6 :     PG_RETURN_INT16(arg1 << arg2);
    1517              : }
    1518              : 
    1519              : Datum
    1520            0 : int2shr(PG_FUNCTION_ARGS)
    1521              : {
    1522            0 :     int16       arg1 = PG_GETARG_INT16(0);
    1523            0 :     int32       arg2 = PG_GETARG_INT32(1);
    1524              : 
    1525            0 :     PG_RETURN_INT16(arg1 >> arg2);
    1526              : }
    1527              : 
    1528              : /*
    1529              :  * non-persistent numeric series generator
    1530              :  */
    1531              : Datum
    1532      8323347 : generate_series_int4(PG_FUNCTION_ARGS)
    1533              : {
    1534      8323347 :     return generate_series_step_int4(fcinfo);
    1535              : }
    1536              : 
    1537              : Datum
    1538      8505976 : generate_series_step_int4(PG_FUNCTION_ARGS)
    1539              : {
    1540              :     FuncCallContext *funcctx;
    1541              :     generate_series_fctx *fctx;
    1542              :     int32       result;
    1543              :     MemoryContext oldcontext;
    1544              : 
    1545              :     /* stuff done only on the first call of the function */
    1546      8505976 :     if (SRF_IS_FIRSTCALL())
    1547              :     {
    1548        38211 :         int32       start = PG_GETARG_INT32(0);
    1549        38211 :         int32       finish = PG_GETARG_INT32(1);
    1550        38211 :         int32       step = 1;
    1551              : 
    1552              :         /* see if we were given an explicit step size */
    1553        38211 :         if (PG_NARGS() == 3)
    1554          196 :             step = PG_GETARG_INT32(2);
    1555        38211 :         if (step == 0)
    1556            0 :             ereport(ERROR,
    1557              :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1558              :                      errmsg("step size cannot equal zero")));
    1559              : 
    1560              :         /* create a function context for cross-call persistence */
    1561        38211 :         funcctx = SRF_FIRSTCALL_INIT();
    1562              : 
    1563              :         /*
    1564              :          * switch to memory context appropriate for multiple function calls
    1565              :          */
    1566        38211 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1567              : 
    1568              :         /* allocate memory for user context */
    1569        38211 :         fctx = palloc_object(generate_series_fctx);
    1570              : 
    1571              :         /*
    1572              :          * Use fctx to keep state from call to call. Seed current with the
    1573              :          * original start value
    1574              :          */
    1575        38211 :         fctx->current = start;
    1576        38211 :         fctx->finish = finish;
    1577        38211 :         fctx->step = step;
    1578              : 
    1579        38211 :         funcctx->user_fctx = fctx;
    1580        38211 :         MemoryContextSwitchTo(oldcontext);
    1581              :     }
    1582              : 
    1583              :     /* stuff done on every call of the function */
    1584      8505976 :     funcctx = SRF_PERCALL_SETUP();
    1585              : 
    1586              :     /*
    1587              :      * get the saved state and use current as the result for this iteration
    1588              :      */
    1589      8505976 :     fctx = funcctx->user_fctx;
    1590      8505976 :     result = fctx->current;
    1591              : 
    1592      8505976 :     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
    1593       138192 :         (fctx->step < 0 && fctx->current >= fctx->finish))
    1594              :     {
    1595              :         /*
    1596              :          * Increment current in preparation for next iteration. If next-value
    1597              :          * computation overflows, this is the final result.
    1598              :          */
    1599      8467789 :         if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
    1600            0 :             fctx->step = 0;
    1601              : 
    1602              :         /* do when there is more left to send */
    1603      8467789 :         SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
    1604              :     }
    1605              :     else
    1606              :         /* do when there is no more left */
    1607        38187 :         SRF_RETURN_DONE(funcctx);
    1608              : }
    1609              : 
    1610              : /*
    1611              :  * Planner support function for generate_series(int4, int4 [, int4])
    1612              :  */
    1613              : Datum
    1614        28573 : generate_series_int4_support(PG_FUNCTION_ARGS)
    1615              : {
    1616        28573 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1617        28573 :     Node       *ret = NULL;
    1618              : 
    1619        28573 :     if (IsA(rawreq, SupportRequestRows))
    1620              :     {
    1621              :         /* Try to estimate the number of rows returned */
    1622         7337 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
    1623              : 
    1624         7337 :         if (is_funcclause(req->node))    /* be paranoid */
    1625              :         {
    1626         7337 :             List       *args = ((FuncExpr *) req->node)->args;
    1627              :             Node       *arg1,
    1628              :                        *arg2,
    1629              :                        *arg3;
    1630              : 
    1631              :             /* We can use estimated argument values here */
    1632         7337 :             arg1 = estimate_expression_value(req->root, linitial(args));
    1633         7337 :             arg2 = estimate_expression_value(req->root, lsecond(args));
    1634         7337 :             if (list_length(args) >= 3)
    1635          208 :                 arg3 = estimate_expression_value(req->root, lthird(args));
    1636              :             else
    1637         7129 :                 arg3 = NULL;
    1638              : 
    1639              :             /*
    1640              :              * If any argument is constant NULL, we can safely assume that
    1641              :              * zero rows are returned.  Otherwise, if they're all non-NULL
    1642              :              * constants, we can calculate the number of rows that will be
    1643              :              * returned.  Use double arithmetic to avoid overflow hazards.
    1644              :              */
    1645         7337 :             if ((IsA(arg1, Const) &&
    1646         7297 :                  ((Const *) arg1)->constisnull) ||
    1647         7337 :                 (IsA(arg2, Const) &&
    1648         7337 :                  ((Const *) arg2)->constisnull) ||
    1649          208 :                 (arg3 != NULL && IsA(arg3, Const) &&
    1650          208 :                  ((Const *) arg3)->constisnull))
    1651              :             {
    1652            0 :                 req->rows = 0;
    1653            0 :                 ret = (Node *) req;
    1654              :             }
    1655         7337 :             else if (IsA(arg1, Const) &&
    1656         7297 :                      IsA(arg2, Const) &&
    1657          208 :                      (arg3 == NULL || IsA(arg3, Const)))
    1658              :             {
    1659              :                 double      start,
    1660              :                             finish,
    1661              :                             step;
    1662              : 
    1663         5314 :                 start = DatumGetInt32(((Const *) arg1)->constvalue);
    1664         5314 :                 finish = DatumGetInt32(((Const *) arg2)->constvalue);
    1665         5314 :                 step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
    1666              : 
    1667              :                 /* This equation works for either sign of step */
    1668         5314 :                 if (step != 0)
    1669              :                 {
    1670         5314 :                     req->rows = floor((finish - start + step) / step);
    1671         5314 :                     ret = (Node *) req;
    1672              :                 }
    1673              :             }
    1674              :         }
    1675              :     }
    1676              : 
    1677        28573 :     PG_RETURN_POINTER(ret);
    1678              : }
        

Generated by: LCOV version 2.0-1