db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r908635 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/sql/compile/ engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/ testing/org/apache/derbyTesting/functionTest...
Date Wed, 10 Feb 2010 19:11:59 GMT
Author: rhillegas
Date: Wed Feb 10 19:11:57 2010
New Revision: 908635

URL: http://svn.apache.org/viewvc?rev=908635&view=rev
Log:
DERBY-4470: Forbid ordering operations on UDTs.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateAliasNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.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/iapi/types/DataTypeDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java?rev=908635&r1=908634&r2=908635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/DataTypeDescriptor.java Wed
Feb 10 19:11:57 2010
@@ -1373,24 +1373,12 @@
     		else
     			return false;
 
-		//User types are comparable to other user types only if
-		//(for now) they are the same type and are being used to
-		//implement some JDBC type.  This is sufficient for
-		//date/time types; it may be generalized later for e.g.
-		//comparison of any user type with one of its subtypes.
-		if (typeId.isUserDefinedTypeId() || typeId.getJDBCTypeId() == Types.OTHER) {
-        	if (forEquals)
-        		return true;
-        	try {
-        	
-        		Class thisClass = cf.getClassInspector().getClass(
-				typeId.getCorrespondingJavaTypeName());
-        		
-        		return java.lang.Comparable.class.isAssignableFrom(thisClass);
-        	} catch (ClassNotFoundException cnfe) {
-        		return false;
-        	}			
-		}
+        // Right now, user defined types are not comparable.
+        // This removes old logic which we might want
+        // to revive when we support comparable UDTs. See
+        // DERBY-4470.
+		if (typeId.isUserDefinedTypeId() || typeId.getJDBCTypeId() == Types.OTHER)
+		{ return false; }
 
 		return false;
 	}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java?rev=908635&r1=908634&r2=908635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java Wed Feb 10 19:11:57
2010
@@ -267,6 +267,32 @@
         private static final TypeId XML_ID = create(
                 StoredFormatIds.XML_TYPE_ID, StoredFormatIds.XML_TYPE_ID_IMPL);
 
+    private static final TypeId[] ALL_BUILTIN_TYPE_IDS =
+    {
+        BOOLEAN_ID,
+        SMALLINT_ID,
+        INTEGER_ID,
+        CHAR_ID,
+        TINYINT_ID,
+        BIGINT_ID,
+        REAL_ID,
+        DOUBLE_ID,
+        DECIMAL_ID,
+        NUMERIC_ID,
+        VARCHAR_ID,
+        DATE_ID,
+        TIME_ID,
+        TIMESTAMP_ID,
+        BIT_ID,
+        VARBIT_ID,
+        REF_ID,
+        LONGVARCHAR_ID,
+        LONGVARBIT_ID,
+        BLOB_ID,
+        CLOB_ID,
+        XML_ID,
+    };
+
         /**
          * Implementation of DECIMAL datatype for generating holders through getNull.
          * Set by the booted DataValueFactory implementation.
@@ -286,6 +312,20 @@
         {
             return new TypeId(typeFormatId, new BaseTypeIdImpl(implTypeFormatId)); 
         }
+
+    /**
+     * Return all of the builtin type ids.
+     */
+    public static TypeId[] getAllBuiltinTypeIds()
+    {
+        int count = ALL_BUILTIN_TYPE_IDS.length;
+
+        TypeId[] retval = new TypeId[ count ];
+
+        for ( int i = 0; i < count; i++ ) { retval[ i ] = ALL_BUILTIN_TYPE_IDS[ i ]; }
+
+        return retval;
+    }
         
         
         /**
@@ -795,6 +835,7 @@
 
                         case StoredFormatIds.REF_TYPE_ID:
                                 typePrecedence = REF_PRECEDENCE;
+                                javaTypeName = "java.sql.Ref";
                                 isRefTypeId = true;
                                 break;
 
@@ -1123,24 +1164,28 @@
                         case StoredFormatIds.USERDEFINED_TYPE_ID_V3:
                                 /* Is this type orderable? */
 
+                            // The following code is disabled until we support
+                            // comparable UDTs.
+                            return false;
+
                                 // For user java classes we are orderable if we
                                 // implement java.lang.Orderable (JDK1.2) or
                                 // have a int compareTo(Object) method (JDK1.1 or JDK1.2)
-                                UserDefinedTypeIdImpl baseUserTypeId =
-                                                                                (UserDefinedTypeIdImpl)
baseTypeId;
-
-                                String className = baseUserTypeId.getClassName();
-
-                                try 
-                                {
-                                        Class c = cf.getClassInspector().getClass(className);
-                                        orderable = java.lang.Comparable.class.isAssignableFrom(c);
-                                } 
-                                catch (ClassNotFoundException cnfe) 
-                                {
-                                        orderable = false;
-                                } 
-                                break;
+                            //                                UserDefinedTypeIdImpl baseUserTypeId
=
+                            //                                                          
                     (UserDefinedTypeIdImpl) baseTypeId;
+                            //
+                            //                                String className = baseUserTypeId.getClassName();
+                            //
+                            //                                try 
+                            //                                {
+                            //                                        Class c = cf.getClassInspector().getClass(className);
+                            //                                        orderable = java.lang.Comparable.class.isAssignableFrom(c);
+                            //                                } 
+                            //                                catch (ClassNotFoundException
cnfe) 
+                            //                                {
+                            //                                        orderable = false;
+                            //                                } 
+                                //                                break;
 
                         default:
                                 orderable = true;
@@ -1187,10 +1232,6 @@
         {
                 if (SanityManager.DEBUG)
                 {
-                        if (formatId == StoredFormatIds.REF_TYPE_ID)
-                        {
-                                SanityManager.THROWASSERT("getCorrespondingJavaTypeName not
implemented for StoredFormatIds.REF_TYPE_ID");
-                        }
                         SanityManager.ASSERT(javaTypeName != null,
                                 "javaTypeName expected to be non-null");
                 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateAliasNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateAliasNode.java?rev=908635&r1=908634&r2=908635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateAliasNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateAliasNode.java
Wed Feb 10 19:11:57 2010
@@ -327,18 +327,53 @@
 
             bindParameterTypes( (RoutineAliasInfo)aliasInfo );
 		}
-		// Procedures and functions do not check class or method validity until
-		// runtime execution. Synonyms do need some validity checks.
-		if (aliasType != AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR)
-			return;
-
+        
         // validity checking for UDTs
         if ( aliasType == AliasInfo.ALIAS_TYPE_UDT_AS_CHAR )
         {
-            // nothing to do yet
+            //
+            // Make sure that the java class name is not the name of a builtin
+            // type. This skirts problems caused by logic across the system
+            // which assumes a tight association between the builtin SQL types
+            // and the Java classes which implement them.
+            //
+            // For security reasons we do not allow the user to bind a UDT
+            // to a Derby class.
+            //
+            TypeId[] allSystemTypeIds = TypeId.getAllBuiltinTypeIds();
+            int systemTypeCount = allSystemTypeIds.length;
+
+            boolean foundConflict = javaClassName.startsWith( "org.apache.derby." );
+
+            if ( !foundConflict )
+            {
+                for ( int i = 0; i < systemTypeCount; i++ )
+                {
+                    TypeId systemType = allSystemTypeIds[ i ];
+                    String systemTypeName = systemType.getCorrespondingJavaTypeName();
+                    
+                    if ( systemTypeName.equals( javaClassName ) )
+                    {
+                        foundConflict = true;
+                        break;
+                    }
+                }
+            }
+            
+            if ( foundConflict )
+            {
+                throw StandardException.newException
+                    ( SQLState.LANG_UDT_BUILTIN_CONFLICT, javaClassName );
+            }
+            
             return;
         }
 
+		// Procedures and functions do not check class or method validity until
+		// runtime execution. Synonyms do need some validity checks.
+		if (aliasType != AliasInfo.ALIAS_TYPE_SYNONYM_AS_CHAR)
+			return;
+
 		// Don't allow creating synonyms in SESSION schema. Causes confusion if
 		// a temporary table is created later with same name.
 		if (isSessionSchema(getSchemaDescriptor().getSchemaName()))

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=908635&r1=908634&r2=908635&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Wed Feb 10 19:11:57
2010
@@ -6148,6 +6148,12 @@
             </msg>
 
             <msg>
+                <name>42Z10</name>
+                <text>The Java class bound to a user defined type may not be a class
used internally by Derby: '{0}'.</text>
+                <arg>javaClassName</arg>
+            </msg>
+
+            <msg>
                 <name>42Z11.U</name>
                 <text>stream</text>
             </msg>

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=908635&r1=908634&r2=908635&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
(original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
Wed Feb 10 19:11:57 2010
@@ -1010,6 +1010,7 @@
 
 	// MORE GENERIC LANGUAGE STUFF
 	String LANG_COLUMN_DEFAULT										   = "42Z09.U";
+	String LANG_UDT_BUILTIN_CONFLICT										   = "42Z10";
 	String LANG_STREAM												   = "42Z11.U";
 
 	// String LANG_UPDATABLE_VTI_BAD_GETMETADATA						   = "42Z14";

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.java?rev=908635&r1=908634&r2=908635&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/GeneratedColumnsHelper.java
Wed Feb 10 19:11:57 2010
@@ -97,6 +97,10 @@
     protected static  final   String  VIEW_DEPENDS_ON_PRIVILEGE = "X0Y23";
     protected static  final   String  NON_EMPTY_SCHEMA = "X0Y54";
     protected static  final   String  JAVA_EXCEPTION = "XJ001";
+    protected static  final   String  ILLEGAL_UDT_CLASS = "42Z10";
+    protected static  final   String  FORBIDDEN_ORDERING_OPERATION = "X0X67";
+    protected static  final   String  ILLEGAL_AGG = "42Y22";
+    protected static  final   String  ILLEGAL_COMPARISON = "42818";
 
     ///////////////////////////////////////////////////////////////////////////////////
     //

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=908635&r1=908634&r2=908635&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
Wed Feb 10 19:11:57 2010
@@ -921,6 +921,104 @@
         expectExecutionError( conn, JAVA_EXCEPTION, "insert into t_13_a( data ) values (
makeSampleSQLData( 3 ) )\n" );
     }
     
+    /**
+     * <p>
+     * Verify that you can't bind UDTs to the classes which back the system types.
+     * </p>
+     */
+    public void test_14_systemClasses() throws Exception
+    {
+        Connection conn = getConnection();
+
+        //
+        // Before checking types, make sure that all types we understand are accounted for.
+        // If a new system type is added, then we need to add it to the following block
+        // of compilation errors.
+        //
+        assertEquals( 20, vetDatatypeCount( conn ) );
+        
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'byte[]' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.lang.Boolean' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.lang.Integer' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.lang.Long' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.lang.Float' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.lang.Double' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.lang.String' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.math.BigDecimal' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.sql.Blob' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.sql.Clob' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.sql.Date' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.sql.Ref' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.sql.Time' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'java.sql.Timestamp' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'org.apache.derby.iapi.types.XML' language java\n" );
+        expectCompilationError( ILLEGAL_UDT_CLASS, "create type java_string external name
'org.apache.derby.Foo' language java\n" );
+    }
+    private int vetDatatypeCount( Connection conn ) throws Exception
+    {
+        ResultSet rs = conn.getMetaData().getTypeInfo();
+        int expectedTypeCount = 0;
+        while ( rs.next() ) { expectedTypeCount++; }
+        rs.close();
+
+        expectedTypeCount--; // eliminate JAVA_OBJECT
+
+        int actualTypeCount = org.apache.derby.iapi.types.TypeId.getAllBuiltinTypeIds().length;
+        actualTypeCount--;  // eliminate BOOLEAN
+        actualTypeCount--;  // eliminate TINYINT
+        actualTypeCount--;  // eliminate REF
+        actualTypeCount++;  // add FLOAT (synonym of REAL)
+
+        //
+        // Make sure that all types have been added to TypeId.getAllBuiltinTypeIds().
+        //
+        assertEquals( expectedTypeCount, actualTypeCount );
+
+        return actualTypeCount;
+    }
+    
+
+    /**
+     * <p>
+     * Verify that UDTs have no ordering.
+     * </p>
+     */
+    public void test_15_ordering() throws Exception
+    {
+        Connection conn = getConnection();
+
+        // Create a Comparable type. We can't take advantage of that interface yet.
+        goodStatement( conn, "create type IntArray_15 external name 'org.apache.derbyTesting.functionTests.tests.lang.IntArray'
language java\n" );
+        goodStatement
+            ( conn,
+              "create function makeIntArray_15( arrayLength int ) returns IntArray_15\n"
+
+              "language java parameter style java no sql external name 'org.apache.derbyTesting.functionTests.tests.lang.IntArray.makeIntArray'\n"
);
+        goodStatement( conn, "create table t_15( a IntArray_15 )\n" );
+        goodStatement( conn, "insert into t_15( a ) values ( makeIntArray_15( 3 ) )\n" );
+        goodStatement( conn, "insert into t_15( a ) values ( makeIntArray_15( 4 ) )\n" );
+
+        expectCompilationError( FORBIDDEN_ORDERING_OPERATION, "create index t_15_idx on t_15(
a )\n" );
+        expectCompilationError( FORBIDDEN_ORDERING_OPERATION, "select * from t_15 order by
a\n" );
+        expectCompilationError( FORBIDDEN_ORDERING_OPERATION, "select * from t_15 group by
a\n" );
+        expectCompilationError( FORBIDDEN_ORDERING_OPERATION, "select distinct a from t_15\n"
);
+        expectCompilationError( ILLEGAL_AGG, "select max( a ) from t_15\n" );
+        expectCompilationError( ILLEGAL_AGG, "select min( a ) from t_15\n" );
+        expectCompilationError( ILLEGAL_AGG, "select avg( a ) from t_15\n" );
+        expectCompilationError( FORBIDDEN_ORDERING_OPERATION, "select * from t_15 union select
* from t_15\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 where a = makeIntArray(
3 )\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 where a between makeIntArray(
2 ) and makeIntArray( 4 )\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 l, t_15 r where l.a
= r.a\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 l, t_15 r where l.a
< r.a\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 l, t_15 r where l.a
> r.a\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 l, t_15 r where l.a
<= r.a\n" );
+        expectCompilationError( ILLEGAL_COMPARISON, "select * from t_15 l, t_15 r where l.a
>= r.a\n" );
+        expectCompilationError( FORBIDDEN_ORDERING_OPERATION, "select count( distinct a )
from t_15\n" );
+
+        // but these don't involve any comparisons
+        goodStatement( conn, "select count(*) from t_15\n" );
+        goodStatement( conn, "select all * from t_15\n" );
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // PROCEDURES AND FUNCTIONS
@@ -956,8 +1054,6 @@
         return ps.executeQuery();
     }
 
-    
-
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // MINIONS



Mime
View raw message