> > 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]