]> granicus.if.org Git - postgresql/commitdiff
Add function (actually an int4 and an int8 version) that generates
authorJoe Conway <mail@joeconway.com>
Tue, 3 Feb 2004 08:29:57 +0000 (08:29 +0000)
committerJoe Conway <mail@joeconway.com>
Tue, 3 Feb 2004 08:29:57 +0000 (08:29 +0000)
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.

src/backend/catalog/information_schema.sql
src/backend/utils/adt/int.c
src/backend/utils/adt/int8.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/utils/builtins.h
src/include/utils/int8.h

index d9c484b0243e08dff4a41367d5360a338f23d9a7..1a699acd1b8e79bf2412f15902ee5a202fe27095 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright 2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.22 2004/01/24 23:45:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.23 2004/02/03 08:29:56 joe Exp $
  */
 
 /*
@@ -399,17 +399,9 @@ GRANT SELECT ON columns TO PUBLIC;
 CREATE FUNCTION _pg_keypositions() RETURNS SETOF integer
     LANGUAGE sql
     IMMUTABLE
-    AS 'select 1 union all select 2 union all select 3 union all
-        select 4 union all select 5 union all select 6 union all
-        select 7 union all select 8 union all select 9 union all
-        select 10 union all select 11 union all select 12 union all
-        select 13 union all select 14 union all select 15 union all
-        select 16 union all select 17 union all select 18 union all
-        select 19 union all select 20 union all select 21 union all
-        select 22 union all select 23 union all select 24 union all
-        select 25 union all select 26 union all select 27 union all
-        select 28 union all select 29 union all select 30 union all
-        select 31 union all select 32';
+    AS 'select g.s
+        from generate_series(1,current_setting(''max_index_keys'')::int,1)
+        as g(s)';
 
 CREATE VIEW constraint_column_usage AS
     SELECT CAST(current_database() AS sql_identifier) AS table_catalog,
index e23706582e268a31ed79be5cfff1f9ec55e7120a..82dab407ff40c52afbb16abbb5e3c0b08367c98a 100644 (file)
@@ -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"
 
 #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);
+}
+
index 016330a053395a716d74914b00508437e0362cfb..200876e7989573a866de2a150bbc25d193f356a8 100644 (file)
@@ -7,21 +7,29 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.50 2003/12/01 21:52:37 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.51 2004/02/03 08:29:56 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include <ctype.h>
+#include <limits.h>
 #include <math.h>
 
+#include "funcapi.h"
 #include "libpq/pqformat.h"
 #include "utils/int8.h"
 
 
 #define MAXINT8LEN             25
 
+typedef struct
+{
+       int64           current;
+       int64           finish;
+       int64           step;
+}      generate_series_fctx;
 
 /***********************************************************************
  **
@@ -936,3 +944,84 @@ int8_text(PG_FUNCTION_ARGS)
 
        PG_RETURN_TEXT_P(result);
 }
+
+/*
+ * non-persistent numeric series generator
+ */
+Datum
+generate_series_int8(PG_FUNCTION_ARGS)
+{
+       return generate_series_step_int8(fcinfo);
+}
+
+Datum
+generate_series_step_int8(PG_FUNCTION_ARGS)
+{
+       FuncCallContext            *funcctx;
+       generate_series_fctx   *fctx;
+       int64                                   result;
+       MemoryContext                   oldcontext;
+
+       /* stuff done only on the first call of the function */
+       if (SRF_IS_FIRSTCALL())
+       {
+               int64                   start = PG_GETARG_INT64(0);
+               int64                   finish = PG_GETARG_INT64(1);
+               int64                   step = 1;
+
+               /* see if we were given an explicit step size */
+               if (PG_NARGS() == 3)
+                       step = PG_GETARG_INT64(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, Int64GetDatum(result));
+       }
+       else
+               /* do when there is no more left */
+               SRF_RETURN_DONE(funcctx);
+}
+
index 7dd262c1e464f424a41acbfb4faf420a7dc3fd2b..fa6a7f1e605240796f63be6de3553ece0530a626 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.216 2004/01/14 23:01:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.217 2004/02/03 08:29:56 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200401141
+#define CATALOG_VERSION_NO     200402021
 
 #endif
index 4f197e99753abfefccf362f549950341e43325a2..fb6eb885d8530735c34734f2846d223285306a0b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.318 2004/01/06 23:55:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.319 2004/02/03 08:29:56 joe Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -3424,6 +3424,17 @@ DESCR("constraint description with pretty-print option");
 DATA(insert OID = 2509 (  pg_get_expr             PGNSP PGUID 12 f f t f s 3 25 "25 26 16" _null_ pg_get_expr_ext - _null_ ));
 DESCR("deparse an encoded expression with pretty-print option");
 
+/* non-persistent series generator */
+DATA(insert OID = 1066 (  generate_series PGNSP PGUID 12 f f t t v 3 23 "23 23 23" _null_ generate_series_step_int4 - _null_ ));
+DESCR("non-persistent series generator");
+DATA(insert OID = 1067 (  generate_series PGNSP PGUID 12 f f t t v 2 23 "23 23" _null_ generate_series_int4 - _null_ ));
+DESCR("non-persistent series generator");
+
+DATA(insert OID = 1068 (  generate_series PGNSP PGUID 12 f f t t v 3 20 "20 20 20" _null_ generate_series_step_int8 - _null_ ));
+DESCR("non-persistent series generator");
+DATA(insert OID = 1069 (  generate_series PGNSP PGUID 12 f f t t v 2 20 "20 20" _null_ generate_series_int8 - _null_ ));
+DESCR("non-persistent series generator");
+
 
 /*
  * Symbolic values for provolatile column: these indicate whether the result
index dc5e2f267cc7dfd94d0c6f57317d90ed2a7b0222..593f002c68f17f5305464875c2234924f2bd5d33 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.233 2004/01/19 19:04:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.234 2004/02/03 08:29:57 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -175,6 +175,8 @@ extern Datum int2xor(PG_FUNCTION_ARGS);
 extern Datum int2not(PG_FUNCTION_ARGS);
 extern Datum int2shl(PG_FUNCTION_ARGS);
 extern Datum int2shr(PG_FUNCTION_ARGS);
+extern Datum generate_series_int4(PG_FUNCTION_ARGS);
+extern Datum generate_series_step_int4(PG_FUNCTION_ARGS);
 
 /* name.c */
 extern Datum namein(PG_FUNCTION_ARGS);
index 7fe9800b2359010ee7f166bcd99a1cb27bffea75..eaaf9448a927b4ad68e7e1b47de04d16469e1155 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.40 2003/12/01 21:52:38 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.41 2004/02/03 08:29:57 joe Exp $
  *
  * NOTES
  * These data types are supported on all 64-bit architectures, and may
@@ -112,4 +112,7 @@ extern Datum oidtoi8(PG_FUNCTION_ARGS);
 extern Datum int8_text(PG_FUNCTION_ARGS);
 extern Datum text_int8(PG_FUNCTION_ARGS);
 
+extern Datum generate_series_int8(PG_FUNCTION_ARGS);
+extern Datum generate_series_step_int8(PG_FUNCTION_ARGS);
+
 #endif   /* INT8_H */