Thread: Error when defining a set returning function
Dear all
Since I was receiving an error when defining a set returning function, I borrowed a function from PostgreSQL as follows
/* C definition */
typedef struct testState
{
int current;
int finish;
int step;
} testState;
/**
* test_srf(startval int, endval int, step int)
*/
PG_FUNCTION_INFO_V1(test_srf);
Datum test_srf(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
testState *fctx;
int result; /* the actual return value */
if (SRF_IS_FIRSTCALL())
{
/* Get input values */
int start = PG_GETARG_INT32(0);
int finish = PG_GETARG_INT32(1);
int step = PG_GETARG_INT32(2);
MemoryContext oldcontext;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
/* switch to memory context appropriate for multiple function calls */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* quick opt-out if we get nonsensical inputs */
if (step <= 0 || start == finish)
{
funcctx = SRF_PERCALL_SETUP();
SRF_RETURN_DONE(funcctx);
}
/* allocate memory for function context */
fctx = (testState *) palloc0(sizeof(testState));
fctx->current = start;
fctx->finish = finish;
fctx->step = step;
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
/* get state */
fctx = funcctx->user_fctx;
result = fctx->current;
fctx->current += fctx->step;
/* Stop when we have generated all values */
if (fctx->current > fctx->finish)
{
SRF_RETURN_DONE(funcctx);
}
SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
}
{
int current;
int finish;
int step;
} testState;
/**
* test_srf(startval int, endval int, step int)
*/
PG_FUNCTION_INFO_V1(test_srf);
Datum test_srf(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
testState *fctx;
int result; /* the actual return value */
if (SRF_IS_FIRSTCALL())
{
/* Get input values */
int start = PG_GETARG_INT32(0);
int finish = PG_GETARG_INT32(1);
int step = PG_GETARG_INT32(2);
MemoryContext oldcontext;
/* create a function context for cross-call persistence */
funcctx = SRF_FIRSTCALL_INIT();
/* switch to memory context appropriate for multiple function calls */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* quick opt-out if we get nonsensical inputs */
if (step <= 0 || start == finish)
{
funcctx = SRF_PERCALL_SETUP();
SRF_RETURN_DONE(funcctx);
}
/* allocate memory for function context */
fctx = (testState *) palloc0(sizeof(testState));
fctx->current = start;
fctx->finish = finish;
fctx->step = step;
funcctx->user_fctx = fctx;
MemoryContextSwitchTo(oldcontext);
}
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
/* get state */
fctx = funcctx->user_fctx;
result = fctx->current;
fctx->current += fctx->step;
/* Stop when we have generated all values */
if (fctx->current > fctx->finish)
{
SRF_RETURN_DONE(funcctx);
}
SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
}
/* SQL definition */
CREATE OR REPLACE FUNCTION testSRF(startval int, endval int, step int)
RETURNS SETOF integer
AS 'MODULE_PATHNAME', 'test_srf'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
RETURNS SETOF integer
AS 'MODULE_PATHNAME', 'test_srf'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
When I execute this function I obtain
select testSRF(1,10, 2);
ERROR: unrecognized table-function returnMode: 257
ERROR: unrecognized table-function returnMode: 257
select version();
PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, 64-bit
PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, 64-bit
Any idea what could be wrong ?
Thanks for your help
Esteban
Esteban Zimanyi <ezimanyi@ulb.ac.be> writes: > Since I was receiving an error when defining a set returning function, I > borrowed a function from PostgreSQL as follows > ... > When I execute this function I obtain > select testSRF(1,10, 2); > ERROR: unrecognized table-function returnMode: 257 Hmm, I compiled this function up and it works for me: regression=# select testSRF(1,10, 2); testsrf ---------- 1 3 5 7 (4 rows) I think your "quick opt-out" code is a bit broken, because it fails to restore the current memory context; but there's nothing wrong with the main code path. Hence, the problem is somewhere else. The first theory that comes to mind is that you're compiling against Postgres headers that don't match the server version you're actually loading the code into. In theory the PG_MODULE_MAGIC infrastructure ought to catch that, but maybe you've found some creative way to fool that :-(. One way maybe would be if the headers were from some pre-release v13 version that wasn't ABI-compatible with 13.0. Or it could be something else, but I'd counsel looking for build process mistakes, cause this C code isn't the problem. regards, tom lane
Dear Tom
Many thanks for asking my question so quickly. After your answer, I downloaded brand new versions of PostgreSQL 13.2, PostGIS 2.5.5, and compiled/installed with the standard parameters. I didn't get any error messages in the build. I then recompiled again MobilityDB and got the same error message.
When debugging the function with gdb, I noticed that the rsinfo variable of the PostgreSQL function ExecMakeFunctionResultSet is modified in the macro SRF_RETURN_NEXT causing the problem. Any idea how to solve this?
4353 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
(gdb) up
#1 0x000055b8a871fc56 in ExecMakeFunctionResultSet (fcache=0x55b8a8e6d9a0, econtext=0x55b8a8e6cfa0,
argContext=0x55b8a9d00dd0, isNull=0x55b8a8e6d930, isDone=0x55b8a8e6d988)
at /home/esteban/src/postgresql-13.2/build_dir/../src/backend/executor/execSRF.c:614
614 result = FunctionCallInvoke(fcinfo);
(gdb) p rsinfo
$5 = {type = T_ReturnSetInfo, econtext = 0x55b8a8e6cfa0, expectedDesc = 0x55b8a8e6e8f0, allowedModes = 3,
returnMode = SFRM_ValuePerCall, isDone = ExprSingleResult, setResult = 0x0, setDesc = 0x0}
(gdb) n
4354 }
(gdb)
ExecMakeFunctionResultSet (fcache=0x55b8a8e6d9a0, econtext=0x55b8a8e6cfa0, argContext=0x55b8a9d00dd0,
isNull=0x55b8a8e6d930, isDone=0x55b8a8e6d988)
at /home/esteban/src/postgresql-13.2/build_dir/../src/backend/executor/execSRF.c:615
615 *isNull = fcinfo->isnull;
(gdb) p rsinfo
$6 = {type = T_ReturnSetInfo, econtext = 0x55b8a8e6cfa0, expectedDesc = 0x55b8a8e6e8f0, allowedModes = 3,
returnMode = (SFRM_ValuePerCall | unknown: 256), isDone = ExprSingleResult, setResult = 0x0, setDesc = 0x0}
(gdb)
(gdb) up
#1 0x000055b8a871fc56 in ExecMakeFunctionResultSet (fcache=0x55b8a8e6d9a0, econtext=0x55b8a8e6cfa0,
argContext=0x55b8a9d00dd0, isNull=0x55b8a8e6d930, isDone=0x55b8a8e6d988)
at /home/esteban/src/postgresql-13.2/build_dir/../src/backend/executor/execSRF.c:614
614 result = FunctionCallInvoke(fcinfo);
(gdb) p rsinfo
$5 = {type = T_ReturnSetInfo, econtext = 0x55b8a8e6cfa0, expectedDesc = 0x55b8a8e6e8f0, allowedModes = 3,
returnMode = SFRM_ValuePerCall, isDone = ExprSingleResult, setResult = 0x0, setDesc = 0x0}
(gdb) n
4354 }
(gdb)
ExecMakeFunctionResultSet (fcache=0x55b8a8e6d9a0, econtext=0x55b8a8e6cfa0, argContext=0x55b8a9d00dd0,
isNull=0x55b8a8e6d930, isDone=0x55b8a8e6d988)
at /home/esteban/src/postgresql-13.2/build_dir/../src/backend/executor/execSRF.c:615
615 *isNull = fcinfo->isnull;
(gdb) p rsinfo
$6 = {type = T_ReturnSetInfo, econtext = 0x55b8a8e6cfa0, expectedDesc = 0x55b8a8e6e8f0, allowedModes = 3,
returnMode = (SFRM_ValuePerCall | unknown: 256), isDone = ExprSingleResult, setResult = 0x0, setDesc = 0x0}
(gdb)
Esteban Zimanyi <ezimanyi@ulb.ac.be> writes: > When debugging the function with gdb, I noticed that the rsinfo variable of > the PostgreSQL function ExecMakeFunctionResultSet is modified in the > macro SRF_RETURN_NEXT causing the problem. Any idea how to solve this? Well, what SRF_RETURN_NEXT thinks it's doing is rsi->isDone = ExprMultipleResult; \ which surely shouldn't change the returnMode field. At this point I'm guessing that you are compiling the PG headers with some compiler pragma that changes the struct packing rules. Don't do that. regards, tom lane
Many thanks Tom for your help !
I removed the flag -fshort-enums and everything works fine !
On Fri, Apr 16, 2021 at 7:04 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
Esteban Zimanyi <ezimanyi@ulb.ac.be> writes:
> When debugging the function with gdb, I noticed that the rsinfo variable of
> the PostgreSQL function ExecMakeFunctionResultSet is modified in the
> macro SRF_RETURN_NEXT causing the problem. Any idea how to solve this?
Well, what SRF_RETURN_NEXT thinks it's doing is
rsi->isDone = ExprMultipleResult; \
which surely shouldn't change the returnMode field. At this point
I'm guessing that you are compiling the PG headers with some compiler
pragma that changes the struct packing rules. Don't do that.
regards, tom lane
On 4/16/21 3:32 PM, Esteban Zimanyi wrote: > Many thanks Tom for your help ! > > I removed the flag -fshort-enums and everything works fine ! > > If you build with pgxs it should supply the appropriate compiler flags. Alternatively, get the right settings from pg_config. In general rolling your own is a bad idea. cheers andrew -- Andrew Dunstan EDB: https://www.enterprisedb.com
If you build with pgxs it should supply the appropriate compiler flags.
Alternatively, get the right settings from pg_config. In general rolling
your own is a bad idea.
I didn't know about pgxs. Many thanks Andrew for pointing this out.