*** ./doc/src/sgml/func.sgml.orig 2008-03-24 18:01:54.000000000 +0100
--- ./doc/src/sgml/func.sgml 2008-03-24 19:03:43.000000000 +0100
***************
*** 10562,10569 ****
This section describes functions that possibly return more than one row.
- Currently the only functions in this class are series generating functions,
- as detailed in .
--- 10562,10567 ----
***************
*** 10641,10646 ****
--- 10639,10697 ----
(3 rows)
+
+
+ Subscripts Generating Functions
+
+
+
+ Function
+ Return Type
+ Description
+
+
+
+
+
+ generate_subscripts(array annyarray, dim int)
+ setof int
+
+ Generate a series of array's subscripts.
+
+
+
+
+ generate_subscripts(array annyarray, dim int, reverse boolean)
+ setof int
+
+ Generate a series of array's subscripts. When reverse is true, then series is reverse order.
+
+
+
+
+
+
+
+
+ -- unnest 2D array
+ create or replace function unnest2(anyarray)
+ returns setof anyelement as $$
+ select $1[i][j]
+ from generate_subscripts($1,1) g1(i),
+ generate_subscripts($1,2) g2(j);
+ $$ language sql immutable;
+ CREATE FUNCTION
+ postgres=# select * from unnest2(array[[1,2],[3,4]]);
+ unnest2
+ ---------
+ 1
+ 2
+ 3
+ 4
+ (4 rows)
+
+
+
*** ./src/backend/utils/adt/arrayfuncs.c.orig 2008-03-24 17:38:45.000000000 +0100
--- ./src/backend/utils/adt/arrayfuncs.c 2008-03-24 18:12:35.000000000 +0100
***************
*** 16,21 ****
--- 16,22 ----
#include
+ #include "funcapi.h"
#include "access/tupmacs.h"
#include "libpq/pqformat.h"
#include "parser/parse_coerce.h"
***************
*** 96,101 ****
--- 97,108 ----
int typlen, bool typbyval, char typalign);
static int array_cmp(FunctionCallInfo fcinfo);
+ typedef struct generate_subscripts_fctx
+ {
+ int4 lower;
+ int4 upper;
+ bool reverse;
+ } generate_subscripts_fctx;
/*
* array_in :
***************
*** 4237,4239 ****
--- 4244,4315 ----
PG_RETURN_ARRAYTYPE_P(result);
}
+
+ /*
+ * array_subscripts(array anyarray, dim int, reverse bool)
+ * returns all subscripts of array for any dimension
+ */
+ Datum
+ array_subscripts_direction(PG_FUNCTION_ARGS)
+ {
+ return array_subscripts(fcinfo);
+ }
+
+ Datum
+ array_subscripts(PG_FUNCTION_ARGS)
+ {
+ FuncCallContext *funcctx;
+ MemoryContext oldcontext;
+ generate_subscripts_fctx *fctx;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL())
+ {
+ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
+ int reqdim = PG_GETARG_INT32(1);
+ int *lb, *dimv;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /* Sanity check: does it look like an array at all? */
+ if (ARR_NDIM(v) <= 0 || ARR_NDIM(v) > MAXDIM)
+ SRF_RETURN_DONE(funcctx);
+
+ /* Sanity check: was the requested dim valid */
+ if (reqdim <= 0 || reqdim > ARR_NDIM(v))
+ SRF_RETURN_DONE(funcctx);
+
+ /*
+ * switch to memory context appropriate for multiple function calls
+ */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+ fctx = (generate_subscripts_fctx *) palloc(sizeof(generate_subscripts_fctx));
+
+ lb = ARR_LBOUND(v);
+ dimv = ARR_DIMS(v);
+
+ fctx->lower = lb[reqdim - 1];
+ fctx->upper = dimv[reqdim - 1] + lb[reqdim - 1] - 1;
+ fctx->reverse = (PG_NARGS() < 3) ? false : PG_GETARG_BOOL(2);
+
+ funcctx->user_fctx = fctx;
+
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ funcctx = SRF_PERCALL_SETUP();
+
+ fctx = funcctx->user_fctx;
+
+ if (fctx->lower <= fctx->upper)
+ {
+ if (!fctx->reverse)
+ SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->lower++));
+ else
+ SRF_RETURN_NEXT(funcctx, Int32GetDatum(fctx->upper--));
+ }
+ else
+ /* do when there is no more left */
+ SRF_RETURN_DONE(funcctx);
+ }
*** ./src/include/catalog/pg_proc.h.orig 2008-03-24 17:39:12.000000000 +0100
--- ./src/include/catalog/pg_proc.h 2008-03-24 18:17:01.000000000 +0100
***************
*** 1015,1020 ****
--- 1015,1025 ----
DESCR("larger of two");
DATA(insert OID = 516 ( array_smaller PGNSP PGUID 12 1 0 f f t f i 2 2277 "2277 2277" _null_ _null_ _null_ array_smaller - _null_ _null_ ));
DESCR("smaller of two");
+ DATA(insert OID = 1191 ( generate_subscripts PGNSP PGUID 12 1 1000 f f t t v 3 23 "2277 23 16" _null_ _null_ _null_ array_subscripts_direction - _null_ _null_ ));
+ DESCR("array subscripts generator");
+ DATA(insert OID = 1192 ( generate_subscripts PGNSP PGUID 12 1 1000 f f t t v 2 23 "2277 23" _null_ _null_ _null_ array_subscripts - _null_ _null_ ));
+ DESCR("array subscripts generator");
+
DATA(insert OID = 760 ( smgrin PGNSP PGUID 12 1 0 f f t f s 1 210 "2275" _null_ _null_ _null_ smgrin - _null_ _null_ ));
DESCR("I/O");
*** ./src/include/utils/array.h.orig 2008-03-24 17:39:36.000000000 +0100
--- ./src/include/utils/array.h 2008-03-24 18:18:12.000000000 +0100
***************
*** 200,205 ****
--- 200,207 ----
extern Datum array_upper(PG_FUNCTION_ARGS);
extern Datum array_larger(PG_FUNCTION_ARGS);
extern Datum array_smaller(PG_FUNCTION_ARGS);
+ extern Datum array_subscripts(PG_FUNCTION_ARGS);
+ extern Datum array_subscripts_direction(PG_FUNCTION_ARGS);
extern Datum array_ref(ArrayType *array, int nSubscripts, int *indx,
int arraytyplen, int elmlen, bool elmbyval, char elmalign,
*** ./src/test/regress/expected/arrays.out.orig 2008-03-21 13:17:42.000000000 +0100
--- ./src/test/regress/expected/arrays.out 2008-03-24 17:42:13.000000000 +0100
***************
*** 903,905 ****
--- 903,935 ----
drop type _comptype;
drop table comptable;
drop type comptype;
+ create or replace function array_expand(anyarray)
+ returns setof anyelement as $$
+ select $1[s] from generate_subscripts($1,1) g(s);
+ $$ language sql immutable;
+ create or replace function array_expand2(anyarray)
+ returns setof anyelement as $$
+ select $1[s1][s2] from generate_subscripts($1,1) g1(s1),
+ generate_subscripts($1,2) g2(s2);
+ $$ language sql immutable;
+ select * from array_expand(array[1,2,3]);
+ array_expand
+ --------------
+ 1
+ 2
+ 3
+ (3 rows)
+
+ select * from array_expand2(array[[1,2,3],[4,5,6]]);
+ array_expand2
+ ---------------
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ (6 rows)
+
+ drop function array_expand(anyarray);
+ drop function array_expand2(anyarray);
*** ./src/test/regress/sql/arrays.sql.orig 2008-03-21 13:17:43.000000000 +0100
--- ./src/test/regress/sql/arrays.sql 2008-03-24 17:42:13.000000000 +0100
***************
*** 340,342 ****
--- 340,359 ----
drop type _comptype;
drop table comptable;
drop type comptype;
+
+ create or replace function array_expand(anyarray)
+ returns setof anyelement as $$
+ select $1[s] from generate_subscripts($1,1) g(s);
+ $$ language sql immutable;
+
+ create or replace function array_expand2(anyarray)
+ returns setof anyelement as $$
+ select $1[s1][s2] from generate_subscripts($1,1) g1(s1),
+ generate_subscripts($1,2) g2(s2);
+ $$ language sql immutable;
+
+ select * from array_expand(array[1,2,3]);
+ select * from array_expand2(array[[1,2,3],[4,5,6]]);
+
+ drop function array_expand(anyarray);
+ drop function array_expand2(anyarray);