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

Generated by: LCOV version 1.14