db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r884970 - in /db/derby/code/trunk/java: engine/org/apache/derby/catalog/ engine/org/apache/derby/catalog/types/ engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/mast...
Date Fri, 27 Nov 2009 19:24:14 GMT
Author: rhillegas
Date: Fri Nov 27 19:24:13 2009
New Revision: 884970

URL: http://svn.apache.org/viewvc?rev=884970&view=rev
Log:
DERBY-651: Add ability to declare UDT columns, parameters, and return values.

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/Price.java   (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/TypeDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DecimalTypeIdImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypeDescriptorImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/UserDefinedTypeIdImpl.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/TypeId.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/UserType.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateAliasNode.java
    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/QueryTreeNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/db2Compatibility.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.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/catalog/TypeDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/TypeDescriptor.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/TypeDescriptor.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/TypeDescriptor.java Fri Nov 27 19:24:13 2009
@@ -186,6 +186,11 @@
 	  */
 	public	boolean isRowMultiSet();
     
+	/**
+	 * Return true if this is a user defined type
+	  */
+	public	boolean isUserDefinedType();
+    
     /**
      * If this catalog type is a row multi-set type
      * then return its array of catalog types.

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/BaseTypeIdImpl.java Fri Nov 27 19:24:13 2009
@@ -72,7 +72,12 @@
     
     private int   formatId;
 
-    String        SQLTypeName;
+    // schema where the type lives. only for UDTs
+    private String schemaName;
+
+    // unqualified type name
+    String unqualifiedName;
+
     /**
      * JDBC type - derived from the format identifier.
      */
@@ -99,26 +104,50 @@
     /**
      * Constructor for an BaseTypeIdImpl
      *
-     * @param SQLTypeName   The SQL name of the type
+     * @param SQLTypeName   The unqualified SQL name of the type
      */
 
     BaseTypeIdImpl(String SQLTypeName)
     {
-        this.SQLTypeName = SQLTypeName;
+        this.schemaName = null;
+        this.unqualifiedName = SQLTypeName;
+    }
+
+    /**
+     * Constructor for an BaseTypeIdImpl which describes a UDT
+     *
+     * @param schemaName The schema that the UDT lives in
+     * @param qualifiedName The qualified name of the UDT in that schema
+     */
+
+    BaseTypeIdImpl(String schemaName, String unqualifiedName )
+    {
+        this.schemaName = schemaName;
+        this.unqualifiedName = unqualifiedName;
     }
 
     /**
-     * Returns the SQL name of the datatype. If it is a user-defined type,
+     * Returns the SQL name of the datatype. If it is a Derby user-defined type,
      * it returns the full Java path name for the datatype, meaning the
-     * dot-separated path including the package names.
+     * dot-separated path including the package names. If it is a UDT, returns
+     * "schemaName"."unqualifiedName".
      *
      * @return      A String containing the SQL name of this type.
      */
     public String   getSQLTypeName()
     {
-        return SQLTypeName;
+        if ( schemaName == null ) { return unqualifiedName; }
+        else { return doubleQuote( schemaName ) + '.' + doubleQuote( unqualifiedName ); }
     }
 
+    /** Get the schema name of this type. Non-null only for UDTs */
+    public String getSchemaName() { return schemaName; }
+
+    /** Get the unqualified name of this type. Except for UDTs, this is the same
+     * value as getSQLTypeName()
+     */
+    public String getUnqualifiedName() { return unqualifiedName; }
+
     /**
      * Get the jdbc type id for this type.  JDBC type can be
      * found in java.sql.Types. 
@@ -237,7 +266,19 @@
     public void readExternal( ObjectInput in )
              throws IOException, ClassNotFoundException
     {
-        SQLTypeName = in.readUTF();
+        unqualifiedName = in.readUTF();
+
+        //
+        // If the name begins with a quote, then it is just the first part
+        // of the type name, viz., the schema that the type lives in.
+        // Strip the quotes from around the name and then read the
+        // following  unqualified name.
+        //
+        if ( unqualifiedName.charAt( 0 ) == '"' )
+        {
+            schemaName = stripQuotes( unqualifiedName );
+            unqualifiedName = in.readUTF();
+        }
     }
 
     /**
@@ -250,7 +291,18 @@
     public void writeExternal( ObjectOutput out )
              throws IOException
     {
-        out.writeUTF( SQLTypeName );
+        if ( schemaName == null ) { out.writeUTF( unqualifiedName ); }
+        else
+        {
+            //
+            // Wrap the schema name in quotes. quotes are illegal characters in
+            // basic SQL type names and in Java class names, so this will flag
+            // readExternal() that this type has a 2-part name
+            // (schemaName.unqualifiedName).
+            //
+            out.writeUTF( doubleQuote( schemaName ) );
+            out.writeUTF( unqualifiedName );
+        }
     }
 
     private void setTypeIdSpecificInstanceVariables()
@@ -258,109 +310,130 @@
         switch (formatId)
         {
           case StoredFormatIds.BOOLEAN_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.BOOLEAN_NAME;
-                JDBCTypeId = JVMInfo.JAVA_SQL_TYPES_BOOLEAN;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.BOOLEAN_NAME;
+              JDBCTypeId = JVMInfo.JAVA_SQL_TYPES_BOOLEAN;
+              break;
 
           case StoredFormatIds.INT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.INTEGER_NAME;
-                JDBCTypeId = Types.INTEGER;
-                 break;
+              schemaName = null;
+              unqualifiedName = TypeId.INTEGER_NAME;
+              JDBCTypeId = Types.INTEGER;
+              break;
 
           case StoredFormatIds.SMALLINT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.SMALLINT_NAME;
-                JDBCTypeId = Types.SMALLINT;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.SMALLINT_NAME;
+              JDBCTypeId = Types.SMALLINT;
+              break;
 
           case StoredFormatIds.TINYINT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.TINYINT_NAME;
-                JDBCTypeId = Types.TINYINT;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.TINYINT_NAME;
+              JDBCTypeId = Types.TINYINT;
+              break;
 
           case StoredFormatIds.LONGINT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.LONGINT_NAME;
-                JDBCTypeId = Types.BIGINT;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.LONGINT_NAME;
+              JDBCTypeId = Types.BIGINT;
+              break;
 
           case StoredFormatIds.DECIMAL_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.DECIMAL_NAME;
-                JDBCTypeId = Types.DECIMAL;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.DECIMAL_NAME;
+              JDBCTypeId = Types.DECIMAL;
+              break;
 
           case StoredFormatIds.DOUBLE_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.DOUBLE_NAME;
-                JDBCTypeId = Types.DOUBLE;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.DOUBLE_NAME;
+              JDBCTypeId = Types.DOUBLE;
+              break;
 
           case StoredFormatIds.REAL_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.REAL_NAME;
-                JDBCTypeId = Types.REAL;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.REAL_NAME;
+              JDBCTypeId = Types.REAL;
+              break;
                 
           case StoredFormatIds.REF_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.REF_NAME;
-                JDBCTypeId = Types.OTHER;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.REF_NAME;
+              JDBCTypeId = Types.OTHER;
+              break;
 
           case StoredFormatIds.CHAR_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.CHAR_NAME;
-                JDBCTypeId = Types.CHAR;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.CHAR_NAME;
+              JDBCTypeId = Types.CHAR;
+              break;
 
           case StoredFormatIds.VARCHAR_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.VARCHAR_NAME;
-                JDBCTypeId = Types.VARCHAR;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.VARCHAR_NAME;
+              JDBCTypeId = Types.VARCHAR;
+              break;
 
           case StoredFormatIds.LONGVARCHAR_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.LONGVARCHAR_NAME;
-                JDBCTypeId = Types.LONGVARCHAR;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.LONGVARCHAR_NAME;
+              JDBCTypeId = Types.LONGVARCHAR;
+              break;
 
           case StoredFormatIds.CLOB_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.CLOB_NAME;
-                JDBCTypeId = Types.CLOB;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.CLOB_NAME;
+              JDBCTypeId = Types.CLOB;
+              break;
 
           case StoredFormatIds.BIT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.BIT_NAME;
-                JDBCTypeId = Types.BINARY;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.BIT_NAME;
+              JDBCTypeId = Types.BINARY;
+              break;
 
           case StoredFormatIds.VARBIT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.VARBIT_NAME;
-                JDBCTypeId = Types.VARBINARY;
-               break;
+              schemaName = null;
+              unqualifiedName = TypeId.VARBIT_NAME;
+              JDBCTypeId = Types.VARBINARY;
+              break;
 
           case StoredFormatIds.LONGVARBIT_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.LONGVARBIT_NAME;
-                JDBCTypeId = Types.LONGVARBINARY;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.LONGVARBIT_NAME;
+              JDBCTypeId = Types.LONGVARBINARY;
+              break;
 
           case StoredFormatIds.BLOB_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.BLOB_NAME;
-                JDBCTypeId = Types.BLOB;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.BLOB_NAME;
+              JDBCTypeId = Types.BLOB;
+              break;
 
           case StoredFormatIds.DATE_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.DATE_NAME;
-                JDBCTypeId = Types.DATE;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.DATE_NAME;
+              JDBCTypeId = Types.DATE;
+              break;
 
           case StoredFormatIds.TIME_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.TIME_NAME;
-                JDBCTypeId = Types.TIME;
-                 break;
+              schemaName = null;
+              unqualifiedName = TypeId.TIME_NAME;
+              JDBCTypeId = Types.TIME;
+              break;
 
           case StoredFormatIds.TIMESTAMP_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.TIMESTAMP_NAME;
-                JDBCTypeId = Types.TIMESTAMP;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.TIMESTAMP_NAME;
+              JDBCTypeId = Types.TIMESTAMP;
+              break;
 
           case StoredFormatIds.XML_TYPE_ID_IMPL:
-                SQLTypeName = TypeId.XML_NAME;
-                JDBCTypeId = JDBC40Translation.SQLXML;
-                break;
+              schemaName = null;
+              unqualifiedName = TypeId.XML_NAME;
+              JDBCTypeId = JDBC40Translation.SQLXML;
+              break;
 
           default:
                 if (SanityManager.DEBUG)
@@ -370,4 +443,11 @@
                 break;
         }
     }
+
+    // wrap a string in quotes
+    private String doubleQuote( String raw ) { return '"' + raw + '"'; }
+
+    // strip the bracketing quotes from a string
+    private String stripQuotes( String quoted ) { return quoted.substring( 1, quoted.length() - 1 ); }
+    
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DecimalTypeIdImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DecimalTypeIdImpl.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DecimalTypeIdImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/DecimalTypeIdImpl.java Fri Nov 27 19:24:13 2009
@@ -80,7 +80,7 @@
 
 	private void setNumericType()
 	{
-		SQLTypeName = "NUMERIC";
+		unqualifiedName = "NUMERIC";
 		JDBCTypeId = Types.NUMERIC;
 	}
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypeDescriptorImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypeDescriptorImpl.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypeDescriptorImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/TypeDescriptorImpl.java Fri Nov 27 19:24:13 2009
@@ -395,6 +395,15 @@
 		return typeId instanceof RowMultiSetImpl;
 	}
 
+	/**
+	* @see TypeDescriptor#isUserDefinedType
+	 */
+    public	boolean isUserDefinedType()
+    {
+        return typeId.userType();
+    }
+
+
 	/** @see TypeDescriptor#getCollationType() */
 	public int	getCollationType()
 	{

Modified: db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/UserDefinedTypeIdImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/UserDefinedTypeIdImpl.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/UserDefinedTypeIdImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/catalog/types/UserDefinedTypeIdImpl.java Fri Nov 27 19:24:13 2009
@@ -54,7 +54,8 @@
 
 	/**
 	 * Constructor for a UserDefinedTypeIdImpl. The SQLTypeName of a UserDefinedType
-	 * is assumed to be its className.
+	 * is assumed to be its className for Derby-only UserDefinedTypes. For
+	 * actual user created UDTs, the SQLTypeName is a schema qualified name.
 	 *
 	 * @param className	The SQL name of the type
 	 */
@@ -66,6 +67,21 @@
 		JDBCTypeId = java.sql.Types.JAVA_OBJECT;
 	}
 
+	/**
+	 * Constructor for a UDT.
+	 *
+	 * @param schemaName	Schema that the UDT lives in.
+	 * @param unqualifiedName	The name of the type inside that schema.
+	 * @param className	The Java class  bound to the SQL type.
+	 */
+
+	public UserDefinedTypeIdImpl(String schemaName, String unqualifiedName, String className)
+	{
+		super( schemaName, unqualifiedName );
+		this.className = className;
+		JDBCTypeId = java.sql.Types.JAVA_OBJECT;
+	}
+
 
 	/** Return the java class name for this type */
 	public String	getClassName()
@@ -78,6 +94,10 @@
 	{
 		return true;
 	}
+    
+	/** Has this user type been bound? */
+	public boolean isBound() { return !(className == null); }
+
 	// Formatable interface.
 
 	/**
@@ -107,6 +127,13 @@
 		 throws IOException
 	{
 		super.writeExternal( out );
+
+        // If the class name is null, then an internal error has occurred. We
+        // are trying to persist a UDT descriptor which has not been bound yet
+        if ( className == null )
+        {
+            throw new IOException( "Internal error: class name for user defined type has not been determined yet." );
+        }
 		out.writeUTF( className );
 	}
 	/**

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=884970&r1=884969&r2=884970&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 Fri Nov 27 19:24:13 2009
@@ -26,6 +26,7 @@
 import org.apache.derby.catalog.TypeDescriptor;
 import org.apache.derby.catalog.types.BaseTypeIdImpl;
 import org.apache.derby.catalog.types.DecimalTypeIdImpl;
+import org.apache.derby.catalog.types.TypeDescriptorImpl;
 import org.apache.derby.catalog.types.UserDefinedTypeIdImpl;
 import org.apache.derby.iapi.reference.JDBC40Translation;
 import org.apache.derby.iapi.reference.Limits;
@@ -378,6 +379,19 @@
                                         );
         }
 
+    /**
+     * This factory  method is used for UDTs. If the className argument is null,
+     * then this TypeId will have to be bound.
+     */
+    public static TypeId getUserDefinedTypeId(String schemaName, String unqualifiedName, String className )
+    {
+        return new TypeId
+            (
+             StoredFormatIds.USERDEFINED_TYPE_ID_V3,
+             new UserDefinedTypeIdImpl(schemaName, unqualifiedName, className )
+             );
+    }
+
         /**
          * Get a TypeId for the class that corresponds to the given Java type
          * name.
@@ -570,15 +584,21 @@
      * @param catalogType
      * @return TypeId that represents the base type, null if not applicable.
      */
-    static TypeId getTypeId(TypeDescriptor catalogType)
+    public static TypeId getTypeId(TypeDescriptor catalogType)
     {
+        TypeDescriptorImpl tdi = (TypeDescriptorImpl) catalogType;
         final int jdbcType = catalogType.getJDBCTypeId();
         TypeId typeId = TypeId.getBuiltInTypeId(jdbcType);
         if (typeId != null)
             return typeId;
         
         if (jdbcType == Types.JAVA_OBJECT) {
-            return TypeId.getUserDefinedTypeId(catalogType.getTypeName(), false);
+            return new TypeId( StoredFormatIds.USERDEFINED_TYPE_ID_V3, tdi.getTypeId() );
+        }
+
+        if ( tdi.isRowMultiSet() )
+        {
+            return new TypeId( StoredFormatIds.ROW_MULTISET_TYPE_ID_IMPL, tdi.getTypeId() );
         }
         
         return null;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/UserType.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/UserType.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/UserType.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/UserType.java Fri Nov 27 19:24:13 2009
@@ -235,6 +235,11 @@
 		return super.getTimestamp(cal);
 	}
 
+	void setObject(Object theValue)
+    {
+        setValue( theValue );
+    }
+    
 	public Object getObject()
 	{
 		return value;

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ColumnDefinitionNode.java Fri Nov 27 19:24:13 2009
@@ -399,14 +399,14 @@
 		if (!getType().getTypeId().userType())
 			return;
 
+        // bind the UDT if necessary
+        setType( bindUserType( getType() ) );
+
 		ClassInspector classInspector = getClassFactory().getClassInspector();
 
 		columnTypeName =
 			getType().getTypeId().getCorrespondingJavaTypeName();
 
-
-
-
 		/* User type - We first check for the columnTypeName as a java class.
 		 * If that fails, then we treat it as a class alias.
 		 */

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=884970&r1=884969&r2=884970&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 Fri Nov 27 19:24:13 2009
@@ -168,7 +168,7 @@
 					for (int i = 0; i < paramCount; i++) {
 						modes[i] = ((Integer) (((Vector) parameters[2]).elementAt(i))).intValue();
 
-						if (TypeId.getBuiltInTypeId(types[i].getJDBCTypeId()).isLongConcatableTypeId())
+						if ( (!types[ i ].isUserDefinedType()) && TypeId.getBuiltInTypeId(types[i].getJDBCTypeId()).isLongConcatableTypeId())
 							throw StandardException.newException(SQLState.LANG_LONG_DATA_TYPE_NOT_ALLOWED, names[i]);
 
 					}
@@ -205,9 +205,22 @@
 				else
 					calledOnNullInput = calledOnNullInputO.booleanValue();
 
+                // bind the return type if it is a user defined type. this fills
+                // in the class name.
+                TypeDescriptor returnType = (TypeDescriptor) routineElements[RETURN_TYPE];
+                if ( returnType != null )
+                {
+                    DataTypeDescriptor dtd = DataTypeDescriptor.getType( returnType );
+                    if ( dtd.getTypeId().isUserDefinedTypeId() )
+                    {
+                        dtd = bindUserType( dtd );
+                        returnType = dtd.getCatalogType();
+                    }
+                }
+
 				aliasInfo = new RoutineAliasInfo(this.methodName, paramCount, names, types, modes, drs,
 						((Short) routineElements[PARAMETER_STYLE]).shortValue(),	// parameter style
-                        sqlAllowed, isDeterministic, calledOnNullInput, (TypeDescriptor) routineElements[RETURN_TYPE]);
+                        sqlAllowed, isDeterministic, calledOnNullInput, returnType );
 
 				implicitCreateSchema = true;
 				}
@@ -314,6 +327,7 @@
             ((RoutineAliasInfo)aliasInfo).setCollationTypeForAllStringTypes(
                     getSchemaDescriptor().getCollationType());
 
+            bindParameterTypes( (RoutineAliasInfo)aliasInfo );
 		}
 		// Procedures and functions do not check class or method validity until
 		// runtime execution. Synonyms do need some validity checks.
@@ -345,6 +359,29 @@
 
 	}
 
+    /** Bind the class names for UDTs */
+    private void bindParameterTypes( RoutineAliasInfo aliasInfo ) throws StandardException
+    {
+        TypeDescriptor[] parameterTypes = aliasInfo.getParameterTypes();
+
+        if ( parameterTypes == null ) { return; }
+
+        int count = parameterTypes.length;
+        for ( int i = 0; i < count; i++ )
+        {
+            TypeDescriptor td = parameterTypes[ i ];
+
+            // if this is a user defined type, resolve the Java class name
+            if ( td.isUserDefinedType() )
+            {
+                DataTypeDescriptor dtd = DataTypeDescriptor.getType( td );
+
+                dtd = bindUserType( dtd );
+                parameterTypes[ i ] = dtd.getCatalogType();
+            }
+        }
+    }
+
 	/**
 	 * Create the Constant information that will drive the guts of Execution.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java?rev=884970&r1=884969&r2=884970&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 Fri Nov 27 19:24:13 2009
@@ -45,6 +45,9 @@
 import org.apache.derby.iapi.sql.compile.TypeCompiler;
 import org.apache.derby.catalog.TypeDescriptor;
 
+import org.apache.derby.catalog.types.TypeDescriptorImpl;
+import org.apache.derby.catalog.types.UserDefinedTypeIdImpl;
+
 import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.reference.JDBC30Translation;
 
@@ -760,7 +763,7 @@
 		else
 		{
 			String promoteName = null;
-			TypeDescriptor returnType = routineInfo.getReturnType();
+			TypeDescriptorImpl returnType = (TypeDescriptorImpl) routineInfo.getReturnType();
 			String requiredType;
 			if (returnType == null)
 			{
@@ -778,6 +781,10 @@
 				{
 				    requiredType = ResultSet.class.getName();
 				}
+                else if ( returnType.getTypeId().userType() )
+                {
+                    requiredType = ((UserDefinedTypeIdImpl) returnType.getTypeId()).getClassName();
+                }
 				else
 				{
 			 		requiredType = returnTypeId.getCorrespondingJavaTypeName();

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/QueryTreeNode.java Fri Nov 27 19:24:13 2009
@@ -26,6 +26,7 @@
 
 import org.apache.derby.catalog.AliasInfo;
 import org.apache.derby.catalog.types.SynonymAliasInfo;
+import org.apache.derby.catalog.types.UserDefinedTypeIdImpl;
 import org.apache.derby.iapi.services.i18n.MessageService;
 import org.apache.derby.iapi.error.StandardException;
 import org.apache.derby.iapi.reference.ClassName;
@@ -1310,6 +1311,7 @@
                 this.getLanguageConnectionContext().getTransactionCompile());
 		if (td == null || td.isSynonymDescriptor())
 			return null;
+
 		return td;
 	}
 
@@ -1597,6 +1599,42 @@
 	}
 
     /**
+     * Bind a UDT. This involves looking it up in the DataDictionary and filling
+     * in its class name.
+     */
+    public DataTypeDescriptor bindUserType( DataTypeDescriptor originalDTD ) throws StandardException
+    {
+        // nothing to do if this is not a user defined type
+        if ( !originalDTD.getTypeId().userType() ) { return originalDTD; }
+
+        UserDefinedTypeIdImpl userTypeID = (UserDefinedTypeIdImpl) originalDTD.getTypeId().getBaseTypeId();
+
+        // also nothing to do if the type has already been resolved
+        if ( userTypeID.isBound() ) { return originalDTD; }
+
+        // ok, we have an unbound UDT. lookup this type in the data dictionary
+
+        DataDictionary dd = getDataDictionary();
+        SchemaDescriptor typeSchema = getSchemaDescriptor( userTypeID.getSchemaName() );
+        char  udtNameSpace = AliasInfo.ALIAS_NAME_SPACE_UDT_AS_CHAR;
+        String unqualifiedTypeName = userTypeID.getUnqualifiedName();
+        AliasDescriptor ad = dd.getAliasDescriptor( typeSchema.getUUID().toString(), unqualifiedTypeName, udtNameSpace );
+
+		if (ad == null)
+		{
+			throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, ad.getAliasType(udtNameSpace),  unqualifiedTypeName);
+		}
+
+        DataTypeDescriptor result = new DataTypeDescriptor
+            (
+             TypeId.getUserDefinedTypeId( typeSchema.getSchemaName(), unqualifiedTypeName, ad.getJavaClassName() ),
+             originalDTD.isNullable()
+             );
+
+        return result;
+    }
+
+    /**
      * Common code for the 2 checkReliability functions.  Always throws StandardException.
      *
      * @param fragmentType Type of fragment as a string, for inclusion in error messages.

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java?rev=884970&r1=884969&r2=884970&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 Fri Nov 27 19:24:13 2009
@@ -271,7 +271,7 @@
 				optimizeDomainValueConversion();
 			
 			TypeDescriptor returnType = routineInfo.getReturnType();
-			if (returnType != null && !returnType.isRowMultiSet())
+			if ( returnType != null && !returnType.isRowMultiSet() && !returnType.isUserDefinedType() )
 			{
 				TypeId returnTypeId = TypeId.getBuiltInTypeId(returnType.getJDBCTypeId());
 
@@ -424,7 +424,7 @@
 
 				TypeDescriptor td = parameterTypes[p];
 
-				TypeId typeId = TypeId.getBuiltInTypeId(td.getJDBCTypeId());
+				TypeId typeId = TypeId.getTypeId(td);
 
 				TypeId parameterTypeId = typeId;
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Fri Nov 27 19:24:13 2009
@@ -288,13 +288,13 @@
 				);
 	}
 
-	private DataTypeDescriptor getJavaClassDataTypeDescriptor(String javaClassName) 
+	private DataTypeDescriptor getJavaClassDataTypeDescriptor(TableName typeName) 
 	{
-		return new DataTypeDescriptor(
-					TypeId.getUserDefinedTypeId(
-								javaClassName, 
-								lastTokenDelimitedIdentifier.booleanValue()),
-					true);
+		return new DataTypeDescriptor
+            (
+                TypeId.getUserDefinedTypeId( typeName.getSchemaName(), typeName.getTableName(), null ),
+                true
+            );
 	}
 	private LanguageConnectionContext getLanguageConnectionContext()
 	{
@@ -668,6 +668,30 @@
 	}
 
 	/**
+	 * Determine whether the next sequence of tokens represents 
+	 * a datatype (could be a common datatype or a schema qualified UDT name).
+	 *
+	 * @return	TRUE iff the next set of tokens names a datatype
+	 */
+	boolean dataTypeCheck(int start)
+	{
+        if ( commonDatatypeName( start, false ) ) { return true; }
+
+        boolean retval = true;
+
+		switch (getToken(start).kind)
+		{
+		  case COMMA:
+		  case LEFT_PAREN:
+		  case RIGHT_PAREN:
+			retval = false;
+            break;
+        }
+
+        return retval;
+    }
+
+	/**
 	 * Determine whether a sequence of tokens represents one of
 	 * the common (built-in) datatypes.
 	 *
@@ -3790,6 +3814,12 @@
 	{
 		return typeDescriptor;
 	}
+|
+    LOOKAHEAD ( { getToken(1).kind != GENERATED } )
+	typeDescriptor = javaType()
+	{
+		return typeDescriptor;
+	}
 }
 
 /**
@@ -4336,12 +4366,12 @@
 DataTypeDescriptor
 javaType() throws StandardException :
 {
-	String	javaClassName;
+	TableName	typeName;
 }
 {
-	javaClassName = javaClassName() 
+	typeName = qualifiedName(Limits.MAX_IDENTIFIER_LENGTH)
 	{
-		return getJavaClassDataTypeDescriptor(javaClassName);
+		return getJavaClassDataTypeDescriptor(typeName);
 	}
 }
 
@@ -10358,7 +10388,7 @@
 	inout = inoutParameter()
 	
 	// Lookahead needed because token could satisfy identifier and dataTypeDDL
-	[   LOOKAHEAD( { commonDatatypeName(2, false) })
+	[   LOOKAHEAD( { dataTypeCheck(2) })
 	    parameterName = identifier(Limits.MAX_IDENTIFIER_LENGTH, true)
 	]
 	typeDescriptor = dataTypeDDL()
@@ -10453,7 +10483,7 @@
 }
 {
 	// Lookahead needed because token could satisfy identifier and dataTypeDDL
-	[   LOOKAHEAD( { commonDatatypeName(2, false) })
+	[   LOOKAHEAD( { dataTypeCheck(2) })
 	    parameterName = identifier(Limits.MAX_IDENTIFIER_LENGTH, true)
 	]
 	typeDescriptor = dataTypeDDL() 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/db2Compatibility.out
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/db2Compatibility.out?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/db2Compatibility.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/db2Compatibility.out Fri Nov 27 19:24:13 2009
@@ -178,22 +178,19 @@
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
 ij> create table NOTYPE(i int, b TINYINT);
-ERROR 42X01: Syntax error: Encountered "TINYINT" at line 1, column 30.
-Issue the 'help' command for general information on IJ command syntax.
-Any unrecognized commands are treated as potential SQL commands and executed directly.
-Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
+ERROR 42X94: TYPE 'TINYINT' does not exist.
 ij> create table NOTYPE(i int, b java.lang.String);
-ERROR 42X01: Syntax error: Encountered "java" at line 1, column 30.
+ERROR 42X01: Syntax error: Encountered "." at line 1, column 39.
 Issue the 'help' command for general information on IJ command syntax.
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
 ij> create table NOTYPE(i int, b com.acme.Address);
-ERROR 42X01: Syntax error: Encountered "com" at line 1, column 30.
+ERROR 42X01: Syntax error: Encountered "." at line 1, column 38.
 Issue the 'help' command for general information on IJ command syntax.
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
 ij> create table NOTYPE(i int, b org.apache.derby.vti.VTIEnvironment);
-ERROR 42X01: Syntax error: Encountered "org" at line 1, column 30.
+ERROR 42X01: Syntax error: Encountered "." at line 1, column 40.
 Issue the 'help' command for general information on IJ command syntax.
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
@@ -587,12 +584,12 @@
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
 ij> create table mm (x org.apache.derbyTesting.functionTests.util.ManyMethods);
-ERROR 42X01: Syntax error: Encountered "org" at line 1, column 20.
+ERROR 42X01: Syntax error: Encountered "." at line 1, column 30.
 Issue the 'help' command for general information on IJ command syntax.
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
 ij> create table sc (x org.apache.derbyTesting.functionTests.util.SubClass);
-ERROR 42X01: Syntax error: Encountered "org" at line 1, column 20.
+ERROR 42X01: Syntax error: Encountered "." at line 1, column 30.
 Issue the 'help' command for general information on IJ command syntax.
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
@@ -717,10 +714,7 @@
 ERROR 0A000: Feature not implemented: NATIONAL CHAR VARYING.
 ij> -- tinyint datatype already disabled
 create table testtype10(col1 TINYINT);
-ERROR 42X01: Syntax error: Encountered "TINYINT" at line 2, column 30.
-Issue the 'help' command for general information on IJ command syntax.
-Any unrecognized commands are treated as potential SQL commands and executed directly.
-Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
+ERROR 42X94: TYPE 'TINYINT' does not exist.
 ij> create table testtype11 (a national character large object (1000));
 ERROR 0A000: Feature not implemented: NCLOB.
 ij> -- beetle5426
@@ -735,10 +729,7 @@
 Any unrecognized commands are treated as potential SQL commands and executed directly.
 Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
 ij> create table testtype13 (a Tour);
-ERROR 42X01: Syntax error: Encountered "Tour" at line 1, column 28.
-Issue the 'help' command for general information on IJ command syntax.
-Any unrecognized commands are treated as potential SQL commands and executed directly.
-Consult your DBMS server reference documentation for details of the SQL syntax supported by your server.
+ERROR 42X94: TYPE 'TOUR' does not exist.
 ij> -- clean up
 drop table testtype1;
 ERROR 42Y55: 'DROP TABLE' cannot be performed on 'TESTTYPE1' because it does not exist.

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java?rev=884970&r1=884969&r2=884970&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java Fri Nov 27 19:24:13 2009
@@ -70,7 +70,7 @@
         
         //-- parser error
         //-- bug 5701        
-        assertStatementError("42X01",30000,s,"create table t(i nt, s smallint)");
+        assertStatementError("42X94",30000,s,"create table t(i nt, s smallint)");
         
         //-- non-boolean where clause
         assertStatementError("42X19", 30000, s, "select * from t where i");

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/Price.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/Price.java?rev=884970&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/Price.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/Price.java Fri Nov 27 19:24:13 2009
@@ -0,0 +1,105 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.lang.Price
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.functionTests.tests.lang;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+
+/**
+ * Sample UDT for tests.
+ */
+public class Price implements Externalizable
+{
+    // initial version id
+    private static final int FIRST_VERSION = 0;
+    private static final int TIMESTAMPED_VERSION = FIRST_VERSION + 1;
+
+    private static final Timestamp DEFAULT_TIMESTAMP = new Timestamp( 0L );
+
+    private static Price _savedPrice;
+
+    public String currencyCode;
+    public BigDecimal amount;
+    public Timestamp timeInstant;
+
+    // methods to be registered as functions
+    public static Price makePrice( String currencyCode, BigDecimal amount, Timestamp timeInstant ) { return new Price( currencyCode, amount, timeInstant ); }
+    public static String getCurrencyCode( Price price ) { return price.currencyCode; }
+    public static BigDecimal getAmount( Price price ) { return price.amount; }
+    public static Timestamp getTimeInstant( Price price ) { return price.timeInstant; }
+    public static void savePrice( Price price ) { _savedPrice = price; }
+    public static Price getSavedPrice() { return _savedPrice; }
+
+    // 0-arg constructor needed by Externalizable machinery
+    public Price() {}
+
+    public Price( String currencyCode, BigDecimal amount, Timestamp timeInstant )
+    {
+        this.currencyCode = currencyCode;
+        this.amount = amount;
+        this.timeInstant = timeInstant;
+    }
+
+    public String toString()
+    {
+        return "Price( " + currencyCode + ", " + amount + ", " + timeInstant + " )";
+    }
+
+    public boolean equals( Object other )
+    {
+        if ( other == null )  { return false; }
+        if ( !(other instanceof Price) ) { return false; }
+
+        Price that = (Price) other;
+
+        return this.toString().equals( that.toString() );
+    }
+
+    // Externalizable implementation
+    public void writeExternal(ObjectOutput out) throws IOException
+    {
+        // first write the version id
+        out.writeInt( FIRST_VERSION );
+
+        // now write the state
+        out.writeObject( currencyCode );
+        out.writeObject( amount );
+        out.writeObject( timeInstant );
+    }  
+    public void readExternal(ObjectInput in)throws IOException, ClassNotFoundException
+    {
+        // read the version id
+        int oldVersion = in.readInt();
+        if ( oldVersion < FIRST_VERSION ) { throw new IOException( "Corrupt data stream." ); }
+        if ( oldVersion > TIMESTAMPED_VERSION ) { throw new IOException( "Can't deserialize from the future." ); }
+
+        currencyCode = (String) in.readObject();
+        amount = (BigDecimal) in.readObject();
+
+        if ( oldVersion >= TIMESTAMPED_VERSION ) { timeInstant = (Timestamp) in.readObject(); }
+        else { timeInstant = DEFAULT_TIMESTAMP; }
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/Price.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=884970&r1=884969&r2=884970&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 Fri Nov 27 19:24:13 2009
@@ -21,9 +21,11 @@
 
 package org.apache.derbyTesting.functionTests.tests.lang;
 
+import java.math.BigDecimal;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.sql.Timestamp;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -141,6 +143,84 @@
         goodStatement( conn, "create type \"SMALLINT\" external name 'mypackage.foo' language java\n" );
     }
 
+    /**
+     * <p>
+     * Basic column, return value, and parameter support.
+     * </p>
+     */
+    public void test_02_basicColumnRetvalParam() throws Exception
+    {
+        Connection conn = getConnection();
+
+        goodStatement( conn, "create type Price external name 'org.apache.derbyTesting.functionTests.tests.lang.Price' language java\n" );
+        goodStatement( conn, "create table orders( orderID int generated always as identity, customerID int, totalPrice price )\n" );
+        goodStatement
+            ( conn,
+              "create function makePrice( currencyCode char( 3 ), amount decimal( 31, 5 ), timeInstant Timestamp )\n" +
+              "returns Price language java parameter style java no sql\n" +
+              "external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.makePrice'\n");
+        goodStatement
+            ( conn,
+              "create function getCurrencyCode( price Price ) returns char( 3 ) language java parameter style java no sql\n" +
+              "external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.getCurrencyCode'\n" );
+        goodStatement
+            ( conn,
+              "create function getAmount( price Price ) returns decimal( 31, 5 ) language java parameter style java no sql\n" +
+              "external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.getAmount'\n" );
+        goodStatement
+            ( conn,
+              "create function getTimeInstant( price Price ) returns timestamp language java parameter style java no sql\n" +
+              "external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.getTimeInstant'\n" );
+        goodStatement
+            ( conn,
+              "create procedure savePrice( in a Price ) language java parameter style java no sql\n" +
+              "external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.savePrice'\n" );
+        goodStatement
+            ( conn,
+              "create function getSavedPrice() returns Price language java parameter style java no sql\n" +
+              "external name 'org.apache.derbyTesting.functionTests.tests.lang.Price.getSavedPrice'\n" );
+        goodStatement
+            ( conn,
+              "insert into orders( customerID, totalPrice ) values\n" +
+              "( 12345, makePrice( 'USD', cast( 9.99 as decimal( 31, 5 ) ), timestamp('2009-10-16 14:24:43') ) )\n" );
+
+        assertResults
+            (
+             conn,
+             "select getCurrencyCode( totalPrice ), getAmount( totalPrice ), getTimeInstant( totalPrice ) from orders",
+             new String[][]
+             {
+                 { "USD" ,         "9.99000" ,        "1969-12-31 16:00:00.0" },
+             },
+             false
+             );
+        assertResults
+            (
+             conn,
+             "select totalPrice from orders",
+             new String[][]
+             {
+                 { "Price( USD, 9.99000, 1969-12-31 16:00:00.0 )" },
+             },
+             false
+             );
+
+        goodStatement
+            ( conn,
+              "call savePrice\n" +
+              "( makePrice( 'EUR', cast( 1.23 as decimal( 31, 5 ) ), timestamp('1969-12-31 16:00:00') ) )\n" );
+        assertResults
+            (
+             conn,
+             "values( getSavedPrice() )",
+             new String[][]
+             {
+                 { "Price( EUR, 1.23000, 1969-12-31 16:00:00.0 )" },
+             },
+             false
+             );
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////
     //
     // MINIONS



Mime
View raw message