From: | Patrick Handja <patrick(dot)bungama(at)gmail(dot)com> |
---|---|
To: | Heikki Linnakangas <hlinnaka(at)iki(dot)fi> |
Cc: | pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: Setof RangeType returns |
Date: | 2020-11-27 18:46:49 |
Message-ID: | CAOKRWVBU5dxL5MawXhdSBVcSNC1qnaVTUsMCUU3+LpA5dznaYg@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | 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(at)iki(dot)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
>
From | Date | Subject | |
---|---|---|---|
Next Message | Stephen Frost | 2020-11-27 18:57:43 | Re: A few new options for CHECKPOINT |
Previous Message | Stephen Frost | 2020-11-27 18:45:09 | Re: proposal: possibility to read dumped table's name from file |