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

Generated by: LCOV version 1.13