db-derby-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel John Debrunner <...@apache.org>
Subject Re: [PATCH] Derby-479 Passing the return of a RETURN NULL ON NULL INPUT function to another function call throws linkage error.
Date Tue, 14 Feb 2006 20:28:22 GMT
Mamta Satoor wrote:

> Please find my replies inline. Hopefully they answer your questions.
> On 2/13/06, *Daniel John Debrunner* <djd@apache.org

I think the confusion is arising out of the fact that because this is a
nested call the return of one method/function is fed into the argument
of the other. In such cases it helps to be very clear about what exactly
is being explained.

> So, getParameterTypeName returns the type as "java.lang.Integer" to generateParameters
at line 536.
> generateParameters compares this type with the type of the Java method which is "int",
>line 541. Since they don't match, on line 549, it does casting of the top
> of the stack to the Java method type. The inside StaticMethodCallNode
> finds the top of stack to be "int" type already (because NumberDataValue's 
> returns int as it's Java primitive value) and hence the casting done on 549
> for inside StaticMethodCallNode, although a no-op, is not a problem.
> But in the case of the outside StaticMethodCallNode, on line 549,
> it finds that the top of the stack is of the type java.lang.Integer
> (because of return null on null input), the casting on line 549
> fails for outside StaticMethodCallNode because it is trying to java.lang.Integer to int.
> I hope this explanation is helpful.

This is good, with your earlier description I think I was confused by an
abrupt change from describing what happens with the inner parameter to
what you were seeing with the outer parameter. Without telling the
reader you are describing something else it becomes hard to understand.

>     I thought the generated code was something like this for a parameter in
>     an returns null on null input function.
>       DataValueDescriptor pdvd = <somthing>
>       if (pdvd.isNull())
>           forceReturnNull = true; // actually generated field name
>       else
>           // needed due to limitation in byte code compiler
>           forceReturnNull = forceReturnNull;
>       int pInner = pdvd.getInt();
>     See SQLToJavaValueNode.generateReturnsNullOnNullCheck()
> You are right about what gets generated, which is primitive int type, at
> this point. But the conversion of int to java.lang.Integer happens after
> all the parameters code generation is finished.

The above code fragment shows the code generated for the inner call
(that takes the constant 90 in this case). Thus the engine takes a SQL
type (NumberDataValue internal representation) and gets a primitive int
from it.

This primitive int parameter is never converted to a java.lang.Integer.

When you say 'But the conversion of int to java.lang.Integer happens
after all the parameters code generation is finished', it is not
occuring for the parameter to the inner call. That int value is not
coverted to a java.lang.Integer.

The return of the inner call does undergo a conversion of int to
java.lang.Integer, the line numbers you give in StaticMethodCallNode
relate to the return value.

So the generated code for the inner call is something like:
(I added an 'int pInner =' to the above code fragment to link it to this)

   Integer innerFunctionVal;
   if (forceReturnNull)
       innerFunctionVal= null;
   else {
       innerFunctionVal= new Integer(Math.abs(pInner));

Then, because the call to the outer method was short circuited directly
into java, we hit the bug, converting from an Integer to an int,
corresponding to the line numbers you gave in MethodCallNode, generating
code like:
(following on from previous fragment)

   // Due to the casts generated by MethodCallNode
   // *BUG* here - casting Integer to an int.
   int pOuter = (int) innerFunctionVal;

   Integer outerFunctionVal;
   if (forceReturnNull)
       outerFunctionVal= null;
   else {
       outerFunctionVal= new Integer(Math.abs(pOuter));

I'm glad that not removing the SQL2Java and Java2SQL nodes seemed to fix
the issue.


View raw message