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

Reply via email to