From derby-commits-return-16322-apmail-db-derby-commits-archive=db.apache.org@db.apache.org Thu Dec 13 00:24:05 2012 Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 08F08DE95 for ; Thu, 13 Dec 2012 00:24:04 +0000 (UTC) Received: (qmail 66425 invoked by uid 500); 13 Dec 2012 00:24:04 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 66368 invoked by uid 500); 13 Dec 2012 00:24:04 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 66361 invoked by uid 99); 13 Dec 2012 00:24:04 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 13 Dec 2012 00:24:04 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 13 Dec 2012 00:24:02 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 3A2DB238890B; Thu, 13 Dec 2012 00:23:42 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1421052 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/compile/ testing/org/apache/derbyTesting/functionTests/tests/lang/ Date: Thu, 13 Dec 2012 00:23:39 -0000 To: derby-commits@db.apache.org From: rhillegas@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121213002342.3A2DB238890B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rhillegas Date: Thu Dec 13 00:23:29 2012 New Revision: 1421052 URL: http://svn.apache.org/viewvc?rev=1421052&view=rev Log: DERBY-3069: Fix varargs bugs in handling of primitive args and out/inout args. Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/MethodCallNode.java db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/StaticMethodCallNode.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsRoutines.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsTest.java 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=1421052&r1=1421051&r2=1421052&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 Thu Dec 13 00:23:29 2012 @@ -373,17 +373,28 @@ abstract class MethodCallNode extends Ja { /* Put the parameter type names into a single string */ StringBuffer parmTypes = new StringBuffer(); - for (int i = 0; i < parmTypeNames.length; i++) + boolean hasVarargs = hasVarargs(); + int firstVarargIdx = getFirstVarargIdx(); + int paramCount = signature.length; + for (int i = 0; i < paramCount; i++) { - if (i != 0) - parmTypes.append(", "); + if (i != 0) { parmTypes.append(", "); } + boolean isVararg = isVararg( i ); + /* RESOLVE - shouldn't be using hard coded strings for output */ - parmTypes.append( (parmTypeNames[i].length() != 0 ? - parmTypeNames[i] : - "UNTYPED")); + String parmType = parmTypeNames[ i ]; + if ( parmTypeNames [i ].length() == 0 ) { parmType = "UNTYPED"; } + else if ( isVararg ) { parmType = getVarargTypeName( parmType ); } + + parmTypes.append( parmType ); + if ((primParmTypeNames != null) && ! primParmTypeNames[i].equals(parmTypeNames[i])) // has primitive - parmTypes.append("(" + primParmTypeNames[i] + ")"); + { + String primTypeName = primParmTypeNames[ i ]; + if ( isVararg ) { primTypeName = getVarargTypeName( primTypeName ); } + parmTypes.append("(" + primTypeName + ")"); + } } throw StandardException.newException(SQLState.LANG_NO_METHOD_FOUND, @@ -392,6 +403,12 @@ abstract class MethodCallNode extends Ja parmTypes); } + /** Turn an array type name into the corresponding vararg type name */ + private String getVarargTypeName( String arrayTypeName ) + { + return stripOneArrayLevel( arrayTypeName ) + "..."; + } + /** * Preprocess an expression tree. We do a number of transformations * here (including subqueries, IN lists, LIKE and BETWEEN) plus @@ -519,7 +536,20 @@ abstract class MethodCallNode extends Ja public boolean hasVarargs() { return (routineInfo == null ) ? false : routineInfo.hasVarargs(); - } + } + + /** Get the index of the first vararg if this is a varargs method */ + public int getFirstVarargIdx() { return signature.length - 1; } + + /** Return true if the parameter is a vararg */ + public boolean isVararg( int parameterNumber ) + { + if ( !hasVarargs() ) { return false; } + else + { + return ( parameterNumber >= getFirstVarargIdx() ); + } + } /** * Generate the parameters to the given method call @@ -616,17 +646,27 @@ abstract class MethodCallNode extends Ja // an array type. right now we only support vararg static methods. // if we have to support vararg constructors in the future, then this code // will need adjustment. - Class[] parameterTypes = ((Method) method).getParameterTypes(); - int firstVarargIdx = parameterTypes.length - 1; - Class varargType = parameterTypes[ firstVarargIdx ].getComponentType(); - + int firstVarargIdx = getFirstVarargIdx(); + String arrayType = methodParameterTypes[ firstVarargIdx ]; + String cellType = stripOneArrayLevel( arrayType ); + String varargType = cellType; + + // must strip another array level off of out and in/out parameters + if ( routineInfo != null ) + { + if ( routineInfo.getParameterModes()[ firstVarargIdx ] != JDBC30Translation.PARAMETER_MODE_IN ) + { + varargType = stripOneArrayLevel( varargType ); + } + } + int varargCount = methodParms.length - firstVarargIdx; if ( varargCount < 0 ) { varargCount = 0; } // allocate an array to hold the varargs - LocalField arrayField = acb.newFieldDeclaration( Modifier.PRIVATE, varargType.getName() + "[]" ); + LocalField arrayField = acb.newFieldDeclaration( Modifier.PRIVATE, arrayType ); MethodBuilder cb = acb.getConstructor(); - cb.pushNewArray( varargType.getName(), varargCount ); + cb.pushNewArray( cellType, varargCount ); cb.setField( arrayField ); // now put the arguments into the array @@ -634,7 +674,7 @@ abstract class MethodCallNode extends Ja { mb.getField( arrayField ); // push the array onto the stack // evaluate the parameter and push it onto the stack - generateAndCastOneParameter( acb, mb, i + firstVarargIdx, methodParameterTypes[ firstVarargIdx ] ); + generateAndCastOneParameter( acb, mb, i + firstVarargIdx, cellType ); mb.setArrayElement( i ); // move the parameter into the array, pop the stack } @@ -654,10 +694,14 @@ abstract class MethodCallNode extends Ja protected int getRoutineArgIdx( int invocationArgIdx ) { if ( routineInfo == null ) { return invocationArgIdx; } - if ( !routineInfo.hasVarargs() ) { return invocationArgIdx; } + else { return getRoutineArgIdx( routineInfo, invocationArgIdx ); } + } + protected int getRoutineArgIdx( RoutineAliasInfo rai, int invocationArgIdx ) + { + if ( !rai.hasVarargs() ) { return invocationArgIdx; } // ok, this is a varargs routine - int firstVarargIdx = routineInfo.getParameterCount() - 1; + int firstVarargIdx = rai.getParameterCount() - 1; return (firstVarargIdx < invocationArgIdx) ? firstVarargIdx : invocationArgIdx; } @@ -929,13 +973,15 @@ abstract class MethodCallNode extends Ja methodParameterTypes = classInspector.getParameterTypes(method); + String methodParameter = null; + for (int i = 0; i < methodParameterTypes.length; i++) { - String methodParameter = methodParameterTypes[i]; + methodParameter = methodParameterTypes[i]; if (routineInfo != null) { if (i < routineInfo.getParameterCount()) { - int parameterMode = routineInfo.getParameterModes()[i]; + int parameterMode = routineInfo.getParameterModes()[ getRoutineArgIdx( i ) ]; switch (parameterMode) { case JDBC30Translation.PARAMETER_MODE_IN: @@ -943,7 +989,7 @@ abstract class MethodCallNode extends Ja case JDBC30Translation.PARAMETER_MODE_IN_OUT: // we need to see if the type of the array is // primitive, not the array itself. - methodParameter = methodParameter.substring(0, methodParameter.length() - 2); + methodParameter = stripOneArrayLevel( methodParameter ); break; case JDBC30Translation.PARAMETER_MODE_OUT: @@ -953,10 +999,43 @@ abstract class MethodCallNode extends Ja } } + // + // Strip off the array type if this is a varargs arg. We are only interested in + // whether we need to cast to the cell type. + // + if ( hasVarargs() && (i >= getFirstVarargIdx()) ) + { + methodParameter = stripOneArrayLevel( methodParameter ); + } + if (ClassInspector.primitiveType(methodParameter)) - methodParms[i].castToPrimitive(true); + { + // varargs may be omitted, so there may not be an invocation argument + // corresponding to the vararg + if ( i < methodParms.length ) + { + methodParms[i].castToPrimitive(true); + } + } } + // the last routine parameter may have been a varargs. if so, + // casting may be needed on the trailing varargs + if ( hasVarargs() ) + { + int firstVarargIdx = getFirstVarargIdx(); + int trailingVarargCount = methodParms.length - firstVarargIdx; + + // the first vararg was handled in the preceding loop + for ( int i = 1; i < trailingVarargCount; i++ ) + { + if (ClassInspector.primitiveType(methodParameter)) + { + methodParms[ i + firstVarargIdx ].castToPrimitive(true); + } + } + } + /* Set type info for any null parameters */ if ( someParametersAreNull() ) { @@ -976,7 +1055,13 @@ abstract class MethodCallNode extends Ja if (getCompilerContext().getReturnParameterFlag()) { getCompilerContext().getParameterTypes()[0] = dts; } - } + } + + /** Strip the trailing [] from a type name */ + protected String stripOneArrayLevel( String typeName ) + { + return typeName.substring( 0, typeName.length() - 2 ); + } /** * Parse the user supplied signature for a method and validate 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=1421052&r1=1421051&r2=1421052&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 Thu Dec 13 00:23:29 2012 @@ -494,7 +494,7 @@ public class StaticMethodCallNode extend // if it's an OUT or INOUT parameter we need an array. - int parameterMode = routineInfo.getParameterModes()[p]; + int parameterMode = routineInfo.getParameterModes()[ getRoutineArgIdx( routineInfo, p ) ]; if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) { @@ -556,7 +556,7 @@ public class StaticMethodCallNode extend coerceMethodParameter ( fromList, subqueryList, aggregateVector, - parameterCount, + methodParms.length, paramdtd, parameterTypeId, parameterMode, idx ); @@ -567,7 +567,7 @@ public class StaticMethodCallNode extend coerceMethodParameter ( fromList, subqueryList, aggregateVector, - parameterCount, + methodParms.length, paramdtd, parameterTypeId, parameterMode, p ); @@ -868,7 +868,7 @@ public class StaticMethodCallNode extend // applicationParameterNumbers is only set up for a procedure. int applicationParameterNumber = pn.getParameterNumber(); - String parameterType = methodParameterTypes[parameterNumber]; + String parameterType = methodParameterTypes[ getRoutineArgIdx( parameterNumber ) ]; if (parameterType.endsWith("[]")) { @@ -916,12 +916,20 @@ public class StaticMethodCallNode extend // application could retain a reference to it and corrupt // future calls with the same CallableStatement object. - String methodParameterType = methodParameterTypes[parameterNumber]; + String methodParameterType = methodParameterTypes[ getRoutineArgIdx( parameterNumber ) ]; String arrayType = methodParameterType.substring(0, methodParameterType.length() - 2); + + // if a varargs arg, then strip off the extra array dimension added by varargs + if ( isVararg( parameterNumber ) ) + { + methodParameterType = stripOneArrayLevel( methodParameterType ); + arrayType = stripOneArrayLevel( arrayType ); + } + LocalField lf = acb.newFieldDeclaration(Modifier.PRIVATE, methodParameterType); if (outParamArrays == null) - outParamArrays = new LocalField[methodParms.length]; + { outParamArrays = new LocalField[methodParms.length]; } outParamArrays[parameterNumber] = lf; @@ -1292,7 +1300,8 @@ public class StaticMethodCallNode extend int[] parameterModes = routineInfo.getParameterModes(); for (int i = 0; i < outParamArrays.length; i++) { - int parameterMode = parameterModes[i]; + int parameterMode = parameterModes[ getRoutineArgIdx( i ) ]; + if (parameterMode != JDBC30Translation.PARAMETER_MODE_IN) { // must be a parameter if it is INOUT or OUT. @@ -1323,7 +1332,11 @@ public class StaticMethodCallNode extend boolean isAnsiUDT = paramdtd.getTypeId().getBaseTypeId().isAnsiUDT(); // is the underlying type for the OUT/INOUT parameter primitive. - boolean isPrimitive = ((java.lang.reflect.Method) method).getParameterTypes()[i].getComponentType().isPrimitive(); + // if this is a varargs arg then we have to strip off another array level + Class cellType = ((java.lang.reflect.Method) method).getParameterTypes()[ getRoutineArgIdx( i ) ]. + getComponentType(); + if ( isVararg( i ) ) { cellType = cellType.getComponentType(); } + boolean isPrimitive = cellType.isPrimitive(); if (isNumericType) { // need to up-cast as the setValue(Number) method only exists on NumberDataValue Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsRoutines.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsRoutines.java?rev=1421052&r1=1421051&r2=1421052&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsRoutines.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsRoutines.java Thu Dec 13 00:23:29 2012 @@ -48,6 +48,12 @@ public class VarargsRoutines // /////////////////////////////////////////////////////////////////////////////////// + ////////////////// + // + // SIMPLE ROUTINES + // + ////////////////// + /** Compute the maximum of a series of ints */ public static Integer max( Integer... values ) { @@ -71,4 +77,116 @@ public class VarargsRoutines return MessageFormat.format( message, args ); } + ////////////////////////// + // + // PRIMITIVES VS OBJECTS + // + ////////////////////////// + + public static String ambiguousTypes( int... a ) { return "primitive";} + public static String ambiguousTypes( Integer... a ) { return "wrapper";} + + public static Integer maxInts( int... values ) + { + if ( values == null ) { return null; } + if ( values.length == 0 ) { return null; } + + int result = Integer.MIN_VALUE; + + for ( int value : values ) { result = Math.max( result, value ); } + + return result; + } + + ////////////////////////// + // + // NON-VARARGS METHODS + // + ////////////////////////// + + public static String nonVarargsMethod( int a ) { return "shouldn't be resolved";} + public static String nonVarargsMethod( int[] a ) { return "shouldn't be resolved";} + + ////////////////////////// + // + // VARARGS & NON-VARARGS RESOLUTIONS + // + ////////////////////////// + + public static Integer vnvr( int a ) { return -a;} + public static Integer vnvr( int... a ) { return maxInts( a );} + + ////////////////////////// + // + // LEADING NON-VARARGS + // + ////////////////////////// + + public static Integer lnv( int... a ) { return maxInts( a );} + public static Integer lnv( int first, int...a ) { return maxInts( a );} + public static Integer lnv( int first, int second, int...a ) { return maxInts( a );} + + ////////////////////////// + // + // IN, OUT, IN/OUT PARAMETERS + // + ////////////////////////// + + public static void inVarargs( String[] result, int... values ) + { + String retval; + if ( values == null ) { retval = null; } + else if ( values.length == 0 ) { retval = null; } + else + { + StringBuilder buffer = new StringBuilder(); + + buffer.append( "RESULT: " ); + + for ( int value : values ) + { + buffer.append( " " + Integer.toString( value ) ); + } + + retval = buffer.toString(); + } + + result[ 0 ] = retval; + } + + public static void outVarargs( int seed, int[]... values ) + throws Exception + { + String retval; + if ( values == null ) { return; } + else + { + for ( int i = 0; i < values.length; i++ ) + { + values[ i ][ 0 ] = seed + i; + } + } + } + + public static void inoutVarargs( int seed, int[]... values ) + throws Exception + { + String retval; + if ( values == null ) { return; } + else + { + for ( int i = 0; i < values.length; i++ ) + { + values[ i ][ 0 ] += seed; + } + } + } + + //////////////////////// + // + // DATATYPE COVERAGE + // + //////////////////////// + + } Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsTest.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsTest.java?rev=1421052&r1=1421051&r2=1421052&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsTest.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/VarargsTest.java Thu Dec 13 00:23:29 2012 @@ -21,6 +21,7 @@ package org.apache.derbyTesting.functionTests.tests.lang; +import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -48,6 +49,8 @@ public class VarargsTest extends Genera private static final String NEEDS_DERBY_STYLE = "42ZC9"; private static final String NEEDS_JAVA_STYLE = "42ZCA"; private static final String RETURNS_RESULT_SETS = "42ZCB"; + private static final String AMBIGUOUS = "42X73"; + private static final String NO_SUCH_METHOD = "42X50"; /////////////////////////////////////////////////////////////////////////////////// // @@ -271,6 +274,278 @@ public class VarargsTest extends Genera ); } + /** + *

+ * Misc tests for varargs routines. + *

+ */ + public void test_03_misc() throws Exception + { + if ( !vmSupportsVarargs() ) { return; } + + Connection conn = getConnection(); + + // primitive and wrapper overloads make method resolution ambiguous + + goodStatement + ( conn, + "create function ambiguousTypes( a int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.ambiguousTypes'\n" + ); + expectCompilationError( AMBIGUOUS, "values ambiguousTypes( 1, 2, 3 )" ); + + // can resolve to a primitive-typed vararg + goodStatement + ( conn, + "create function maxInts( a int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.maxInts'\n" + ); + assertResults + ( + conn, + "values maxInts( 3 )", + new String[][] + { + { "3" }, + }, + false + ); + assertResults + ( + conn, + "values maxInts( 1, 2, 5, 4, 3 )", + new String[][] + { + { "5" }, + }, + false + ); + + // error if the matching method isn't varargs + goodStatement + ( conn, + "create function nonVarargsMethod( a int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.nonVarargsMethod'\n" + ); + expectCompilationError( NO_SUCH_METHOD, "values nonVarargsMethod( 3 )" ); + + // correctly disambiguate similar varargs and non-varargs methods + goodStatement + ( conn, + "create function vnvr_vararg( a int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.vnvr'\n" + ); + goodStatement + ( conn, + "create function vnvr_nonvararg( a int ) returns int\n" + + "language java parameter style java no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.vnvr'\n" + ); + assertResults + ( + conn, + "values vnvr_vararg( 3 )", + new String[][] + { + { "3" }, + }, + false + ); + assertResults + ( + conn, + "values vnvr_nonvararg( 3 )", + new String[][] + { + { "-3" }, + }, + false + ); + + // correctly disambiguate overloads with different numbers of leading non-vararg arguments + goodStatement + ( conn, + "create function lnv( a int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.lnv'\n" + ); + goodStatement + ( conn, + "create function lnv_1( a int, b int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.lnv'\n" + ); + goodStatement + ( conn, + "create function lnv_2( a int, b int, c int ... ) returns int\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.lnv'\n" + ); + assertResults + ( + conn, + "values lnv( 5, 4, 3, 2, 1 )", + new String[][] + { + { "5" }, + }, + false + ); + assertResults + ( + conn, + "values lnv_1( 5, 4, 3, 2, 1 )", + new String[][] + { + { "4" }, + }, + false + ); + assertResults + ( + conn, + "values lnv_2( 5, 4, 3, 2, 1 )", + new String[][] + { + { "3" }, + }, + false + ); + } + + /** + *

+ * Test in, out, and in/out procedure arguments which are varargs. + *

+ */ + public void test_04_inOut() throws Exception + { + if ( !vmSupportsVarargs() ) { return; } + + Connection conn = getConnection(); + CallableStatement cs = null; + + // one input vararg + goodStatement + ( conn, + "create procedure inVarargs( out result varchar( 32672 ), b int ... )\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.inVarargs'\n" + ); + cs = chattyPrepareCall + ( conn, "call inVarargs( ?, ? )" ); + cs.registerOutParameter( 1, java.sql.Types.VARCHAR ); + cs.setInt( 2, 5 ); + cs.execute(); + assertEquals( "RESULT: 5", cs.getString( 1 ) ); + + cs = chattyPrepareCall + ( conn, "call inVarargs( ?, ?, ? )" ); + cs.registerOutParameter( 1, java.sql.Types.VARCHAR ); + cs.setInt( 2, 5 ); + cs.setInt( 3, 4 ); + cs.execute(); + assertEquals( "RESULT: 5 4", cs.getString( 1 ) ); + + cs = chattyPrepareCall + ( conn, "call inVarargs( ?, ?, ?, ? )" ); + cs.registerOutParameter( 1, java.sql.Types.VARCHAR ); + cs.setInt( 2, 5 ); + cs.setInt( 3, 4 ); + cs.setInt( 4, 3 ); + cs.execute(); + assertEquals( "RESULT: 5 4 3", cs.getString( 1 ) ); + + // output vararg + goodStatement + ( conn, + "create procedure outVarargs( seed int, out b int ... )\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.outVarargs'\n" + ); + cs = chattyPrepareCall + ( conn, "call outVarargs( ? )" ); + cs.setInt( 1, 5 ); + cs.execute(); + + cs = chattyPrepareCall + ( conn, "call outVarargs( ?, ? )" ); + cs.registerOutParameter( 2, java.sql.Types.INTEGER ); + cs.setInt( 1, 5 ); + cs.execute(); + assertEquals( 5, cs.getInt( 2 ) ); + + cs = chattyPrepareCall + ( conn, "call outVarargs( ?, ?, ? )" ); + cs.registerOutParameter( 2, java.sql.Types.INTEGER ); + cs.registerOutParameter( 3, java.sql.Types.INTEGER ); + cs.setInt( 1, 5 ); + cs.execute(); + assertEquals( 5, cs.getInt( 2 ) ); + assertEquals( 6, cs.getInt( 3 ) ); + + cs = chattyPrepareCall + ( conn, "call outVarargs( ?, ?, ?, ? )" ); + cs.registerOutParameter( 2, java.sql.Types.INTEGER ); + cs.registerOutParameter( 3, java.sql.Types.INTEGER ); + cs.registerOutParameter( 4, java.sql.Types.INTEGER ); + cs.setInt( 1, 5 ); + cs.execute(); + assertEquals( 5, cs.getInt( 2 ) ); + assertEquals( 6, cs.getInt( 3 ) ); + assertEquals( 7, cs.getInt( 4 ) ); + + // in/out vararg + goodStatement + ( conn, + "create procedure inoutVarargs( seed int, inout b int ... )\n" + + "language java parameter style derby no sql deterministic\n" + + "external name 'org.apache.derbyTesting.functionTests.tests.lang.VarargsRoutines.inoutVarargs'\n" + ); + cs = chattyPrepareCall + ( conn, "call inoutVarargs( ? )" ); + cs.setInt( 1, 5 ); + cs.execute(); + + cs = chattyPrepareCall + ( conn, "call inoutVarargs( ?, ? )" ); + cs.registerOutParameter( 2, java.sql.Types.INTEGER ); + cs.setInt( 1, 5 ); + cs.setInt( 2, 3 ); + cs.execute(); + assertEquals( 8, cs.getInt( 2 ) ); + + cs = chattyPrepareCall + ( conn, "call inoutVarargs( ?, ?, ? )" ); + cs.registerOutParameter( 2, java.sql.Types.INTEGER ); + cs.registerOutParameter( 3, java.sql.Types.INTEGER ); + cs.setInt( 1, 5 ); + cs.setInt( 2, 3 ); + cs.setInt( 3, 10 ); + cs.execute(); + assertEquals( 8, cs.getInt( 2 ) ); + assertEquals( 15, cs.getInt( 3 ) ); + + cs = chattyPrepareCall + ( conn, "call inoutVarargs( ?, ?, ?, ? )" ); + cs.registerOutParameter( 2, java.sql.Types.INTEGER ); + cs.registerOutParameter( 3, java.sql.Types.INTEGER ); + cs.registerOutParameter( 4, java.sql.Types.INTEGER ); + cs.setInt( 1, 5 ); + cs.setInt( 2, 3 ); + cs.setInt( 3, 10 ); + cs.setInt( 4, 100 ); + cs.execute(); + assertEquals( 8, cs.getInt( 2 ) ); + assertEquals( 15, cs.getInt( 3 ) ); + assertEquals( 105, cs.getInt( 4 ) ); + + } + /////////////////////////////////////////////////////////////////////////////////// // // MINIONS