aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/int.c
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2004-02-03 08:29:57 +0000
committerJoe Conway <mail@joeconway.com>2004-02-03 08:29:57 +0000
commit12661642c88d3cba0d77d7cb6efc17a95fc04b32 (patch)
treeec6f807e5656fd110f1040ad280fd0d5b14129b1 /src/backend/utils/adt/int.c
parent9dac52649db6e182e5cbddd979aebc4cc4983701 (diff)
downloadpostgresql-12661642c88d3cba0d77d7cb6efc17a95fc04b32.tar.gz
postgresql-12661642c88d3cba0d77d7cb6efc17a95fc04b32.zip
Add function (actually an int4 and an int8 version) that generates
a series of numbers, optionally using an explicit step size other than the default value (one). Use function in the information_schema to replace hard-wired knowledge of INDEX_MAX_KEYS. initdb forced due to pg_proc change. Documentation update still needed -- will be committed separately.
Diffstat (limited to 'src/backend/utils/adt/int.c')
-rw-r--r--src/backend/utils/adt/int.c91
1 files changed, 90 insertions, 1 deletions
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index e23706582e2..82dab407ff4 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.59 2003/12/01 21:52:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.60 2004/02/03 08:29:56 joe Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,6 +34,7 @@
#include <ctype.h>
#include <limits.h>
+#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
@@ -44,6 +45,13 @@
#define SHRT_MIN (-0x8000)
#endif
+typedef struct
+{
+ int32 current;
+ int32 finish;
+ int32 step;
+} generate_series_fctx;
+
/*****************************************************************************
* USER I/O ROUTINES *
*****************************************************************************/
@@ -1021,3 +1029,84 @@ int2shr(PG_FUNCTION_ARGS)
PG_RETURN_INT16(arg1 >> arg2);
}
+
+/*
+ * non-persistent numeric series generator
+ */
+Datum
+generate_series_int4(PG_FUNCTION_ARGS)
+{
+ return generate_series_step_int4(fcinfo);
+}
+
+Datum
+generate_series_step_int4(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ generate_series_fctx *fctx;
+ int32 result;
+ MemoryContext oldcontext;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL())
+ {
+ int32 start = PG_GETARG_INT32(0);
+ int32 finish = PG_GETARG_INT32(1);
+ int32 step = 1;
+
+ /* see if we were given an explicit step size */
+ if (PG_NARGS() == 3)
+ step = PG_GETARG_INT32(2);
+ if (step == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("step size may not equal zero")));
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /*
+ * switch to memory context appropriate for multiple function
+ * calls
+ */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ /* allocate memory for user context */
+ fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
+
+ /*
+ * Use fctx to keep state from call to call.
+ * Seed current with the original start value
+ */
+ fctx->current = start;
+ fctx->finish = finish;
+ fctx->step = step;
+
+ funcctx->user_fctx = fctx;
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+
+ /*
+ * get the saved state and use current as the result for
+ * this iteration
+ */
+ fctx = funcctx->user_fctx;
+ result = fctx->current;
+
+ if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
+ (fctx->step < 0 && fctx->current >= fctx->finish))
+ {
+ /* increment current in preparation for next iteration */
+ fctx->current += fctx->step;
+
+ /* do when there is more left to send */
+ SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
+ }
+ else
+ /* do when there is no more left */
+ SRF_RETURN_DONE(funcctx);
+}
+