You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by dj...@apache.org on 2006/02/28 04:55:31 UTC

svn commit: r381553 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/master/ testing/org/apache/derbyTesting/functionTests/tests/lang/

Author: djd
Date: Mon Feb 27 19:55:29 2006
New Revision: 381553

URL: http://svn.apache.org/viewcvs?rev=381553&view=rev
Log:
DERBY-479 Fix linkage error when passing the value of a RETURNS NULL ON NULL INPUT function
to another function. Fixed by only removing SQLToJava/JavaToSQL nodes for the function's
return value when the function is a CALLED ON NULL INPUT function.

Fix contributed by Mamta Satoor - msatoor@gmail.com

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/functions.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/functions.sql

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java?rev=381553&r1=381552&r2=381553&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java Mon Feb 27 19:55:29 2006
@@ -200,32 +200,18 @@
 
 			qt = (QueryTreeNode) parameterList.elementAt(index);
 
-
-
 			/*
-			** If the parameter is a SQL ValueNode, there are two
-			** possibilities.  Either it is a JavaValueNode with
-			** a JavaToSQLValueNode on top of it, or it is a plain
-			** SQL ValueNode.  In the former case, just get rid of
-			** the JavaToSQLValueNode.  In the latter case, put a
-			** SQLToJavaValueNode on top of it.  In general, we
-			** want to avoid converting the same value back and forth
-			** between the SQL and Java domains.
+			** Since we need the parameter to be in Java domain format, put a
+			** SQLToJavaValueNode on top of the parameter node if it is a 
+			** SQLValueNode. But if the parameter is already in Java domain 
+			** format, then we don't need to do anything.
 			*/
 			if ( ! (qt instanceof JavaValueNode))
 			{
-				if (qt instanceof JavaToSQLValueNode)
-				{
-					qt = ((JavaToSQLValueNode) qt).getJavaValueNode();
-				}
-				else
-				{
-					qt = (SQLToJavaValueNode) getNodeFactory().
-							getNode(
-								C_NodeTypes.SQL_TO_JAVA_VALUE_NODE,
-								qt,
-								getContextManager());
-				}
+				qt = (SQLToJavaValueNode) getNodeFactory().getNode(
+						C_NodeTypes.SQL_TO_JAVA_VALUE_NODE, 
+						qt, 
+						getContextManager());
 			}
 
 			methodParms[index] = (JavaValueNode) qt;
@@ -545,9 +531,7 @@
 				// In any other case the expression type must be assignable
 				// to the parameter type.
 				if (classInspector.primitiveType(parameterType)) {
-
 					mb.cast(parameterType);
-
 				} else {
 
 					// for a prodcedure

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java?rev=381553&r1=381552&r2=381553&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java Mon Feb 27 19:55:29 2006
@@ -240,6 +240,9 @@
 		// return type, then we need to push a CAST node.
 		if (routineInfo != null)
 		{
+			if (methodParms != null) 
+				optimizeDomainValueConversion();
+			
 			TypeDescriptor returnType = routineInfo.getReturnType();
 			if (returnType != null)
 			{
@@ -283,6 +286,47 @@
 
 		getCompilerContext().addRequiredRoutinePriv(ad);
 		return this;
+	}
+
+	/**
+	 * If this SQL function has parameters which are SQLToJavaValueNode over
+	 * JavaToSQLValueNode and the java value node underneath is a SQL function
+	 * defined with CALLED ON NULL INPUT, then we can get rid of the wrapper
+	 * nodes over the java value node for such parameters. This is because
+	 * SQL functions defined with CALLED ON NULL INPUT need access to only
+	 * java domain values.
+	 * This can't be done for parameters which are wrappers over SQL function
+	 * defined with RETURN NULL ON NULL INPUT because such functions need
+	 * access to both sql domain value and java domain value. - Derby479
+	 */
+	private void optimizeDomainValueConversion() throws StandardException {
+		int		count = methodParms.length;
+		for (int parm = 0; parm < count; parm++)
+		{
+			if (methodParms[parm] instanceof SQLToJavaValueNode &&
+				((SQLToJavaValueNode)methodParms[parm]).getSQLValueNode() instanceof
+				JavaToSQLValueNode)
+			{
+				//If we are here, then it means that the parameter is
+				//SQLToJavaValueNode on top of JavaToSQLValueNode
+				JavaValueNode paramIsJavaValueNode =
+					((JavaToSQLValueNode)((SQLToJavaValueNode)methodParms[parm]).getSQLValueNode()).getJavaValueNode();
+				if (paramIsJavaValueNode instanceof StaticMethodCallNode)
+				{
+					//If we are here, then it means that the parameter has
+					//a MethodCallNode underneath it.
+					StaticMethodCallNode paramIsMethodCallNode = (StaticMethodCallNode)paramIsJavaValueNode;
+					//If the MethodCallNode parameter is defined as
+					//CALLED ON NULL INPUT, then we can remove the wrappers
+					//for the param and just set the parameter to the
+					//java value node.
+					if (paramIsMethodCallNode.routineInfo != null &&
+							paramIsMethodCallNode.routineInfo.calledOnNullInput())
+						methodParms[parm] =
+							((JavaToSQLValueNode)((SQLToJavaValueNode)methodParms[parm]).getSQLValueNode()).getJavaValueNode();
+				}
+			}
+		}
 	}
 
 	/**

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/functions.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/functions.out?rev=381553&r1=381552&r2=381553&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/functions.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/functions.out Mon Feb 27 19:55:29 2006
@@ -549,18 +549,39 @@
 CALLED ON NULL INPUT
 LANGUAGE JAVA PARAMETER STYLE JAVA;
 0 rows inserted/updated/deleted
-ij> -- DERBY-479;
--- VALUES CAST( RN_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
-VALUES CAST( CALL_COS(CALL_RADIANS(90.0)) AS DECIMAL(3,2));
+ij> -- Test cases for DERBY-479
+VALUES CAST( RN_COS(RN_RADIANS(null)) AS DECIMAL(3,2));
+1     
+------
+NULL  
+ij> VALUES CAST( RN_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
+1     
+------
+0.00  
+ij> VALUES CAST( CALL_COS(CALL_RADIANS(90.0)) AS DECIMAL(3,2));
+1     
+------
+0.00  
+ij> VALUES CAST( CALL_COS(CALL_RADIANS(null)) AS DECIMAL(3,2));
+1     
+------
+ERROR 39004: A NULL value cannot be passed to a method which takes a parameter of primitive type 'double'.
+ij> VALUES CAST( CALL_COS(RN_RADIANS(null)) AS DECIMAL(3,2));
+1     
+------
+ERROR 39004: A NULL value cannot be passed to a method which takes a parameter of primitive type 'double'.
+ij> VALUES CAST( CALL_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
 1     
 ------
 0.00  
-ij> -- DERBY-479;
--- VALUES CAST( CALL_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
-VALUES CAST( RN_COS(CALL_RADIANS(90.0)) AS DECIMAL(3,2));
+ij> VALUES CAST( RN_COS(CALL_RADIANS(90.0)) AS DECIMAL(3,2));
 1     
 ------
 0.00  
+ij> VALUES CAST( RN_COS(CALL_RADIANS(null)) AS DECIMAL(3,2));
+1     
+------
+ERROR 39004: A NULL value cannot be passed to a method which takes a parameter of primitive type 'double'.
 ij> DROP FUNCTION RN_COS;
 0 rows inserted/updated/deleted
 ij> DROP FUNCTION RN_RADIANS;

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/functions.sql
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/functions.sql?rev=381553&r1=381552&r2=381553&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/functions.sql (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/functions.sql Mon Feb 27 19:55:29 2006
@@ -247,12 +247,15 @@
 CALLED ON NULL INPUT
 LANGUAGE JAVA PARAMETER STYLE JAVA;
 
--- DERBY-479;
--- VALUES CAST( RN_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
+-- Test cases for DERBY-479
+VALUES CAST( RN_COS(RN_RADIANS(null)) AS DECIMAL(3,2));
+VALUES CAST( RN_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
 VALUES CAST( CALL_COS(CALL_RADIANS(90.0)) AS DECIMAL(3,2));
--- DERBY-479;
--- VALUES CAST( CALL_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
+VALUES CAST( CALL_COS(CALL_RADIANS(null)) AS DECIMAL(3,2));
+VALUES CAST( CALL_COS(RN_RADIANS(null)) AS DECIMAL(3,2));
+VALUES CAST( CALL_COS(RN_RADIANS(90.0)) AS DECIMAL(3,2));
 VALUES CAST( RN_COS(CALL_RADIANS(90.0)) AS DECIMAL(3,2));
+VALUES CAST( RN_COS(CALL_RADIANS(null)) AS DECIMAL(3,2));
 
 DROP FUNCTION RN_COS;
 DROP FUNCTION RN_RADIANS;