Re: Setof RangeType returns

Поиск
Список
Период
Сортировка
От Patrick Handja
Тема Re: Setof RangeType returns
Дата
Msg-id CAOKRWVBU5dxL5MawXhdSBVcSNC1qnaVTUsMCUU3+LpA5dznaYg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: Setof RangeType returns  (Heikki Linnakangas <hlinnaka@iki.fi>)
Ответы Re: Setof RangeType returns
Список 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 по дате отправления:

Предыдущее
От: Stephen Frost
Дата:
Сообщение: Re: proposal: possibility to read dumped table's name from file
Следующее
От: Stephen Frost
Дата:
Сообщение: Re: A few new options for CHECKPOINT