Re: Setof RangeType returns - Mailing list pgsql-hackers

From Patrick Handja
Subject Re: Setof RangeType returns
Date
Msg-id CAOKRWVBU5dxL5MawXhdSBVcSNC1qnaVTUsMCUU3+LpA5dznaYg@mail.gmail.com
Whole thread Raw
In response to Re: Setof RangeType returns  (Heikki Linnakangas <hlinnaka@iki.fi>)
Responses Re: Setof RangeType returns  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
Hello Heikki,

Thank you for responding to my email.
This is what I am doing:

//========================= C file ====================================
static int
get_range_lower(FunctionCallInfo fcinfo, RangeType *r1)
{
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;

typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower, &upper, &empty);

/* Return NULL if there's no finite lower bound */
if (empty || lower.infinite)
PG_RETURN_NULL();

return (lower.val);
}

static int
get_range_upper_griis(FunctionCallInfo fcinfo, RangeType *r1)
{
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;

typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower, &upper, &empty);

/* Return NULL if there's no finite upper bound */
if (empty || upper.infinite)
PG_RETURN_NULL();

return (upper.val);
}

static RangeType *
make_range(int start, int finish)
{
RangeBound lower;
RangeBound upper;

lower.val = (Datum) (start);
lower.infinite = false;
lower.inclusive = true;
lower.lower = true;

upper.val = (Datum) (finish);
upper.infinite = false;
upper.inclusive = false;
upper.lower = false;

if (!lower.infinite && !lower.inclusive)
{
lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
lower.inclusive = true;
}

if (!upper.infinite && upper.inclusive)
{
upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
upper.inclusive = false;
}

TypeCacheEntry *typcache;
PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
}

typedef struct
{
int32 current;
int32 finish;
int32 step;
} generate_series_range_fctx;

static inline bool
control_increment(int32 a, int32 b, int32 *result)
{
int64 res = (int64) a + (int64) b;

if (res > PG_INT32_MAX || res < PG_INT32_MIN)
{
*result = 0x5EED;
return true;
}
*result = (int32) res;
return false;
}

PG_FUNCTION_INFO_V1(generate_ranges);
Datum
generate_ranges(PG_FUNCTION_ARGS)
{  
FuncCallContext *funcctx;
generate_series_range_fctx *fctx;
MemoryContext oldcontext;

RangeType  *r1 = PG_GETARG_RANGE_P(0);
RangeType *result;
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
int32 lower = get_range_lower(fcinfo, r1);
int32 upper = get_range_upper(fcinfo, r1);

if (SRF_IS_FIRSTCALL())
{
int32 start =   lower;
int32 finish =  upper;
int32 step = 1;

funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
fctx = (generate_series_range_fctx *) palloc(sizeof(generate_series_range_fctx));

fctx->current = start;
fctx->finish = finish;
fctx->step = step;

funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}

funcctx = SRF_PERCALL_SETUP();
fctx = funcctx->user_fctx;

result = make_range(fctx->current, fctx->current+1);

if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
(fctx->step < 0 && fctx->current >= fctx->finish))
{
if (control_increment(fctx->current, fctx->step, &fctx->current))
fctx->step = 0;

SRF_RETURN_NEXT(funcctx, PointerGetDatum(result));
}
else
SRF_RETURN_DONE(funcctx);
}

//============================= SQL file ================================
CREATE FUNCTION generate_ranges(anyrange) RETURNS setof anyrange
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
//========================= Test File Expected ============================
SELECT generate_ranges(int4range(4,10));
 generate_ranges
-----------------------
 [4,5)
 [5,6)
 [6,7)
 [7,8)
 [8,9)
 [9,10)
 [10,11)
(7 row)
//=====================================================================

Regards,

Andjasubu Bungama, Patrick 



Le ven. 27 nov. 2020 à 04:01, Heikki Linnakangas <hlinnaka@iki.fi> a écrit :
On 26/11/2020 23:28, Patrick Handja wrote:
> Hello,
>
> I am currently working on Library with some specific operators to
> manipulate RangeType in PostGreSQL. I would like to know if it is
> possible to return a setof rangetype elements in Postresql in C-Language
> function using the suggestion like specified here:
> https://www.postgresql.org/docs/current/xfunc-c.html#XFUNC-C-RETURN-SET
> <https://www.postgresql.org/docs/current/xfunc-c.html#XFUNC-C-RETURN-SET>.
> I have been trying this for days. If what I am trying to do is
> impossible, is there any way I can use to have a RangeType set return?

Yes, it is possible.

I bet there's just a silly little bug or misunderstanding in your code.
This stuff can be fiddly. Feel free to post what you have here, and I'm
sure someone will point out where the problem is very quickly.

- Heikki

pgsql-hackers by date:

Previous
From: Stephen Frost
Date:
Subject: Re: proposal: possibility to read dumped table's name from file
Next
From: Stephen Frost
Date:
Subject: Re: A few new options for CHECKPOINT