Thread: OUT parameters in PL/Java
I've read about changes in CVS head needed to accomodate OUT parameters. I tried to compile PL/Java and it fails (of course). Is there any brief text somewhere that highligts the changes that where made and explains how the new stuff works? It's hard and somewhat time consuming to try to deduct everything just by looking at the code in pl/pgsql. Regards, Thomas Hallgren
Thomas Hallgren <thhal@mailblocks.com> writes: > I've read about changes in CVS head needed to accomodate OUT parameters. > I tried to compile PL/Java and it fails (of course). Is there any brief > text somewhere that highligts the changes that where made and explains > how the new stuff works? It's hard and somewhat time consuming to try to > deduct everything just by looking at the code in pl/pgsql. Could you give more details about what problem you are having? Simply recompiling an existing PL shouldn't fail (of course, it wouldn't know about OUT parameters either). regards, tom lane
Tom Lane wrote: > Thomas Hallgren <thhal@mailblocks.com> writes: > >>I've read about changes in CVS head needed to accomodate OUT parameters. >>I tried to compile PL/Java and it fails (of course). Is there any brief >>text somewhere that highligts the changes that where made and explains >>how the new stuff works? It's hard and somewhat time consuming to try to >>deduct everything just by looking at the code in pl/pgsql. > > > Could you give more details about what problem you are having? Simply > recompiling an existing PL shouldn't fail (of course, it wouldn't know > about OUT parameters either). > My compile failure was due to the change of proargtypes from Oid* to an oidvector. I initially thought that had something to do with OUT parameters. Some diffs on plperl helped me a bit. I found the new get_call_result_type() function. I've made some assumptions that I would like to verify the correctness of: - I assume that by using the get_call_result_type() PL/Java will not need any specific handling of functions returning OUT parameters since they are similar to functions returning a complex type. - The TupleDesc returned by the get_call_result_type() is not always reachable using an Oid. I.e. I cannot use TypeGetTupleDesc(oid, NIL) with the Form_pg_proc.prorettype of my function as the first argument. - The Form_pg_proc.pronargs denotes the number of IN parameters, i.e. its safe to access proargtypes.values[idx] with an idx ranging from 0 to pronargs - 1. Regards, Thomas Hallgren
Thomas Hallgren <thhal@mailblocks.com> writes: > My compile failure was due to the change of proargtypes from Oid* to an > oidvector. I initially thought that had something to do with OUT parameters. No, not directly. The diffs needed for that are pretty simple though. > - I assume that by using the get_call_result_type() PL/Java will not > need any specific handling of functions returning OUT parameters since > they are similar to functions returning a complex type. If you use that, it will look just the same as the existing situation where you are declared to return RECORD and someone calls you with a column name/type list in FROM. Whether you want any additional smarts is up to you. > - The TupleDesc returned by the get_call_result_type() is not always > reachable using an Oid. I.e. I cannot use TypeGetTupleDesc(oid, NIL) > with the Form_pg_proc.prorettype of my function as the first argument. That was true before for the RECORD case. > - The Form_pg_proc.pronargs denotes the number of IN parameters, i.e. > its safe to access proargtypes.values[idx] with an idx ranging from 0 to > pronargs - 1. Right, pronargs/proargtypes still denote the call signature and thus only count IN (and INOUT) parameters. One thing to be a bit wary of is that when OUT arguments are present, subscripts in proargnames line up with proallargtypes not proargtypes. I dunno if you are using proargnames at all, but if you are, the code is likely to misbehave if it doesn't know that. regards, tom lane
Tom Lane wrote: > If you use that, it will look just the same as the existing situation > where you are declared to return RECORD and someone calls you with > a column name/type list in FROM. Whether you want any additional > smarts is up to you. > > >>- The TupleDesc returned by the get_call_result_type() is not always >>reachable using an Oid. I.e. I cannot use TypeGetTupleDesc(oid, NIL) >>with the Form_pg_proc.prorettype of my function as the first argument. > > > That was true before for the RECORD case. > PL/Java will not handle the RECORD case gracefully at present I'm afraid. The 8.0 compatible version will need some improvements. How is the TupleDesc obtained in case of RECORD in 8.0.x? Is it the same in 7.4? > >>- The Form_pg_proc.pronargs denotes the number of IN parameters, i.e. >>its safe to access proargtypes.values[idx] with an idx ranging from 0 to >>pronargs - 1. > > > Right, pronargs/proargtypes still denote the call signature and thus > only count IN (and INOUT) parameters. > > One thing to be a bit wary of is that when OUT arguments are present, > subscripts in proargnames line up with proallargtypes not proargtypes. > I dunno if you are using proargnames at all, but if you are, the code > is likely to misbehave if it doesn't know that. > Thanks a lot. Now I know how to go about this. Seems pretty stright forward. Nice work! Regards, Thomas Hallgren
Thomas Hallgren <thhal@mailblocks.com> writes: > PL/Java will not handle the RECORD case gracefully at present I'm > afraid. The 8.0 compatible version will need some improvements. How is > the TupleDesc obtained in case of RECORD in 8.0.x? Is it the same in 7.4? In 8.0 and before I think you have to look in fcinfo->resultinfo to see if an expectedDesc is supplied via a ReturnSetInfo. get_call_result_type() handles that case along with the OUT-parameters case and the returns-a- named-composite-type case, so it makes things a little easier and more consistent. You could do worse than to back-port get_call_result_type() into your older branches and just leave out the code for the OUT parameter case. regards, tom lane
Tom Lane wrote: >You could do worse than to back-port get_call_result_type() into your >older branches and just leave out the code for the OUT parameter case. > > Great advice! I went ahead and did just that. Now PL/Java handles IN/INOUT/OUT parameters correctly with 8.1 and it handles functions returning SETOF RECORD in all versions. The only thing that doesn't work right now is a function that returns RECORD (not SETOF) since the rsinfo in this case is NULL. Can you shed some light on that? Regards, Thomas Hallgren
Thomas Hallgren <thhal@mailblocks.com> writes: > ... The only thing that doesn't work > right now is a function that returns RECORD (not SETOF) since the rsinfo > in this case is NULL. Can you shed some light on that? What's the test case exactly? regards, tom lane
Tom Lane wrote: >Thomas Hallgren <thhal@mailblocks.com> writes: > > >>... The only thing that doesn't work >>right now is a function that returns RECORD (not SETOF) since the rsinfo >>in this case is NULL. Can you shed some light on that? >> >> > >What's the test case exactly? > > > thhal=# create function javatest.recordExample(int, int) returns record as 'org.postgresql.pljava.example.ComplexReturn.complexReturn' immutable language java; CREATE FUNCTION thhal=# select * from javatest.recordExample(3, 4) as (foo int, bar int, baz timestamptz); ERROR: could not determine row description for function returning record (the error occurs since I make an attempt to fetch by Oid when the TupleDesc is NULL. Oid in this case is RECORDOID). Regards, Thomas Hallgren
Thomas Hallgren <thhal@mailblocks.com> writes: > thhal=# create function javatest.recordExample(int, int) returns record > as 'org.postgresql.pljava.example.ComplexReturn.complexReturn' immutable > language java; > CREATE FUNCTION > thhal=# select * from javatest.recordExample(3, 4) as (foo int, bar int, > baz timestamptz); > ERROR: could not determine row description for function returning record Hmm. I think this is not your bug. Is the call coming from evaluate_function in clauses.c? We need to either prevent that from pre-evaluating a function returning RECORD, or fix it so it can pass the expected tuple descriptor ... probably the former :-( regards, tom lane
Tom Lane wrote: >Thomas Hallgren <thhal@mailblocks.com> writes: > > >>thhal=# create function javatest.recordExample(int, int) returns record >>as 'org.postgresql.pljava.example.ComplexReturn.complexReturn' immutable >>language java; >>CREATE FUNCTION >>thhal=# select * from javatest.recordExample(3, 4) as (foo int, bar int, >>baz timestamptz); >>ERROR: could not determine row description for function returning record >> >> > >Hmm. I think this is not your bug. Is the call coming from >evaluate_function in clauses.c? We need to either prevent that from >pre-evaluating a function returning RECORD, or fix it so it can pass >the expected tuple descriptor ... probably the former :-( > > Here's the stack backtrace when this happens. #6 0xf5a104c3 in java_call_handler (fcinfo=0xfef8aba0) at /home/thhal/work/org.postgresql.pljava/src/C/pljava/Backend.c:907 #7 0x08120358 in ExecMakeFunctionResult (fcache=0xa2623a8, econtext=0xa262830, isNull=0xfef8ae1b "þ", isDone=0x0) at execQual.c:1026 #8 0x0812261c in ExecEvalExprSwitchContext (expression=0x40, econtext=0xa1ff75c, isNull=0xfef8ae1b "þ", isDone=0x0) at execQual.c:2752 #9 0x0815fecf in evaluate_expr (expr=0xa2623a8, result_type=2249) at clauses.c:2544 #10 0x08161a84 in simplify_function (funcid=17158, result_type=2249, args=0xa25566c, allow_inline=1 '\001', context=0xfef8af30) at clauses.c:2158 #11 0x08161f4f in eval_const_expressions_mutator (node=0xa254cfc, context=0xfef8af30) at clauses.c:1301 #12 0x081629c0 in eval_const_expressions (node=0xa254cfc) at clauses.c:1207 #13 0x08158add in preprocess_expression (parse=0xa25420c, expr=0xa1ff75c, kind=2) at planner.c:405 #14 0x0815a0c0 in subquery_planner (parse=0xa25420c, tuple_fraction=0) at planner.c:275 #15 0x0815a23e in planner (parse=0xa25420c, isCursor=0 '\0', cursorOptions=0, boundParams=0x0) at planner.c:133 #16 0x0818e5fa in pg_plan_query (querytree=0xa25420c, boundParams=0x0) at postgres.c:648 #17 0x0818e680 in pg_plan_queries (querytrees=0xa1ff75c, boundParams=0x0, needSnapshot=0 '\0') at postgres.c:716 #18 0x081902ce in PostgresMain (argc=4, argv=0xa1ee71c, username=0xa1ee6f4 "thhal") at postgres.c:875 #19 0x0816bc0a in ServerLoop () at postmaster.c:2784 #20 0x0816cfd7 in PostmasterMain (argc=3, argv=0xa1ed9e8) at postmaster.c:917 #21 0x08138f1f in main (argc=3, argv=0xa1ed9e8) at main.c:268 Regards, Thomas Hallgren
Thomas Hallgren <thhal@mailblocks.com> writes: > Tom Lane wrote: >> Hmm. I think this is not your bug. Is the call coming from >> evaluate_function in clauses.c? We need to either prevent that from >> pre-evaluating a function returning RECORD, or fix it so it can pass >> the expected tuple descriptor ... probably the former :-( I committed a patch to prevent that problem. > I've found another problem that might be related. The same example as > above but this time I use "returns setof record". Using the CVS head I > now get: > thhal=# select * from javatest.recordExample(3, 4) as (foo int, bar int, > baz timestamptz); > ERROR: record type has not been registered > this happens before the java_call_handler is called. Here's the stacktrace: > #0 lookup_rowtype_tupdesc_noerror (type_id=2249, typmod=-1, noError=0 '\0') > at typcache.c:425 > #1 0x081f435b in lookup_rowtype_tupdesc (type_id=2249, typmod=-1) > at typcache.c:390 > #2 0x0812081a in ExecMakeTableFunctionResult (funcexpr=0x9c4e288, > econtext=0x9c4ded0, expectedDesc=0x9c4e068, returnDesc=0x9c52200) > at execQual.c:1298 Looking at the code, it appears that the java call handler *has* been called once, and what it returned was a tuple that didn't carry any type identification. This is probably because you didn't call BlessTupleDesc. nodeFunctionscan.c formerly did that, and I suppose it should keep doing it for backwards compatibility. I put back the call... regards, tom lane
Tom Lane wrote: > Looking at the code, it appears that the java call handler *has* been > called once, indeed. Obviously I didn't pay too much attention to the trace. > and what it returned was a tuple that didn't carry any > type identification. This is probably because you didn't call > BlessTupleDesc. nodeFunctionscan.c formerly did that, and I suppose > it should keep doing it for backwards compatibility. I put back the > call... > I hope that doesn't have a negative performance impact in general. If so, I'd be happy to add the missing BlessTupleDesc at my end instead. Regards, Thomas Hallgren