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

Generated by: LCOV version 1.13