Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 193159 Details for
Bug 339905
EclipseLink needs new query processing to handle optional arguments
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
patch
2011-04-13-optional-arguments.patch (text/plain), 183.72 KB, created by
James Sutherland
on 2011-04-13 09:54:46 EDT
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
James Sutherland
Created:
2011-04-13 09:54:46 EDT
Size:
183.72 KB
patch
obsolete
>Index: dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/internal/xr/StoredFunctionQueryHandler.java >=================================================================== >--- dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/internal/xr/StoredFunctionQueryHandler.java (revision 9200) >+++ dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/internal/xr/StoredFunctionQueryHandler.java (working copy) >@@ -66,7 +66,7 @@ > platform = new DatabasePlatform(); > } > // StoredFunction's return value is the first parameter >- ((DatabaseField)sfCall.getParameters().firstElement()).setSqlType( >+ ((DatabaseField)sfCall.getParameters().get(0)).setSqlType( > platform.getJDBCType(clz)); > } > } >Index: foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/plsql/PLSQLProject.java >=================================================================== >--- foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/plsql/PLSQLProject.java (revision 9200) >+++ foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/plsql/PLSQLProject.java (working copy) >@@ -15,6 +15,7 @@ > import org.eclipse.persistence.queries.DataModifyQuery; > import org.eclipse.persistence.queries.DataReadQuery; > import org.eclipse.persistence.queries.DatabaseQuery; >+import org.eclipse.persistence.queries.StoredProcedureCall; > import org.eclipse.persistence.sessions.Project; > > /** >@@ -105,6 +106,53 @@ > return query; > } > >+ protected DatabaseQuery buildSimpleInDefaults2Query() { >+ PLSQLStoredProcedureCall call = new PLSQLStoredProcedureCall(); >+ call.setProcedureName("PLSQL_SIMPLE_IN_DEFAULTS"); >+ call.addNamedArgument("P_VARCHAR", JDBCTypes.VARCHAR_TYPE, 30); >+ call.addNamedArgument("P_BOOLEAN", OraclePLSQLTypes.PLSQLBoolean); >+ call.addNamedArgument("P_BINARY_INTEGER", OraclePLSQLTypes.BinaryInteger); >+ call.addNamedArgument("P_DEC", OraclePLSQLTypes.Dec); >+ call.addNamedArgument("P_INT", OraclePLSQLTypes.Int); >+ call.addNamedArgument("P_NATURAL", OraclePLSQLTypes.Natural); >+ call.addNamedArgument("P_NATURALN", OraclePLSQLTypes.NaturalN); >+ call.addNamedArgument("P_PLS_INTEGER", OraclePLSQLTypes.PLSQLInteger); >+ call.addNamedArgument("P_POSITIVE", OraclePLSQLTypes.Positive); >+ call.addNamedArgument("P_POSITIVEN", OraclePLSQLTypes.PositiveN); >+ call.addNamedArgument("P_SIGNTYPE", OraclePLSQLTypes.SignType); >+ call.addNamedArgument("P_NUMBER", JDBCTypes.NUMERIC_TYPE, 10, 2); >+ >+ call.addOptionalArgument("P_VARCHAR"); >+ call.addOptionalArgument("P_BOOLEAN"); >+ call.addOptionalArgument("P_BINARY_INTEGER"); >+ call.addOptionalArgument("P_DEC"); >+ call.addOptionalArgument("P_INT"); >+ call.addOptionalArgument("P_NATURAL"); >+ call.addOptionalArgument("P_NATURALN"); >+ call.addOptionalArgument("P_PLS_INTEGER"); >+ call.addOptionalArgument("P_POSITIVE"); >+ call.addOptionalArgument("P_POSITIVEN"); >+ call.addOptionalArgument("P_SIGNTYPE"); >+ call.addOptionalArgument("P_NUMBER"); >+ >+ DataModifyQuery query = new DataModifyQuery(); >+ query.addArgument("P_VARCHAR", String.class, true); >+ query.addArgument("P_BOOLEAN", Integer.class, true); >+ query.addArgument("P_BINARY_INTEGER", Integer.class, true); >+ query.addArgument("P_DEC", Integer.class, true); >+ query.addArgument("P_INT", Integer.class, true); >+ query.addArgument("P_NATURAL", Integer.class, true); >+ query.addArgument("P_NATURALN", Integer.class, true); >+ query.addArgument("P_PLS_INTEGER", Integer.class, true); >+ query.addArgument("P_POSITIVE", Integer.class, true); >+ query.addArgument("P_POSITIVEN", Integer.class, true); >+ query.addArgument("P_SIGNTYPE", BigDecimal.class, true); >+ query.addArgument("P_NUMBER", BigDecimal.class, true); >+ query.setCall(call); >+ >+ return query; >+ } >+ > protected DatabaseQuery buildSimpleInFuncQuery() { > PLSQLStoredFunctionCall call = new PLSQLStoredFunctionCall(OraclePLSQLTypes.PLSQLBoolean); > call.setProcedureName("PLSQL_SIMPLE_IN_Func"); >@@ -444,7 +492,29 @@ > > return query; > } >+ >+ protected DatabaseQuery buildAddressOutCursorQuery() { >+ >+ StoredProcedureCall call = new StoredProcedureCall(); >+ call.setProcedureName("PLSQL_P.PLSQL_ADDRESS_CUR_OUT"); >+ call.useNamedCursorOutputAsResultSet("P_ADDRESS"); >+ DataReadQuery query = new DataReadQuery(); >+ query.setCall(call); > >+ return query; >+ } >+ >+ protected DatabaseQuery buildAddressRecOutCursorQuery() { >+ >+ StoredProcedureCall call = new StoredProcedureCall(); >+ call.setProcedureName("PLSQL_P.PLSQL_ADDRESS_REC_CUR_OUT"); >+ call.useNamedCursorOutputAsResultSet("P_ADDRESS"); >+ DataReadQuery query = new DataReadQuery(); >+ query.setCall(call); >+ >+ return query; >+ } >+ > protected DatabaseQuery buildAddressListInOutQuery() { > PLSQLrecord record = buildAddressRecord(); > >@@ -595,6 +665,7 @@ > > descriptor.getQueryManager().addQuery("SimpleIn", buildSimpleInQuery()); > descriptor.getQueryManager().addQuery("SimpleInDefaults", buildSimpleInDefaultsQuery()); >+ descriptor.getQueryManager().addQuery("SimpleInDefaults2", buildSimpleInDefaults2Query()); > descriptor.getQueryManager().addQuery("SimpleInFunc", buildSimpleInFuncQuery()); > descriptor.getQueryManager().addQuery("SimpleOut", buildSimpleOutQuery()); > descriptor.getQueryManager().addQuery("SimpleInOut", buildSimpleInOutQuery()); >@@ -613,6 +684,8 @@ > descriptor.getQueryManager().addQuery("AddressListInOut", buildAddressListInOutQuery()); > descriptor.getQueryManager().addQuery("BadAddressOut", buildBadAddressOutObjectQuery()); > descriptor.getQueryManager().addQuery("MissingTypeAddressListOut", buildMissingTypeAddressListOutQuery()); >+ descriptor.getQueryManager().addQuery("AddressOutCursor", buildAddressOutCursorQuery()); >+ descriptor.getQueryManager().addQuery("AddressRecOutCursor", buildAddressRecOutCursorQuery()); > > descriptor.addFieldOrdering("ADDRESS_ID"); > DirectToFieldMapping idMapping = new DirectToFieldMapping(); >Index: foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/plsql/PLSQLSystem.java >=================================================================== >--- foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/plsql/PLSQLSystem.java (revision 9200) >+++ foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/models/plsql/PLSQLSystem.java (working copy) >@@ -34,12 +34,18 @@ > } catch (Exception ignore) {} > session.executeNonSelectingSQL("CREATE TABLE PLSQL_ADDRESS (" > + "ADDRESS_ID NUMBER(10) NOT NULL, STREET_NUM NUMBER(10), STREET VARCHAR2(30), CITY VARCHAR2(30), STATE VARCHAR2(30), PRIMARY KEY (ADDRESS_ID))"); >+ session.executeNonSelectingSQL("INSERT INTO PLSQL_ADDRESS (" >+ + "ADDRESS_ID, CITY) values (1234, 'Ottawa')"); > > // Procedures > session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_IN(P_VARCHAR IN VARCHAR2 DEFAULT '', P_BOOLEAN IN BOOLEAN, P_BINARY_INTEGER IN BINARY_INTEGER, " > + "P_DEC IN DEC, P_INT IN INT, P_NATURAL IN NATURAL, P_NATURALN IN NATURALN, " > + "P_PLS_INTEGER IN PLS_INTEGER, P_POSITIVE IN POSITIVE, P_POSITIVEN IN POSITIVEN, P_SIGNTYPE IN SIGNTYPE, P_NUMBER IN NUMBER) AS " > + "BEGIN NULL; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_IN_DEFAULTS(P_VARCHAR IN VARCHAR2 DEFAULT '', P_BOOLEAN IN BOOLEAN DEFAULT TRUE, P_BINARY_INTEGER IN BINARY_INTEGER DEFAULT 0, " >+ + "P_DEC IN DEC DEFAULT 0, P_INT IN INT DEFAULT 0, P_NATURAL IN NATURAL DEFAULT 1, P_NATURALN IN NATURALN DEFAULT 1, " >+ + "P_PLS_INTEGER IN PLS_INTEGER DEFAULT 0, P_POSITIVE IN POSITIVE DEFAULT 1, P_POSITIVEN IN POSITIVEN DEFAULT 1, P_SIGNTYPE IN SIGNTYPE DEFAULT 1, P_NUMBER IN NUMBER DEFAULT 0) AS " >+ + "BEGIN NULL; END;"); > session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_OUT(P_VARCHAR OUT VARCHAR2, P_BOOLEAN OUT BOOLEAN, P_BINARY_INTEGER OUT BINARY_INTEGER, " > + "P_DEC OUT DEC, P_INT OUT INT, P_NATURAL OUT NATURAL, " //P_NATURALN OUT NATURALN, " > + "P_PLS_INTEGER OUT PLS_INTEGER, P_POSITIVE OUT POSITIVE, " //P_POSITIVEN OUT POSITIVEN, " >@@ -74,7 +80,7 @@ > session.executeNonSelectingSQL("CREATE OR REPLACE FUNCTION PLSQL_ADDRESS_OUT_FUNC RETURN PLSQL_ADDRESS%ROWTYPE AS " > + " P_ADDRESS PLSQL_ADDRESS%ROWTYPE; " > + "BEGIN P_ADDRESS.ADDRESS_ID := 1234; P_ADDRESS.STREET_NUM := 17; P_ADDRESS.STREET := 'Bank'; P_ADDRESS.CITY := 'Ottawa'; P_ADDRESS.STATE := 'ON'; RETURN P_ADDRESS; END;"); >- >+ > // Types > try { > session.executeNonSelectingSQL("DROP TYPE PLSQL_P_PLSQL_EMP_REC FORCE"); >@@ -97,6 +103,8 @@ > session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_EMP_LIST AS VARRAY(255) OF PLSQL_P_PLSQL_EMP_REC"); > session.executeNonSelectingSQL("CREATE OR REPLACE PACKAGE PLSQL_P AS \n" > + "TYPE PLSQL_ADDRESS_REC IS RECORD (ADDRESS_ID NUMBER(10), STREET_NUM NUMBER(10), STREET VARCHAR2(30), CITY VARCHAR2(30), STATE VARCHAR2(2)); \n" >+ + "TYPE PLSQL_ADDRESS_CUR IS REF CURSOR RETURN PLSQL_ADDRESS%ROWTYPE; \n" >+ + "TYPE PLSQL_ADDRESS_REC_CUR IS REF CURSOR RETURN PLSQL_ADDRESS_REC; \n" > + "TYPE PLSQL_PHONE_REC IS RECORD (AREA_CODE VARCHAR2(3), P_NUM VARCHAR2(7)); \n" > + "TYPE PLSQL_PHONE_LIST IS TABLE OF PLSQL_PHONE_REC INDEX BY BINARY_INTEGER; \n" > + "TYPE PLSQL_EMP_REC IS RECORD (EMP_ID NUMBER(10), NAME VARCHAR2(30), ACTIVE BOOLEAN, ADDRESS PLSQL_ADDRESS_REC, PHONES PLSQL_PHONE_LIST); \n" >@@ -115,6 +123,8 @@ > + "PROCEDURE PLSQL_EMP_IN(P_EMP IN PLSQL_EMP_REC, P_CITY IN VARCHAR2); \n" > + "PROCEDURE PLSQL_EMP_OUT(P_EMP OUT PLSQL_EMP_REC, P_CITY OUT VARCHAR2); \n" > + "PROCEDURE PLSQL_EMP_INOUT(P_EMP IN OUT PLSQL_EMP_REC, P_CITY IN OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_ADDRESS_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_CUR); \n" >+ + "PROCEDURE PLSQL_ADDRESS_REC_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_REC_CUR); \n" > + "END PLSQL_P; \n"); > session.executeNonSelectingSQL("CREATE OR REPLACE PACKAGE BODY PLSQL_P AS \n" > + "PROCEDURE PLSQL_CITY_LIST_IN(P_CITY_LIST IN PLSQL_CITY_LIST, P_CITY IN VARCHAR2) AS \n" >@@ -165,8 +175,16 @@ > + "END PLSQL_EMP_OUT; \n" > + "PROCEDURE PLSQL_EMP_INOUT(P_EMP IN OUT PLSQL_EMP_REC, P_CITY IN OUT VARCHAR2) AS \n" > + "BEGIN \n" >- + "P_CITY := 'Nepean'; " >+ + "P_CITY := 'Nepean'; \n" > + "END PLSQL_EMP_INOUT; \n" >+ + "PROCEDURE PLSQL_ADDRESS_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_CUR) AS \n" >+ + "BEGIN \n" >+ + "OPEN P_ADDRESS FOR SELECT * FROM PLSQL_ADDRESS; \n" >+ + "END PLSQL_ADDRESS_CUR_OUT; \n" >+ + "PROCEDURE PLSQL_ADDRESS_REC_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_REC_CUR) AS \n" >+ + "BEGIN \n" >+ + "OPEN P_ADDRESS FOR SELECT * FROM PLSQL_ADDRESS; \n" >+ + "END PLSQL_ADDRESS_REC_CUR_OUT; \n" > + "END PLSQL_P; \n"); > } > >Index: foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/plsql/PLSQLTestModel.java >=================================================================== >--- foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/plsql/PLSQLTestModel.java (revision 9200) >+++ foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/plsql/PLSQLTestModel.java (working copy) >@@ -16,6 +16,7 @@ > import java.util.ArrayList; > import java.util.Arrays; > import java.util.List; >+import java.util.Vector; > > import org.eclipse.persistence.exceptions.QueryException; > import org.eclipse.persistence.sessions.DatabaseRecord; >@@ -121,6 +122,23 @@ > suite.addTest(test); > > args = new ArrayList(); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ args.add(null); >+ test = new PLSQLTest("SimpleInDefaults2", Address.class, args); >+ test.setName("SimpleInDefaults2"); >+ suite.addTest(test); >+ >+ args = new ArrayList(); > test = new PLSQLTest("SimpleOut", Address.class, args); > test.setName("SimpleOutTest"); > suite.addTest(test); >@@ -299,6 +317,14 @@ > test = new PLSQLTest("EmployeeInOutObject", Employee.class, args, result); > test.setName("EmployeeInOutObjectTest"); > suite.addTest(test); >+ >+ test = new PLSQLTest("AddressOutCursor", Address.class, new ArrayList(), new Vector()); >+ test.setName("AddressOutCursorTest"); >+ suite.addTest(test); >+ >+ test = new PLSQLTest("AddressRecOutCursor", Address.class, new ArrayList(), new Vector()); >+ test.setName("AddressRecOutCursorTest"); >+ suite.addTest(test); > > return suite; > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/NamedStoredFunctionQueries.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/NamedStoredFunctionQueries.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/NamedStoredFunctionQueries.java (working copy) >@@ -23,7 +23,7 @@ > * NamedStoredFunctionQuery. > * > * @author James >- * @since Oracle TopLink 11.1.1.0.0 >+ * @since EclipseLink 2.3 > */ > @Target({TYPE}) > @Retention(RUNTIME) >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/StoredProcedureParameter.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/StoredProcedureParameter.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/StoredProcedureParameter.java (working copy) >@@ -44,8 +44,13 @@ > * (Required) The query parameter name. > */ > String queryParameter(); >- >+ > /** >+ * (Optional) Define if the parameter is required, or optional and defaulted by the procedure. >+ */ >+ boolean optional() default false; >+ >+ /** > * (Optional) The type of Java class desired back from the procedure, > * this is dependent on the type returned from the procedure. > */ >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/EISInteraction.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/EISInteraction.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/EISInteraction.java (working copy) >@@ -287,11 +287,10 @@ > writer.write(Helper.cr()); > writer.write("\tinput => ["); > if (!getParameters().isEmpty()) { >- // Unfortunately vectors cannot print if they have nulls in them... >- for (Enumeration paramsEnum = getParameters().elements(); paramsEnum.hasMoreElements();) { >- Object parameter = paramsEnum.nextElement(); >+ for (Iterator iterator = getParameters().iterator(); iterator.hasNext();) { >+ Object parameter = iterator.next(); > writer.write(String.valueOf(parameter)); >- if (paramsEnum.hasMoreElements()) { >+ if (iterator.hasNext()) { > writer.write(", "); > } else { > writer.write("]"); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/QueryStringInteraction.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/QueryStringInteraction.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/QueryStringInteraction.java (working copy) >@@ -99,11 +99,10 @@ > writer.write(Helper.cr()); > writer.write("\tparameters => ["); > if (hasParameters()) { >- // Unfortunately vectors cannot print if they have nulls in them... >- for (Enumeration paramsEnum = getParameters().elements(); paramsEnum.hasMoreElements();) { >- Object parameter = paramsEnum.nextElement(); >+ for (Iterator iterator = getParameters().iterator(); iterator.hasNext();) { >+ Object parameter = iterator.next(); > writer.write(String.valueOf(parameter)); >- if (paramsEnum.hasMoreElements()) { >+ if (iterator.hasNext()) { > writer.write(", "); > } > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/XQueryInteraction.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/XQueryInteraction.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/interactions/XQueryInteraction.java (working copy) >@@ -145,11 +145,10 @@ > writer.write(Helper.cr()); > writer.write("\tinput => ["); > if (hasParameters()) { >- // Unfortunately vectors cannot print if they have nulls in them... >- for (Enumeration paramsEnum = getParameters().elements(); paramsEnum.hasMoreElements();) { >- Object parameter = paramsEnum.nextElement(); >+ for (Iterator iterator = getParameters().iterator(); iterator.hasNext();) { >+ Object parameter = iterator.next(); > writer.write(String.valueOf(parameter)); >- if (paramsEnum.hasMoreElements()) { >+ if (iterator.hasNext()) { > writer.write(", "); > } else { > writer.write("]"); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabaseCall.java (working copy) >@@ -212,7 +212,7 @@ > } catch (IOException exception) { > throw ValidationException.fileError(exception); > } >- getParameters().addElement(parameter); >+ getParameters().add(parameter); > } > > /** >@@ -343,8 +343,9 @@ > * Return 1-based index of out cursor parameter, or -1. > */ > public int getCursorOutIndex() { >- for (int i = 0; i < getParameters().size(); i++) { >- Object parameter = getParameters().elementAt(i); >+ int size = getParameters().size(); >+ for (int i = 0; i < size; i++) { >+ Object parameter = this.parameters.get(i); > if (parameter instanceof OutputParameterForCallableStatement) { > if (((OutputParameterForCallableStatement)parameter).isCursor()) { > return i + 1; >@@ -424,9 +425,10 @@ > */ > public Vector getOutputRowFields() { > Vector fields = new Vector(); >- for (int i = 0; i < getParameters().size(); i++) { >- Integer parameterType = (Integer)getParameterTypes().elementAt(i); >- Object parameter = getParameters().elementAt(i); >+ int size = getParameters().size(); >+ for (int i = 0; i < size; i++) { >+ Integer parameterType = this.parameterTypes.get(i); >+ Object parameter = this.parameters.get(i); > if (parameterType == OUT) { > fields.add(parameter); > } else if (parameterType == INOUT) { >@@ -578,14 +580,13 @@ > * Allow pre-printing of the SQL string for fully bound calls, to save from reprinting. > * Should be called before translation. > */ >+ @Override > public void prepare(AbstractSession session) { >- if (isPrepared()) { >+ if (this.isPrepared) { > return; > } >- > prepareInternal(session); >- >- setIsPrepared(true); >+ this.isPrepared = true; > } > > /** >@@ -606,8 +607,9 @@ > // 2. If there are multiple OUT_CURSOR parameters - throw Validation exception > int nFirstOutParameterIndex = -1; > boolean hasFoundOutCursor = false; >- for (int index = 0; index < parameters.size(); index++) { >- Integer parameterType = (Integer)parameterTypes.elementAt(index); >+ int size = this.parameters.size(); >+ for (int index = 0; index < size; index++) { >+ Integer parameterType = this.parameterTypes.get(index); > if (parameterType == DatasourceCall.OUT_CURSOR) { > if (hasFoundOutCursor) { > // one cursor has been already found >@@ -625,18 +627,19 @@ > } > } > if (!hasFoundOutCursor && (nFirstOutParameterIndex >= 0)) { >- parameterTypes.setElementAt(DatasourceCall.OUT_CURSOR, nFirstOutParameterIndex); >+ this.parameterTypes.set(nFirstOutParameterIndex, DatasourceCall.OUT_CURSOR); > } > } > >- for (int i = 0; i < getParameters().size(); i++) { >- Object parameter = getParameters().elementAt(i); >- Integer parameterType = (Integer)getParameterTypes().elementAt(i); >+ int size = getParameters().size(); >+ for (int i = 0; i < size; i++) { >+ Object parameter = this.parameters.get(i); >+ Integer parameterType = this.parameterTypes.get(i); > if (parameterType == MODIFY) { > // in case the field's type is not set, the parameter type is set to CUSTOM_MODIFY. > DatabaseField field = (DatabaseField)parameter; > if ((field.getType() == null) || session.getPlatform().shouldUseCustomModifyForCall(field)) { >- getParameterTypes().setElementAt(CUSTOM_MODIFY, i); >+ this.parameterTypes.set(i, CUSTOM_MODIFY); > } > } else if (parameterType == INOUT) { > // In case there is a type in outField, outParameter is created. >@@ -672,9 +675,9 @@ > > // outParameter contains all the info for registerOutputParameter call. > OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session, isCursor); >- getParameters().setElementAt(outParameter, i); >+ this.parameters.set(i, outParameter); > // nothing to do during translate method >- getParameterTypes().setElementAt(LITERAL, i); >+ this.parameterTypes.set(i, LITERAL); > } > } > if (this.returnsResultSet == null) { >@@ -941,14 +944,15 @@ > * INTERNAL: > * Allow the call to translate from the translation for predefined calls. > */ >+ @Override > public void translate(AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) { > if (!isPrepared()) { > throw ValidationException.cannotTranslateUnpreparedCall(toString()); > } > if (usesBinding(session) && (this.parameters != null)) { > boolean hasParameterizedIN = false; >- Vector parameters = getParameters(); >- Vector parameterTypes = getParameterTypes(); >+ List parameters = getParameters(); >+ List<Integer> parameterTypes = getParameterTypes(); > int size = parameters.size(); > Vector parametersValues = new Vector(size); > for (int index = 0; index < size; index++) { >@@ -1005,19 +1009,26 @@ > } > // If the value is null, the field is passed as the value so the type can be obtained from the field. > if ((value == null) && (field != null)) { >- value = translationRow.getField(field); >- // The field from the row is used, as the calls field may not have the type, >- // but if the field is missing the calls field may also have the type. >- if (value == null) { >- value = field; >+ if (!this.query.hasNullableArguments() || !this.query.getNullableArguments().contains(field)) { >+ value = translationRow.getField(field); >+ // The field from the row is used, as the calls field may not have the type, >+ // but if the field is missing the calls field may also have the type. >+ if (value == null) { >+ value = field; >+ } >+ parametersValues.add(value); > } >+ } else { >+ parametersValues.add(value); > } >- parametersValues.add(value); > } else if (parameterType == LITERAL) { > parametersValues.add(parameter); > } else if (parameterType == IN) { > Object value = getValueForInParameter(parameter, translationRow, modifyRow, session, true); >- parametersValues.add(value); >+ // Returning this means the parameter was optional and should not be included. >+ if (value != this) { >+ parametersValues.add(value); >+ } > } else if (parameterType == INOUT) { > Object value = getValueForInOutParameter(parameter, translationRow, modifyRow, session); > parametersValues.add(value); >@@ -1045,8 +1056,8 @@ > Writer writer = new CharArrayWriter(queryString.length() + 50); > try { > // PERF: This method is heavily optimized do not touch anything unless you know "very well" what your doing. >- Vector parameters = getParameters(); >- Vector parametersValues = new Vector(parameters.size()); >+ List parameters = getParameters(); >+ List parametersValues = new ArrayList(parameters.size()); > while (lastIndex != -1) { > int tokenIndex = queryString.indexOf(argumentMarker(), lastIndex); > String token; >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java (working copy) >@@ -423,8 +423,8 @@ > appendLiteralToCallWithBinding(call, writer, literal); > } else { > int nParametersToAdd = appendParameterInternal(call, writer, literal); >- for(int i=0; i < nParametersToAdd; i++ ) { >- ((DatabaseCall)call).getParameterTypes().addElement(DatabaseCall.LITERAL); >+ for (int i = 0; i < nParametersToAdd; i++) { >+ ((DatabaseCall)call).getParameterTypes().add(DatabaseCall.LITERAL); > } > } > } >@@ -714,7 +714,7 @@ > /** > * Return the proc syntax for this platform. > */ >- public String buildProcedureCallString(StoredProcedureCall call, AbstractSession session) { >+ public String buildProcedureCallString(StoredProcedureCall call, AbstractSession session, AbstractRecord row) { > StringWriter writer = new StringWriter(); > writer.write(call.getCallHeader(this)); > writer.write(call.getProcedureName()); >@@ -725,24 +725,29 @@ > } > > int indexFirst = call.getFirstParameterIndexForCallString(); >- for (int index = indexFirst; index < call.getParameters().size(); index++) { >- String name = (String)call.getProcedureArgumentNames().elementAt(index); >- Integer parameterType = (Integer)call.getParameterTypes().elementAt(index); >- if (name != null && shouldPrintStoredProcedureArgumentNameInCall()) { >- writer.write(getProcedureArgumentString()); >- writer.write(name); >- writer.write(getProcedureArgumentSetter()); >- } >- writer.write("?"); >- if (call.isOutputParameterType(parameterType)) { >- if (requiresProcedureCallOuputToken()) { >- writer.write(" "); >- writer.write(getOutputProcedureToken()); >+ int size = call.getParameters().size(); >+ for (int index = indexFirst; index < size; index++) { >+ String name = call.getProcedureArgumentNames().get(index); >+ Object parameter = call.getParameters().get(index); >+ Integer parameterType = call.getParameterTypes().get(index); >+ // If the argument is optional and null, ignore it. >+ if (!call.hasOptionalArguments() || !call.getOptionalArguments().contains(parameter) || (row.get(parameter) != null)) { >+ if (name != null && shouldPrintStoredProcedureArgumentNameInCall()) { >+ writer.write(getProcedureArgumentString()); >+ writer.write(name); >+ writer.write(getProcedureArgumentSetter()); > } >+ writer.write("?"); >+ if (call.isOutputParameterType(parameterType)) { >+ if (requiresProcedureCallOuputToken()) { >+ writer.write(" "); >+ writer.write(getOutputProcedureToken()); >+ } >+ } >+ if ((index + 1) < call.getParameters().size()) { >+ writer.write(", "); >+ } > } >- if ((index + 1) < call.getParameters().size()) { >- writer.write(", "); >- } > } > call.setProcedureArgumentNames(null); > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatasourceCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatasourceCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/DatasourceCall.java (working copy) >@@ -39,10 +39,10 @@ > protected DatabaseQuery query; > > // The parameters (values) are ordered as they appear in the call. >- transient protected Vector parameters; >+ transient protected List parameters; > > // The parameter types determine if the parameter is a modify, translation or literal type. >- transient protected Vector parameterTypes; >+ transient protected List<Integer> parameterTypes; > public static final Integer LITERAL = Integer.valueOf(1); > public static final Integer MODIFY = Integer.valueOf(2); > public static final Integer TRANSLATION = Integer.valueOf(3); >@@ -77,9 +77,9 @@ > * The parameters are the values in order of occurrence in the SQL statement. > * This is lazy initialized to conserve space on calls that have no parameters. > */ >- public Vector getParameters() { >+ public List getParameters() { > if (parameters == null) { >- parameters = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(); >+ parameters = new ArrayList(); > } > return parameters; > } >@@ -87,9 +87,9 @@ > /** > * The parameter types determine if the parameter is a modify, translation or literal type. > */ >- public Vector getParameterTypes() { >+ public List<Integer> getParameterTypes() { > if (parameterTypes == null) { >- parameterTypes = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(); >+ parameterTypes = new ArrayList<Integer>(); > } > return parameterTypes; > } >@@ -97,14 +97,14 @@ > /** > * The parameters are the values in order of occurrence in the SQL statement. > */ >- public void setParameters(Vector parameters) { >+ public void setParameters(List parameters) { > this.parameters = parameters; > } > > /** > * The parameter types determine if the parameter is a modify, translation or literal type. > */ >- public void setParameterTypes(Vector parameterTypes) { >+ public void setParameterTypes(List<Integer> parameterTypes) { > this.parameterTypes = parameterTypes; > } > >@@ -130,14 +130,14 @@ > /** > * Bound calls can have the SQL pre generated. > */ >- protected boolean isPrepared() { >+ public boolean isPrepared() { > return isPrepared; > } > > /** > * Bound calls can have the SQL pre generated. > */ >- protected void setIsPrepared(boolean isPrepared) { >+ public void setIsPrepared(boolean isPrepared) { > this.isPrepared = isPrepared; > } > >@@ -525,8 +525,8 @@ > } catch (IOException exception) { > throw ValidationException.fileError(exception); > } >- getParameters().addElement(literal); >- getParameterTypes().addElement(LITERAL); >+ getParameters().add(literal); >+ getParameterTypes().add(LITERAL); > } > > /** >@@ -539,8 +539,8 @@ > } catch (IOException exception) { > throw ValidationException.fileError(exception); > } >- getParameters().addElement(modifyField); >- getParameterTypes().addElement(TRANSLATION); >+ getParameters().add(modifyField); >+ getParameterTypes().add(TRANSLATION); > } > > /** >@@ -553,8 +553,8 @@ > } catch (IOException exception) { > throw ValidationException.fileError(exception); > } >- getParameters().addElement(modifyField); >- getParameterTypes().addElement(MODIFY); >+ getParameters().add(modifyField); >+ getParameterTypes().add(MODIFY); > } > > /** >@@ -567,8 +567,8 @@ > } catch (IOException exception) { > throw ValidationException.fileError(exception); > } >- getParameters().addElement(field); >- getParameterTypes().addElement(IN); >+ getParameters().add(field); >+ getParameterTypes().add(IN); > } > > /** >@@ -582,8 +582,8 @@ > throw ValidationException.fileError(exception); > } > Object[] inOut = { inoutField, inoutField }; >- getParameters().addElement(inOut); >- getParameterTypes().addElement(INOUT); >+ getParameters().add(inOut); >+ getParameterTypes().add(INOUT); > } > > /** >@@ -596,8 +596,8 @@ > } catch (IOException exception) { > throw ValidationException.fileError(exception); > } >- getParameters().addElement(outField); >- getParameterTypes().addElement(OUT); >+ getParameters().add(outField); >+ getParameterTypes().add(OUT); > } > > /** >@@ -648,8 +648,8 @@ > // PERF: This method is heavily optimized do not touch anything unless you know "very well" what your doing. > // Must translate field parameters and may get new bound parameters for large data. > List parameterFields = getParameters(); >- List parameterTypes = getParameterTypes(); >- setParameters(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(parameterFields.size())); >+ List<Integer> parameterTypes = getParameterTypes(); >+ setParameters(NonSynchronizedVector.newInstance(parameterFields.size())); > while (lastIndex != -1) { > int tokenIndex = queryString.indexOf(argumentMarker(), lastIndex); > String token; >@@ -689,7 +689,7 @@ > writer.write(token); > if (tokenIndex != -1) { > // Process next parameter. >- Integer parameterType = (Integer)parameterTypes.get(parameterIndex); >+ Integer parameterType = parameterTypes.get(parameterIndex); > if (parameterType == MODIFY) { > DatabaseField field = (DatabaseField)parameterFields.get(parameterIndex); > Object value = modifyRow.get(field); >@@ -756,12 +756,15 @@ > */ > protected Object getValueForInParameter(Object parameter, AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session, boolean shouldBind) { > Object value = parameter; >- >+ DatabaseField field = null; >+ boolean isNull = false; >+ > // Parameter expressions are used for nesting and correct mapping conversion of the value. > if (parameter instanceof ParameterExpression) { > value = ((ParameterExpression)parameter).getValue(translationRow, session); >+ field = ((ParameterExpression)parameter).getField(); > } else if (parameter instanceof DatabaseField) { >- DatabaseField field = (DatabaseField)parameter; >+ field = (DatabaseField)parameter; > value = translationRow.get(field); > // Must check for the modify row as well for custom SQL compatibility as only one # is required. > if (modifyRow != null) { >@@ -777,7 +780,8 @@ > } > } > } >- if ((value == null) && shouldBind) { >+ if (value == null && shouldBind) { >+ isNull = true; > if ((field.getType() != null) ||(field.getSqlType()!= DatabaseField.NULL_SQL_TYPE)){ > value = field; > } else if (modifyRow != null) { >@@ -795,12 +799,15 @@ > value = translationField; > } > } >- }else { >+ } else { > if (parameter instanceof ObjectRelationalDatabaseField){ >- value = new InParameterForCallableStatement( value, (DatabaseField)parameter); >+ value = new InParameterForCallableStatement(value, (DatabaseField)parameter); > } > } > } >+ if ((value == null || isNull) && this.query.hasNullableArguments() && this.query.getNullableArguments().contains(field)) { >+ return this; >+ } > return value; > } > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/QueryStringCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/QueryStringCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/databaseaccess/QueryStringCall.java (working copy) >@@ -34,12 +34,12 @@ > * The parameters are the values in order of occurance in the SQL statement. > * This is lazy initialized to conserv space on calls that have no parameters. > */ >- public Vector getParameters(); >+ public List getParameters(); > > /** > * The parameter types determine if the parameter is a modify, translation or litteral type. > */ >- public Vector getParameterTypes(); >+ public List<Integer> getParameterTypes(); > > /** > * The parameters are the values in order of occurance in call. >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/ComplexDatabaseType.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/ComplexDatabaseType.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/ComplexDatabaseType.java (working copy) >@@ -12,11 +12,9 @@ > ******************************************************************************/ > package org.eclipse.persistence.internal.helper; > >-//javase imports > import java.util.ListIterator; >-import java.util.Vector; >+import java.util.List; > >-//EclipseLink imports > import org.eclipse.persistence.exceptions.QueryException; > import org.eclipse.persistence.internal.sessions.AbstractRecord; > import org.eclipse.persistence.platform.database.DatabasePlatform; >@@ -114,7 +112,6 @@ > this.javaTypeName = javaTypeName; > } > >- @Override > public ComplexDatabaseType clone() { > try { > ComplexDatabaseType clone = (ComplexDatabaseType)super.clone(); >@@ -167,7 +164,7 @@ > public void buildBeginBlock(StringBuilder sb, PLSQLargument arg, PLSQLStoredProcedureCall call) { > String sql2PlName = call.getSQL2PlName(this); > if (sql2PlName == null) { >- // TODO exception >+ // TODO exception > throw new NullPointerException("no SQL2Pl conversion routine for " + typeName); > } > String target = databaseTypeHelper.buildTarget(arg); >@@ -185,7 +182,7 @@ > public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call) { > String sql2PlName = call.getPl2SQLName(this); > if (sql2PlName == null) { >- // TODO: Error. >+ // TODO: Error. > throw new NullPointerException("no Pl2SQL conversion routine for " + typeName); > } > String target = databaseTypeHelper.buildTarget(outArg); >@@ -200,7 +197,7 @@ > } > > public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, >- DatabaseRecord newOutputRow, Vector outputRowFields, Vector outputRowValues) { >+ DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) { > databaseTypeHelper.buildOutputRow(outArg, outputRow, > newOutputRow, outputRowFields, outputRowValues); > } >@@ -214,13 +211,13 @@ > } > > public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg, >- AbstractRecord translationRow, DatabasePlatform platform) { >+ AbstractRecord translationRow, DatabasePlatform platform) { > databaseTypeHelper.logParameter(sb, direction, arg, translationRow, platform); > } > > public void translate(PLSQLargument arg, AbstractRecord translationRow, >- AbstractRecord copyOfTranslationRow, Vector copyOfTranslationFields, >- Vector translationRowFields, Vector translationRowValues, StoredProcedureCall call) { >+ AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields, >+ List<DatabaseField> translationRowFields, List translationRowValues, StoredProcedureCall call) { > databaseTypeHelper.translate(arg, translationRow, copyOfTranslationRow, > copyOfTranslationFields, translationRowFields, translationRowValues, call); > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/DatabaseType.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/DatabaseType.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/DatabaseType.java (working copy) >@@ -13,15 +13,11 @@ > > package org.eclipse.persistence.internal.helper; > >-// Javase imports > import java.util.Iterator; >+import java.util.List; > import java.util.ListIterator; >-import java.util.Vector; > import static java.lang.Integer.MIN_VALUE; > >-// Java extension imports >- >-// EclipseLink imports > import org.eclipse.persistence.internal.sessions.AbstractRecord; > import org.eclipse.persistence.platform.database.DatabasePlatform; > import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall; >@@ -70,12 +66,12 @@ > public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call); > > public void translate(PLSQLargument arg, AbstractRecord translationRow, >- AbstractRecord copyOfTranslationRow, Vector copyOfTranslationFields, >- Vector translationRowFields, Vector translationRowValues, >+ AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields, >+ List<DatabaseField> translationRowFields, List translationRowValues, > StoredProcedureCall call); > > public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, >- DatabaseRecord newOutputRow, Vector outputRowFields, Vector outputRowValues); >+ DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues); > > public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg, > AbstractRecord translationRow, DatabasePlatform platform); >@@ -122,9 +118,9 @@ > } > > public void translate(PLSQLargument arg, AbstractRecord translationRow, >- AbstractRecord copyOfTranslationRow, Vector copyOfTranslationFields, >- Vector translationRowFields, Vector translationRowValues, >- StoredProcedureCall call) { >+ AbstractRecord copyOfTranslationRow, List copyOfTranslationFields, >+ List translationRowFields, List translationRowValues, >+ StoredProcedureCall call) { > DatabaseField field = null; > for (Iterator i = copyOfTranslationFields.iterator(); i.hasNext(); ) { > DatabaseField f = (DatabaseField)i.next(); >@@ -142,13 +138,13 @@ > if (arg.scale != MIN_VALUE) { > field.setScale(arg.scale); > } >- translationRowFields.setElementAt(field, arg.inIndex-1); >+ translationRowFields.set(arg.inIndex - 1, field); > Object value = copyOfTranslationRow.get(field); >- translationRowValues.setElementAt(value, arg.inIndex-1); >+ translationRowValues.set(arg.inIndex - 1, value); > } > > public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, >- DatabaseRecord newOutputRow, Vector outputRowFields, Vector outputRowValues) { >+ DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) { > DatabaseField field = null; > for (Iterator i = outputRowFields.iterator(); i.hasNext(); ) { > DatabaseField f = (DatabaseField)i.next(); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/CallQueryMechanism.java (working copy) >@@ -61,6 +61,35 @@ > } > > /** >+ * Unprepare the call if required. >+ * Clone and unprepare stored procedure calls, so they can be reprepared with possible different optional arguments. >+ */ >+ public void unprepare() { >+ DatabaseQuery query = this.query; >+ if (hasMultipleCalls()) { >+ this.calls = ((Vector)this.calls.clone()); >+ int size = this.calls.size(); >+ for (int index = 0; index < size; index++) { >+ DatabaseCall call = (DatabaseCall)this.calls.get(index); >+ if (call.isPrepared() && call.isStoredProcedureCall() >+ && ((StoredProcedureCall)call).hasOptionalArguments()) { >+ call = (DatabaseCall)call.clone(); >+ call.setIsPrepared(false); >+ call.setQuery(query); >+ this.calls.set(index, call); >+ } >+ } >+ } else if (this.call != null) { >+ if (this.call.isPrepared() && this.call.isStoredProcedureCall() >+ && ((StoredProcedureCall)this.call).hasOptionalArguments()) { >+ this.call = (DatabaseCall)this.call.clone(); >+ this.call.setIsPrepared(false); >+ this.call.setQuery(query); >+ } >+ } >+ } >+ >+ /** > * INTERNAL: > * This is different from 'prepareForExecution' in that this is called on the original query, > * and the other is called on the copy of the query. >@@ -68,15 +97,21 @@ > * will apply to any future execution of this query. > */ > public void prepareCall() throws QueryException { >- DatabaseQuery query = getQuery(); >+ DatabaseQuery query = this.query; > AbstractSession executionSession = query.getExecutionSession(); > if (hasMultipleCalls()) { >- if(getQuery().shouldCloneCall()){ >- //For glassFish bug2689, the call needs to be cloned when query asks to do so. >- calls = ((Vector)getCalls().clone()); >+ if (query.shouldCloneCall()) { >+ this.calls = ((Vector)this.calls.clone()); > } >- for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) { >- DatabaseCall call = (DatabaseCall)callsEnum.nextElement(); >+ int size = this.calls.size(); >+ for (int index = 0; index < size; index++) { >+ DatabaseCall call = (DatabaseCall)this.calls.get(index); >+ if (query.shouldCloneCall()) { >+ // Need to clone the call if setting query specific properties on it as the call may be shared. >+ call = (DatabaseCall)call.clone(); >+ call.setQuery(query); >+ this.calls.set(index, call); >+ } > if (!query.shouldIgnoreBindAllParameters()) { > call.setUsesBinding(query.shouldBindAllParameters()); > } >@@ -102,13 +137,13 @@ > } > call.prepare(executionSession); > } >- } else if (getCall() != null) { >- if (getQuery().shouldCloneCall()){ >- //For glassFish bug2689, the call needs to be cloned when query asks to do so. >- call = (DatabaseCall)getDatabaseCall().clone(); >- setCall(call); >- } >- DatabaseCall call = getDatabaseCall(); >+ } else if (this.call != null) { >+ if (query.shouldCloneCall()) { >+ // Need to clone the call if setting query specific properties on it as the call may be shared. >+ this.call = (DatabaseCall)this.call.clone(); >+ call.setQuery(query); >+ } >+ DatabaseCall call = (DatabaseCall)this.call; > if (!query.shouldIgnoreBindAllParameters()) { > call.setUsesBinding(query.shouldBindAllParameters()); > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatabaseQueryMechanism.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatabaseQueryMechanism.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatabaseQueryMechanism.java (working copy) >@@ -1059,4 +1059,11 @@ > eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostUpdateEvent, writeQuery)); > } > } >+ >+ /** >+ * Unprepare the call if required. >+ */ >+ public void unprepare() { >+ >+ } > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatasourceCallQueryMechanism.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatasourceCallQueryMechanism.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatasourceCallQueryMechanism.java (working copy) >@@ -418,15 +418,14 @@ > DatabaseQuery query = getQuery(); > AbstractSession executionSession = query.getExecutionSession(); > if (hasMultipleCalls()) { >- for (Enumeration callsEnum = getCalls().elements(); callsEnum.hasMoreElements();) { >- DatasourceCall call = (DatasourceCall)callsEnum.nextElement(); >+ for (DatasourceCall call : (List<DatasourceCall>)getCalls()) { > call.prepare(executionSession); > } > } else if (getCall() != null) { > getCall().prepare(executionSession); > } > } >- >+ > /** > * Pre-build configure the call. > */ >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/factories/ObjectPersistenceRuntimeXMLProject_11_1_1.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/factories/ObjectPersistenceRuntimeXMLProject_11_1_1.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/factories/ObjectPersistenceRuntimeXMLProject_11_1_1.java (working copy) >@@ -963,10 +963,10 @@ > @Override > public Object getAttributeValueFromObject(Object anObject) throws DescriptorException { > StoredProcedureCall spc = (StoredProcedureCall)anObject; >- Vector parameterTypes = spc.getParameterTypes(); >- Vector parameters = spc.getParameters(); >- Vector procedureArgumentNames = spc.getProcedureArgumentNames(); >- Vector storedProcedureArguments = new Vector(); >+ List parameterTypes = spc.getParameterTypes(); >+ List parameters = spc.getParameters(); >+ List procedureArgumentNames = spc.getProcedureArgumentNames(); >+ List storedProcedureArguments = new Vector(); > for (int i = spc.getFirstParameterIndexForCallString(); i < parameterTypes.size(); i++) { > StoredProcedureArgument spa = null; > Integer direction = (Integer)parameterTypes.get(i); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/jdbc/JDBCTypes.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/jdbc/JDBCTypes.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/jdbc/JDBCTypes.java (working copy) >@@ -13,11 +13,10 @@ > > package org.eclipse.persistence.platform.database.jdbc; > >-//javase imports > import java.sql.Array; > import java.sql.Struct; >+import java.util.List; > import java.util.ListIterator; >-import java.util.Vector; > import static java.lang.Integer.MIN_VALUE; > import static java.sql.Types.ARRAY; > import static java.sql.Types.BIGINT; >@@ -50,8 +49,8 @@ > import static java.sql.Types.VARBINARY; > import static java.sql.Types.VARCHAR; > >-//EclipseLink imports > import org.eclipse.persistence.internal.helper.ClassConstants; >+import org.eclipse.persistence.internal.helper.DatabaseField; > import org.eclipse.persistence.internal.helper.DatabaseType; > import org.eclipse.persistence.internal.sessions.AbstractRecord; > import org.eclipse.persistence.platform.database.DatabasePlatform; >@@ -221,21 +220,21 @@ > } > > public void translate(PLSQLargument arg, AbstractRecord translationRow, >- AbstractRecord copyOfTranslationRow, Vector copyOfTranslationFields, >- Vector translationRowFields, Vector translationRowValues, >- StoredProcedureCall call) { >+ AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields, >+ List<DatabaseField> translationRowFields, List translationRowValues, >+ StoredProcedureCall call) { > databaseTypeHelper.translate(arg, translationRow, copyOfTranslationRow, > copyOfTranslationFields, translationRowFields, translationRowValues, call); > } > > public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, >- DatabaseRecord newOutputRow, Vector outputRowFields, Vector outputRowValues) { >+ DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) { > databaseTypeHelper.buildOutputRow(outArg, outputRow, > newOutputRow, outputRowFields, outputRowValues); > } > > public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg, >- AbstractRecord translationRow, DatabasePlatform platform) { >+ AbstractRecord translationRow, DatabasePlatform platform) { > databaseTypeHelper.logParameter(sb, direction, arg, translationRow, platform); > } > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/MySQLPlatform.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/MySQLPlatform.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/MySQLPlatform.java (working copy) >@@ -24,6 +24,7 @@ > import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter; > import org.eclipse.persistence.internal.expressions.SQLSelectStatement; > import org.eclipse.persistence.internal.helper.*; >+import org.eclipse.persistence.internal.sessions.AbstractRecord; > import org.eclipse.persistence.internal.sessions.AbstractSession; > import org.eclipse.persistence.queries.StoredProcedureCall; > import org.eclipse.persistence.queries.ValueReadQuery; >@@ -157,11 +158,11 @@ > } > > /** >- * Return the proc syntax for this platform. >+ * Return the stored procedure syntax for this platform. > */ > @Override >- public String buildProcedureCallString(StoredProcedureCall call, AbstractSession session) { >- return "{ " + super.buildProcedureCallString(call, session); >+ public String buildProcedureCallString(StoredProcedureCall call, AbstractSession session, AbstractRecord row) { >+ return "{ " + super.buildProcedureCallString(call, session, row); > } > > /** >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredFunctionQueries.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredFunctionQueries.java (revision 0) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredFunctionQueries.java (revision 0) >@@ -0,0 +1,35 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * Oracle - initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.persistence.platform.database.oracle.annotations; >+ >+import java.lang.annotation.Retention; >+import java.lang.annotation.Target; >+ >+import static java.lang.annotation.ElementType.TYPE; >+import static java.lang.annotation.RetentionPolicy.RUNTIME; >+ >+/** >+ * A NamedPLSQLStoredFunctionQueries annotation allows the definition of multiple >+ * NamedPLSQLStoredFunctionQuery. >+ * >+ * @author James >+ * @since EclipseLink 2.3 >+ */ >+@Target({TYPE}) >+@Retention(RUNTIME) >+public @interface NamedPLSQLStoredFunctionQueries { >+ /** >+ * (Required) An array of named PLSQL stored procedure query. >+ */ >+ NamedPLSQLStoredFunctionQuery[] value(); >+} >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredFunctionQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredFunctionQuery.java (revision 0) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredFunctionQuery.java (revision 0) >@@ -0,0 +1,67 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * Oracle - initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.persistence.platform.database.oracle.annotations; >+ >+import java.lang.annotation.Retention; >+import java.lang.annotation.Target; >+ >+import static java.lang.annotation.ElementType.TYPE; >+import static java.lang.annotation.RetentionPolicy.RUNTIME; >+ >+import javax.persistence.QueryHint; >+ >+/** >+ * A NamedPLSQLStoredFunctionQuery annotation allows the definition of queries that >+ * call PLSQL stored functions as named queries. >+ * The PLSQL support adds support for complex PLSQL types such as RECORD and TABLE types, >+ * that are not accessible from JDBC. >+ * >+ * A NamedPLSQLStoredFunctionQuery annotation may be defined on an Entity or >+ * MappedSuperclass. >+ * >+ * @author James Sutherland >+ * @since EclipseLink 2.3 >+ */ >+@Target({TYPE}) >+@Retention(RUNTIME) >+public @interface NamedPLSQLStoredFunctionQuery { >+ /** >+ * (Required) Unique name that references this stored procedure query. >+ */ >+ String name(); >+ >+ /** >+ * (Optional) Query hints. >+ */ >+ QueryHint[] hints() default {}; >+ >+ /** >+ * (Optional) The name of the SQLResultMapping. >+ */ >+ String resultSetMapping() default ""; >+ >+ /** >+ * (Required) The name of the stored procedure. >+ */ >+ String functionName(); >+ >+ /** >+ * (Optional) Defines the parameters to the stored procedure. >+ */ >+ PLSQLParameter[] parameters() default {}; >+ >+ /** >+ * (Required) Defines the return value of the stored function. >+ */ >+ PLSQLParameter returnParameter(); >+} >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredProcedureQueries.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredProcedureQueries.java (revision 0) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredProcedureQueries.java (revision 0) >@@ -0,0 +1,35 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * Oracle - initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.persistence.platform.database.oracle.annotations; >+ >+import java.lang.annotation.Retention; >+import java.lang.annotation.Target; >+ >+import static java.lang.annotation.ElementType.TYPE; >+import static java.lang.annotation.RetentionPolicy.RUNTIME; >+ >+/** >+ * A NamedPLSQLStoredProcedureQueries annotation allows the definition of multiple >+ * NamedPLSQLStoredProcedureQuery. >+ * >+ * @author James Sutherland >+ * @since EclipseLink 2.3 >+ */ >+@Target({TYPE}) >+@Retention(RUNTIME) >+public @interface NamedPLSQLStoredProcedureQueries { >+ /** >+ * (Required) An array of named PLSQL stored procedure query. >+ */ >+ NamedPLSQLStoredProcedureQuery[] value(); >+} >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredProcedureQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredProcedureQuery.java (revision 0) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/NamedPLSQLStoredProcedureQuery.java (revision 0) >@@ -0,0 +1,67 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * Oracle - initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.persistence.platform.database.oracle.annotations; >+ >+import java.lang.annotation.Retention; >+import java.lang.annotation.Target; >+ >+import static java.lang.annotation.ElementType.TYPE; >+import static java.lang.annotation.RetentionPolicy.RUNTIME; >+ >+import javax.persistence.QueryHint; >+ >+/** >+ * A PLSQLNamedStoredProcedureQuery annotation allows the definition of queries that >+ * call PLSQL stored procedures as named queries. >+ * The PLSQL support adds support for complex PLSQL types such as RECORD and TABLE types, >+ * that are not accessible from JDBC. >+ * >+ * A PLSQLNamedStoredProcedureQuery annotation may be defined on an Entity or >+ * MappedSuperclass. >+ * >+ * @author James Sutherland >+ * @since EclipseLink 2.3 >+ */ >+@Target({TYPE}) >+@Retention(RUNTIME) >+public @interface NamedPLSQLStoredProcedureQuery { >+ /** >+ * (Required) Unique name that references this stored procedure query. >+ */ >+ String name(); >+ >+ /** >+ * (Optional) Query hints. >+ */ >+ QueryHint[] hints() default {}; >+ >+ /** >+ * (Optional) Refers to the class of the result. >+ */ >+ Class resultClass() default void.class; >+ >+ /** >+ * (Optional) The name of the SQLResultMapping. >+ */ >+ String resultSetMapping() default ""; >+ >+ /** >+ * (Required) The name of the stored procedure. >+ */ >+ String procedureName(); >+ >+ /** >+ * (Optional) Defines the parameters to the stored procedure. >+ */ >+ PLSQLParameter[] parameters() default {}; >+} >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/PLSQLParameter.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/PLSQLParameter.java (revision 0) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/annotations/PLSQLParameter.java (revision 0) >@@ -0,0 +1,82 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * Oracle - initial API and implementation >+ ******************************************************************************/ >+package org.eclipse.persistence.platform.database.oracle.annotations; >+ >+import java.lang.annotation.Retention; >+import java.lang.annotation.Target; >+ >+import org.eclipse.persistence.annotations.Direction; >+import org.eclipse.persistence.platform.database.jdbc.JDBCTypes; >+import org.eclipse.persistence.platform.database.oracle.plsql.OraclePLSQLTypes; >+ >+import static java.lang.annotation.RetentionPolicy.RUNTIME; >+ >+import static org.eclipse.persistence.annotations.Direction.IN; >+ >+/** >+ * A PLSQLParameter annotation is used within a >+ * NamedPLSQLStoredProcedureQuery or PLSQLRecord annotation. >+ * >+ * @see NamedPLSQLStoredProcedureQuery >+ * @see PLSQLRecord >+ * @author James Sutherland >+ * @since EclipseLink 2.3 >+ */ >+@Target({}) >+@Retention(RUNTIME) >+public @interface PLSQLParameter { >+ /** >+ * (Optional) The direction of the stored procedure parameter. >+ */ >+ Direction direction() default IN; >+ >+ /** >+ * (Optional) Stored procedure parameter name. >+ */ >+ String name() default ""; >+ >+ /** >+ * (Required) The query parameter name. >+ */ >+ String queryParameter(); >+ >+ /** >+ * (Optional) Define if the parameter is required, or optional and defaulted by the procedure. >+ */ >+ boolean optional() default false; >+ >+ /** >+ * (Optional) The database data-type for the paramter. >+ * This either one of the type constants defined in OraclePLSQLTypes, or JDBCTypes, >+ * or a custom record or table type name. >+ * @see PLSQLRecord >+ * @see OraclePLSQLTypes >+ * @see JDBCTypes >+ */ >+ String databaseType() default "VARCHAR"; >+ >+ /** >+ * (Optional) The max length of the field value. >+ */ >+ int length() default 255; >+ >+ /** >+ * (Optional) If a numeric, the max scale value. >+ */ >+ int scale() default 0; >+ >+ /** >+ * (Optional) If a numeric, the max precision value. >+ */ >+ int precision() default 0; >+} >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/OraclePLSQLTypes.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/OraclePLSQLTypes.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/OraclePLSQLTypes.java (working copy) >@@ -13,12 +13,11 @@ > > package org.eclipse.persistence.platform.database.oracle.plsql; > >-//javse imports >+import java.util.List; > import java.util.ListIterator; >-import java.util.Vector; > import static java.sql.Types.OTHER; > >-// EclipseLink imports >+import org.eclipse.persistence.internal.helper.DatabaseField; > import org.eclipse.persistence.internal.helper.DatabaseType; > import org.eclipse.persistence.internal.helper.SimpleDatabaseType; > import org.eclipse.persistence.internal.sessions.AbstractRecord; >@@ -187,8 +186,8 @@ > * Translate the argument value from the query translation row to call translation row. > */ > public void translate(PLSQLargument arg, AbstractRecord translationRow, >- AbstractRecord copyOfTranslationRow, Vector copyOfTranslationFields, >- Vector translationRowFields, Vector translationRowValues, StoredProcedureCall call) { >+ AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields, >+ List<DatabaseField> translationRowFields, List translationRowValues, StoredProcedureCall call) { > databaseTypeHelper.translate(arg, translationRow, copyOfTranslationRow, > copyOfTranslationFields, translationRowFields, translationRowValues, call); > } >@@ -198,7 +197,7 @@ > * Build the query output row from the call output row. > */ > public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, >- DatabaseRecord newOutputRow, Vector outputRowFields, Vector outputRowValues) { >+ DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) { > databaseTypeHelper.buildOutputRow(outArg, outputRow, > newOutputRow, outputRowFields, outputRowValues); > } >@@ -208,7 +207,7 @@ > * Append the parameter for logging purposes. > */ > public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg, >- AbstractRecord translationRow, DatabasePlatform platform) { >+ AbstractRecord translationRow, DatabasePlatform platform) { > databaseTypeHelper.logParameter(sb, direction, arg, translationRow, platform); > } > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLrecord.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLrecord.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLrecord.java (working copy) >@@ -13,18 +13,16 @@ > > package org.eclipse.persistence.platform.database.oracle.plsql; > >-// javase imports > import java.util.ArrayList; > import java.util.Iterator; > import java.util.List; > import java.util.ListIterator; >-import java.util.Vector; > import static java.sql.Types.OTHER; > import static java.sql.Types.STRUCT; > >-// EclipseLink imports > import org.eclipse.persistence.exceptions.QueryException; > import org.eclipse.persistence.internal.helper.ComplexDatabaseType; >+import org.eclipse.persistence.internal.helper.DatabaseField; > import org.eclipse.persistence.internal.helper.DatabaseType; > import org.eclipse.persistence.internal.sessions.AbstractRecord; > import org.eclipse.persistence.platform.database.DatabasePlatform; >@@ -189,9 +187,9 @@ > } > > public void translate(PLSQLargument arg, AbstractRecord translationRow, >- AbstractRecord copyOfTranslationRow, Vector copyOfTranslationFields, >- Vector translationRowFields, Vector translationRowValues, >- StoredProcedureCall call) { >+ AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields, >+ List<DatabaseField> translationRowFields, List translationRowValues, >+ StoredProcedureCall call) { > if (hasCompatibleType()) { > super.translate(arg, translationRow, copyOfTranslationRow, > copyOfTranslationFields, translationRowFields, translationRowValues, call); >@@ -204,7 +202,7 @@ > } > > public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow, >- DatabaseRecord newOutputRow, Vector outputRowFields, Vector outputRowValues) { >+ DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) { > if (hasCompatibleType()) { > super.buildOutputRow(outArg, outputRow, newOutputRow, outputRowFields, outputRowValues); > } else { >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLStoredFunctionCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLStoredFunctionCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLStoredFunctionCall.java (working copy) >@@ -15,6 +15,8 @@ > import static org.eclipse.persistence.internal.helper.DatabaseType.DatabaseTypeHelper.databaseTypeHelper; > import static org.eclipse.persistence.internal.helper.Helper.NL; > >+import java.util.List; >+ > import org.eclipse.persistence.internal.helper.*; > import org.eclipse.persistence.internal.sessions.AbstractSession; > import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; >@@ -59,6 +61,7 @@ > * INTERNAL: > * Return call header for the call string. > */ >+ @Override > public String getCallHeader(DatabasePlatform platform) { > return platform.getFunctionCallHeader(); > } >@@ -68,6 +71,7 @@ > * Return the first index of parameter to be placed inside brackets > * in the call string. > */ >+ @Override > public int getFirstParameterIndexForCallString() { > return 1; > } >@@ -75,6 +79,7 @@ > /** > * INTERNAL: > */ >+ @Override > public boolean isStoredFunctionCall() { > return true; > } >@@ -82,6 +87,7 @@ > /** > * INTERNAL: > */ >+ @Override > public void prepareInternal(AbstractSession session) { > if (session.getPlatform().supportsStoredFunctions()) { > super.prepareInternal(session); >@@ -120,16 +126,17 @@ > /** > * INTERNAL Generate portion of the Anonymous PL/SQL block that invokes the target function. > */ >- protected void buildProcedureInvocation(StringBuilder sb) { >+ @Override >+ protected void buildProcedureInvocation(StringBuilder sb, List<PLSQLargument> arguments) { > sb.append(" "); >- PLSQLargument argument = this.arguments.get(0); >+ PLSQLargument argument = arguments.get(0); > sb.append(databaseTypeHelper.buildTarget(argument)); > sb.append(" := "); > sb.append(getProcedureName()); > sb.append("("); >- int size = this.arguments.size(); >+ int size = arguments.size(); > for (int index = 1; index < size; index++) { >- argument = this.arguments.get(index); >+ argument = arguments.get(index); > sb.append(argument.name); > sb.append("=>"); > sb.append(databaseTypeHelper.buildTarget(argument)); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLStoredProcedureCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLStoredProcedureCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/platform/database/oracle/plsql/PLSQLStoredProcedureCall.java (working copy) >@@ -566,11 +566,9 @@ > /** > * INTERNAL > * Generate portion of the Anonymous PL/SQL block that declares the temporary variables >- * in the DECLARE section >- * >- * @param sb >+ * in the DECLARE section. > */ >- protected void buildDeclareBlock(StringBuilder sb) { >+ protected void buildDeclareBlock(StringBuilder sb, List<PLSQLargument> arguments) { > List<PLSQLargument> inArguments = getArguments(arguments, IN); > List<PLSQLargument> inOutArguments = getArguments(arguments, INOUT); > inArguments.addAll(inOutArguments); >@@ -891,14 +889,12 @@ > /** > * INTERNAL > * Generate portion of the Anonymous PL/SQL block with PL/SQL conversion routines as >- * nested functions >- * >- * @param sb >+ * nested functions. > */ >- protected void buildNestedFunctions(StringBuilder stream) { >+ protected void buildNestedFunctions(StringBuilder stream, List<PLSQLargument> arguments) { > List<String> nestedFunctions = new ArrayList<String>(); > Set<DatabaseType> processed = new HashSet<DatabaseType>(); >- for (PLSQLargument arg : this.arguments) { >+ for (PLSQLargument arg : arguments) { > DatabaseType type = arg.databaseType; > addNestedFunctionsForArgument(nestedFunctions, arg, type, processed); > } >@@ -911,12 +907,9 @@ > > /** > * INTERNAL Generate portion of the Anonymous PL/SQL block that assigns fields at the beginning >- * of the BEGIN block (before invoking the target procedure) >- * >- * @param sb >+ * of the BEGIN block (before invoking the target procedure). > */ >- protected void buildBeginBlock(StringBuilder sb) { >- >+ protected void buildBeginBlock(StringBuilder sb, List<PLSQLargument> arguments) { > List<PLSQLargument> inArguments = getArguments(arguments, IN); > inArguments.addAll(getArguments(arguments, INOUT)); > for (PLSQLargument arg : inArguments) { >@@ -925,20 +918,17 @@ > } > > /** >- * INTERNAL Generate portion of the Anonymous PL/SQL block that invokes the target procedure >- * >- * @param sb >+ * INTERNAL Generate portion of the Anonymous PL/SQL block that invokes the target procedure. > */ >- protected void buildProcedureInvocation(StringBuilder sb) { >- >+ protected void buildProcedureInvocation(StringBuilder sb, List<PLSQLargument> arguments) { > sb.append(" "); > sb.append(getProcedureName()); > sb.append("("); > int size = arguments.size(), idx = 1; >- for (PLSQLargument arg : arguments) { >- sb.append(arg.name); >+ for (PLSQLargument argument : arguments) { >+ sb.append(argument.name); > sb.append("=>"); >- sb.append(databaseTypeHelper.buildTarget(arg)); >+ sb.append(databaseTypeHelper.buildTarget(argument)); > if (idx < size) { > sb.append(", "); > idx++; >@@ -950,11 +940,9 @@ > > /** > * INTERNAL Generate portion of the Anonymous PL/SQL block after the target procedures has been >- * invoked and OUT parameters must be handled >- * >- * @param sb >+ * invoked and OUT parameters must be handled. > */ >- protected void buildOutAssignments(StringBuilder sb) { >+ protected void buildOutAssignments(StringBuilder sb, List<PLSQLargument> arguments) { > List<PLSQLargument> outArguments = getArguments(arguments, OUT); > outArguments.addAll(getArguments(arguments, INOUT)); > for (PLSQLargument arg : outArguments) { >@@ -970,17 +958,36 @@ > // build any and all required type conversion routines for > // complex PL/SQL types in packages > this.typesInfo = new HashMap<String, TypeInfo>(); >+ // Rest parameters to be recomputed if being reprepared. >+ this.parameters = null; > // create a copy of the arguments re-ordered with different indices > assignIndices(); >+ >+ // Filter out any optional arguments that are null. >+ List<PLSQLargument> specifiedArguments = this.arguments; >+ AbstractRecord row = getQuery().getTranslationRow(); >+ if ((row != null) && hasOptionalArguments()) { >+ for (PLSQLargument argument : this.arguments) { >+ DatabaseField queryArgument = new DatabaseField(argument.name); >+ if (this.optionalArguments.contains(queryArgument) && (row.get(queryArgument) == null)) { >+ if (specifiedArguments == this.arguments) { >+ specifiedArguments = new ArrayList<PLSQLargument>(this.arguments); >+ } >+ specifiedArguments.remove(argument); >+ } >+ } >+ } > // build the Anonymous PL/SQL block in sections > StringBuilder sb = new StringBuilder(); >- sb.append(BEGIN_DECLARE_BLOCK); >- buildDeclareBlock(sb); >- buildNestedFunctions(sb); >+ if (!specifiedArguments.isEmpty()) { >+ sb.append(BEGIN_DECLARE_BLOCK); >+ buildDeclareBlock(sb, specifiedArguments); >+ buildNestedFunctions(sb, specifiedArguments); >+ } > sb.append(BEGIN_BEGIN_BLOCK); >- buildBeginBlock(sb); >- buildProcedureInvocation(sb); >- buildOutAssignments(sb); >+ buildBeginBlock(sb, specifiedArguments); >+ buildProcedureInvocation(sb, specifiedArguments); >+ buildOutAssignments(sb, specifiedArguments); > sb.append(END_BEGIN_BLOCK); > setSQLStringInternal(sb.toString()); > super.prepareInternalParameters(session); >@@ -992,14 +999,13 @@ > * This handles expanding and re-ordering parameters. > */ > @Override >- public void translate(AbstractRecord translationRow, AbstractRecord modifyRow, >- AbstractSession session) { >+ public void translate(AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) { > // re-order elements in translationRow to conform to re-ordered indices > AbstractRecord copyOfTranslationRow = translationRow.clone(); > int len = copyOfTranslationRow.size(); >- Vector copyOfTranslationFields = copyOfTranslationRow.getFields(); >+ List<DatabaseField> copyOfTranslationFields = copyOfTranslationRow.getFields(); > translationRow.clear(); >- Vector translationRowFields = translationRow.getFields(); >+ Vector<DatabaseField> translationRowFields = translationRow.getFields(); > translationRowFields.setSize(len); > Vector translationRowValues = translationRow.getValues(); > translationRowValues.setSize(len); >@@ -1055,8 +1061,21 @@ > sb.append(Helper.cr()); > sb.append(INDENT); > sb.append("bind => ["); >- List<PLSQLargument> inArguments = getArguments(arguments, IN); >- inArguments.addAll(getArguments(arguments, INOUT)); >+ List<PLSQLargument> specifiedArguments = this.arguments; >+ AbstractRecord row = getQuery().getTranslationRow(); >+ if ((row != null) && hasOptionalArguments()) { >+ for (PLSQLargument argument : this.arguments) { >+ DatabaseField queryArgument = new DatabaseField(argument.name); >+ if (this.optionalArguments.contains(queryArgument) && (row.get(queryArgument) == null)) { >+ if (specifiedArguments == this.arguments) { >+ specifiedArguments = new ArrayList<PLSQLargument>(this.arguments); >+ } >+ specifiedArguments.remove(argument); >+ } >+ } >+ } >+ List<PLSQLargument> inArguments = getArguments(specifiedArguments, IN); >+ inArguments.addAll(getArguments(specifiedArguments, INOUT)); > Collections.sort(inArguments, new Comparator<PLSQLargument>() { > public int compare(PLSQLargument o1, PLSQLargument o2) { > return o1.inIndex - o2.inIndex; >@@ -1070,8 +1089,8 @@ > sb.append(", "); > } > } >- List<PLSQLargument> outArguments = getArguments(arguments, OUT); >- outArguments.addAll(getArguments(arguments, INOUT)); >+ List<PLSQLargument> outArguments = getArguments(specifiedArguments, OUT); >+ outArguments.addAll(getArguments(specifiedArguments, INOUT)); > Collections.sort(outArguments, new Comparator<PLSQLargument>() { > public int compare(PLSQLargument o1, PLSQLargument o2) { > return o1.outIndex - o2.outIndex; >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DatabaseQuery.java (working copy) >@@ -176,6 +176,12 @@ > * non-pre SQL generated queries. > */ > protected boolean shouldPrepare; >+ >+ /** >+ * List of arguments to check for null. >+ * If any are null, the query needs to be re-prepared. >+ */ >+ protected List<DatabaseField> nullableArguments; > > /** Bind all arguments to the SQL statement. */ > >@@ -359,10 +365,7 @@ > * executeQuery() > */ > public void addArgument(String argumentName) { >- // CR#3545 - Changed the default argument type to make argument types >- // work more consistently >- // with the SDK >- addArgument(argumentName, java.lang.Object.class); >+ addArgument(argumentName, Object.class); > } > > /** >@@ -373,9 +376,25 @@ > * identically named queries are used but with different argument lists. > */ > public void addArgument(String argumentName, Class type) { >+ addArgument(argumentName, type, false); >+ } >+ >+ /** >+ * PUBLIC: Add the argument named argumentName and its class type. This will >+ * cause the translation of references of argumentName in the receiver's >+ * expression, with the value of the argument as supplied to the query in >+ * order from executeQuery(). Specifying the class type is important if >+ * identically named queries are used but with different argument lists. >+ * If the argument can be null, and null must be treated differently in the >+ * generated SQL, then nullable should be set to true. >+ */ >+ public void addArgument(String argumentName, Class type, boolean nullable) { > getArguments().add(argumentName); > getArgumentTypes().add(type); > getArgumentTypeNames().add(type.getName()); >+ if (nullable) { >+ getNullableArguments().add(new DatabaseField(argumentName)); >+ } > } > > /** >@@ -597,26 +616,22 @@ > try { > DatabaseQuery cloneQuery = (DatabaseQuery) super.clone(); > >- // Keep a reference back to the original source query. >- cloneQuery.sourceMapping = this.sourceMapping; >- > // partial fix for 3054240 > // need to pay attention to other components of the query, too MWN > if (cloneQuery.properties != null) { > if (cloneQuery.properties.isEmpty()) { >- cloneQuery.setProperties(null); >+ cloneQuery.properties = null; > } else { >- cloneQuery.setProperties(new HashMap(getProperties())); >+ cloneQuery.properties = new HashMap(this.properties); > } > } > > // bug 3524620: now that the query mechanism is lazy-init'd, > // only clone the query mechanism if we have one. >- if (hasQueryMechanism()) { >- cloneQuery.setQueryMechanism(getQueryMechanism().clone(cloneQuery)); >+ if (this.queryMechanism != null) { >+ cloneQuery.queryMechanism = this.queryMechanism.clone(cloneQuery); > } >- cloneQuery.setIsPrepared(isPrepared());// Setting some things will >- // trigger unprepare. >+ cloneQuery.isPrepared = this.isPrepared; // Setting some things may trigger unprepare. > return cloneQuery; > } catch (CloneNotSupportedException e) { > return null; >@@ -775,7 +790,8 @@ > // so the query keeps track if it has been cloned already. > queryToExecute = session.prepareDatabaseQuery(queryToExecute); > >- if (queryToExecute.shouldPrepare()) { >+ boolean prepare = queryToExecute.shouldPrepare(translationRow); >+ if (prepare) { > queryToExecute.checkPrepare(session, translationRow); > } > >@@ -791,7 +807,9 @@ > > // If the prepare has been disable the clone is prepare dynamically to > // not parameterize the SQL. >- if (!queryToExecute.shouldPrepare()) { >+ if (!prepare) { >+ queryToExecute.setIsPrepared(false); >+ queryToExecute.setTranslationRow(translationRow); > queryToExecute.checkPrepare(session, translationRow); > } > queryToExecute.setSession(session); >@@ -1642,6 +1660,7 @@ > this.cascadePolicy = query.cascadePolicy; > this.flushOnExecute = query.flushOnExecute; > this.arguments = query.arguments; >+ this.nullableArguments = query.nullableArguments; > this.argumentTypes = query.argumentTypes; > this.argumentTypeNames = query.argumentTypeNames; > this.argumentValues = query.argumentValues; >@@ -1658,6 +1677,8 @@ > this.shouldRetrieveBypassCache = query.shouldRetrieveBypassCache; > this.shouldStoreBypassCache = query.shouldStoreBypassCache; > this.parameterDelimiter = query.parameterDelimiter; >+ this.shouldCloneCall = query.shouldCloneCall; >+ this.partitioningPolicy = query.partitioningPolicy; > } > > /** >@@ -1968,8 +1989,11 @@ > */ > public void setIsPrepared(boolean isPrepared) { > this.isPrepared = isPrepared; >- if (!isPrepared){ >+ if (!isPrepared) { > this.isCustomQueryUsed = null; >+ if (this.queryMechanism != null) { >+ this.queryMechanism.unprepare(); >+ } > } > } > >@@ -2366,6 +2390,26 @@ > public boolean shouldPrepare() { > return shouldPrepare; > } >+ >+ /** >+ * INTERNAL: >+ * Check if the query should be prepared, or dynamic, depending on the arguments. >+ * This allows null parameters to affect the SQL, such as stored procedure default values, >+ * or IS NULL, or insert defaults. >+ */ >+ public boolean shouldPrepare(AbstractRecord translationRow) { >+ if (!this.shouldPrepare) { >+ return false; >+ } >+ if (this.nullableArguments != null) { >+ for (DatabaseField argument : this.nullableArguments) { >+ if (translationRow.get(argument) == null) { >+ return false; >+ } >+ } >+ } >+ return true; >+ } > > /** > * ADVANCED: JPA flag used to control the behavior of the shared cache. This >@@ -2487,4 +2531,33 @@ > public void setBatchObjects(Map<Object, Object> batchObjects) { > setProperty(BATCH_FETCH_PROPERTY, batchObjects); > } >+ >+ /** >+ * INTERNAL: >+ * Return if the query has any nullable arguments. >+ */ >+ public boolean hasNullableArguments() { >+ return (this.nullableArguments != null) && !this.nullableArguments.isEmpty(); >+ } >+ >+ /** >+ * INTERNAL: >+ * Return the list of arguments to check for null. >+ * If any are null, the query needs to be re-prepared. >+ */ >+ public List<DatabaseField> getNullableArguments() { >+ if (this.nullableArguments == null) { >+ this.nullableArguments = new ArrayList<DatabaseField>(); >+ } >+ return nullableArguments; >+ } >+ >+ /** >+ * INTERNAL: >+ * Set the list of arguments to check for null. >+ * If any are null, the query needs to be re-prepared. >+ */ >+ public void setNullableArguments(List<DatabaseField> nullableArguments) { >+ this.nullableArguments = nullableArguments; >+ } > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DataReadQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DataReadQuery.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DataReadQuery.java (working copy) >@@ -88,6 +88,7 @@ > * It will cause the original to be cached in the query results if the query > * is set to do so. > */ >+ @Override > public void cacheResult(Object results) { > setTemporaryCachedQueryResults(results); > } >@@ -96,9 +97,10 @@ > * INTERNAL: > * Clone the query. > */ >+ @Override > public Object clone() { > DataReadQuery cloneQuery = (DataReadQuery)super.clone(); >- cloneQuery.setContainerPolicy(getContainerPolicy().clone(cloneQuery)); >+ cloneQuery.containerPolicy = this.containerPolicy.clone(cloneQuery); > return cloneQuery; > } > >@@ -107,10 +109,11 @@ > * Execute the query. If there are cached results return those. > * This must override the super to support result caching. > * >- * @param aSession - the session in which the receiver will be executed. >- * @return An object or vector, the result of executing the query. >+ * @param session - the session in which the receiver will be executed. >+ * @return An object or collection, the result of executing the query. > * @exception DatabaseException - an error has occurred on the database > */ >+ @Override > public Object execute(AbstractSession session, AbstractRecord row) throws DatabaseException { > if (shouldCacheQueryResults()) { > if (this.containerPolicy.overridesRead()) { >@@ -141,6 +144,7 @@ > * @exception DatabaseException an error has occurred on the database > * @return a collection or cursor of Records representing the result set > */ >+ @Override > public Object executeDatabaseQuery() throws DatabaseException { > if (getContainerPolicy().overridesRead()) { > return getContainerPolicy().execute(); >@@ -162,6 +166,7 @@ > * INTERNAL: > * Build the result value for the row. > */ >+ @Override > public Object buildObject(AbstractRecord row) { > if (this.resultType == AUTO) { > List values = row.getValues(); >@@ -230,7 +235,6 @@ > /** > * PUBLIC: > * Return the query's ContainerPolicy. >- * @return org.eclipse.persistence.internal.queries.ContainerPolicy > */ > public ContainerPolicy getContainerPolicy() { > return containerPolicy; >@@ -240,6 +244,7 @@ > * PUBLIC: > * Return if this is a data read query. > */ >+ @Override > public boolean isDataReadQuery() { > return true; > } >@@ -248,10 +253,11 @@ > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > protected void prepare() { > super.prepare(); >- getContainerPolicy().prepare(this, getSession()); >- if (getContainerPolicy().overridesRead()) { >+ this.containerPolicy.prepare(this, this.session); >+ if (this.containerPolicy.overridesRead()) { > return; > } > getQueryMechanism().prepareExecuteSelect(); >@@ -261,14 +267,17 @@ > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > public void prepareForExecution() throws QueryException { > super.prepareForExecution(); >- getContainerPolicy().prepareForExecution(); >+ this.containerPolicy.prepareForExecution(); > } > > /** > * INTERNAL: >+ * Used by RemoteSession. > */ >+ @Override > public Object remoteExecute() { > if (getContainerPolicy().overridesRead()) { > return getContainerPolicy().remoteExecute(); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java (working copy) >@@ -251,6 +251,7 @@ > * Return if the query is equal to the other. > * This is used to allow dynamic expression query SQL to be cached. > */ >+ @Override > public boolean equals(Object object) { > if (this == object) { > return true; >@@ -302,8 +303,12 @@ > } else if (query.hasOrderByExpressions()) { > return false; > } >- return ((getReferenceClass() == query.getReferenceClass()) || ((getReferenceClass() != null) && getReferenceClass().equals(query.getReferenceClass()))) >- && ((getSelectionCriteria() == query.getSelectionCriteria()) || ((getSelectionCriteria() != null) && getSelectionCriteria().equals(query.getSelectionCriteria()))); >+ if (! ((this.referenceClass == query.referenceClass) || ((this.referenceClass != null) && this.referenceClass.equals(query.referenceClass)))) { >+ return false; >+ } >+ Expression selectionCriteria = getSelectionCriteria(); >+ Expression otherSelectionCriteria = query.getSelectionCriteria(); >+ return ((selectionCriteria == otherSelectionCriteria) || ((selectionCriteria != null) && selectionCriteria.equals(otherSelectionCriteria))); > } > > /** >@@ -311,16 +316,18 @@ > * Compute a consistent hash-code for the expression. > * This is used to allow dynamic expression's SQL to be cached. > */ >+ @Override > public int hashCode() { > if (!isExpressionQuery()) { > return super.hashCode(); > } > int hashCode = 32; >- if (getReferenceClass() != null) { >- hashCode = hashCode + getReferenceClass().hashCode(); >+ if (this.referenceClass != null) { >+ hashCode = hashCode + this.referenceClass.hashCode(); > } >- if (getSelectionCriteria() != null) { >- hashCode = hashCode + getSelectionCriteria().hashCode(); >+ Expression selectionCriteria = getSelectionCriteria(); >+ if (selectionCriteria != null) { >+ hashCode = hashCode + selectionCriteria.hashCode(); > } > return hashCode; > } >@@ -398,6 +405,7 @@ > * INTERNAL: > * Clone the query > */ >+ @Override > public Object clone() { > ObjectLevelReadQuery cloneQuery = (ObjectLevelReadQuery)super.clone(); > >@@ -431,6 +439,7 @@ > * Normally selection criteria are not cloned here as they are cloned > * later on during prepare. > */ >+ @Override > public Object deepClone() { > ObjectLevelReadQuery clone = (ObjectLevelReadQuery)clone(); > if (getSelectionCriteria() != null) { >@@ -719,6 +728,7 @@ > * INTERNAL: > * Used to build the object, and register it if in the context of a unit of work. > */ >+ @Override > public Object buildObject(AbstractRecord row) { > return this.descriptor.getObjectBuilder().buildObject(this, row); > } >@@ -738,6 +748,7 @@ > * INTERNAL: > * Ensure that the descriptor has been set. > */ >+ @Override > public void checkDescriptor(AbstractSession session) throws QueryException { > if (this.descriptor == null) { > if (getReferenceClass() == null) { >@@ -761,6 +772,7 @@ > * INTERNAL: > * Check to see if this query already knows the return value without performing any further work. > */ >+ @Override > public Object checkEarlyReturn(AbstractSession session, AbstractRecord translationRow) { > // For bug 3136413/2610803 building the selection criteria from an EJBQL string or > // an example object is done just in time. >@@ -818,6 +830,7 @@ > * Check to see if this query needs to be prepare and prepare it. > * The prepare is done on the original query to ensure that the work is not repeated. > */ >+ @Override > public void checkPrepare(AbstractSession session, AbstractRecord translationRow, boolean force) { > // CR#3823735 For custom queries the prePrepare may not have been called yet. > if (!this.isPrePrepared || (this.descriptor == null)) { >@@ -1033,6 +1046,7 @@ > * @exception OptimisticLockException - an error has occurred using the optimistic lock feature. > * @return An object, the result of executing the query. > */ >+ @Override > public Object execute(AbstractSession session, AbstractRecord translationRow) throws DatabaseException, OptimisticLockException { > //Bug#2839852 Refreshing is not possible if the query uses checkCacheOnly. > if (shouldRefreshIdentityMapResult() && shouldCheckCacheOnly()) { >@@ -1046,6 +1060,7 @@ > * INTERNAL: > * Executes the prepared query on the datastore. > */ >+ @Override > public Object executeDatabaseQuery() throws DatabaseException { > // PERF: If the query has been set to optimize building its result > // directly from the database result-set then follow an optimized path. >@@ -1119,6 +1134,7 @@ > * Execute the query in the unit of work. > * This allows any pre-execute checks to be done for unit of work queries. > */ >+ @Override > public Object executeInUnitOfWork(UnitOfWorkImpl unitOfWork, AbstractRecord translationRow) throws DatabaseException, OptimisticLockException { > Object result = null; > >@@ -1415,10 +1431,6 @@ > /** > * INTERNAL: > * Lookup the descriptor for this item by traversing its expression recursively. >- * @param expression >- * @param rootDescriptor >- * @return >- * @throws org.eclipse.persistence.exceptions.QueryException > */ > public ClassDescriptor getLeafDescriptorFor(Expression expression, ClassDescriptor rootDescriptor) throws QueryException { > // The base case >@@ -1522,6 +1534,7 @@ > * PUBLIC: > * Return the reference class of the query. > */ >+ @Override > public Class getReferenceClass() { > return referenceClass; > } >@@ -1645,6 +1658,11 @@ > public Set<DatabaseField> getFetchGroupNonNestedFieldsSet() { > return getFetchGroupNonNestedFieldsSet(null); > } >+ >+ /** >+ * INTERNAL: >+ * Return the set of fields required in the select clause, for fetch group reading. >+ */ > public Set<DatabaseField> getFetchGroupNonNestedFieldsSet(DatabaseMapping nestedMapping) { > Set fetchedFields = new HashSet(getExecutionFetchGroup().getAttributeNames().size()); > >@@ -1827,6 +1845,7 @@ > * PUBLIC: > * Return if this is an object level read query. > */ >+ @Override > public boolean isObjectLevelReadQuery() { > return true; > } >@@ -1906,14 +1925,17 @@ > */ > public void setIsPrepared(boolean isPrepared) { > super.setIsPrepared(isPrepared); >- this.isReferenceClassLocked = null; >- this.concreteSubclassCalls = null; >+ if (!isPrepared) { >+ this.isReferenceClassLocked = null; >+ this.concreteSubclassCalls = null; >+ } > } > > /** > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > protected void prepare() throws QueryException { > super.prepare(); > prepareQuery(); >@@ -1955,6 +1977,7 @@ > * By default this calls prepareFromQuery, but additional properties may be required > * to be copied as prepareFromQuery only copies properties that affect the SQL. > */ >+ @Override > public void copyFromQuery(DatabaseQuery query) { > super.copyFromQuery(query); > if (query.isObjectLevelReadQuery()) { >@@ -1977,6 +2000,7 @@ > * dynamic queries. > * This only copies over properties that are configured through EJBQL. > */ >+ @Override > public void prepareFromQuery(DatabaseQuery query) { > super.prepareFromQuery(query); > if (query.isObjectLevelReadQuery()) { >@@ -2181,6 +2205,7 @@ > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > protected void prepareForRemoteExecution() throws QueryException { > super.prepareForRemoteExecution(); > checkPrePrepare(getSession()); >@@ -2502,6 +2527,7 @@ > * REQUIRED: > * Set the reference class for the query. > */ >+ @Override > public void setReferenceClass(Class aClass) { > if (referenceClass != aClass) { > setIsPrepared(false); >@@ -2513,24 +2539,31 @@ > * INTERNAL: > * Set the reference class for the query. > */ >+ @Override > public void setReferenceClassName(String aClass) { >- if (referenceClassName != aClass) { >+ if (this.referenceClassName != aClass) { > setIsPrepared(false); > } >- referenceClassName = aClass; >+ this.referenceClassName = aClass; > } > > >+ /** >+ * PUBLIC: >+ * Set the Expression/where clause of the query. >+ * The expression should be defined using the query's ExpressionBuilder. >+ */ >+ @Override > public void setSelectionCriteria(Expression expression) { > super.setSelectionCriteria(expression); >- if ((expression != null) && (defaultBuilder != null) && (defaultBuilder.getQueryClass() == null)){ >+ if ((expression != null) && (this.defaultBuilder != null) && (this.defaultBuilder.getQueryClass() == null)){ > // For flashback: Must make sure expression and defaultBuilder always in sync. > ExpressionBuilder newBuilder = expression.getBuilder(); >- if (newBuilder != defaultBuilder) { >+ if (newBuilder != this.defaultBuilder) { > if (hasAsOfClause() && getAsOfClause().isUniversal()) { >- newBuilder.asOf(defaultBuilder.getAsOfClause()); >+ newBuilder.asOf(this.defaultBuilder.getAsOfClause()); > } >- defaultBuilder = newBuilder; >+ this.defaultBuilder = newBuilder; > } > } > } >@@ -2711,6 +2744,7 @@ > * i.e. does not use any properties that may conflict with another query > * with the same JPQL or selection criteria. > */ >+ @Override > public boolean isDefaultPropertiesQuery() { > return super.isDefaultPropertiesQuery() > && (!this.isResultSetOptimizedQuery) >@@ -3111,6 +3145,7 @@ > getBatchFetchPolicy().setBatchObjects(batchObjects); > } > >+ @Override > public String toString() { > String str = super.toString(); > if(this.fetchGroup != null) { >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadAllQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadAllQuery.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadAllQuery.java (working copy) >@@ -148,6 +148,7 @@ > * It will cause the original to be cached in the query results if the query > * is set to do so. > */ >+ @Override > public void cacheResult(Object unwrappedOriginal) { > Collection container = (Collection)getTemporaryCachedQueryResults(); > if (container == null) { >@@ -161,6 +162,7 @@ > * INTERNAL: > * The cache check is done before the prepare as a hit will not require the work to be done. > */ >+ @Override > protected Object checkEarlyReturnLocal(AbstractSession session, AbstractRecord translationRow) { > // Check for in-memory only query. > if (shouldCheckCacheOnly()) { >@@ -196,6 +198,7 @@ > * This is done before the query is copied and prepared/executed. > * null means there is none. > */ >+ @Override > protected DatabaseQuery checkForCustomQuery(AbstractSession session, AbstractRecord translationRow) { > checkDescriptor(session); > >@@ -214,6 +217,7 @@ > * INTERNAL: > * Clone the query. > */ >+ @Override > public Object clone() { > ReadAllQuery cloneQuery = (ReadAllQuery)super.clone(); > >@@ -343,6 +347,7 @@ > * @return An object or vector, the result of executing the query. > * @exception DatabaseException - an error has occurred on the database > */ >+ @Override > public Object execute(AbstractSession session, AbstractRecord row) throws DatabaseException { > if (shouldCacheQueryResults()) { > if (getContainerPolicy().overridesRead()) { >@@ -392,6 +397,7 @@ > * @exception DatabaseException - an error has occurred on the database > * @return java.lang.Object collection of objects resulting from execution of query. > */ >+ @Override > protected Object executeObjectLevelReadQuery() throws DatabaseException { > Object result = null; > >@@ -456,6 +462,7 @@ > * @exception DatabaseException - an error has occurred on the database > * @return an ArrayList of the resulting objects. > */ >+ @Override > protected Object executeObjectLevelReadQueryFromResultSet() throws DatabaseException { > AbstractSession session = this.session; > DatabasePlatform platform = session.getPlatform(); >@@ -511,6 +518,7 @@ > * INTERNAL: > * Extract the correct query result from the transporter. > */ >+ @Override > public Object extractRemoteResult(Transporter transporter) { > return ((RemoteSession)getSession()).getObjectsCorrespondingToAll(transporter.getObject(), transporter.getObjectDescriptors(), new IdentityHashMap(), this, getContainerPolicy()); > } >@@ -518,7 +526,6 @@ > /** > * INTERNAL: > * Return the query's container policy. >- * @return org.eclipse.persistence.internal.queries.ContainerPolicy > */ > public ContainerPolicy getContainerPolicy() { > return containerPolicy; >@@ -529,7 +536,8 @@ > * Returns the specific default redirector for this query type. There are numerous default query redirectors. > * See ClassDescriptor for their types. > */ >- protected QueryRedirector getDefaultRedirector(){ >+ @Override >+ protected QueryRedirector getDefaultRedirector() { > return descriptor.getDefaultReadAllQueryRedirector(); > } > >@@ -573,6 +581,7 @@ > * i.e. does not use any properties that may conflict with another query > * with the same JPQL or selection criteria. > */ >+ @Override > public boolean isDefaultPropertiesQuery() { > return super.isDefaultPropertiesQuery() > && (!hasBatchReadAttributes()) >@@ -585,6 +594,7 @@ > * Return if the query is equal to the other. > * This is used to allow dynamic expression query SQL to be cached. > */ >+ @Override > public boolean equals(Object object) { > if (this == object) { > return true; >@@ -603,6 +613,7 @@ > * PUBLIC: > * Return if this is a read all query. > */ >+ @Override > public boolean isReadAllQuery() { > return true; > } >@@ -611,6 +622,7 @@ > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > protected void prepare() throws QueryException { > if ((!isReportQuery()) && prepareFromCachedQuery()) { > return; >@@ -638,6 +650,7 @@ > * dynamic queries. > * This only copies over properties that are configured through JPQL. > */ >+ @Override > public void prepareFromQuery(DatabaseQuery query) { > super.prepareFromQuery(query); > if (query.isReadAllQuery()) { >@@ -655,6 +668,7 @@ > * INTERNAL: > * Set the properties needed to be cascaded into the custom query. > */ >+ @Override > protected void prepareCustomQuery(DatabaseQuery customQuery) { > ReadAllQuery customReadQuery = (ReadAllQuery)customQuery; > customReadQuery.containerPolicy = this.containerPolicy; >@@ -668,6 +682,7 @@ > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > public void prepareForExecution() throws QueryException { > super.prepareForExecution(); > >@@ -710,6 +725,7 @@ > * > * @return the final (conformed, refreshed, wrapped) UnitOfWork query result > */ >+ @Override > public Object registerResultInUnitOfWork(Object result, UnitOfWorkImpl unitOfWork, AbstractRecord arguments, boolean buildDirectlyFromRows) { > // For bug 2612366: Conforming results in UOW extremely slow. > // Replacing results with registered versions in the UOW is a part of >@@ -795,6 +811,7 @@ > * INTERNAL: > * Execute the query through remote session. > */ >+ @Override > public Object remoteExecute() { > if (this.containerPolicy.overridesRead()) { > return this.containerPolicy.remoteExecute(); >@@ -812,6 +829,7 @@ > * INTERNAL: > * replace the value holders in the specified result object(s) > */ >+ @Override > public Map replaceValueHoldersIn(Object object, RemoteSessionController controller) { > return controller.replaceValueHoldersInAll(object, getContainerPolicy()); > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReportQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReportQuery.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReportQuery.java (working copy) >@@ -582,6 +582,7 @@ > * By default return the row. > * Used by cursored stream. > */ >+ @Override > public Object buildObject(AbstractRecord row) { > return buildObject(row, null); > } >@@ -658,6 +659,7 @@ > * INTERNAL: > * The cache check is done before the prepare as a hit will not require the work to be done. > */ >+ @Override > protected Object checkEarlyReturnLocal(AbstractSession session, AbstractRecord translationRow) { > // Check for in-memory only query. > if (shouldCheckCacheOnly()) { >@@ -673,6 +675,7 @@ > * This is done before the query is copied and prepared/executed. > * null means there is none. > */ >+ @Override > protected DatabaseQuery checkForCustomQuery(AbstractSession session, AbstractRecord translationRow) { > return null; > } >@@ -681,6 +684,7 @@ > * INTERNAL: > * Clone the query. > */ >+ @Override > public Object clone() { > ReportQuery cloneQuery = (ReportQuery)super.clone(); > cloneQuery.items = new ArrayList<ReportItem>(this.items.size()); >@@ -813,6 +817,7 @@ > * @exception DatabaseException - an error has occurred on the database > * @return either collection of objects, or report data resulting from execution of query. > */ >+ @Override > public Object executeDatabaseQuery() throws DatabaseException { > // ensure a pessimistic locking query will go down the write connection > if (isLockQuery() && getSession().isUnitOfWork()) { >@@ -845,6 +850,7 @@ > * INTERNAL: > * Extract the correct query result from the transporter. > */ >+ @Override > public Object extractRemoteResult(Transporter transporter) { > return transporter.getObject(); > } >@@ -916,6 +922,7 @@ > * Returns the specific default redirector for this query type. There are numerous default query redirectors. > * See ClassDescriptor for their types. > */ >+ @Override > protected QueryRedirector getDefaultRedirector(){ > return descriptor.getDefaultReportQueryRedirector(); > } >@@ -1014,6 +1021,7 @@ > * PUBLIC: > * Return if this is a report query. > */ >+ @Override > public boolean isReportQuery() { > return true; > } >@@ -1023,6 +1031,7 @@ > * Prepare the receiver for execution in a session. > * Initialize each item with its DTF mapping > */ >+ @Override > protected void prepare() throws QueryException { > if (prepareFromCachedQuery()) { > return; >@@ -1067,6 +1076,7 @@ > * dynamic queries. > * This only copies over properties that are configured through EJBQL. > */ >+ @Override > public void prepareFromQuery(DatabaseQuery query) { > super.prepareFromQuery(query); > if (query.isReportQuery()) { >@@ -1080,26 +1090,13 @@ > this.shouldRetrievePrimaryKeys = reportQuery.shouldRetrievePrimaryKeys; > } > } >- >- /** >- * INTERNAL: >- * Return true if the query uses default properties. >- * This is used to determine if this query is cacheable. >- * i.e. does not use any properties that may conflict with another query >- * with the same EJBQL or selection criteria. >- */ >- public boolean isDefaultPropertiesQuery() { >- return super.isDefaultPropertiesQuery() >- && (!hasBatchReadAttributes()) >- && (!hasHierarchicalExpressions()) >- && (!getContainerPolicy().isCursorPolicy()); >- } > > /** > * INTERNAL: > * Return if the query is equal to the other. > * This is used to allow dynamic expression query SQL to be cached. > */ >+ @Override > public boolean equals(Object object) { > if (this == object) { > return true; >@@ -1292,6 +1289,7 @@ > * INTERNAL: > * Prepare the mechanism. > */ >+ @Override > protected void prepareSelectAllRows() { > prepareObjectAttributeCount(null); > >@@ -1335,19 +1333,12 @@ > setSession(null); > setTranslationRow(null); > } >- >- /** >- * INTERNAL: >- * Avoid processing fetch-groups for report query. >- */ >- public void initializeFetchGroup() { >- // Do nothing. >- } > > /** > * INTERNAL: > * replace the value holders in the specified result object(s) > */ >+ @Override > public Map replaceValueHoldersIn(Object object, RemoteSessionController controller) { > // do nothing, since report queries do not return domain objects > return null; >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ResultSetMappingQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ResultSetMappingQuery.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ResultSetMappingQuery.java (working copy) >@@ -72,6 +72,7 @@ > * It will cause the original to be cached in the query results if the query > * is set to do so. > */ >+ @Override > public void cacheResult(Object unwrappedOriginal) { > Object cachableObject = unwrappedOriginal; > if (shouldUseWrapperPolicy()){ >@@ -80,41 +81,19 @@ > setTemporaryCachedQueryResults(cachableObject); > } > >-/** >- * INTERNAL: >- * Clone the query. >- */ >- public Object clone() { >- ResultSetMappingQuery cloneQuery = (ResultSetMappingQuery)super.clone(); >- cloneQuery.resultSetMapping = this.resultSetMapping; >- cloneQuery.resultSetMappingName = this.resultSetMappingName; >- return cloneQuery; >- } >- > /** > * INTERNAL: > * Convert all the class-name-based settings in this ResultSetMapping to actual class-based > * settings. This method is used when converting a project that has been built > * with class names to a project with classes. >- * @param classLoader > */ >+ @Override > public void convertClassNamesToClasses(ClassLoader classLoader){ >- resultSetMapping.convertClassNamesToClasses(classLoader); >- }; >+ this.resultSetMapping.convertClassNamesToClasses(classLoader); >+ } > > /** > * PUBLIC: >- * Used to define a store procedure or SQL query. >- */ >-/* public void setCall(Call call) { >- if (call instanceof SQLCall){ >- ((SQLCall)call).setSQLString(((SQLCall)call).getCallString().replace('?','#')); >- } >- super.setCall(call); >- } >-*/ >- /** >- * PUBLIC: > * This will be the SQLResultSetMapping that is used by this query to process > * the database results > */ >@@ -177,6 +156,7 @@ > * INTERNAL: > * Executes the prepared query on the datastore. > */ >+ @Override > public Object executeDatabaseQuery() throws DatabaseException { > if (getSession().isUnitOfWork()) { > UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)getSession(); >@@ -219,6 +199,7 @@ > * INTERNAL: > * Prepare the receiver for execution in a session. > */ >+ @Override > protected void prepare() { > if ((!shouldMaintainCache()) && shouldRefreshIdentityMapResult()) { > throw QueryException.refreshNotPossibleWithoutCache(this); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/SQLCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/SQLCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/SQLCall.java (working copy) >@@ -13,7 +13,7 @@ > ******************************************************************************/ > package org.eclipse.persistence.queries; > >-import java.util.Vector; >+import java.util.List; > import java.io.*; > import org.eclipse.persistence.internal.databaseaccess.*; > import org.eclipse.persistence.internal.helper.DatabaseField; >@@ -56,33 +56,34 @@ > * INTERNAL: > * Set the data passed through setCustomSQLArgumentType and useCustomSQLCursorOutputAsResultSet methods. > */ >- protected void afterTranslateCustomQuery(Vector updatedParameters, Vector updatedParameterTypes) { >- for (int i = 0; i < getParameters().size(); i++) { >- Integer parameterType = (Integer)getParameterTypes().elementAt(i); >- Object parameter = getParameters().elementAt(i); >+ protected void afterTranslateCustomQuery(List updatedParameters, List<Integer> updatedParameterTypes) { >+ int size = getParameters().size(); >+ for (int i = 0; i < size; i++) { >+ Integer parameterType = this.parameterTypes.get(i); >+ Object parameter = this.parameters.get(i); > if ((parameterType == MODIFY) || (parameterType == OUT) || (parameterType == OUT_CURSOR) || ((parameterType == IN) && parameter instanceof DatabaseField)) { > DatabaseField field = afterTranslateCustomQueryUpdateParameter((DatabaseField)parameter, i, parameterType, updatedParameters, updatedParameterTypes); > if (field!=null){ >- getParameters().setElementAt(field, i); >+ this.parameters.set(i, field); > } > } else if (parameterType == INOUT) { > DatabaseField outField = afterTranslateCustomQueryUpdateParameter((DatabaseField)((Object[])parameter)[1], i, parameterType, updatedParameters, updatedParameterTypes); >- if (outField !=null){ >+ if (outField != null) { > if (((Object[])parameter)[0] instanceof DatabaseField){ > if ( ((Object[])parameter)[0] != ((Object[])parameter)[1] ) { > DatabaseField inField = outField.clone(); > inField.setName( ((DatabaseField)((Object[])parameter)[0]).getName()); > ((Object[])parameter)[0] = inField; >- }else { >+ } else { > ((Object[])parameter)[0] = outField; > } > } > ((Object[])parameter)[1] = outField; > } >- } else if ((parameterType == IN)&& (parameter instanceof DatabaseField)){ >+ } else if ((parameterType == IN) && (parameter instanceof DatabaseField)){ > DatabaseField field = afterTranslateCustomQueryUpdateParameter((DatabaseField)parameter, i, parameterType, updatedParameters, updatedParameterTypes); >- if (field!=null){ >- getParameters().setElementAt(field, i); >+ if (field != null) { >+ this.parameters.set(i, field); > } > } > } >@@ -93,16 +94,17 @@ > * Set the data passed through setCustomSQLArgumentType and useCustomSQLCursorOutputAsResultSet methods. > * This will return the null if the user did not add the field/type using the setCustomSQLArgumentType method > */ >- protected DatabaseField afterTranslateCustomQueryUpdateParameter(DatabaseField field, int index, Integer parameterType, Vector updatedParameters, Vector updatedParameterTypes) { >- for (int j = 0; j < updatedParameters.size(); j++) { >- DatabaseField updateField = (DatabaseField)updatedParameters.elementAt(j); >+ protected DatabaseField afterTranslateCustomQueryUpdateParameter(DatabaseField field, int index, Integer parameterType, List updatedParameters, List<Integer> updatedParameterTypes) { >+ int size = updatedParameters.size(); >+ for (int j = 0; j < size; j++) { >+ DatabaseField updateField = (DatabaseField)updatedParameters.get(j); > if (field.equals(updateField)) { >- Integer updateParameterType = (Integer)updatedParameterTypes.elementAt(j); >+ Integer updateParameterType = updatedParameterTypes.get(j); > if (updateParameterType == null) { > return updateField; > } else if (updateParameterType == OUT_CURSOR) { > if (parameterType == OUT) { >- getParameterTypes().setElementAt(OUT_CURSOR, index); >+ this.parameterTypes.set(index, OUT_CURSOR); > return updateField; > } else { > throw ValidationException.cannotSetCursorForParameterTypeOtherThanOut(field.getName(), toString()); >@@ -122,10 +124,12 @@ > return hasCustomSQLArguments; > } > >+ @Override > public boolean isSQLCall() { > return true; > } > >+ @Override > public boolean isQueryStringCall() { > return true; > } >@@ -134,11 +138,12 @@ > * INTERNAL: > * Called by prepare method only. > */ >+ @Override > protected void prepareInternal(AbstractSession session) { > if (hasCustomSQLArguments()) { > // hold results of setCustomSQLArgumentType and useCustomSQLCursorOutputAsResultSet methods >- Vector updatedParameters = null; >- Vector updatedParameterTypes = null; >+ List updatedParameters = null; >+ List updatedParameterTypes = null; > if (getParameters().size() > 0) { > updatedParameters = getParameters(); > setParameters(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance()); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/StoredFunctionCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/StoredFunctionCall.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/StoredFunctionCall.java (working copy) >@@ -94,7 +94,7 @@ > * Define the field name to be substitute for the function return. > */ > public void setResult(String name) { >- DatabaseField returnField = (DatabaseField)getParameters().firstElement(); >+ DatabaseField returnField = (DatabaseField)getParameters().get(0); > returnField.setName(name); > } > >@@ -104,8 +104,31 @@ > * The type is the type of Java class desired back from the function, this is dependent on the type returned from the function. > */ > public void setResult(String name, Class type) { >- DatabaseField returnField = (DatabaseField)getParameters().firstElement(); >+ DatabaseField returnField = (DatabaseField)getParameters().get(0); > returnField.setName(name); > returnField.setType(type); > } >+ >+ /** >+ * PUBLIC: >+ * Define the field name to be substitute for the function return. >+ * The type is the type of Java class desired back from the function, this is dependent on the type returned from the function. >+ */ >+ public void setResult(String name, int type, String typeName) { >+ ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(name); >+ field.setSqlType(type); >+ field.setSqlTypeName(typeName); >+ getParameters().set(0, field); >+ } >+ >+ /** >+ * PUBLIC: >+ * Define the field name to be substitute for the function return. >+ * The type is the type of Java class desired back from the function, this is dependent on the type returned from the function. >+ */ >+ public void setResult(String name, int type) { >+ DatabaseField returnField = (DatabaseField)getParameters().get(0); >+ returnField.setName(name); >+ returnField.setSqlType(type); >+ } > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/StoredProcedureCall.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/StoredProcedureCall.java (revision 9204) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/StoredProcedureCall.java (working copy) >@@ -12,10 +12,9 @@ > ******************************************************************************/ > package org.eclipse.persistence.queries; > >-//javase imports >-import java.util.Vector; >+import java.util.ArrayList; >+import java.util.List; > >-//EclipseLink imports > import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; > import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; > import org.eclipse.persistence.internal.helper.DatabaseField; >@@ -30,7 +29,8 @@ > */ > public class StoredProcedureCall extends DatabaseCall { > protected String procedureName; >- protected Vector procedureArgumentNames; >+ protected List<String> procedureArgumentNames; >+ protected List<DatabaseField> optionalArguments; > > public StoredProcedureCall() { > super(); >@@ -769,9 +769,9 @@ > * The if the names are provide the order is not required to match the call def. > * This is lazy initialized to conserve space on calls that have no parameters. > */ >- public Vector getProcedureArgumentNames() { >+ public List<String> getProcedureArgumentNames() { > if (procedureArgumentNames == null) { >- procedureArgumentNames = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(); >+ procedureArgumentNames = new ArrayList<String>(); > } > return procedureArgumentNames; > } >@@ -792,8 +792,9 @@ > * INTERNAL: > * Called by prepare method only. > */ >- protected void prepareInternal(AbstractSession session) { >- setSQLStringInternal(session.getPlatform().buildProcedureCallString(this, session)); >+ @Override >+ protected void prepareInternal(AbstractSession session) { >+ setSQLStringInternal(session.getPlatform().buildProcedureCallString(this, session, getQuery().getTranslationRow())); > super.prepareInternal(session); > } > >@@ -802,7 +803,7 @@ > * The if the names are provide the order is not required to match the call def. > * This is lazy initialized to conserve space on calls that have no parameters. > */ >- public void setProcedureArgumentNames(Vector procedureArgumentNames) { >+ public void setProcedureArgumentNames(List<String> procedureArgumentNames) { > this.procedureArgumentNames = procedureArgumentNames; > } > >@@ -884,6 +885,44 @@ > * For Oracle a cursored output parameter can be used instead of a result set. > */ > public void setReturnsResultSet(boolean returnsResultSet) { >- this.returnsResultSet = Boolean.valueOf(returnsResultSet); >+ super.setReturnsResultSet(returnsResultSet); > } >+ >+ /** >+ * PUBLIC: >+ * Add the optional argument. >+ * This will be ignored if null and defaulted by the database. >+ */ >+ public void addOptionalArgument(String argument) { >+ getOptionalArguments().add(new DatabaseField(argument)); >+ } >+ >+ /** >+ * INTERNAL: >+ * Return if there are any optional arguments. >+ */ >+ public boolean hasOptionalArguments() { >+ return (this.optionalArguments != null) && !this.optionalArguments.isEmpty(); >+ } >+ >+ /** >+ * INTERNAL: >+ * Return the list of optional arguments. >+ * These will be ignored if null and defaulted by the database. >+ */ >+ public List<DatabaseField> getOptionalArguments() { >+ if (this.optionalArguments == null) { >+ this.optionalArguments = new ArrayList<DatabaseField>(); >+ } >+ return this.optionalArguments; >+ } >+ >+ /** >+ * INTERNAL: >+ * Set the list of optional arguments. >+ * These will be ignored if null and defaulted by the database. >+ */ >+ public void setOptionalArguments(List<DatabaseField> optionalArguments) { >+ this.optionalArguments = optionalArguments; >+ } > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/tools/schemaframework/StoredProcedureGenerator.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/tools/schemaframework/StoredProcedureGenerator.java (revision 9200) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/tools/schemaframework/StoredProcedureGenerator.java (working copy) >@@ -107,7 +107,7 @@ > while (tokenIndex != -1) { > stringWriter.write(stringToModify.substring(startIndex, tokenIndex)); > startIndex = tokenIndex + 1; >- Object parameter = call.getParameters().elementAt(nextParamIndex); >+ Object parameter = call.getParameters().get(nextParamIndex); > if (parameter instanceof DatabaseField) { > stringWriter.write(replacementToken); > stringWriter.write(((DatabaseField)parameter).getName()); >Index: jpa/eclipselink.jpa.test/build.xml >=================================================================== >--- jpa/eclipselink.jpa.test/build.xml (revision 9200) >+++ jpa/eclipselink.jpa.test/build.xml (working copy) >@@ -477,7 +477,7 @@ > </target> > > <!-- Packages JPA persistent unit test jars. --> >- <target name="package" depends="config-trunk, config-flat, package-annotation, package-ddl, package-xml-only, package-xml-merge, package-xml-extended, package-validation-failed, package-jpa-advanced-field-access, package-jpa-advanced-properties, package-jpa-pu_with_spaces, package-partitioned, package-jpa-performance, package-cascade-deletes, package-jpa-metamodel, package-delimited, package-beanvalidation" description="build EclipseLink jar"> >+ <target name="package" depends="config-trunk, config-flat, package-annotation, package-ddl, package-xml-only, package-xml-merge, package-xml-extended, package-validation-failed, package-jpa-advanced-field-access, package-jpa-advanced-properties, package-jpa-pu_with_spaces, package-partitioned, package-plsql, package-jpa-performance, package-cascade-deletes, package-jpa-metamodel, package-delimited, package-beanvalidation" description="build EclipseLink jar"> > <jar jarfile="${eclipselink.jpa.test}/${eclipselink.tests.jar}"> > <fileset dir="${eclipselink.jpa.test}/${classes.dir}" > includes="org/eclipse/persistence/testing/framework/**/*.class, >@@ -543,6 +543,7 @@ > org/eclipse/persistence/testing/models/jpa/jpaadvancedproperties/** > org/eclipse/persistence/testing/models/jpa/metamodel/** > org/eclipse/persistence/testing/models/jpa/partitioned/** >+ org/eclipse/persistence/testing/models/jpa/plsql/** > org/eclipse/persistence/testing/models/jpa/performance/** > org/eclipse/persistence/testing/models/jpa/performance2/** > org/eclipse/persistence/testing/models/jpa/beanvalidation/** >@@ -719,6 +720,20 @@ > </jar> > </target> > >+ <target name="package-plsql" depends=""> >+ <copy todir="${eclipselink.jpa.test}/${build.dir}/eclipselink-plsql-model/META-INF"> >+ <fileset dir="${eclipselink.jpa.test}/resource/eclipselink-plsql-model" includes="*.xml"/> >+ </copy> >+ <copy todir="${eclipselink.jpa.test}/${build.dir}/eclipselink-plsql-model"> >+ <fileset dir="${eclipselink.jpa.test}/${classes.dir}" >+ includes="org/eclipse/persistence/testing/models/jpa/plsql/**"/> >+ </copy> >+ <jar jarfile="${eclipselink.jpa.test}/eclipselink-plsql-model.jar"> >+ <fileset dir="${eclipselink.jpa.test}/${build.dir}/eclipselink-plsql-model"> >+ </fileset> >+ </jar> >+ </target> >+ > <target name="package-jpa-pu_with_multibyte" depends=""> > <!--copy todir="${eclipselink.jpa.test}/${build.dir}/${eclipselink.pu.with.multibyte}/META-INF"> > <fileset dir="${eclipselink.jpa.test}/resource/${eclipselink.pu.with.multibyte}" includes="*.xml"/> >Index: jpa/eclipselink.jpa.test/resource/eclipselink-partitioned-model/partitioned-orm.xml >=================================================================== >--- jpa/eclipselink.jpa.test/resource/eclipselink-partitioned-model/partitioned-orm.xml (revision 9200) >+++ jpa/eclipselink.jpa.test/resource/eclipselink-partitioned-model/partitioned-orm.xml (working copy) >@@ -138,7 +138,7 @@ > <inheritance strategy="JOINED"/> > <discriminator-value>P</discriminator-value> > <discriminator-column name="PROJ_TYPE"/> >- <range-partitioning name="RangePartitioningByPROJ_ID" union-unpartitionable-queries="true"> >+ <range-partitioning name="RangePartitioningByPROJ_ID" partition-value-type="java.lang.Integer" union-unpartitionable-queries="true"> > <partition-column name="PROJ_ID"/> > <partition connection-pool="default" start-value="0" end-value="1000"/> > <partition connection-pool="node2" start-value="1000" end-value="2000"/> >Index: jpa/eclipselink.jpa.test/resource/eclipselink-plsql-model/persistence.xml >=================================================================== >--- jpa/eclipselink.jpa.test/resource/eclipselink-plsql-model/persistence.xml (revision 0) >+++ jpa/eclipselink.jpa.test/resource/eclipselink-plsql-model/persistence.xml (revision 0) >@@ -0,0 +1,26 @@ >+<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd" version="1.0"> >+ <persistence-unit name="plsql" transaction-type="RESOURCE_LOCAL"> >+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> >+ <exclude-unlisted-classes>false</exclude-unlisted-classes> >+ <properties> >+ <property name="javax.persistence.jdbc.driver" value="TEST_DRIVER_CLASS"/> >+ <property name="javax.persistence.jdbc.url" value="TEST_DATABASE_URL"/> >+ <property name="javax.persistence.jdbc.user" value="TEST_DATABASE_USER"/> >+ <property name="javax.persistence.jdbc.password" value="TEST_DATABASE_PASSWORD"/> >+ <!--property name="eclipselink.logging.level" value="FINEST"/--> >+ </properties> >+ </persistence-unit> >+ <persistence-unit name="plsql-xml" transaction-type="RESOURCE_LOCAL"> >+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> >+ <mapping-file>META-INF/plsql-orm.xml</mapping-file> >+ <exclude-unlisted-classes>false</exclude-unlisted-classes> >+ <properties> >+ <property name="javax.persistence.jdbc.driver" value="TEST_DRIVER_CLASS"/> >+ <property name="javax.persistence.jdbc.url" value="TEST_DATABASE_URL"/> >+ <property name="javax.persistence.jdbc.user" value="TEST_DATABASE_USER"/> >+ <property name="javax.persistence.jdbc.password" value="TEST_DATABASE_PASSWORD"/> >+ <property name="eclipselink.orm.validate.schema" value="true"/> >+ <!--property name="eclipselink.logging.level" value="FINEST"/--> >+ </properties> >+ </persistence-unit> >+</persistence> >Index: jpa/eclipselink.jpa.test/resource/eclipselink-plsql-model/plsql-orm.xml >=================================================================== >--- jpa/eclipselink.jpa.test/resource/eclipselink-plsql-model/plsql-orm.xml (revision 0) >+++ jpa/eclipselink.jpa.test/resource/eclipselink-plsql-model/plsql-orm.xml (revision 0) >@@ -0,0 +1,46 @@ >+<?xml version="1.0" encoding="UTF-8"?> >+<entity-mappings version="2.3" xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> >+ <persistence-unit-metadata> >+ <xml-mapping-metadata-complete/> >+ </persistence-unit-metadata> >+ <package>org.eclipse.persistence.testing.models.jpa.plsql</package> >+ <named-plsql-stored-procedure-query name="PLSQL_SIMPLE_IN_DEFAULTS" procedure-name="PLSQL_SIMPLE_IN_DEFAULTS"> >+ <parameter query-parameter="P_VARCHAR" database-type="VARCHAR_TYPE" optional="true"/> >+ <parameter query-parameter="P_BOOLEAN" database-type="PLSQLBoolean" optional="true"/> >+ <parameter query-parameter="P_BINARY_INTEGER" database-type="BinaryInteger" optional="true"/> >+ <parameter query-parameter="P_DEC" database-type="Dec" optional="true"/> >+ <parameter query-parameter="P_INT" database-type="Int" optional="true"/> >+ <parameter query-parameter="P_NATURAL" database-type="Natural" optional="true"/> >+ <parameter query-parameter="P_NATURALN" database-type="NaturalN" optional="true"/> >+ <parameter query-parameter="P_PLS_INTEGER" database-type="PLSQLInteger" optional="true"/> >+ <parameter query-parameter="P_POSITIVE" database-type="Positive" optional="true"/> >+ <parameter query-parameter="P_POSITIVEN" database-type="PositiveN" optional="true"/> >+ <parameter query-parameter="P_SIGNTYPE" database-type="SignType" optional="true"/> >+ <parameter query-parameter="P_NUMBER" database-type="Number" optional="true"/> >+ </named-plsql-stored-procedure-query> >+ <named-plsql-stored-procedure-query name="PLSQL_ADDRESS_OUT" procedure-name="PLSQL_ADDRESS_OUT"> >+ <parameter query-parameter="P_ADDRESS" direction="OUT" database-type="PLSQL_ADDRESS%ROWTYPE"/> >+ </named-plsql-stored-procedure-query> >+ <named-plsql-stored-function-query name="PLSQL_SIMPLE_IN_FUNC" function-name="PLSQL_SIMPLE_IN_FUNC"> >+ <parameter query-parameter="P_VARCHAR" database-type="VARCHAR_TYPE"/> >+ <parameter query-parameter="P_BOOLEAN" database-type="PLSQLBoolean"/> >+ <parameter query-parameter="P_BINARY_INTEGER" database-type="BinaryInteger"/> >+ <parameter query-parameter="P_DEC" database-type="Dec"/> >+ <parameter query-parameter="P_INT" database-type="Int"/> >+ <parameter query-parameter="P_NATURAL" database-type="Natural"/> >+ <parameter query-parameter="P_NATURALN" database-type="NaturalN"/> >+ <parameter query-parameter="P_PLS_INTEGER" database-type="PLSQLInteger"/> >+ <parameter query-parameter="P_POSITIVE" database-type="Positive"/> >+ <parameter query-parameter="P_POSITIVEN" database-type="PositiveN"/> >+ <parameter query-parameter="P_SIGNTYPE" database-type="SignType"/> >+ <parameter query-parameter="P_NUMBER" database-type="Number"/> >+ <return-parameter query-parameter="RESULT" database-type="PLSQLBoolean"/> >+ </named-plsql-stored-function-query> >+ <entity class="Employee" access="FIELD"> >+ <attributes> >+ <id name="id"/> >+ </attributes> >+ </entity> >+ <embeddable class="Address" access="FIELD"/> >+ <embeddable class="Phone" access="FIELD"/> >+</entity-mappings> >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Address.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Address.java (revision 0) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Address.java (revision 0) >@@ -0,0 +1,94 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * James - initial impl >+ ******************************************************************************/ >+package org.eclipse.persistence.testing.models.jpa.plsql; >+ >+import java.math.BigDecimal; >+ >+import javax.persistence.Embeddable; >+ >+/** >+ * Used to test simple PLSQL record types. >+ * >+ * @author James >+ */ >+@Embeddable >+public class Address { >+ protected BigDecimal id; >+ protected Integer number; >+ protected String street; >+ protected String city; >+ protected String state; >+ >+ public String getCity() { >+ return city; >+ } >+ >+ public void setCity(String city) { >+ this.city = city; >+ } >+ >+ public BigDecimal getId() { >+ return id; >+ } >+ >+ public void setId(BigDecimal id) { >+ this.id = id; >+ } >+ >+ public Integer getNumber() { >+ return number; >+ } >+ >+ public void setNumber(Integer number) { >+ this.number = number; >+ } >+ >+ public String getStreet() { >+ return street; >+ } >+ >+ public void setStreet(String street) { >+ this.street = street; >+ } >+ >+ public String getState() { >+ return state; >+ } >+ >+ public void setState(String state) { >+ this.state = state; >+ } >+ >+ public boolean equals(Object object) { >+ if (!(object instanceof Address)) { >+ return false; >+ } >+ Address address = (Address)object; >+ if (this.id != null && !this.id.equals(address.id)) { >+ return false; >+ } >+ if (this.number != null && !this.number.equals(address.number)) { >+ return false; >+ } >+ if (this.street != null && !this.street.equals(address.street)) { >+ return false; >+ } >+ if (this.city != null && !this.city.equals(address.city)) { >+ return false; >+ } >+ if (this.state != null && !this.state.equals(address.state)) { >+ return false; >+ } >+ return true; >+ } >+} >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Employee.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Employee.java (revision 0) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Employee.java (revision 0) >@@ -0,0 +1,135 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * James - initial impl >+ ******************************************************************************/ >+package org.eclipse.persistence.testing.models.jpa.plsql; >+ >+import java.math.BigDecimal; >+import java.util.ArrayList; >+import java.util.List; >+ >+import javax.persistence.Entity; >+import javax.persistence.Id; >+ >+import org.eclipse.persistence.annotations.Direction; >+import org.eclipse.persistence.platform.database.oracle.annotations.NamedPLSQLStoredFunctionQuery; >+import org.eclipse.persistence.platform.database.oracle.annotations.NamedPLSQLStoredProcedureQueries; >+import org.eclipse.persistence.platform.database.oracle.annotations.NamedPLSQLStoredProcedureQuery; >+import org.eclipse.persistence.platform.database.oracle.annotations.PLSQLParameter; >+ >+@NamedPLSQLStoredProcedureQueries({ >+ @NamedPLSQLStoredProcedureQuery( >+ name="PLSQL_SIMPLE_IN_DEFAULTS", >+ procedureName="PLSQL_SIMPLE_IN_DEFAULTS", >+ parameters={ >+ @PLSQLParameter(queryParameter="P_VARCHAR", databaseType="VARCHAR_TYPE", optional=true), >+ @PLSQLParameter(queryParameter="P_BOOLEAN", databaseType="PLSQLBoolean", optional=true), >+ @PLSQLParameter(queryParameter="P_BINARY_INTEGER", databaseType="BinaryInteger", optional=true), >+ @PLSQLParameter(queryParameter="P_DEC", databaseType="Dec", optional=true), >+ @PLSQLParameter(queryParameter="P_INT", databaseType="Int", optional=true), >+ @PLSQLParameter(queryParameter="P_NATURAL", databaseType="Natural", optional=true), >+ @PLSQLParameter(queryParameter="P_NATURALN", databaseType="NaturalN", optional=true), >+ @PLSQLParameter(queryParameter="P_PLS_INTEGER", databaseType="PLSQLInteger", optional=true), >+ @PLSQLParameter(queryParameter="P_POSITIVE", databaseType="Positive", optional=true), >+ @PLSQLParameter(queryParameter="P_POSITIVEN", databaseType="PositiveN", optional=true), >+ @PLSQLParameter(queryParameter="P_SIGNTYPE", databaseType="SignType", optional=true), >+ @PLSQLParameter(queryParameter="P_NUMBER", databaseType="Number", optional=true) >+ } >+ ), >+ @NamedPLSQLStoredProcedureQuery( >+ name="PLSQL_ADDRESS_OUT", >+ procedureName="PLSQL_ADDRESS_OUT", >+ parameters={ >+ @PLSQLParameter(queryParameter="P_ADDRESS", direction=Direction.OUT, databaseType="PLSQL_ADDRESS%ROWTYPE") >+ } >+ ) >+}) >+@NamedPLSQLStoredFunctionQuery( >+ name="PLSQL_SIMPLE_IN_FUNC", >+ functionName="PLSQL_SIMPLE_IN_FUNC", >+ parameters={ >+ @PLSQLParameter(queryParameter="P_VARCHAR", databaseType="VARCHAR_TYPE"), >+ @PLSQLParameter(queryParameter="P_BOOLEAN", databaseType="PLSQLBoolean"), >+ @PLSQLParameter(queryParameter="P_BINARY_INTEGER", databaseType="BinaryInteger"), >+ @PLSQLParameter(queryParameter="P_DEC", databaseType="Dec"), >+ @PLSQLParameter(queryParameter="P_INT", databaseType="Int"), >+ @PLSQLParameter(queryParameter="P_NATURAL", databaseType="Natural"), >+ @PLSQLParameter(queryParameter="P_NATURALN", databaseType="NaturalN"), >+ @PLSQLParameter(queryParameter="P_PLS_INTEGER", databaseType="PLSQLInteger"), >+ @PLSQLParameter(queryParameter="P_POSITIVE", databaseType="Positive"), >+ @PLSQLParameter(queryParameter="P_POSITIVEN", databaseType="PositiveN"), >+ @PLSQLParameter(queryParameter="P_SIGNTYPE", databaseType="SignType"), >+ @PLSQLParameter(queryParameter="P_NUMBER", databaseType="Number") >+ }, >+ returnParameter=@PLSQLParameter(queryParameter="RESULT", direction=Direction.OUT, databaseType="PLSQLBoolean") >+) >+/** >+ * Used to test simple PLSQL record types. >+ * >+ * @author James >+ */ >+@Entity >+public class Employee { >+ @Id >+ protected BigDecimal id; >+ protected String name; >+ protected boolean active; >+ protected Address address; >+ protected List<Phone> phones = new ArrayList<Phone>(); >+ >+ public BigDecimal getId() { >+ return id; >+ } >+ public void setId(BigDecimal id) { >+ this.id = id; >+ } >+ public String getName() { >+ return name; >+ } >+ public void setName(String name) { >+ this.name = name; >+ } >+ public Address getAddress() { >+ return address; >+ } >+ public void setAddress(Address address) { >+ this.address = address; >+ } >+ public List<Phone> getPhones() { >+ return phones; >+ } >+ public void setPhones(List<Phone> phones) { >+ this.phones = phones; >+ } >+ >+ public boolean equals(Object object) { >+ if (!(object instanceof Employee)) { >+ return false; >+ } >+ Employee employee = (Employee)object; >+ if (this.id != null && !this.id.equals(employee.id)) { >+ return false; >+ } >+ if (this.name != null && !this.name.equals(employee.name)) { >+ return false; >+ } >+ if (this.address != null && !this.address.equals(employee.address)) { >+ return false; >+ } >+ return true; >+ } >+ public boolean isActive() { >+ return active; >+ } >+ public void setActive(boolean active) { >+ this.active = active; >+ } >+} >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Phone.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Phone.java (revision 0) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/plsql/Phone.java (revision 0) >@@ -0,0 +1,56 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * James - initial impl >+ ******************************************************************************/ >+package org.eclipse.persistence.testing.models.jpa.plsql; >+ >+import javax.persistence.Embeddable; >+ >+/** >+ * Used to test simple PLSQL record types. >+ * >+ * @author James >+ */ >+@Embeddable >+public class Phone { >+ protected String areaCode; >+ protected String number; >+ >+ public String getAreaCode() { >+ return areaCode; >+ } >+ >+ public void setAreaCode(String areaCode) { >+ this.areaCode = areaCode; >+ } >+ >+ public String getNumber() { >+ return number; >+ } >+ >+ public void setNumber(String number) { >+ this.number = number; >+ } >+ >+ public boolean equals(Object object) { >+ if (!(object instanceof Phone)) { >+ return false; >+ } >+ Phone address = (Phone)object; >+ if (this.areaCode != null && !this.areaCode.equals(address.areaCode)) { >+ return false; >+ } >+ if (this.number != null && !this.number.equals(address.number)) { >+ return false; >+ } >+ return true; >+ } >+} >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/AdvancedJPAJunitTest.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/AdvancedJPAJunitTest.java (revision 9200) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/AdvancedJPAJunitTest.java (working copy) >@@ -270,7 +270,10 @@ > try { > query = em.createNamedQuery("StoredFunction_In"); > query.setParameter("P_IN", 1); >- query.getResultList(); >+ int result = (Integer)query.getSingleResult(); >+ if (result != 1000) { >+ fail("Incorrect result returned:" + result); >+ } > } finally { > closeEntityManager(em); > } >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/FullRegressionTestSuite.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/FullRegressionTestSuite.java (revision 9200) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/FullRegressionTestSuite.java (working copy) >@@ -57,6 +57,8 @@ > > import org.eclipse.persistence.testing.tests.jpa.partitioned.PartitionedTestSuite; > import org.eclipse.persistence.testing.tests.jpa.partitioned.PartitionedXMLTestSuite; >+import org.eclipse.persistence.testing.tests.jpa.plsql.PLSQLTestSuite; >+import org.eclipse.persistence.testing.tests.jpa.plsql.XMLPLSQLTestSuite; > import org.eclipse.persistence.testing.tests.jpa.relationships.EMQueryJUnitTestSuite; > import org.eclipse.persistence.testing.tests.jpa.relationships.ExpressionJUnitTestSuite; > import org.eclipse.persistence.testing.tests.jpa.relationships.IsolatedCacheTestSuite; >@@ -286,6 +288,8 @@ > > fullSuite.addTest(PartitionedTestSuite.suite()); > fullSuite.addTest(PartitionedXMLTestSuite.suite()); >+ fullSuite.addTest(PLSQLTestSuite.suite()); >+ fullSuite.addTest(XMLPLSQLTestSuite.suite()); > > return fullSuite; > } >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/plsql/PLSQLTestSuite.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/plsql/PLSQLTestSuite.java (revision 0) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/plsql/PLSQLTestSuite.java (revision 0) >@@ -0,0 +1,310 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * James Sutherland (Oracle) - initial impl >+ ******************************************************************************/ >+package org.eclipse.persistence.testing.tests.jpa.plsql; >+ >+import javax.persistence.EntityManager; >+import javax.persistence.Query; >+ >+import junit.framework.*; >+ >+import org.eclipse.persistence.sessions.DatabaseSession; >+import org.eclipse.persistence.testing.framework.junit.JUnitTestCase; >+ >+public class PLSQLTestSuite extends JUnitTestCase { >+ public static boolean validDatabase = true; >+ >+ public static Test suite() { >+ TestSuite suite = new TestSuite("PLSQLTests"); >+ suite.addTest(new PLSQLTestSuite("testSetup")); >+ suite.addTest(new PLSQLTestSuite("testSimpleProcedure")); >+ suite.addTest(new PLSQLTestSuite("testSimpleFunction")); >+ suite.addTest(new PLSQLTestSuite("testRecordOut")); >+ return suite; >+ } >+ >+ public PLSQLTestSuite(String name) { >+ super(name); >+ } >+ >+ /** >+ * Return the name of the persistence context this test uses. >+ * This allow a subclass test to set this only in one place. >+ */ >+ @Override >+ public String getPersistenceUnitName() { >+ return "plsql"; >+ } >+ >+ /** >+ * The setup is done as a test, both to record its failure, and to allow execution in the server. >+ */ >+ public void testSetup() { >+ if (!getServerSession().getPlatform().isOracle()) { >+ warning("This test can only be run on Oracle."); >+ return; >+ } >+ createTables(getDatabaseSession()); >+ } >+ >+ public void createTables(DatabaseSession session) { >+ // Tables >+ try { >+ session.executeNonSelectingSQL("DROP TABLE PLSQL_ADDRESS"); >+ } catch (Exception ignore) {} >+ session.executeNonSelectingSQL("CREATE TABLE PLSQL_ADDRESS (" >+ + "ADDRESS_ID NUMBER(10) NOT NULL, STREET_NUM NUMBER(10), STREET VARCHAR2(30), CITY VARCHAR2(30), STATE VARCHAR2(30), PRIMARY KEY (ADDRESS_ID))"); >+ session.executeNonSelectingSQL("INSERT INTO PLSQL_ADDRESS (" >+ + "ADDRESS_ID, CITY) values (1234, 'Ottawa')"); >+ >+ // Procedures >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_IN(P_VARCHAR IN VARCHAR2 DEFAULT '', P_BOOLEAN IN BOOLEAN, P_BINARY_INTEGER IN BINARY_INTEGER, " >+ + "P_DEC IN DEC, P_INT IN INT, P_NATURAL IN NATURAL, P_NATURALN IN NATURALN, " >+ + "P_PLS_INTEGER IN PLS_INTEGER, P_POSITIVE IN POSITIVE, P_POSITIVEN IN POSITIVEN, P_SIGNTYPE IN SIGNTYPE, P_NUMBER IN NUMBER) AS " >+ + "BEGIN NULL; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_IN_DEFAULTS(P_VARCHAR IN VARCHAR2 DEFAULT '', P_BOOLEAN IN BOOLEAN DEFAULT TRUE, P_BINARY_INTEGER IN BINARY_INTEGER DEFAULT 0, " >+ + "P_DEC IN DEC DEFAULT 0, P_INT IN INT DEFAULT 0, P_NATURAL IN NATURAL DEFAULT 1, P_NATURALN IN NATURALN DEFAULT 1, " >+ + "P_PLS_INTEGER IN PLS_INTEGER DEFAULT 0, P_POSITIVE IN POSITIVE DEFAULT 1, P_POSITIVEN IN POSITIVEN DEFAULT 1, P_SIGNTYPE IN SIGNTYPE DEFAULT 1, P_NUMBER IN NUMBER DEFAULT 0) AS " >+ + "BEGIN NULL; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_OUT(P_VARCHAR OUT VARCHAR2, P_BOOLEAN OUT BOOLEAN, P_BINARY_INTEGER OUT BINARY_INTEGER, " >+ + "P_DEC OUT DEC, P_INT OUT INT, P_NATURAL OUT NATURAL, " //P_NATURALN OUT NATURALN, " >+ + "P_PLS_INTEGER OUT PLS_INTEGER, P_POSITIVE OUT POSITIVE, " //P_POSITIVEN OUT POSITIVEN, " >+ + "P_SIGNTYPE OUT SIGNTYPE, P_NUMBER OUT NUMBER) AS " >+ + "BEGIN P_VARCHAR := 'varchar'; P_BOOLEAN := true; P_BINARY_INTEGER := 123; " >+ + "P_DEC := 1; P_INT := 1; P_NATURAL := 1; " //P_NATURALN := 1; " >+ + "P_PLS_INTEGER := 1; P_POSITIVE := 1; " //P_POSITIVEN := 1; " >+ + "P_SIGNTYPE := 1; P_NUMBER := 123; \n" >+ + "END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_SIMPLE_INOUT(P_VARCHAR IN OUT VARCHAR2, P_BOOLEAN IN OUT BOOLEAN, P_BINARY_INTEGER IN OUT BINARY_INTEGER, " >+ + "P_DEC IN OUT DEC, P_INT IN OUT INT, P_NATURAL IN OUT NATURAL, P_NATURALN IN OUT NATURALN, " >+ + "P_PLS_INTEGER IN OUT PLS_INTEGER, P_POSITIVE IN OUT POSITIVE, P_POSITIVEN IN OUT POSITIVEN, P_SIGNTYPE IN OUT SIGNTYPE, P_NUMBER IN OUT NUMBER) AS " >+ + "BEGIN NULL; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_ADDRESS_IN(P_ADDRESS IN PLSQL_ADDRESS%ROWTYPE) AS " >+ + "BEGIN NULL; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_ADDRESS_IN_DATA(P_ADDRESS IN PLSQL_ADDRESS%ROWTYPE, P_LOCAL IN VARCHAR2) AS " >+ + "BEGIN NULL; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_ADDRESS_OUT(P_ADDRESS OUT PLSQL_ADDRESS%ROWTYPE) AS " >+ + "BEGIN P_ADDRESS.ADDRESS_ID := 1234; P_ADDRESS.STREET_NUM := 17; P_ADDRESS.STREET := 'Bank'; P_ADDRESS.CITY := 'Ottawa'; P_ADDRESS.STATE := 'ON'; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_ADDRESS_OUT_DATA(P_ADDRESS OUT PLSQL_ADDRESS%ROWTYPE, P_LOCAL OUT VARCHAR2) AS " >+ + "BEGIN P_ADDRESS.ADDRESS_ID := 1234; P_ADDRESS.STREET_NUM := 17; P_ADDRESS.STREET := 'Bank'; P_ADDRESS.CITY := 'Ottawa'; P_ADDRESS.STATE := 'ON'; P_LOCAL := 'Local'; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_ADDRESS_INOUT(P_ADDRESS IN OUT PLSQL_ADDRESS%ROWTYPE) AS " >+ + "BEGIN P_ADDRESS.ADDRESS_ID := 1234; P_ADDRESS.STREET_NUM := 17; P_ADDRESS.STREET := 'Bank'; P_ADDRESS.CITY := 'Ottawa'; P_ADDRESS.STATE := 'ON'; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PROCEDURE PLSQL_ADDRESS_INOUT_DATA(P_ADDRESS IN OUT PLSQL_ADDRESS%ROWTYPE, P_LOCAL IN OUT VARCHAR2) AS " >+ + "BEGIN P_ADDRESS.ADDRESS_ID := 1234; P_ADDRESS.STREET_NUM := 17; P_ADDRESS.STREET := 'Bank'; P_ADDRESS.CITY := 'Ottawa'; P_ADDRESS.STATE := 'ON'; P_LOCAL := 'Local'; END;"); >+ >+ // Functions >+ session.executeNonSelectingSQL("CREATE OR REPLACE FUNCTION PLSQL_SIMPLE_IN_FUNC(P_VARCHAR IN VARCHAR2, P_BOOLEAN IN BOOLEAN, P_BINARY_INTEGER IN BINARY_INTEGER, " >+ + "P_DEC IN DEC, P_INT IN INT, P_NATURAL IN NATURAL, P_NATURALN IN NATURALN, " >+ + "P_PLS_INTEGER IN PLS_INTEGER, P_POSITIVE IN POSITIVE, P_POSITIVEN IN POSITIVEN, P_SIGNTYPE IN SIGNTYPE, P_NUMBER IN NUMBER) RETURN BOOLEAN AS " >+ + "BEGIN RETURN TRUE; END;"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE FUNCTION PLSQL_ADDRESS_OUT_FUNC RETURN PLSQL_ADDRESS%ROWTYPE AS " >+ + " P_ADDRESS PLSQL_ADDRESS%ROWTYPE; " >+ + "BEGIN P_ADDRESS.ADDRESS_ID := 1234; P_ADDRESS.STREET_NUM := 17; P_ADDRESS.STREET := 'Bank'; P_ADDRESS.CITY := 'Ottawa'; P_ADDRESS.STATE := 'ON'; RETURN P_ADDRESS; END;"); >+ >+ // Types >+ try { >+ session.executeNonSelectingSQL("DROP TYPE PLSQL_P_PLSQL_EMP_REC FORCE"); >+ } catch (Exception ignore) {} >+ try { >+ session.executeNonSelectingSQL("DROP TYPE PLSQL_P_PLSQL_ADDRESS_REC FORCE"); >+ } catch (Exception ignore) {} >+ try { >+ session.executeNonSelectingSQL("DROP TYPE PLSQL_P_PLSQL_PHONE_REC FORCE"); >+ } catch (Exception ignore) {} >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_ADDRESS_REC AS OBJECT (" >+ + "ADDRESS_ID NUMBER(10), STREET_NUM NUMBER(10), STREET VARCHAR2(30), CITY VARCHAR2(30), STATE VARCHAR2(2))"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_PHONE_REC AS OBJECT (" >+ + "AREA_CODE VARCHAR2(3), P_NUM VARCHAR2(7))"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_PHONE_LIST AS VARRAY(30) OF PLSQL_P_PLSQL_PHONE_REC"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_EMP_REC AS OBJECT (" >+ + "EMP_ID NUMBER(10), NAME VARCHAR2(30), ACTIVE NUMBER(1), ADDRESS PLSQL_P_PLSQL_ADDRESS_REC, PHONES PLSQL_P_PLSQL_PHONE_LIST)"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_CITY_LIST AS VARRAY(255) OF VARCHAR2(100)"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_ADDRESS_LIST AS VARRAY(255) OF PLSQL_P_PLSQL_ADDRESS_REC"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE TYPE PLSQL_P_PLSQL_EMP_LIST AS VARRAY(255) OF PLSQL_P_PLSQL_EMP_REC"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PACKAGE PLSQL_P AS \n" >+ + "TYPE PLSQL_ADDRESS_REC IS RECORD (ADDRESS_ID NUMBER(10), STREET_NUM NUMBER(10), STREET VARCHAR2(30), CITY VARCHAR2(30), STATE VARCHAR2(2)); \n" >+ + "TYPE PLSQL_ADDRESS_CUR IS REF CURSOR RETURN PLSQL_ADDRESS%ROWTYPE; \n" >+ + "TYPE PLSQL_ADDRESS_REC_CUR IS REF CURSOR RETURN PLSQL_ADDRESS_REC; \n" >+ + "TYPE PLSQL_PHONE_REC IS RECORD (AREA_CODE VARCHAR2(3), P_NUM VARCHAR2(7)); \n" >+ + "TYPE PLSQL_PHONE_LIST IS TABLE OF PLSQL_PHONE_REC INDEX BY BINARY_INTEGER; \n" >+ + "TYPE PLSQL_EMP_REC IS RECORD (EMP_ID NUMBER(10), NAME VARCHAR2(30), ACTIVE BOOLEAN, ADDRESS PLSQL_ADDRESS_REC, PHONES PLSQL_PHONE_LIST); \n" >+ + "TYPE PLSQL_CITY_LIST IS TABLE OF VARCHAR2(100) INDEX BY BINARY_INTEGER; \n" >+ + "TYPE PLSQL_ADDRESS_LIST IS TABLE OF PLSQL_ADDRESS_REC INDEX BY BINARY_INTEGER; \n" >+ + "TYPE PLSQL_EMP_LIST IS TABLE OF PLSQL_EMP_REC INDEX BY BINARY_INTEGER; \n" >+ + "PROCEDURE PLSQL_CITY_LIST_IN(P_CITY_LIST IN PLSQL_CITY_LIST, P_CITY IN VARCHAR2); \n" >+ + "PROCEDURE PLSQL_CITY_LIST_OUT(P_CITY_LIST OUT PLSQL_CITY_LIST, P_CITY OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_CITY_LIST_INOUT(P_CITY_LIST IN OUT PLSQL_CITY_LIST, P_CITY IN OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_ADDRESS_LIST_IN(P_ADDRESS_LIST IN PLSQL_ADDRESS_LIST, P_CITY IN VARCHAR2); \n" >+ + "PROCEDURE PLSQL_ADDRESS_LIST_OUT(P_ADDRESS_LIST OUT PLSQL_ADDRESS_LIST, P_CITY OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_ADDRESS_LIST_INOUT(P_ADDRESS_LIST IN OUT PLSQL_ADDRESS_LIST, P_CITY IN OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_EMP_LIST_IN(P_EMP_LIST IN PLSQL_EMP_LIST, P_CITY IN VARCHAR2); \n" >+ + "PROCEDURE PLSQL_EMP_LIST_OUT(P_EMP_LIST OUT PLSQL_EMP_LIST, P_CITY OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_EMP_LIST_INOUT(P_EMP_LIST IN OUT PLSQL_EMP_LIST, P_CITY IN OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_EMP_IN(P_EMP IN PLSQL_EMP_REC, P_CITY IN VARCHAR2); \n" >+ + "PROCEDURE PLSQL_EMP_OUT(P_EMP OUT PLSQL_EMP_REC, P_CITY OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_EMP_INOUT(P_EMP IN OUT PLSQL_EMP_REC, P_CITY IN OUT VARCHAR2); \n" >+ + "PROCEDURE PLSQL_ADDRESS_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_CUR); \n" >+ + "PROCEDURE PLSQL_ADDRESS_REC_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_REC_CUR); \n" >+ + "END PLSQL_P; \n"); >+ session.executeNonSelectingSQL("CREATE OR REPLACE PACKAGE BODY PLSQL_P AS \n" >+ + "PROCEDURE PLSQL_CITY_LIST_IN(P_CITY_LIST IN PLSQL_CITY_LIST, P_CITY IN VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "NULL; \n" >+ + "END PLSQL_CITY_LIST_IN; \n" >+ + "PROCEDURE PLSQL_CITY_LIST_OUT(P_CITY_LIST OUT PLSQL_CITY_LIST, P_CITY OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; \n" >+ + "P_CITY_LIST(1) := 'Ottawa'; \n" >+ + "END PLSQL_CITY_LIST_OUT; \n" >+ + "PROCEDURE PLSQL_CITY_LIST_INOUT(P_CITY_LIST IN OUT PLSQL_CITY_LIST, P_CITY IN OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; \n" >+ + "P_CITY_LIST(1) := 'Ottawa'; \n" >+ + "END PLSQL_CITY_LIST_INOUT; \n" >+ + "PROCEDURE PLSQL_ADDRESS_LIST_IN(P_ADDRESS_LIST IN PLSQL_ADDRESS_LIST, P_CITY IN VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "NULL; \n" >+ + "END PLSQL_ADDRESS_LIST_IN; \n" >+ + "PROCEDURE PLSQL_ADDRESS_LIST_OUT(P_ADDRESS_LIST OUT PLSQL_ADDRESS_LIST, P_CITY OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; " >+ + "END PLSQL_ADDRESS_LIST_OUT; \n" >+ + "PROCEDURE PLSQL_ADDRESS_LIST_INOUT(P_ADDRESS_LIST IN OUT PLSQL_ADDRESS_LIST, P_CITY IN OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; \n" >+ + "END PLSQL_ADDRESS_LIST_INOUT; \n" >+ + "PROCEDURE PLSQL_EMP_LIST_IN(P_EMP_LIST IN PLSQL_EMP_LIST, P_CITY IN VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "NULL; \n" >+ + "END PLSQL_EMP_LIST_IN; \n" >+ + "PROCEDURE PLSQL_EMP_LIST_OUT(P_EMP_LIST OUT PLSQL_EMP_LIST, P_CITY OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; " >+ + "END PLSQL_EMP_LIST_OUT; \n" >+ + "PROCEDURE PLSQL_EMP_LIST_INOUT(P_EMP_LIST IN OUT PLSQL_EMP_LIST, P_CITY IN OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; " >+ + "END PLSQL_EMP_LIST_INOUT; \n" >+ + "PROCEDURE PLSQL_EMP_IN(P_EMP IN PLSQL_EMP_REC, P_CITY IN VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "NULL; \n" >+ + "END PLSQL_EMP_IN; \n" >+ + "PROCEDURE PLSQL_EMP_OUT(P_EMP OUT PLSQL_EMP_REC, P_CITY OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; " >+ + "END PLSQL_EMP_OUT; \n" >+ + "PROCEDURE PLSQL_EMP_INOUT(P_EMP IN OUT PLSQL_EMP_REC, P_CITY IN OUT VARCHAR2) AS \n" >+ + "BEGIN \n" >+ + "P_CITY := 'Nepean'; \n" >+ + "END PLSQL_EMP_INOUT; \n" >+ + "PROCEDURE PLSQL_ADDRESS_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_CUR) AS \n" >+ + "BEGIN \n" >+ + "OPEN P_ADDRESS FOR SELECT * FROM PLSQL_ADDRESS; \n" >+ + "END PLSQL_ADDRESS_CUR_OUT; \n" >+ + "PROCEDURE PLSQL_ADDRESS_REC_CUR_OUT(P_ADDRESS OUT PLSQL_ADDRESS_REC_CUR) AS \n" >+ + "BEGIN \n" >+ + "OPEN P_ADDRESS FOR SELECT * FROM PLSQL_ADDRESS; \n" >+ + "END PLSQL_ADDRESS_REC_CUR_OUT; \n" >+ + "END PLSQL_P; \n"); >+ } >+ >+ /** >+ * Test a simple procedure. >+ */ >+ public void testSimpleProcedure() { >+ if (!getServerSession().getPlatform().isOracle()) { >+ return; >+ } >+ EntityManager em = createEntityManager(); >+ beginTransaction(em); >+ try { >+ Query query = em.createNamedQuery("PLSQL_SIMPLE_IN_DEFAULTS"); >+ query.setParameter("P_VARCHAR", "test"); >+ query.executeUpdate(); >+ query = em.createNamedQuery("PLSQL_SIMPLE_IN_DEFAULTS"); >+ query.setParameter("P_BOOLEAN", true); >+ query.executeUpdate(); >+ query = em.createNamedQuery("PLSQL_SIMPLE_IN_DEFAULTS"); >+ query.setParameter("P_VARCHAR", "test"); >+ query.setParameter("P_BOOLEAN", true); >+ query.setParameter("P_BINARY_INTEGER", 1); >+ query.setParameter("P_DEC", 1); >+ query.setParameter("P_INT", 1); >+ query.setParameter("P_NATURAL", 1); >+ query.setParameter("P_NATURALN", 1); >+ query.setParameter("P_PLS_INTEGER", 1); >+ query.setParameter("P_POSITIVE", 1); >+ query.setParameter("P_POSITIVEN", 1); >+ query.setParameter("P_SIGNTYPE", 1); >+ query.setParameter("P_NUMBER", 1); >+ query.executeUpdate(); >+ query.executeUpdate(); >+ query = em.createNamedQuery("PLSQL_SIMPLE_IN_DEFAULTS"); >+ query.setParameter("P_BOOLEAN", true); >+ query.executeUpdate(); >+ } finally { >+ closeEntityManagerAndTransaction(em); >+ } >+ } >+ >+ /** >+ * Test a simple function. >+ */ >+ public void testSimpleFunction() { >+ if (!getServerSession().getPlatform().isOracle()) { >+ return; >+ } >+ EntityManager em = createEntityManager(); >+ beginTransaction(em); >+ try { >+ Query query = em.createNamedQuery("PLSQL_SIMPLE_IN_FUNC"); >+ query.setParameter("P_VARCHAR", "test"); >+ query.setParameter("P_BOOLEAN", true); >+ query.setParameter("P_BINARY_INTEGER", 1); >+ query.setParameter("P_DEC", 1); >+ query.setParameter("P_INT", 1); >+ query.setParameter("P_NATURAL", 1); >+ query.setParameter("P_NATURALN", 1); >+ query.setParameter("P_PLS_INTEGER", 1); >+ query.setParameter("P_POSITIVE", 1); >+ query.setParameter("P_POSITIVEN", 1); >+ query.setParameter("P_SIGNTYPE", 1); >+ query.setParameter("P_NUMBER", 1); >+ int result = (Integer)query.getSingleResult(); >+ if (result != 1) { >+ fail("Incorrect result."); >+ } >+ } finally { >+ closeEntityManagerAndTransaction(em); >+ } >+ } >+ >+ /** >+ * Test a record out procedure. >+ */ >+ public void testRecordOut() { >+ if (!getServerSession().getPlatform().isOracle()) { >+ return; >+ } >+ EntityManager em = createEntityManager(); >+ beginTransaction(em); >+ try { >+ Query query = em.createNamedQuery("PLSQL_ADDRESS_OUT"); >+ Object result = query.getSingleResult(); >+ if (result == null) { >+ fail("Incorrect result."); >+ } >+ } finally { >+ closeEntityManagerAndTransaction(em); >+ } >+ } >+} >\ No newline at end of file >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/plsql/XMLPLSQLTestSuite.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/plsql/XMLPLSQLTestSuite.java (revision 0) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/plsql/XMLPLSQLTestSuite.java (revision 0) >@@ -0,0 +1,42 @@ >+/******************************************************************************* >+ * Copyright (c) 2011 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * James Sutherland (Oracle) - initial impl >+ ******************************************************************************/ >+package org.eclipse.persistence.testing.tests.jpa.plsql; >+ >+import junit.framework.*; >+ >+public class XMLPLSQLTestSuite extends PLSQLTestSuite { >+ public static boolean validDatabase = true; >+ >+ public static Test suite() { >+ TestSuite suite = new TestSuite("XMLPLSQLTestSuite"); >+ suite.addTest(new XMLPLSQLTestSuite("testSetup")); >+ suite.addTest(new XMLPLSQLTestSuite("testSimpleProcedure")); >+ suite.addTest(new XMLPLSQLTestSuite("testSimpleFunction")); >+ suite.addTest(new XMLPLSQLTestSuite("testRecordOut")); >+ return suite; >+ } >+ >+ public XMLPLSQLTestSuite(String name) { >+ super(name); >+ } >+ >+ /** >+ * Return the name of the persistence context this test uses. >+ * This allow a subclass test to set this only in one place. >+ */ >+ @Override >+ public String getPersistenceUnitName() { >+ return "plsql-xml"; >+ } >+ >+} >\ No newline at end of file
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 339905
: 193159