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 ka...@apache.org on 2013/12/05 13:08:59 UTC

svn commit: r1548104 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/CastNode.java testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java

Author: kahatlen
Date: Thu Dec  5 12:08:59 2013
New Revision: 1548104

URL: http://svn.apache.org/r1548104
Log:
DERBY-6421: Cast to UDT in CHECK constraint causes NPE or assert failure

Delay binding of target UDT in CastNode till bind time.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CastNode.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CastNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CastNode.java?rev=1548104&r1=1548103&r2=1548104&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CastNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CastNode.java Thu Dec  5 12:08:59 2013
@@ -55,7 +55,10 @@ class CastNode extends ValueNode
 	private int					targetCharType;
 	TypeId	sourceCTI = null;
 	private boolean forDataTypeFunction = false;
-    
+
+    /** The original, unbound descriptor for the target type, if it is a UDT. */
+    private DataTypeDescriptor targetUDT;
+
     /** This variable gets set by the parser to indicate that this CAST node
 	 * has been generated by the parser. This means that we should use the 
      * collation info of the current compilation schema for this node's
@@ -99,7 +102,17 @@ class CastNode extends ValueNode
              ContextManager cm) throws StandardException {
         super(cm);
         this.castOperand = castOperand;
-        setType(castTarget);
+
+        // DERBY-6421: setType() tries to bind user defined types. We don't
+        // want to do any binding here, since we could be called during
+        // parsing. If the target type is a UDT, just store it for now and
+        // do the binding later when bindExpression() or bindCastNodeOnly()
+        // is called.
+        if (castTarget.getTypeId().isUserDefinedTypeId()) {
+            targetUDT = castTarget;
+        } else {
+            setType(castTarget);
+        }
 	}
 
 	/**
@@ -192,6 +205,11 @@ class CastNode extends ValueNode
 								fromList, subqueryList,
                                 aggregates);
 
+        // Bind the target UDT.
+        if (targetUDT != null) {
+            setType(targetUDT);
+        }
+
 		if (getTypeServices() == null)   //CHAR or VARCHAR function without specifying target length
 		{
 			DataTypeDescriptor opndType = castOperand.getTypeServices();
@@ -355,6 +373,10 @@ class CastNode extends ValueNode
     void bindCastNodeOnly()
 		throws StandardException
 	{
+        // Bind the target UDT.
+        if (targetUDT != null) {
+            setType(targetUDT);
+        }
 
 		/*
 		** The result type is always castTarget.

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java?rev=1548104&r1=1548103&r2=1548104&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UDTTest.java Thu Dec  5 12:08:59 2013
@@ -28,6 +28,8 @@ import java.sql.ParameterMetaData;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.HashMap;
 
 import junit.framework.Test;
@@ -48,7 +50,6 @@ public class UDTTest  extends GeneratedC
     ///////////////////////////////////////////////////////////////////////////////////
 
     public static final String OBJECT_EXISTS = "X0Y68";
-    public static final String SYNTAX_ERROR = "42X01";
     public static final String VIEW_DEPENDS_ON_TYPE = "X0Y23";
     public static final String TRIGGER_DEPENDS_ON_TYPE = "X0Y24";
 
@@ -1219,6 +1220,25 @@ public class UDTTest  extends GeneratedC
         assertEquals( "[ 0, 0 ]", obj.toString() );
     }
 
+    /**
+     * Verify that you can cast a value to an UDT in a generation clause or
+     * a CHECK constraint. Regression test case for DERBY-6421.
+     */
+    public void test_18_derby6421() throws SQLException {
+        setAutoCommit(false);
+
+        Statement s = createStatement();
+        s.execute("create type d6421_type external name 'java.util.ArrayList' "
+                + "language java");
+        s.execute("create table d6421_table "
+                + "(x generated always as (cast(null as d6421_type)), "
+                + "check (cast(null as d6421_type) is null))");
+
+        // This insert used to cause assert failure (in sane builds) or
+        // NullPointerException (in insane builds).
+        s.execute("insert into d6421_table values default");
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // PROCEDURES AND FUNCTIONS