> > The switch statement could probably be done in a different way, but > > there doesn't seem to be any good examples of how to return anyitem. If > > anyone have a better way, please let me know. > > Why do you need the switch statement at all? array->elements is already > an array of Datums. Won't simply returning > array->elements[array->i] > work?
yea,. sorry,. worked it out shortly after posting this, but forgot to repost.... so here it is... attached. > The problem is: > test=# select * from unnest('{1,2,3,4,5}'::int8[]); > unnest > ---------- > 25314880 > 25314888 > 25314896 > 25314904 > 25314912 > (5 rows)
# ----------------------------------------------------------------------------- unnest : gcc -I /usr/include/postgresql/server/ -I /usr/include/postgresql/ -shared -o unnest.so unnest.c install : install -s -m 755 unnest.so $(DESTDIR)/usr/lib/postgresql/lib/; clean : rm -f *.o *~ core *.so;
#include "postgres.h" #include "fmgr.h" #include "funcapi.h" #include "catalog/pg_type.h" #include "utils/acl.h" #include "utils/array.h" #include "utils/date.h" #include "utils/geo_decls.h" #include "utils/inet.h" #include "utils/nabstime.h" #include "utils/numeric.h" #include "utils/timestamp.h" #include "utils/varbit.h" #include "utils/lsyscache.h" typedef struct { Datum *elements; int num_elements; Oid typelem; bool typbyval; int i; } UNNEST; PG_FUNCTION_INFO_V1(unnest); Datum unnest(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; UNNEST *array; if(PG_ARGISNULL(0)) ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),errmsg("null array elements not supported"))); if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); array = (UNNEST *)palloc(sizeof(UNNEST)); ArrayType *v = PG_GETARG_ARRAYTYPE_P(0); int nitems = ArrayGetNItems(ARR_NDIM(v), ARR_DIMS(v)); ArrayMetaState *my_extra; my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; if (my_extra == NULL) { fcinfo->flinfo->fn_extra = palloc(sizeof(ArrayMetaState)); my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra; my_extra->element_type = InvalidOid; } if (my_extra->element_type != ARR_ELEMTYPE(v)) { get_typlenbyvalalign(ARR_ELEMTYPE(v), &my_extra->typlen, &my_extra->typbyval,&my_extra->typalign); my_extra->element_type = ARR_ELEMTYPE(v); } array->typelem = my_extra->element_type; array->typbyval = my_extra->typbyval; array->i = 0; deconstruct_array(v,my_extra->element_type,my_extra->typlen,my_extra->typbyval,my_extra->typalign,&array->elements,&array->num_elements); if(array->num_elements != nitems) elog(WARNING,"array unnests to %d elements but consists of %d items",array->num_elements,nitems); funcctx->user_fctx = (void *)array; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); array = (UNNEST *)funcctx->user_fctx; if (array->i < array->num_elements) { Datum retval = (Datum)array->elements[array->i]; array->i++; SRF_RETURN_NEXT(funcctx,retval); } else { SRF_RETURN_DONE(funcctx); } }
CREATE FUNCTION unnest(anyarray) RETURNS setof anyelement AS 'unnest.so','unnest' LANGUAGE 'C' IMMUTABLE;
---------------------------(end of broadcast)--------------------------- TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]