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 rh...@apache.org on 2012/10/01 14:49:56 UTC
svn commit: r1392307 - in /db/derby/code/trunk/java:
engine/org/apache/derby/iapi/services/loader/
engine/org/apache/derby/impl/sql/compile/ engine/org/apache/derby/loc/
testing/org/apache/derbyTesting/functionTests/tests/lang/
Author: rhillegas
Date: Mon Oct 1 12:49:55 2012
New Revision: 1392307
URL: http://svn.apache.org/viewvc?rev=1392307&view=rev
Log:
DERBY-672: Allow binding of user-defined aggregates to generic classes.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/ClassInspector.java
db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/Java5ClassInspector.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AggregateNode.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UserAggregateDefinition.java
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java
db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UserDefinedAggregatesTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/ClassInspector.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/ClassInspector.java?rev=1392307&r1=1392306&r2=1392307&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/ClassInspector.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/ClassInspector.java Mon Oct 1 12:49:55 2012
@@ -484,15 +484,11 @@ public class ClassInspector
}
/**
- * Given an implementation of a parameterized class/interface, return
- * the actual concrete types of the parameters. Types are returned in the
- * order that they are declared by the parameterized class/interface.
- * So for instance, if the parameterized class is Map<K,V> and the
- * implementation is HashMap<Integer,String>, then the return value is
- * [ Integer.class, String.class ]. This method raises an exception if the
+ * Given an implementation of a parameterized interface, return
+ * the bounds on the type variables. This method raises an exception if the
* JVM does not support generics. May return null if type resolution fails.
*/
- public Class[] getGenericParameterTypes( Class parameterizedType, Class implementation )
+ public Class[][] getTypeBounds( Class parameterizedInterface, Class implementation )
throws StandardException
{
throw StandardException.newException( SQLState.VM_LEVEL_TOO_LOW, "Java 5" );
Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/Java5ClassInspector.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/Java5ClassInspector.java?rev=1392307&r1=1392306&r2=1392307&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/Java5ClassInspector.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/loader/Java5ClassInspector.java Mon Oct 1 12:49:55 2012
@@ -66,150 +66,88 @@ public class Java5ClassInspector extends
//
///////////////////////////////////////////////////////////////////////////////////
- @Override
- public Class[] getGenericParameterTypes( Class parameterizedType, Class implementation )
- throws StandardException
- {
- // construct the inheritance chain stretching from the parameterized type
- // down to the concrete implemention
- ArrayList<Class<?>> chain = getTypeChain( parameterizedType, implementation );
-
- // walk the chain, filling in a map of generic types to their resolved types
- HashMap<Type,Type> resolvedTypes = getResolvedTypes( chain );
-
- // compose the resolved types together in order to compute the actual
- // classes which are plugged into the variables of the parameterized type
- ArrayList<Class<?>> parameterTypes = getParameterTypes( parameterizedType, resolvedTypes );
-
- // turn the list into an array
- if ( parameterTypes == null ) { return null; }
-
- Class[] result = new Class[ parameterTypes.size() ];
- parameterTypes.toArray( result );
-
- return result;
- }
-
/**
- * Construct an inheritance chain of types stretching from a supertype down
- * to a concrete implementation.
+ * Get the bounds for the type variables of a parameterized interface
+ * as declared for an implementing class. A given set of type bounds could
+ * be null if we're confused.
*/
- private ArrayList<Class<?>> getTypeChain( Class<?> chainEnd, Class<?> start )
+ @Override
+ public Class[][] getTypeBounds( Class parameterizedInterface, Class implementation )
+ throws StandardException
{
- ArrayList<Class<?>> result = null;
+ if ( implementation == null ) { return null; }
- if ( start == null ) { return null; }
- if ( !chainEnd.isAssignableFrom( start ) ) { return null; }
-
- if ( start == chainEnd ) { result = new ArrayList<Class<?>>(); }
- if ( result == null )
+ Type[] genericInterfaces = implementation.getGenericInterfaces();
+ for ( Type genericInterface : genericInterfaces )
{
- result = getTypeChain( chainEnd, start.getSuperclass() );
-
- if ( result == null )
+ //
+ // Look for the generic interface whose raw type is the parameterized interface
+ // we're interested in.
+ //
+ if ( genericInterface instanceof ParameterizedType )
{
- for ( Class<?> iface : start.getInterfaces() )
+ ParameterizedType pt = (ParameterizedType) genericInterface;
+ Type rawType = pt.getRawType();
+
+ // found it!
+ if ( parameterizedInterface == rawType )
{
- result = getTypeChain( chainEnd, iface );
- if ( result != null ) { break; }
+ return findTypeBounds( pt );
}
}
}
- if ( result != null ) { result.add( start ); }
-
- return result;
+ // couldn't find the interface we're looking for. check our superclass.
+ return getTypeBounds( parameterizedInterface, implementation.getSuperclass() );
}
/**
- * Given an inheritance chain of types, stretching from a superclass down
- * to a terminal concrete class, construct a map of generic types to their
- * resolved types.
+ * Get the type bounds for all of the type variables of the given
+ * parameterized type.
*/
- private HashMap<Type,Type> getResolvedTypes( ArrayList<Class<?>> chain )
+ private Class[][] findTypeBounds( ParameterizedType pt )
{
- if ( chain == null ) { return null; }
-
- HashMap<Type,Type> resolvedTypes = new HashMap<Type,Type>();
+ Type[] actualTypeArguments = pt.getActualTypeArguments();
+ int argCount = actualTypeArguments.length;
+ Class[][] retval = new Class[ argCount ][];
- for ( Class<?> klass : chain )
- {
- addResolvedTypes( resolvedTypes, klass.getGenericSuperclass() );
+ for ( int i = 0; i < argCount; i++ ) { retval[ i ] = boundType( actualTypeArguments[ i ] ); }
- for ( Type iface : klass.getGenericInterfaces() )
- {
- addResolvedTypes( resolvedTypes, iface );
- }
- }
-
- return resolvedTypes;
+ return retval;
}
/**
- * Given a generic type, add its parameter types to an evolving
- * map of resolved types. Some of the resolved types may be
- * generic type variables which will need further resolution from
- * other generic types.
+ * Get the bounds for a single type variable.
*/
- private void addResolvedTypes
- ( HashMap<Type,Type> resolvedTypes, Type genericType )
+ private Class[] boundType( Type type )
{
- if ( genericType == null ) { return; }
-
- if ( genericType instanceof ParameterizedType )
+ if ( type instanceof Class )
{
- ParameterizedType pt = (ParameterizedType) genericType;
- Class rawType = (Class) pt.getRawType();
-
- Type[] actualTypeArguments = pt.getActualTypeArguments();
- TypeVariable[] typeParameters = rawType.getTypeParameters();
- for (int i = 0; i < actualTypeArguments.length; i++)
- {
- resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
- }
+ return new Class[] { (Class) type };
}
- }
+ else if ( type instanceof TypeVariable )
+ {
+ Type[] bounds = ((TypeVariable) type).getBounds();
+ int count = bounds.length;
+ Class[] retval = new Class[ count ];
- /**
- * Given a map of resolved types, compose them together in order
- * to resolve the actual concrete types that are plugged into the
- * parameterized type.
- */
- private ArrayList<Class<?>> getParameterTypes
- ( Class<?> parameterizedType, HashMap<Type,Type> resolvedTypes )
- {
- if ( resolvedTypes == null ) { return null; }
-
- Type[] actualTypeArguments = parameterizedType.getTypeParameters();
+ for ( int i = 0; i < count; i++ ) { retval[ i ] = getRawType( bounds[ i ] ); }
- ArrayList<Class<?>> result = new ArrayList<Class<?>>();
-
- // resolve types by composing type variables.
- for (Type baseType: actualTypeArguments)
- {
- while ( resolvedTypes.containsKey( baseType ) )
- {
- baseType = resolvedTypes.get(baseType);
- }
-
- result.add( getClass( baseType ) );
+ return retval;
}
-
- return result;
+ else { return null; }
}
/**
- * Get the underlying class for a type, or null if the type is a variable type.
+ * Get the raw type of a type bound.
*/
- private Class<?> getClass( Type type )
+ private Class getRawType( Type bound )
{
- if ( type instanceof Class ) { return (Class) type; }
- else if (type instanceof ParameterizedType)
- {
- return getClass( ((ParameterizedType) type).getRawType() );
- }
+ if ( bound instanceof Class ) { return (Class) bound; }
+ else if ( bound instanceof ParameterizedType ) { return getRawType( ((ParameterizedType) bound).getRawType() ); }
else { return null; }
}
+
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AggregateNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AggregateNode.java?rev=1392307&r1=1392306&r2=1392307&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AggregateNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/AggregateNode.java Mon Oct 1 12:49:55 2012
@@ -415,9 +415,12 @@ public class AggregateNode extends Unary
if (resultType == null)
{
- throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE,
- aggregateName,
- operand.getTypeId().getSQLTypeName());
+ throw StandardException.newException
+ (
+ SQLState.LANG_USER_AGGREGATE_BAD_TYPE,
+ getSQLName(),
+ operand.getTypeId().getSQLTypeName()
+ );
}
checkAggregatorClassName(aggregatorClassName.toString());
@@ -699,4 +702,15 @@ public class AggregateNode extends Unary
{
return false;
}
+
+ /** Get the SQL name of the aggregate */
+ public String getSQLName()
+ throws StandardException
+ {
+ if ( uad instanceof UserAggregateDefinition )
+ {
+ return ((UserAggregateDefinition) uad).getAliasDescriptor().getQualifiedName();
+ }
+ else { return aggregateName; }
+ }
}
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UserAggregateDefinition.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UserAggregateDefinition.java?rev=1392307&r1=1392306&r2=1392307&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UserAggregateDefinition.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UserAggregateDefinition.java Mon Oct 1 12:49:55 2012
@@ -35,9 +35,6 @@ import org.apache.derby.iapi.types.TypeI
import org.apache.derby.iapi.types.JSQLType;
import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.sql.compile.TypeCompiler;
-import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
-
import org.apache.derby.iapi.sql.compile.CompilerContext;
import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
@@ -107,69 +104,83 @@ public class UserAggregateDefinition imp
{
try
{
- TypeId compType = inputType.getTypeId();
-
CompilerContext cc = (CompilerContext)
ContextService.getContext(CompilerContext.CONTEXT_ID);
- TypeCompilerFactory tcf = cc.getTypeCompilerFactory();
- TypeCompiler tc = tcf.getTypeCompiler(compType);
ClassFactory classFactory = cc.getClassFactory();
Class userAggregatorClass = classFactory.loadApplicationClass( _alias.getJavaClassName() );
Class derbyAggregatorInterface = classFactory.loadApplicationClass( "org.apache.derby.agg.Aggregator" );
- Class[] aggregatorTypes = classFactory.getClassInspector().getGenericParameterTypes
+ Class[][] typeBounds = classFactory.getClassInspector().getTypeBounds
( derbyAggregatorInterface, userAggregatorClass );
if (
- !derbyAggregatorInterface.isAssignableFrom( userAggregatorClass ) ||
- (aggregatorTypes == null) ||
- (aggregatorTypes.length != AGGREGATOR_PARAM_COUNT) ||
- (aggregatorTypes[ INPUT_TYPE ] == null) ||
- (aggregatorTypes[ RETURN_TYPE ] == null)
- )
+ (typeBounds == null) ||
+ (typeBounds.length != AGGREGATOR_PARAM_COUNT) ||
+ (typeBounds[ INPUT_TYPE ] == null) ||
+ (typeBounds[ RETURN_TYPE ] == null)
+ )
{
- throw StandardException.newException
+ throw StandardException.newException
(
SQLState.LANG_ILLEGAL_UDA_CLASS,
_alias.getSchemaName(),
_alias.getName(),
- _alias.getJavaClassName()
+ userAggregatorClass.getName()
);
}
- Class actualInputClass = aggregatorTypes[ INPUT_TYPE ];
- Class actualReturnClass = aggregatorTypes[ RETURN_TYPE ];
-
AggregateAliasInfo aai = (AggregateAliasInfo) _alias.getAliasInfo();
DataTypeDescriptor expectedInputType = DataTypeDescriptor.getType( aai.getForType() );
DataTypeDescriptor expectedReturnType = DataTypeDescriptor.getType( aai.getReturnType() );
Class expectedInputClass = getJavaClass( expectedInputType );
Class expectedReturnClass = getJavaClass( expectedReturnType );
- // check that the aggregator has the correct input and return types
- if ( actualInputClass != expectedInputClass )
+ // the input operand must be the expected input type of the aggregate
+ if ( !inputType.getTypeId().equals( expectedInputType.getTypeId() ) ) { return null; }
+
+ //
+ // Make sure that the declared input type of the UDA actually falls within
+ // the type bounds of the Aggregator implementation.
+ //
+ Class[] inputBounds = typeBounds[ INPUT_TYPE ];
+ for ( int i = 0; i < inputBounds.length; i++ )
{
- throw StandardException.newException
- (
- SQLState.LANG_UDA_WRONG_INPUT_TYPE,
- _alias.getSchemaName(),
- _alias.getName(),
- expectedInputClass.toString(),
- actualInputClass.toString()
- );
+ Class inputBound = inputBounds[ i ];
+
+ if ( !inputBound.isAssignableFrom( expectedInputClass ) )
+ {
+ throw StandardException.newException
+ (
+ SQLState.LANG_UDA_WRONG_INPUT_TYPE,
+ _alias.getSchemaName(),
+ _alias.getName(),
+ expectedInputClass.toString(),
+ inputBound.toString()
+ );
+ }
}
-
- if ( actualReturnClass != expectedReturnClass )
+
+ //
+ // Make sure that the declared return type of the UDA actually falls within
+ // the type bounds of the Aggregator implementation.
+ //
+ Class[] returnBounds = typeBounds[ RETURN_TYPE ];
+ for ( int i = 0; i < returnBounds.length; i++ )
{
- throw StandardException.newException
- (
- SQLState.LANG_UDA_WRONG_RETURN_TYPE,
- _alias.getSchemaName(),
- _alias.getName(),
- expectedReturnClass.toString(),
- actualReturnClass.toString()
+ Class returnBound = returnBounds[ i ];
+
+ if ( !returnBound.isAssignableFrom( expectedReturnClass ) )
+ {
+ throw StandardException.newException
+ (
+ SQLState.LANG_UDA_WRONG_RETURN_TYPE,
+ _alias.getSchemaName(),
+ _alias.getName(),
+ expectedReturnClass.toString(),
+ returnBound.toString()
);
+ }
}
aggregatorClass.append( ClassName.UserDefinedAggregator );
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java?rev=1392307&r1=1392306&r2=1392307&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ValueNode.java Mon Oct 1 12:49:55 2012
@@ -442,7 +442,13 @@ public abstract class ValueNode extends
C_NodeTypes.JAVA_TO_SQL_VALUE_NODE,
stjvn,
getContextManager());
- jtsvn.setType(DataTypeDescriptor.getSQLDataTypeDescriptor(stjvn.getJavaTypeName()));
+
+ DataTypeDescriptor resultType;
+ if ( (getTypeServices() != null) && getTypeId().userType() ) { resultType = getTypeServices(); }
+ else { resultType = DataTypeDescriptor.getSQLDataTypeDescriptor(stjvn.getJavaTypeName()); }
+
+ jtsvn.setType( resultType );
+
return jtsvn;
}
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=1392307&r1=1392306&r2=1392307&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 Mon Oct 1 12:49:55 2012
@@ -2979,7 +2979,7 @@ Guide.
<msg>
<name>42ZC6</name>
- <text>User defined aggregate '{0}'.'{1}' was declared to have this input Java type: '{2}'. However, the actual input Java type is '{3}'.</text>
+ <text>User defined aggregate '{0}'.'{1}' was declared to have this input Java type: '{2}'. This does not extend the following actual bounding input Java type: '{3}'.</text>
<arg>schemaName</arg>
<arg>aggregateName</arg>
<arg>javaDataType</arg>
@@ -2988,7 +2988,7 @@ Guide.
<msg>
<name>42ZC7</name>
- <text>User defined aggregate '{0}'.'{1}' was declared to have this return Java type: '{2}'. However, the actual return Java type is '{3}'.</text>
+ <text>User defined aggregate '{0}'.'{1}' was declared to have this return Java type: '{2}'. This does not extend the following actual bounding return Java type: '{3}'.</text>
<arg>schemaName</arg>
<arg>aggregateName</arg>
<arg>javaDataType</arg>
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UserDefinedAggregatesTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UserDefinedAggregatesTest.java?rev=1392307&r1=1392306&r2=1392307&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UserDefinedAggregatesTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/UserDefinedAggregatesTest.java Mon Oct 1 12:49:55 2012
@@ -54,6 +54,7 @@ public class UserDefinedAggregatesTest
public static final String MISSING_SCHEMA = "42Y07";
public static final String BAD_AGGREGATE_USAGE = "42903";
public static final String BAD_ORDER_BY = "42Y35";
+ public static final String INPUT_MISMATCH = "42Y22";
///////////////////////////////////////////////////////////////////////////////////
//
@@ -661,7 +662,7 @@ public class UserDefinedAggregatesTest
conn,
"intMode",
"int",
- "IntMode",
+ "org.apache.derbyTesting.functionTests.tests.lang.GenericMode$IntMode",
"( 1, 1 ), ( 1, 2 ), ( 1, 2 ), ( 1, 2 ), ( 2, 3 ), ( 2, 3 ), ( 2, 4 )",
new String[][]
{
@@ -688,7 +689,7 @@ public class UserDefinedAggregatesTest
conn,
"varcharMode",
"varchar( 5 )",
- "StringMode",
+ "org.apache.derbyTesting.functionTests.tests.lang.GenericMode$StringMode",
"( 1, 'a' ), ( 1, 'ab' ), ( 1, 'ab' ), ( 1, 'ab' ), ( 2, 'abc' ), ( 2, 'abc' ), ( 2, 'abcd' )",
new String[][]
{
@@ -716,7 +717,7 @@ public class UserDefinedAggregatesTest
Connection conn,
String aggName,
String sqlType,
- String nestedClassName,
+ String externalName,
String values,
String[][] scalarResult,
String[][] groupedResult,
@@ -729,7 +730,7 @@ public class UserDefinedAggregatesTest
goodStatement
( conn, "create derby aggregate " + aggName + " for " + sqlType + "\n" +
- "external name 'org.apache.derbyTesting.functionTests.tests.lang.GenericMode$" + nestedClassName + "'" );
+ "external name '" + externalName + "'" );
goodStatement( conn, "create table " + tableName + "( a int, b " + sqlType + " )" );
goodStatement( conn, "insert into " + tableName + "( a, b ) values " + values );
@@ -749,21 +750,27 @@ public class UserDefinedAggregatesTest
false
);
- assertResults
- (
- conn,
- "select " + aggName + "( distinct b ) from " + tableName,
- distinctScalarResult,
- false
- );
-
- assertResults
- (
- conn,
- "select a, " + aggName + "( distinct b ) from " + tableName + " group by a",
- distinctGroupedResult,
- false
- );
+ if ( distinctScalarResult != null )
+ {
+ assertResults
+ (
+ conn,
+ "select " + aggName + "( distinct b ) from " + tableName,
+ distinctScalarResult,
+ false
+ );
+ }
+
+ if ( distinctGroupedResult != null )
+ {
+ assertResults
+ (
+ conn,
+ "select a, " + aggName + "( distinct b ) from " + tableName + " group by a",
+ distinctGroupedResult,
+ false
+ );
+ }
}
/**
@@ -882,4 +889,133 @@ public class UserDefinedAggregatesTest
);
}
+ /**
+ * <p>
+ * Test aggregates bound to generic classes.
+ * </p>
+ */
+ public void test_09_genericAggregates() throws Exception
+ {
+ Connection conn = getConnection();
+
+ vetParameterizedAggregate
+ (
+ conn,
+ "intMode_09",
+ "int",
+ "org.apache.derbyTesting.functionTests.tests.lang.GenericMode",
+ "( 1, 1 ), ( 1, 2 ), ( 1, 2 ), ( 1, 2 ), ( 2, 3 ), ( 2, 3 ), ( 2, 4 )",
+ new String[][]
+ {
+ { "2" },
+ },
+ new String[][]
+ {
+ { "1", "2" },
+ { "2", "3" },
+ },
+ new String[][]
+ {
+ { "4" },
+ },
+ new String[][]
+ {
+ { "1", "2" },
+ { "2", "4" },
+ }
+ );
+
+ vetParameterizedAggregate
+ (
+ conn,
+ "varcharMode_09",
+ "varchar( 5 )",
+ "org.apache.derbyTesting.functionTests.tests.lang.GenericMode",
+ "( 1, 'a' ), ( 1, 'ab' ), ( 1, 'ab' ), ( 1, 'ab' ), ( 2, 'abc' ), ( 2, 'abc' ), ( 2, 'abcd' )",
+ new String[][]
+ {
+ { "ab" },
+ },
+ new String[][]
+ {
+ { "1", "ab" },
+ { "2", "abc" },
+ },
+ new String[][]
+ {
+ { "abcd" },
+ },
+ new String[][]
+ {
+ { "1", "ab" },
+ { "2", "abcd" },
+ }
+ );
+
+ goodStatement
+ (
+ conn,
+ "create type FullName_09 external name 'org.apache.derbyTesting.functionTests.tests.lang.FullName' language java"
+ );
+ goodStatement
+ (
+ conn,
+ "create function makeFullName_09( firstName varchar( 32672 ), lastName varchar( 32672 ) )\n" +
+ "returns FullName_09 language java parameter style java\n" +
+ "external name 'org.apache.derbyTesting.functionTests.tests.lang.FullName.makeFullName'\n"
+ );
+ vetParameterizedAggregate
+ (
+ conn,
+ "fullNameMode_09",
+ "FullName_09",
+ "org.apache.derbyTesting.functionTests.tests.lang.GenericMode",
+ "( 1, makeFullName_09( 'one', 'name' ) ),\n" +
+ "( 1, makeFullName_09( 'two', 'name' ) ),\n" +
+ "( 1, makeFullName_09( 'two', 'name' ) ),\n" +
+ "( 1, makeFullName_09( 'two', 'name' ) ),\n" +
+ "( 2, makeFullName_09( 'three', 'name' ) ),\n" +
+ "( 2, makeFullName_09( 'three', 'name' ) ),\n" +
+ "( 2, makeFullName_09( 'four', 'name' ) )\n",
+ new String[][]
+ {
+ { "two name" },
+ },
+ new String[][]
+ {
+ { "1", "two name" },
+ { "2", "three name" },
+ },
+ null,
+ null
+ );
+ }
+
+ /**
+ * <p>
+ * Negative tests.
+ * </p>
+ */
+ public void test_10_negative() throws Exception
+ {
+ Connection conn = getConnection();
+
+ //
+ // Input operand must agree with input type of aggregate
+ //
+ goodStatement
+ (
+ conn,
+ "create derby aggregate intMode_10 for int\n" +
+ "external name 'org.apache.derbyTesting.functionTests.tests.lang.GenericMode$IntMode'\n"
+ );
+ goodStatement
+ (
+ conn,
+ "create table intMode_10_inputs( a int, b varchar( 10 ) )"
+ );
+ expectCompilationError( INPUT_MISMATCH, "select intMode_10( b ) from intMode_10_inputs" );
+
+ }
+
}