Header And Logo

PostgreSQL
| The world's most advanced open source database.

int.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * int.c
00004  *    Functions for the built-in integer types (except int8).
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/utils/adt/int.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 /*
00016  * OLD COMMENTS
00017  *      I/O routines:
00018  *       int2in, int2out, int2recv, int2send
00019  *       int4in, int4out, int4recv, int4send
00020  *       int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
00021  *      Boolean operators:
00022  *       inteq, intne, intlt, intle, intgt, intge
00023  *      Arithmetic operators:
00024  *       intpl, intmi, int4mul, intdiv
00025  *
00026  *      Arithmetic operators:
00027  *       intmod
00028  */
00029 #include "postgres.h"
00030 
00031 #include <ctype.h>
00032 #include <limits.h>
00033 
00034 #include "catalog/pg_type.h"
00035 #include "funcapi.h"
00036 #include "libpq/pqformat.h"
00037 #include "utils/array.h"
00038 #include "utils/builtins.h"
00039 
00040 
00041 #define SAMESIGN(a,b)   (((a) < 0) == ((b) < 0))
00042 
00043 #define Int2VectorSize(n)   (offsetof(int2vector, values) + (n) * sizeof(int16))
00044 
00045 typedef struct
00046 {
00047     int32       current;
00048     int32       finish;
00049     int32       step;
00050 } generate_series_fctx;
00051 
00052 
00053 /*****************************************************************************
00054  *   USER I/O ROUTINES                                                       *
00055  *****************************************************************************/
00056 
00057 /*
00058  *      int2in          - converts "num" to short
00059  */
00060 Datum
00061 int2in(PG_FUNCTION_ARGS)
00062 {
00063     char       *num = PG_GETARG_CSTRING(0);
00064 
00065     PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
00066 }
00067 
00068 /*
00069  *      int2out         - converts short to "num"
00070  */
00071 Datum
00072 int2out(PG_FUNCTION_ARGS)
00073 {
00074     int16       arg1 = PG_GETARG_INT16(0);
00075     char       *result = (char *) palloc(7);    /* sign, 5 digits, '\0' */
00076 
00077     pg_itoa(arg1, result);
00078     PG_RETURN_CSTRING(result);
00079 }
00080 
00081 /*
00082  *      int2recv            - converts external binary format to int2
00083  */
00084 Datum
00085 int2recv(PG_FUNCTION_ARGS)
00086 {
00087     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
00088 
00089     PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
00090 }
00091 
00092 /*
00093  *      int2send            - converts int2 to binary format
00094  */
00095 Datum
00096 int2send(PG_FUNCTION_ARGS)
00097 {
00098     int16       arg1 = PG_GETARG_INT16(0);
00099     StringInfoData buf;
00100 
00101     pq_begintypsend(&buf);
00102     pq_sendint(&buf, arg1, sizeof(int16));
00103     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00104 }
00105 
00106 /*
00107  * construct int2vector given a raw array of int2s
00108  *
00109  * If int2s is NULL then caller must fill values[] afterward
00110  */
00111 int2vector *
00112 buildint2vector(const int16 *int2s, int n)
00113 {
00114     int2vector *result;
00115 
00116     result = (int2vector *) palloc0(Int2VectorSize(n));
00117 
00118     if (n > 0 && int2s)
00119         memcpy(result->values, int2s, n * sizeof(int16));
00120 
00121     /*
00122      * Attach standard array header.  For historical reasons, we set the index
00123      * lower bound to 0 not 1.
00124      */
00125     SET_VARSIZE(result, Int2VectorSize(n));
00126     result->ndim = 1;
00127     result->dataoffset = 0;     /* never any nulls */
00128     result->elemtype = INT2OID;
00129     result->dim1 = n;
00130     result->lbound1 = 0;
00131 
00132     return result;
00133 }
00134 
00135 /*
00136  *      int2vectorin            - converts "num num ..." to internal form
00137  */
00138 Datum
00139 int2vectorin(PG_FUNCTION_ARGS)
00140 {
00141     char       *intString = PG_GETARG_CSTRING(0);
00142     int2vector *result;
00143     int         n;
00144 
00145     result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
00146 
00147     for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
00148     {
00149         while (*intString && isspace((unsigned char) *intString))
00150             intString++;
00151         if (*intString == '\0')
00152             break;
00153         result->values[n] = pg_atoi(intString, sizeof(int16), ' ');
00154         while (*intString && !isspace((unsigned char) *intString))
00155             intString++;
00156     }
00157     while (*intString && isspace((unsigned char) *intString))
00158         intString++;
00159     if (*intString)
00160         ereport(ERROR,
00161                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00162                  errmsg("int2vector has too many elements")));
00163 
00164     SET_VARSIZE(result, Int2VectorSize(n));
00165     result->ndim = 1;
00166     result->dataoffset = 0;     /* never any nulls */
00167     result->elemtype = INT2OID;
00168     result->dim1 = n;
00169     result->lbound1 = 0;
00170 
00171     PG_RETURN_POINTER(result);
00172 }
00173 
00174 /*
00175  *      int2vectorout       - converts internal form to "num num ..."
00176  */
00177 Datum
00178 int2vectorout(PG_FUNCTION_ARGS)
00179 {
00180     int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
00181     int         num,
00182                 nnums = int2Array->dim1;
00183     char       *rp;
00184     char       *result;
00185 
00186     /* assumes sign, 5 digits, ' ' */
00187     rp = result = (char *) palloc(nnums * 7 + 1);
00188     for (num = 0; num < nnums; num++)
00189     {
00190         if (num != 0)
00191             *rp++ = ' ';
00192         pg_itoa(int2Array->values[num], rp);
00193         while (*++rp != '\0')
00194             ;
00195     }
00196     *rp = '\0';
00197     PG_RETURN_CSTRING(result);
00198 }
00199 
00200 /*
00201  *      int2vectorrecv          - converts external binary format to int2vector
00202  */
00203 Datum
00204 int2vectorrecv(PG_FUNCTION_ARGS)
00205 {
00206     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
00207     FunctionCallInfoData locfcinfo;
00208     int2vector *result;
00209 
00210     /*
00211      * Normally one would call array_recv() using DirectFunctionCall3, but
00212      * that does not work since array_recv wants to cache some data using
00213      * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
00214      * parameter.
00215      */
00216     InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
00217                              InvalidOid, NULL, NULL);
00218 
00219     locfcinfo.arg[0] = PointerGetDatum(buf);
00220     locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
00221     locfcinfo.arg[2] = Int32GetDatum(-1);
00222     locfcinfo.argnull[0] = false;
00223     locfcinfo.argnull[1] = false;
00224     locfcinfo.argnull[2] = false;
00225 
00226     result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
00227 
00228     Assert(!locfcinfo.isnull);
00229 
00230     /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
00231     if (ARR_NDIM(result) != 1 ||
00232         ARR_HASNULL(result) ||
00233         ARR_ELEMTYPE(result) != INT2OID ||
00234         ARR_LBOUND(result)[0] != 0)
00235         ereport(ERROR,
00236                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
00237                  errmsg("invalid int2vector data")));
00238 
00239     /* check length for consistency with int2vectorin() */
00240     if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
00241         ereport(ERROR,
00242                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00243                  errmsg("oidvector has too many elements")));
00244 
00245     PG_RETURN_POINTER(result);
00246 }
00247 
00248 /*
00249  *      int2vectorsend          - converts int2vector to binary format
00250  */
00251 Datum
00252 int2vectorsend(PG_FUNCTION_ARGS)
00253 {
00254     return array_send(fcinfo);
00255 }
00256 
00257 /*
00258  * We don't have a complete set of int2vector support routines,
00259  * but we need int2vectoreq for catcache indexing.
00260  */
00261 Datum
00262 int2vectoreq(PG_FUNCTION_ARGS)
00263 {
00264     int2vector *a = (int2vector *) PG_GETARG_POINTER(0);
00265     int2vector *b = (int2vector *) PG_GETARG_POINTER(1);
00266 
00267     if (a->dim1 != b->dim1)
00268         PG_RETURN_BOOL(false);
00269     PG_RETURN_BOOL(memcmp(a->values, b->values, a->dim1 * sizeof(int16)) == 0);
00270 }
00271 
00272 
00273 /*****************************************************************************
00274  *   PUBLIC ROUTINES                                                         *
00275  *****************************************************************************/
00276 
00277 /*
00278  *      int4in          - converts "num" to int4
00279  */
00280 Datum
00281 int4in(PG_FUNCTION_ARGS)
00282 {
00283     char       *num = PG_GETARG_CSTRING(0);
00284 
00285     PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
00286 }
00287 
00288 /*
00289  *      int4out         - converts int4 to "num"
00290  */
00291 Datum
00292 int4out(PG_FUNCTION_ARGS)
00293 {
00294     int32       arg1 = PG_GETARG_INT32(0);
00295     char       *result = (char *) palloc(12);   /* sign, 10 digits, '\0' */
00296 
00297     pg_ltoa(arg1, result);
00298     PG_RETURN_CSTRING(result);
00299 }
00300 
00301 /*
00302  *      int4recv            - converts external binary format to int4
00303  */
00304 Datum
00305 int4recv(PG_FUNCTION_ARGS)
00306 {
00307     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
00308 
00309     PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
00310 }
00311 
00312 /*
00313  *      int4send            - converts int4 to binary format
00314  */
00315 Datum
00316 int4send(PG_FUNCTION_ARGS)
00317 {
00318     int32       arg1 = PG_GETARG_INT32(0);
00319     StringInfoData buf;
00320 
00321     pq_begintypsend(&buf);
00322     pq_sendint(&buf, arg1, sizeof(int32));
00323     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
00324 }
00325 
00326 
00327 /*
00328  *      ===================
00329  *      CONVERSION ROUTINES
00330  *      ===================
00331  */
00332 
00333 Datum
00334 i2toi4(PG_FUNCTION_ARGS)
00335 {
00336     int16       arg1 = PG_GETARG_INT16(0);
00337 
00338     PG_RETURN_INT32((int32) arg1);
00339 }
00340 
00341 Datum
00342 i4toi2(PG_FUNCTION_ARGS)
00343 {
00344     int32       arg1 = PG_GETARG_INT32(0);
00345 
00346     if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
00347         ereport(ERROR,
00348                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00349                  errmsg("smallint out of range")));
00350 
00351     PG_RETURN_INT16((int16) arg1);
00352 }
00353 
00354 /* Cast int4 -> bool */
00355 Datum
00356 int4_bool(PG_FUNCTION_ARGS)
00357 {
00358     if (PG_GETARG_INT32(0) == 0)
00359         PG_RETURN_BOOL(false);
00360     else
00361         PG_RETURN_BOOL(true);
00362 }
00363 
00364 /* Cast bool -> int4 */
00365 Datum
00366 bool_int4(PG_FUNCTION_ARGS)
00367 {
00368     if (PG_GETARG_BOOL(0) == false)
00369         PG_RETURN_INT32(0);
00370     else
00371         PG_RETURN_INT32(1);
00372 }
00373 
00374 /*
00375  *      ============================
00376  *      COMPARISON OPERATOR ROUTINES
00377  *      ============================
00378  */
00379 
00380 /*
00381  *      inteq           - returns 1 iff arg1 == arg2
00382  *      intne           - returns 1 iff arg1 != arg2
00383  *      intlt           - returns 1 iff arg1 < arg2
00384  *      intle           - returns 1 iff arg1 <= arg2
00385  *      intgt           - returns 1 iff arg1 > arg2
00386  *      intge           - returns 1 iff arg1 >= arg2
00387  */
00388 
00389 Datum
00390 int4eq(PG_FUNCTION_ARGS)
00391 {
00392     int32       arg1 = PG_GETARG_INT32(0);
00393     int32       arg2 = PG_GETARG_INT32(1);
00394 
00395     PG_RETURN_BOOL(arg1 == arg2);
00396 }
00397 
00398 Datum
00399 int4ne(PG_FUNCTION_ARGS)
00400 {
00401     int32       arg1 = PG_GETARG_INT32(0);
00402     int32       arg2 = PG_GETARG_INT32(1);
00403 
00404     PG_RETURN_BOOL(arg1 != arg2);
00405 }
00406 
00407 Datum
00408 int4lt(PG_FUNCTION_ARGS)
00409 {
00410     int32       arg1 = PG_GETARG_INT32(0);
00411     int32       arg2 = PG_GETARG_INT32(1);
00412 
00413     PG_RETURN_BOOL(arg1 < arg2);
00414 }
00415 
00416 Datum
00417 int4le(PG_FUNCTION_ARGS)
00418 {
00419     int32       arg1 = PG_GETARG_INT32(0);
00420     int32       arg2 = PG_GETARG_INT32(1);
00421 
00422     PG_RETURN_BOOL(arg1 <= arg2);
00423 }
00424 
00425 Datum
00426 int4gt(PG_FUNCTION_ARGS)
00427 {
00428     int32       arg1 = PG_GETARG_INT32(0);
00429     int32       arg2 = PG_GETARG_INT32(1);
00430 
00431     PG_RETURN_BOOL(arg1 > arg2);
00432 }
00433 
00434 Datum
00435 int4ge(PG_FUNCTION_ARGS)
00436 {
00437     int32       arg1 = PG_GETARG_INT32(0);
00438     int32       arg2 = PG_GETARG_INT32(1);
00439 
00440     PG_RETURN_BOOL(arg1 >= arg2);
00441 }
00442 
00443 Datum
00444 int2eq(PG_FUNCTION_ARGS)
00445 {
00446     int16       arg1 = PG_GETARG_INT16(0);
00447     int16       arg2 = PG_GETARG_INT16(1);
00448 
00449     PG_RETURN_BOOL(arg1 == arg2);
00450 }
00451 
00452 Datum
00453 int2ne(PG_FUNCTION_ARGS)
00454 {
00455     int16       arg1 = PG_GETARG_INT16(0);
00456     int16       arg2 = PG_GETARG_INT16(1);
00457 
00458     PG_RETURN_BOOL(arg1 != arg2);
00459 }
00460 
00461 Datum
00462 int2lt(PG_FUNCTION_ARGS)
00463 {
00464     int16       arg1 = PG_GETARG_INT16(0);
00465     int16       arg2 = PG_GETARG_INT16(1);
00466 
00467     PG_RETURN_BOOL(arg1 < arg2);
00468 }
00469 
00470 Datum
00471 int2le(PG_FUNCTION_ARGS)
00472 {
00473     int16       arg1 = PG_GETARG_INT16(0);
00474     int16       arg2 = PG_GETARG_INT16(1);
00475 
00476     PG_RETURN_BOOL(arg1 <= arg2);
00477 }
00478 
00479 Datum
00480 int2gt(PG_FUNCTION_ARGS)
00481 {
00482     int16       arg1 = PG_GETARG_INT16(0);
00483     int16       arg2 = PG_GETARG_INT16(1);
00484 
00485     PG_RETURN_BOOL(arg1 > arg2);
00486 }
00487 
00488 Datum
00489 int2ge(PG_FUNCTION_ARGS)
00490 {
00491     int16       arg1 = PG_GETARG_INT16(0);
00492     int16       arg2 = PG_GETARG_INT16(1);
00493 
00494     PG_RETURN_BOOL(arg1 >= arg2);
00495 }
00496 
00497 Datum
00498 int24eq(PG_FUNCTION_ARGS)
00499 {
00500     int16       arg1 = PG_GETARG_INT16(0);
00501     int32       arg2 = PG_GETARG_INT32(1);
00502 
00503     PG_RETURN_BOOL(arg1 == arg2);
00504 }
00505 
00506 Datum
00507 int24ne(PG_FUNCTION_ARGS)
00508 {
00509     int16       arg1 = PG_GETARG_INT16(0);
00510     int32       arg2 = PG_GETARG_INT32(1);
00511 
00512     PG_RETURN_BOOL(arg1 != arg2);
00513 }
00514 
00515 Datum
00516 int24lt(PG_FUNCTION_ARGS)
00517 {
00518     int16       arg1 = PG_GETARG_INT16(0);
00519     int32       arg2 = PG_GETARG_INT32(1);
00520 
00521     PG_RETURN_BOOL(arg1 < arg2);
00522 }
00523 
00524 Datum
00525 int24le(PG_FUNCTION_ARGS)
00526 {
00527     int16       arg1 = PG_GETARG_INT16(0);
00528     int32       arg2 = PG_GETARG_INT32(1);
00529 
00530     PG_RETURN_BOOL(arg1 <= arg2);
00531 }
00532 
00533 Datum
00534 int24gt(PG_FUNCTION_ARGS)
00535 {
00536     int16       arg1 = PG_GETARG_INT16(0);
00537     int32       arg2 = PG_GETARG_INT32(1);
00538 
00539     PG_RETURN_BOOL(arg1 > arg2);
00540 }
00541 
00542 Datum
00543 int24ge(PG_FUNCTION_ARGS)
00544 {
00545     int16       arg1 = PG_GETARG_INT16(0);
00546     int32       arg2 = PG_GETARG_INT32(1);
00547 
00548     PG_RETURN_BOOL(arg1 >= arg2);
00549 }
00550 
00551 Datum
00552 int42eq(PG_FUNCTION_ARGS)
00553 {
00554     int32       arg1 = PG_GETARG_INT32(0);
00555     int16       arg2 = PG_GETARG_INT16(1);
00556 
00557     PG_RETURN_BOOL(arg1 == arg2);
00558 }
00559 
00560 Datum
00561 int42ne(PG_FUNCTION_ARGS)
00562 {
00563     int32       arg1 = PG_GETARG_INT32(0);
00564     int16       arg2 = PG_GETARG_INT16(1);
00565 
00566     PG_RETURN_BOOL(arg1 != arg2);
00567 }
00568 
00569 Datum
00570 int42lt(PG_FUNCTION_ARGS)
00571 {
00572     int32       arg1 = PG_GETARG_INT32(0);
00573     int16       arg2 = PG_GETARG_INT16(1);
00574 
00575     PG_RETURN_BOOL(arg1 < arg2);
00576 }
00577 
00578 Datum
00579 int42le(PG_FUNCTION_ARGS)
00580 {
00581     int32       arg1 = PG_GETARG_INT32(0);
00582     int16       arg2 = PG_GETARG_INT16(1);
00583 
00584     PG_RETURN_BOOL(arg1 <= arg2);
00585 }
00586 
00587 Datum
00588 int42gt(PG_FUNCTION_ARGS)
00589 {
00590     int32       arg1 = PG_GETARG_INT32(0);
00591     int16       arg2 = PG_GETARG_INT16(1);
00592 
00593     PG_RETURN_BOOL(arg1 > arg2);
00594 }
00595 
00596 Datum
00597 int42ge(PG_FUNCTION_ARGS)
00598 {
00599     int32       arg1 = PG_GETARG_INT32(0);
00600     int16       arg2 = PG_GETARG_INT16(1);
00601 
00602     PG_RETURN_BOOL(arg1 >= arg2);
00603 }
00604 
00605 /*
00606  *      int[24]pl       - returns arg1 + arg2
00607  *      int[24]mi       - returns arg1 - arg2
00608  *      int[24]mul      - returns arg1 * arg2
00609  *      int[24]div      - returns arg1 / arg2
00610  */
00611 
00612 Datum
00613 int4um(PG_FUNCTION_ARGS)
00614 {
00615     int32       arg = PG_GETARG_INT32(0);
00616     int32       result;
00617 
00618     result = -arg;
00619     /* overflow check (needed for INT_MIN) */
00620     if (arg != 0 && SAMESIGN(result, arg))
00621         ereport(ERROR,
00622                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00623                  errmsg("integer out of range")));
00624     PG_RETURN_INT32(result);
00625 }
00626 
00627 Datum
00628 int4up(PG_FUNCTION_ARGS)
00629 {
00630     int32       arg = PG_GETARG_INT32(0);
00631 
00632     PG_RETURN_INT32(arg);
00633 }
00634 
00635 Datum
00636 int4pl(PG_FUNCTION_ARGS)
00637 {
00638     int32       arg1 = PG_GETARG_INT32(0);
00639     int32       arg2 = PG_GETARG_INT32(1);
00640     int32       result;
00641 
00642     result = arg1 + arg2;
00643 
00644     /*
00645      * Overflow check.  If the inputs are of different signs then their sum
00646      * cannot overflow.  If the inputs are of the same sign, their sum had
00647      * better be that sign too.
00648      */
00649     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00650         ereport(ERROR,
00651                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00652                  errmsg("integer out of range")));
00653     PG_RETURN_INT32(result);
00654 }
00655 
00656 Datum
00657 int4mi(PG_FUNCTION_ARGS)
00658 {
00659     int32       arg1 = PG_GETARG_INT32(0);
00660     int32       arg2 = PG_GETARG_INT32(1);
00661     int32       result;
00662 
00663     result = arg1 - arg2;
00664 
00665     /*
00666      * Overflow check.  If the inputs are of the same sign then their
00667      * difference cannot overflow.  If they are of different signs then the
00668      * result should be of the same sign as the first input.
00669      */
00670     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00671         ereport(ERROR,
00672                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00673                  errmsg("integer out of range")));
00674     PG_RETURN_INT32(result);
00675 }
00676 
00677 Datum
00678 int4mul(PG_FUNCTION_ARGS)
00679 {
00680     int32       arg1 = PG_GETARG_INT32(0);
00681     int32       arg2 = PG_GETARG_INT32(1);
00682     int32       result;
00683 
00684     result = arg1 * arg2;
00685 
00686     /*
00687      * Overflow check.  We basically check to see if result / arg2 gives arg1
00688      * again.  There are two cases where this fails: arg2 = 0 (which cannot
00689      * overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
00690      * overflow and thus incorrectly match).
00691      *
00692      * Since the division is likely much more expensive than the actual
00693      * multiplication, we'd like to skip it where possible.  The best bang for
00694      * the buck seems to be to check whether both inputs are in the int16
00695      * range; if so, no overflow is possible.
00696      */
00697     if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
00698           arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
00699         arg2 != 0 &&
00700         ((arg2 == -1 && arg1 < 0 && result < 0) ||
00701          result / arg2 != arg1))
00702         ereport(ERROR,
00703                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00704                  errmsg("integer out of range")));
00705     PG_RETURN_INT32(result);
00706 }
00707 
00708 Datum
00709 int4div(PG_FUNCTION_ARGS)
00710 {
00711     int32       arg1 = PG_GETARG_INT32(0);
00712     int32       arg2 = PG_GETARG_INT32(1);
00713     int32       result;
00714 
00715     if (arg2 == 0)
00716     {
00717         ereport(ERROR,
00718                 (errcode(ERRCODE_DIVISION_BY_ZERO),
00719                  errmsg("division by zero")));
00720         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
00721         PG_RETURN_NULL();
00722     }
00723 
00724     /*
00725      * INT_MIN / -1 is problematic, since the result can't be represented on a
00726      * two's-complement machine.  Some machines produce INT_MIN, some produce
00727      * zero, some throw an exception.  We can dodge the problem by recognizing
00728      * that division by -1 is the same as negation.
00729      */
00730     if (arg2 == -1)
00731     {
00732         result = -arg1;
00733         /* overflow check (needed for INT_MIN) */
00734         if (arg1 != 0 && SAMESIGN(result, arg1))
00735             ereport(ERROR,
00736                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00737                      errmsg("integer out of range")));
00738         PG_RETURN_INT32(result);
00739     }
00740 
00741     /* No overflow is possible */
00742 
00743     result = arg1 / arg2;
00744 
00745     PG_RETURN_INT32(result);
00746 }
00747 
00748 Datum
00749 int4inc(PG_FUNCTION_ARGS)
00750 {
00751     int32       arg = PG_GETARG_INT32(0);
00752     int32       result;
00753 
00754     result = arg + 1;
00755     /* Overflow check */
00756     if (arg > 0 && result < 0)
00757         ereport(ERROR,
00758                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00759                  errmsg("integer out of range")));
00760 
00761     PG_RETURN_INT32(result);
00762 }
00763 
00764 Datum
00765 int2um(PG_FUNCTION_ARGS)
00766 {
00767     int16       arg = PG_GETARG_INT16(0);
00768     int16       result;
00769 
00770     result = -arg;
00771     /* overflow check (needed for SHRT_MIN) */
00772     if (arg != 0 && SAMESIGN(result, arg))
00773         ereport(ERROR,
00774                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00775                  errmsg("smallint out of range")));
00776     PG_RETURN_INT16(result);
00777 }
00778 
00779 Datum
00780 int2up(PG_FUNCTION_ARGS)
00781 {
00782     int16       arg = PG_GETARG_INT16(0);
00783 
00784     PG_RETURN_INT16(arg);
00785 }
00786 
00787 Datum
00788 int2pl(PG_FUNCTION_ARGS)
00789 {
00790     int16       arg1 = PG_GETARG_INT16(0);
00791     int16       arg2 = PG_GETARG_INT16(1);
00792     int16       result;
00793 
00794     result = arg1 + arg2;
00795 
00796     /*
00797      * Overflow check.  If the inputs are of different signs then their sum
00798      * cannot overflow.  If the inputs are of the same sign, their sum had
00799      * better be that sign too.
00800      */
00801     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00802         ereport(ERROR,
00803                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00804                  errmsg("smallint out of range")));
00805     PG_RETURN_INT16(result);
00806 }
00807 
00808 Datum
00809 int2mi(PG_FUNCTION_ARGS)
00810 {
00811     int16       arg1 = PG_GETARG_INT16(0);
00812     int16       arg2 = PG_GETARG_INT16(1);
00813     int16       result;
00814 
00815     result = arg1 - arg2;
00816 
00817     /*
00818      * Overflow check.  If the inputs are of the same sign then their
00819      * difference cannot overflow.  If they are of different signs then the
00820      * result should be of the same sign as the first input.
00821      */
00822     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00823         ereport(ERROR,
00824                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00825                  errmsg("smallint out of range")));
00826     PG_RETURN_INT16(result);
00827 }
00828 
00829 Datum
00830 int2mul(PG_FUNCTION_ARGS)
00831 {
00832     int16       arg1 = PG_GETARG_INT16(0);
00833     int16       arg2 = PG_GETARG_INT16(1);
00834     int32       result32;
00835 
00836     /*
00837      * The most practical way to detect overflow is to do the arithmetic in
00838      * int32 (so that the result can't overflow) and then do a range check.
00839      */
00840     result32 = (int32) arg1 *(int32) arg2;
00841 
00842     if (result32 < SHRT_MIN || result32 > SHRT_MAX)
00843         ereport(ERROR,
00844                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00845                  errmsg("smallint out of range")));
00846 
00847     PG_RETURN_INT16((int16) result32);
00848 }
00849 
00850 Datum
00851 int2div(PG_FUNCTION_ARGS)
00852 {
00853     int16       arg1 = PG_GETARG_INT16(0);
00854     int16       arg2 = PG_GETARG_INT16(1);
00855     int16       result;
00856 
00857     if (arg2 == 0)
00858     {
00859         ereport(ERROR,
00860                 (errcode(ERRCODE_DIVISION_BY_ZERO),
00861                  errmsg("division by zero")));
00862         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
00863         PG_RETURN_NULL();
00864     }
00865 
00866     /*
00867      * SHRT_MIN / -1 is problematic, since the result can't be represented on
00868      * a two's-complement machine.  Some machines produce SHRT_MIN, some
00869      * produce zero, some throw an exception.  We can dodge the problem by
00870      * recognizing that division by -1 is the same as negation.
00871      */
00872     if (arg2 == -1)
00873     {
00874         result = -arg1;
00875         /* overflow check (needed for SHRT_MIN) */
00876         if (arg1 != 0 && SAMESIGN(result, arg1))
00877             ereport(ERROR,
00878                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00879                      errmsg("smallint out of range")));
00880         PG_RETURN_INT16(result);
00881     }
00882 
00883     /* No overflow is possible */
00884 
00885     result = arg1 / arg2;
00886 
00887     PG_RETURN_INT16(result);
00888 }
00889 
00890 Datum
00891 int24pl(PG_FUNCTION_ARGS)
00892 {
00893     int16       arg1 = PG_GETARG_INT16(0);
00894     int32       arg2 = PG_GETARG_INT32(1);
00895     int32       result;
00896 
00897     result = arg1 + arg2;
00898 
00899     /*
00900      * Overflow check.  If the inputs are of different signs then their sum
00901      * cannot overflow.  If the inputs are of the same sign, their sum had
00902      * better be that sign too.
00903      */
00904     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00905         ereport(ERROR,
00906                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00907                  errmsg("integer out of range")));
00908     PG_RETURN_INT32(result);
00909 }
00910 
00911 Datum
00912 int24mi(PG_FUNCTION_ARGS)
00913 {
00914     int16       arg1 = PG_GETARG_INT16(0);
00915     int32       arg2 = PG_GETARG_INT32(1);
00916     int32       result;
00917 
00918     result = arg1 - arg2;
00919 
00920     /*
00921      * Overflow check.  If the inputs are of the same sign then their
00922      * difference cannot overflow.  If they are of different signs then the
00923      * result should be of the same sign as the first input.
00924      */
00925     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00926         ereport(ERROR,
00927                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00928                  errmsg("integer out of range")));
00929     PG_RETURN_INT32(result);
00930 }
00931 
00932 Datum
00933 int24mul(PG_FUNCTION_ARGS)
00934 {
00935     int16       arg1 = PG_GETARG_INT16(0);
00936     int32       arg2 = PG_GETARG_INT32(1);
00937     int32       result;
00938 
00939     result = arg1 * arg2;
00940 
00941     /*
00942      * Overflow check.  We basically check to see if result / arg2 gives arg1
00943      * again.  There is one case where this fails: arg2 = 0 (which cannot
00944      * overflow).
00945      *
00946      * Since the division is likely much more expensive than the actual
00947      * multiplication, we'd like to skip it where possible.  The best bang for
00948      * the buck seems to be to check whether both inputs are in the int16
00949      * range; if so, no overflow is possible.
00950      */
00951     if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
00952         result / arg2 != arg1)
00953         ereport(ERROR,
00954                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00955                  errmsg("integer out of range")));
00956     PG_RETURN_INT32(result);
00957 }
00958 
00959 Datum
00960 int24div(PG_FUNCTION_ARGS)
00961 {
00962     int16       arg1 = PG_GETARG_INT16(0);
00963     int32       arg2 = PG_GETARG_INT32(1);
00964 
00965     if (arg2 == 0)
00966     {
00967         ereport(ERROR,
00968                 (errcode(ERRCODE_DIVISION_BY_ZERO),
00969                  errmsg("division by zero")));
00970         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
00971         PG_RETURN_NULL();
00972     }
00973 
00974     /* No overflow is possible */
00975     PG_RETURN_INT32((int32) arg1 / arg2);
00976 }
00977 
00978 Datum
00979 int42pl(PG_FUNCTION_ARGS)
00980 {
00981     int32       arg1 = PG_GETARG_INT32(0);
00982     int16       arg2 = PG_GETARG_INT16(1);
00983     int32       result;
00984 
00985     result = arg1 + arg2;
00986 
00987     /*
00988      * Overflow check.  If the inputs are of different signs then their sum
00989      * cannot overflow.  If the inputs are of the same sign, their sum had
00990      * better be that sign too.
00991      */
00992     if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
00993         ereport(ERROR,
00994                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
00995                  errmsg("integer out of range")));
00996     PG_RETURN_INT32(result);
00997 }
00998 
00999 Datum
01000 int42mi(PG_FUNCTION_ARGS)
01001 {
01002     int32       arg1 = PG_GETARG_INT32(0);
01003     int16       arg2 = PG_GETARG_INT16(1);
01004     int32       result;
01005 
01006     result = arg1 - arg2;
01007 
01008     /*
01009      * Overflow check.  If the inputs are of the same sign then their
01010      * difference cannot overflow.  If they are of different signs then the
01011      * result should be of the same sign as the first input.
01012      */
01013     if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
01014         ereport(ERROR,
01015                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01016                  errmsg("integer out of range")));
01017     PG_RETURN_INT32(result);
01018 }
01019 
01020 Datum
01021 int42mul(PG_FUNCTION_ARGS)
01022 {
01023     int32       arg1 = PG_GETARG_INT32(0);
01024     int16       arg2 = PG_GETARG_INT16(1);
01025     int32       result;
01026 
01027     result = arg1 * arg2;
01028 
01029     /*
01030      * Overflow check.  We basically check to see if result / arg1 gives arg2
01031      * again.  There is one case where this fails: arg1 = 0 (which cannot
01032      * overflow).
01033      *
01034      * Since the division is likely much more expensive than the actual
01035      * multiplication, we'd like to skip it where possible.  The best bang for
01036      * the buck seems to be to check whether both inputs are in the int16
01037      * range; if so, no overflow is possible.
01038      */
01039     if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
01040         result / arg1 != arg2)
01041         ereport(ERROR,
01042                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01043                  errmsg("integer out of range")));
01044     PG_RETURN_INT32(result);
01045 }
01046 
01047 Datum
01048 int42div(PG_FUNCTION_ARGS)
01049 {
01050     int32       arg1 = PG_GETARG_INT32(0);
01051     int16       arg2 = PG_GETARG_INT16(1);
01052     int32       result;
01053 
01054     if (arg2 == 0)
01055     {
01056         ereport(ERROR,
01057                 (errcode(ERRCODE_DIVISION_BY_ZERO),
01058                  errmsg("division by zero")));
01059         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
01060         PG_RETURN_NULL();
01061     }
01062 
01063     /*
01064      * INT_MIN / -1 is problematic, since the result can't be represented on a
01065      * two's-complement machine.  Some machines produce INT_MIN, some produce
01066      * zero, some throw an exception.  We can dodge the problem by recognizing
01067      * that division by -1 is the same as negation.
01068      */
01069     if (arg2 == -1)
01070     {
01071         result = -arg1;
01072         /* overflow check (needed for INT_MIN) */
01073         if (arg1 != 0 && SAMESIGN(result, arg1))
01074             ereport(ERROR,
01075                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01076                      errmsg("integer out of range")));
01077         PG_RETURN_INT32(result);
01078     }
01079 
01080     /* No overflow is possible */
01081 
01082     result = arg1 / arg2;
01083 
01084     PG_RETURN_INT32(result);
01085 }
01086 
01087 Datum
01088 int4mod(PG_FUNCTION_ARGS)
01089 {
01090     int32       arg1 = PG_GETARG_INT32(0);
01091     int32       arg2 = PG_GETARG_INT32(1);
01092 
01093     if (arg2 == 0)
01094     {
01095         ereport(ERROR,
01096                 (errcode(ERRCODE_DIVISION_BY_ZERO),
01097                  errmsg("division by zero")));
01098         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
01099         PG_RETURN_NULL();
01100     }
01101 
01102     /*
01103      * Some machines throw a floating-point exception for INT_MIN % -1, which
01104      * is a bit silly since the correct answer is perfectly well-defined,
01105      * namely zero.
01106      */
01107     if (arg2 == -1)
01108         PG_RETURN_INT32(0);
01109 
01110     /* No overflow is possible */
01111 
01112     PG_RETURN_INT32(arg1 % arg2);
01113 }
01114 
01115 Datum
01116 int2mod(PG_FUNCTION_ARGS)
01117 {
01118     int16       arg1 = PG_GETARG_INT16(0);
01119     int16       arg2 = PG_GETARG_INT16(1);
01120 
01121     if (arg2 == 0)
01122     {
01123         ereport(ERROR,
01124                 (errcode(ERRCODE_DIVISION_BY_ZERO),
01125                  errmsg("division by zero")));
01126         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
01127         PG_RETURN_NULL();
01128     }
01129 
01130     /*
01131      * Some machines throw a floating-point exception for INT_MIN % -1, which
01132      * is a bit silly since the correct answer is perfectly well-defined,
01133      * namely zero.  (It's not clear this ever happens when dealing with
01134      * int16, but we might as well have the test for safety.)
01135      */
01136     if (arg2 == -1)
01137         PG_RETURN_INT16(0);
01138 
01139     /* No overflow is possible */
01140 
01141     PG_RETURN_INT16(arg1 % arg2);
01142 }
01143 
01144 
01145 /* int[24]abs()
01146  * Absolute value
01147  */
01148 Datum
01149 int4abs(PG_FUNCTION_ARGS)
01150 {
01151     int32       arg1 = PG_GETARG_INT32(0);
01152     int32       result;
01153 
01154     result = (arg1 < 0) ? -arg1 : arg1;
01155     /* overflow check (needed for INT_MIN) */
01156     if (result < 0)
01157         ereport(ERROR,
01158                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01159                  errmsg("integer out of range")));
01160     PG_RETURN_INT32(result);
01161 }
01162 
01163 Datum
01164 int2abs(PG_FUNCTION_ARGS)
01165 {
01166     int16       arg1 = PG_GETARG_INT16(0);
01167     int16       result;
01168 
01169     result = (arg1 < 0) ? -arg1 : arg1;
01170     /* overflow check (needed for SHRT_MIN) */
01171     if (result < 0)
01172         ereport(ERROR,
01173                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
01174                  errmsg("smallint out of range")));
01175     PG_RETURN_INT16(result);
01176 }
01177 
01178 Datum
01179 int2larger(PG_FUNCTION_ARGS)
01180 {
01181     int16       arg1 = PG_GETARG_INT16(0);
01182     int16       arg2 = PG_GETARG_INT16(1);
01183 
01184     PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
01185 }
01186 
01187 Datum
01188 int2smaller(PG_FUNCTION_ARGS)
01189 {
01190     int16       arg1 = PG_GETARG_INT16(0);
01191     int16       arg2 = PG_GETARG_INT16(1);
01192 
01193     PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
01194 }
01195 
01196 Datum
01197 int4larger(PG_FUNCTION_ARGS)
01198 {
01199     int32       arg1 = PG_GETARG_INT32(0);
01200     int32       arg2 = PG_GETARG_INT32(1);
01201 
01202     PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
01203 }
01204 
01205 Datum
01206 int4smaller(PG_FUNCTION_ARGS)
01207 {
01208     int32       arg1 = PG_GETARG_INT32(0);
01209     int32       arg2 = PG_GETARG_INT32(1);
01210 
01211     PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
01212 }
01213 
01214 /*
01215  * Bit-pushing operators
01216  *
01217  *      int[24]and      - returns arg1 & arg2
01218  *      int[24]or       - returns arg1 | arg2
01219  *      int[24]xor      - returns arg1 # arg2
01220  *      int[24]not      - returns ~arg1
01221  *      int[24]shl      - returns arg1 << arg2
01222  *      int[24]shr      - returns arg1 >> arg2
01223  */
01224 
01225 Datum
01226 int4and(PG_FUNCTION_ARGS)
01227 {
01228     int32       arg1 = PG_GETARG_INT32(0);
01229     int32       arg2 = PG_GETARG_INT32(1);
01230 
01231     PG_RETURN_INT32(arg1 & arg2);
01232 }
01233 
01234 Datum
01235 int4or(PG_FUNCTION_ARGS)
01236 {
01237     int32       arg1 = PG_GETARG_INT32(0);
01238     int32       arg2 = PG_GETARG_INT32(1);
01239 
01240     PG_RETURN_INT32(arg1 | arg2);
01241 }
01242 
01243 Datum
01244 int4xor(PG_FUNCTION_ARGS)
01245 {
01246     int32       arg1 = PG_GETARG_INT32(0);
01247     int32       arg2 = PG_GETARG_INT32(1);
01248 
01249     PG_RETURN_INT32(arg1 ^ arg2);
01250 }
01251 
01252 Datum
01253 int4shl(PG_FUNCTION_ARGS)
01254 {
01255     int32       arg1 = PG_GETARG_INT32(0);
01256     int32       arg2 = PG_GETARG_INT32(1);
01257 
01258     PG_RETURN_INT32(arg1 << arg2);
01259 }
01260 
01261 Datum
01262 int4shr(PG_FUNCTION_ARGS)
01263 {
01264     int32       arg1 = PG_GETARG_INT32(0);
01265     int32       arg2 = PG_GETARG_INT32(1);
01266 
01267     PG_RETURN_INT32(arg1 >> arg2);
01268 }
01269 
01270 Datum
01271 int4not(PG_FUNCTION_ARGS)
01272 {
01273     int32       arg1 = PG_GETARG_INT32(0);
01274 
01275     PG_RETURN_INT32(~arg1);
01276 }
01277 
01278 Datum
01279 int2and(PG_FUNCTION_ARGS)
01280 {
01281     int16       arg1 = PG_GETARG_INT16(0);
01282     int16       arg2 = PG_GETARG_INT16(1);
01283 
01284     PG_RETURN_INT16(arg1 & arg2);
01285 }
01286 
01287 Datum
01288 int2or(PG_FUNCTION_ARGS)
01289 {
01290     int16       arg1 = PG_GETARG_INT16(0);
01291     int16       arg2 = PG_GETARG_INT16(1);
01292 
01293     PG_RETURN_INT16(arg1 | arg2);
01294 }
01295 
01296 Datum
01297 int2xor(PG_FUNCTION_ARGS)
01298 {
01299     int16       arg1 = PG_GETARG_INT16(0);
01300     int16       arg2 = PG_GETARG_INT16(1);
01301 
01302     PG_RETURN_INT16(arg1 ^ arg2);
01303 }
01304 
01305 Datum
01306 int2not(PG_FUNCTION_ARGS)
01307 {
01308     int16       arg1 = PG_GETARG_INT16(0);
01309 
01310     PG_RETURN_INT16(~arg1);
01311 }
01312 
01313 
01314 Datum
01315 int2shl(PG_FUNCTION_ARGS)
01316 {
01317     int16       arg1 = PG_GETARG_INT16(0);
01318     int32       arg2 = PG_GETARG_INT32(1);
01319 
01320     PG_RETURN_INT16(arg1 << arg2);
01321 }
01322 
01323 Datum
01324 int2shr(PG_FUNCTION_ARGS)
01325 {
01326     int16       arg1 = PG_GETARG_INT16(0);
01327     int32       arg2 = PG_GETARG_INT32(1);
01328 
01329     PG_RETURN_INT16(arg1 >> arg2);
01330 }
01331 
01332 /*
01333  * non-persistent numeric series generator
01334  */
01335 Datum
01336 generate_series_int4(PG_FUNCTION_ARGS)
01337 {
01338     return generate_series_step_int4(fcinfo);
01339 }
01340 
01341 Datum
01342 generate_series_step_int4(PG_FUNCTION_ARGS)
01343 {
01344     FuncCallContext *funcctx;
01345     generate_series_fctx *fctx;
01346     int32       result;
01347     MemoryContext oldcontext;
01348 
01349     /* stuff done only on the first call of the function */
01350     if (SRF_IS_FIRSTCALL())
01351     {
01352         int32       start = PG_GETARG_INT32(0);
01353         int32       finish = PG_GETARG_INT32(1);
01354         int32       step = 1;
01355 
01356         /* see if we were given an explicit step size */
01357         if (PG_NARGS() == 3)
01358             step = PG_GETARG_INT32(2);
01359         if (step == 0)
01360             ereport(ERROR,
01361                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01362                      errmsg("step size cannot equal zero")));
01363 
01364         /* create a function context for cross-call persistence */
01365         funcctx = SRF_FIRSTCALL_INIT();
01366 
01367         /*
01368          * switch to memory context appropriate for multiple function calls
01369          */
01370         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
01371 
01372         /* allocate memory for user context */
01373         fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
01374 
01375         /*
01376          * Use fctx to keep state from call to call. Seed current with the
01377          * original start value
01378          */
01379         fctx->current = start;
01380         fctx->finish = finish;
01381         fctx->step = step;
01382 
01383         funcctx->user_fctx = fctx;
01384         MemoryContextSwitchTo(oldcontext);
01385     }
01386 
01387     /* stuff done on every call of the function */
01388     funcctx = SRF_PERCALL_SETUP();
01389 
01390     /*
01391      * get the saved state and use current as the result for this iteration
01392      */
01393     fctx = funcctx->user_fctx;
01394     result = fctx->current;
01395 
01396     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
01397         (fctx->step < 0 && fctx->current >= fctx->finish))
01398     {
01399         /* increment current in preparation for next iteration */
01400         fctx->current += fctx->step;
01401 
01402         /* if next-value computation overflows, this is the final result */
01403         if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
01404             fctx->step = 0;
01405 
01406         /* do when there is more left to send */
01407         SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
01408     }
01409     else
01410         /* do when there is no more left */
01411         SRF_RETURN_DONE(funcctx);
01412 }