diff --git a/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/plsqlcollection/PLSQLcollectionTestSuite.java b/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/plsqlcollection/PLSQLcollectionTestSuite.java index fb1c20a2ad2..e25edf4713b 100644 --- a/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/plsqlcollection/PLSQLcollectionTestSuite.java +++ b/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/plsqlcollection/PLSQLcollectionTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -45,7 +45,7 @@ import org.eclipse.persistence.oxm.XMLMarshaller; import org.eclipse.persistence.oxm.mappings.XMLTransformationMapping; import org.eclipse.persistence.platform.database.jdbc.JDBCTypes; -import org.eclipse.persistence.platform.database.oracle.Oracle10Platform; +import org.eclipse.persistence.platform.database.OraclePlatform; import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall; import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLCollection; import org.eclipse.persistence.platform.xml.XMLComparer; @@ -273,7 +273,7 @@ public void fromProjectXML() { login.setPassword(password); ((DatabaseLogin)login).setConnectionString(url); ((DatabaseLogin)login).setDriverClassName("oracle.jdbc.OracleDriver"); - Platform platform = new Oracle10Platform(); + Platform platform = new OraclePlatform(); ConversionManager cm = platform.getConversionManager(); cm.setLoader(xrdecl); login.setDatasourcePlatform(platform); diff --git a/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/veearray/VeearrayTestSuite.java b/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/veearray/VeearrayTestSuite.java index 7f9553822e8..01b6c75f0ce 100644 --- a/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/veearray/VeearrayTestSuite.java +++ b/dbws/eclipselink.dbws.test.oracle/src/it/java/dbws/testing/veearray/VeearrayTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -64,7 +64,7 @@ import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; import org.eclipse.persistence.oxm.schema.XMLSchemaReference; import org.eclipse.persistence.oxm.schema.XMLSchemaURLReference; -import org.eclipse.persistence.platform.database.oracle.Oracle10Platform; +import org.eclipse.persistence.platform.database.OraclePlatform; import org.eclipse.persistence.platform.xml.XMLComparer; import org.eclipse.persistence.platform.xml.XMLParser; import org.eclipse.persistence.platform.xml.XMLPlatform; @@ -250,7 +250,7 @@ public static void setUp() { login.setPassword(password); login.setConnectionString(url); login.setDriverClassName(driver); - login.setDatasourcePlatform(new Oracle10Platform()); + login.setDatasourcePlatform(new OraclePlatform()); login.bindAllParameters(); orProject.setDatasourceLogin(login); diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java index 8e780171318..8ecde174ffd 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/internal/databaseaccess/DatabasePlatform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019 IBM Corporation. All rights reserved. * * This program and the accompanying materials are made available under the @@ -2815,7 +2815,7 @@ public boolean usesStringBinding() { * Write LOB value - only on Oracle8 and up */ public void writeLOB(DatabaseField field, Object value, ResultSet resultSet, AbstractSession session) throws SQLException { - // used by Oracle8Platform + // used by OraclePlatform } /** diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle10Platform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle10Platform.java deleted file mode 100644 index 5559938e6a9..00000000000 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle10Platform.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2019 IBM Corporation. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -// Contributors: -// 06/26/2018 - Will Dazey -// - 532160 : Add support for non-extension OracleXPlatform classes -package org.eclipse.persistence.platform.database; - -/** - *

Purpose: - * Provides Oracle version specific behavior when - * org.eclipse.persistence.oracle bundle is not available. - */ -public class Oracle10Platform extends Oracle9Platform { - - public Oracle10Platform(){ - super(); - } - - /** - * Build the hint string used for first rows. - * - * Allows it to be overridden - * @param max - * @return - */ - protected String buildFirstRowsHint(int max){ - //bug 374136: override setting the FIRST_ROWS hint as this is not needed on Oracle10g - return ""; - } - - /** - * INTERNAL: - * Indicate whether app. server should unwrap connection - * to use lob locator. - * No need to unwrap connection because - * writeLob method doesn't use oracle proprietary classes. - */ - @Override - public boolean isNativeConnectionRequiredForLobLocator() { - return false; - } -} diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle11Platform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle11Platform.java index 25bfd7e0307..c74aa0d53e7 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle11Platform.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle11Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019 IBM Corporation. All rights reserved. * * This program and the accompanying materials are made available under the @@ -24,7 +24,7 @@ * Provides Oracle version specific behavior when * org.eclipse.persistence.oracle bundle is not available. */ -public class Oracle11Platform extends Oracle10Platform { +public class Oracle11Platform extends OraclePlatform { public Oracle11Platform() { super(); diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle9Platform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle9Platform.java deleted file mode 100644 index bf4d795173e..00000000000 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/Oracle9Platform.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018 IBM Corporation. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -// Contributors: -// 06/26/2018 - Will Dazey -// - 532160 : Add support for non-extension OracleXPlatform classes -package org.eclipse.persistence.platform.database; - -/** - *

Purpose: - * Provides Oracle version specific behavior when - * org.eclipse.persistence.oracle bundle is not available. - */ -public class Oracle9Platform extends Oracle8Platform { - public Oracle9Platform(){ - super(); - } - - /** - * Build the hint string used for first rows. - * - * Allows it to be overridden - * @param max - * @return - */ - protected String buildFirstRowsHint(int max){ - return HINT_START + '(' + max + ')'+ HINT_END; - } -} diff --git a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/OraclePlatform.java b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/OraclePlatform.java index 20c419e0f3c..babcacdd3d2 100644 --- a/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/OraclePlatform.java +++ b/foundation/org.eclipse.persistence.core/src/main/java/org/eclipse/persistence/platform/database/OraclePlatform.java @@ -32,6 +32,8 @@ import java.io.IOException; import java.io.StringWriter; import java.io.Writer; +import java.sql.Blob; +import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -51,6 +53,8 @@ import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; import org.eclipse.persistence.internal.databaseaccess.DatasourceCall; import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition; +import org.eclipse.persistence.internal.databaseaccess.Platform; +import org.eclipse.persistence.internal.databaseaccess.SimpleAppendCallCustomParameter; import org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter; import org.eclipse.persistence.internal.expressions.FunctionExpression; import org.eclipse.persistence.internal.expressions.RelationExpression; @@ -63,6 +67,8 @@ import org.eclipse.persistence.internal.localization.ExceptionLocalization; import org.eclipse.persistence.internal.sessions.AbstractSession; import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl; +import org.eclipse.persistence.logging.SessionLog; +import org.eclipse.persistence.queries.Call; import org.eclipse.persistence.queries.DataModifyQuery; import org.eclipse.persistence.queries.DataReadQuery; import org.eclipse.persistence.queries.DatabaseQuery; @@ -178,9 +184,9 @@ protected void appendTime(java.sql.Time time, Writer writer) throws IOException @Override protected void appendTimestamp(java.sql.Timestamp timestamp, Writer writer) throws IOException { if (usesNativeSQL()) { - writer.write("to_date('"); - writer.write(Helper.printTimestampWithoutNanos(timestamp)); - writer.write("','yyyy-mm-dd hh24:mi:ss')"); + writer.write("to_timestamp('"); + writer.write(Helper.printTimestamp(timestamp)); + writer.write("','yyyy-mm-dd HH24:MI:SS.FF')"); } else { super.appendTimestamp(timestamp, writer); } @@ -215,7 +221,7 @@ public ExpressionOperator atan2Operator() { */ @Override protected Hashtable buildFieldTypes() { - Hashtable fieldTypeMapping; + Hashtable fieldTypeMapping = super.buildFieldTypes(); fieldTypeMapping = new Hashtable(); fieldTypeMapping.put(Boolean.class, new FieldTypeDefinition("NUMBER(1) default 0", false)); @@ -251,18 +257,13 @@ protected Hashtable buildFieldTypes() { fieldTypeMapping.put(java.util.Calendar.class, new FieldTypeDefinition("TIMESTAMP")); fieldTypeMapping.put(java.util.Date.class, new FieldTypeDefinition("TIMESTAMP")); - return fieldTypeMapping; - } + fieldTypeMapping.put(java.time.LocalDate.class, new FieldTypeDefinition("DATE")); + fieldTypeMapping.put(java.time.LocalDateTime.class, new FieldTypeDefinition("TIMESTAMP")); + fieldTypeMapping.put(java.time.LocalTime.class, new FieldTypeDefinition("TIMESTAMP")); + fieldTypeMapping.put(java.time.OffsetDateTime.class, new FieldTypeDefinition("TIMESTAMP")); //TIMESTAMP WITH TIME ZONE ??? + fieldTypeMapping.put(java.time.OffsetTime.class, new FieldTypeDefinition("TIMESTAMP")); //TIMESTAMP WITH TIME ZONE ??? - /** - * Build the hint string used for first rows. - * - * Allows it to be overridden - * @param max - * @return - */ - protected String buildFirstRowsHint(int max){ - return HINT_START + HINT_END; + return fieldTypeMapping; } /** @@ -952,8 +953,6 @@ public boolean useJDBCStoredProcedureSyntax() { //Oracle Rownum support protected String SELECT = "SELECT * FROM (SELECT "; - protected String HINT_START = "/*+ FIRST_ROWS"; - protected String HINT_END = " */ "; protected String FROM = "a.*, ROWNUM rnum FROM ("; protected String END_FROM = ") a "; protected String MAX_ROW = "WHERE ROWNUM <= "; @@ -967,6 +966,10 @@ public boolean useJDBCStoredProcedureSyntax() { protected String FROM_ID = ", ROWNUM rnum FROM ("; protected String END_FROM_ID = ") "; protected String ORDER_BY_ID = " ORDER BY "; + /** Locator is required for Oracle thin driver to write LOB value exceeds the limits */ + protected boolean usesLocatorForLOBWrite = false; + /** The LOB value limits when the Locator is required for the writing */ + protected int lobValueLimits = 0; /** * INTERNAL: @@ -1021,7 +1024,6 @@ public void printSQLSelectStatement(DatabaseCall call, ExpressionSQLPrinter prin printer.printString(SELECT_ID_PREFIX); printer.printString(primaryKeyFields); printer.printString(SELECT_ID_SUFFIX); - printer.printString(buildFirstRowsHint(max)); printer.printString(primaryKeyFields); printer.printString(FROM_ID); printer.printString(queryString); @@ -1039,7 +1041,6 @@ public void printSQLSelectStatement(DatabaseCall call, ExpressionSQLPrinter prin } else { if (max > 0) { printer.printString(SELECT); - printer.printString(buildFirstRowsHint(max)); printer.printString(FROM); call.setFields(statement.printSQL(printer)); @@ -1226,6 +1227,7 @@ protected DataReadQuery getTableExistsQuery(final TableDefinition table) { * @param suppressLogging whether to suppress logging during query execution * @return value of {@code true} if given table exists or {@code false} otherwise */ + @Override public boolean checkTableExists(final DatabaseSessionImpl session, final TableDefinition table, final boolean suppressLogging) { try { @@ -1241,4 +1243,185 @@ public boolean checkTableExists(final DatabaseSessionImpl session, public int getINClauseLimit() { return 1000; } + /** + * INTERNAL: + * Return if the LOB value size is larger than the limit, i.e. 4k. + */ + protected boolean lobValueExceedsLimit(Object value) { + if (value == null) { + return false; + } + int limit = getLobValueLimits(); + if (value instanceof byte[]) {//blob + return ((byte[])value).length >= limit; + } else if (value instanceof String) {//clob + return ((String)value).length() >= limit; + } else { + return false; + } + } + + /** + * PUBLIC: + * Return if the locator is required for the LOB write. The default is true. + * For Oracle thin driver, the locator is recommended for large size + * ( >4k for Oracle8, >5.9K for Oracle9) BLOB/CLOB value write. + */ + public boolean shouldUseLocatorForLOBWrite() { + return usesLocatorForLOBWrite; + } + + /** + * PUBLIC: + * Return the BLOB/CLOB value limits on thin driver. The default value is 0. + * If usesLocatorForLOBWrite is true, locator will be used in case the + * lob's size is larger than lobValueLimit. + */ + public int getLobValueLimits() { + return lobValueLimits; + } + + /** + * PUBLIC: + * Set the BLOB/CLOB value limits on thin driver. The default value is 0. + * If usesLocatorForLOBWrite is true, locator will be used in case the + * lob's size is larger than lobValueLimit. + */ + public void setLobValueLimits(int lobValueLimits) { + this.lobValueLimits = lobValueLimits; + } + + /** + * INTERNAL: + * Write LOB value - works on Oracle 10 and newer + */ + @Override + public void writeLOB(DatabaseField field, Object value, ResultSet resultSet, AbstractSession session) throws SQLException { + if (isBlob(field.getType())) { + //change for 338585 to use getName instead of getNameDelimited + Blob blob = (Blob) resultSet.getObject(field.getName()); + blob.setBytes(1, (byte[]) value); + //impose the localization + session.log(SessionLog.FINEST, SessionLog.SQL, "write_BLOB", Long.valueOf(blob.length()), field.getName()); + } else if (isClob(field.getType())) { + //change for 338585 to use getName instead of getNameDelimited + Clob clob = (Clob) resultSet.getObject(field.getName()); + clob.setString(1, (String) value); + //impose the localization + session.log(SessionLog.FINEST, SessionLog.SQL, "write_CLOB", Long.valueOf(clob.length()), field.getName()); + } else { + //do nothing for now, open to BFILE or NCLOB types + } + } + + /** + * INTERNAL: + * Used in writeLOB method only to identify a BLOB + */ + protected boolean isBlob(Class type) { + return ClassConstants.BLOB.equals(type); + } + + /** + * INTERNAL: + * Used in writeLOB method only to identify a CLOB + */ + protected boolean isClob(Class type) { + return ClassConstants.CLOB.equals(type); + } + + /** + * PUBLIC: + * Set if the locator is required for the LOB write. The default is true. + * For Oracle thin driver, the locator is recommended for large size + * ( >4k for Oracle8, >5.9K for Oracle9) BLOB/CLOB value write. + */ + public void setShouldUseLocatorForLOBWrite(boolean usesLocatorForLOBWrite) { + this.usesLocatorForLOBWrite = usesLocatorForLOBWrite; + } + + /** + * INTERNAL + * Used by SQLCall.translate(..) + * Typically there is no field translation (and this is default implementation). + * However on different platforms (Oracle) there are cases such that the values for + * binding and appending may be different (BLOB, CLOB). + * In these special cases the method returns a wrapper object + * which knows whether it should be bound or appended and knows how to do that. + */ + @Override + public Object getCustomModifyValueForCall(Call call, Object value, DatabaseField field, boolean shouldBind) { + Class type = field.getType(); + if (isBlob(type) || isClob(type)) { + if(value == null) { + return null; + } + value = convertToDatabaseType(value); + if (shouldUseLocatorForLOBWrite()) { + if (lobValueExceedsLimit(value)) { + ((DatabaseCall)call).addContext(field, value); + if (isBlob(type)) { + if (shouldBind) { + value = new byte[1]; + } else { + value = new SimpleAppendCallCustomParameter("empty_blob()"); + } + } else { + if (shouldBind) { + value = new String(" "); + } else { + value = new SimpleAppendCallCustomParameter("empty_clob()"); + } + } + } + } + return value; + } + return super.getCustomModifyValueForCall(call, value, field, shouldBind); + } + + /** + * INTERNAL + * Used by SQLCall.appendModify(..) + * If the field should be passed to customModifyInDatabaseCall, retun true, + * otherwise false. + * Methods shouldCustomModifyInDatabaseCall and customModifyInDatabaseCall should be + * kept in sync: shouldCustomModifyInDatabaseCall should return true if and only if the field + * is handled by customModifyInDatabaseCall. + */ + @Override + public boolean shouldUseCustomModifyForCall(DatabaseField field) { + if (shouldUseLocatorForLOBWrite()) { + Class type = field.getType(); + if (isBlob(type) || isClob(type)) { + return true; + } + } + return super.shouldUseCustomModifyForCall(field); + } + + /** + * INTERNAL: + * Allow for conversion from the Oralce type to the Java type. + */ + @Override + public void copyInto(Platform platform) { + super.copyInto(platform); + if (!(platform instanceof OraclePlatform)) { + return; + } + OraclePlatform oraclePlatform = (OraclePlatform)platform; + oraclePlatform.setShouldUseLocatorForLOBWrite(shouldUseLocatorForLOBWrite()); + oraclePlatform.setLobValueLimits(getLobValueLimits()); + } + + /** + * INTERNAL: + * Supports Batch Writing with Optimistic Locking. + */ + @Override + public boolean canBatchWriteWithOptimisticLocking(DatabaseCall call){ + return true;//usesNativeBatchWriting || !call.hasParameters(); + } + } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/framework/oracle/OracleDBPlatformHelper.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/framework/oracle/OracleDBPlatformHelper.java index b6c2780d763..558d29f3cbb 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/framework/oracle/OracleDBPlatformHelper.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/framework/oracle/OracleDBPlatformHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -15,16 +15,18 @@ package org.eclipse.persistence.testing.framework.oracle; import org.eclipse.persistence.platform.database.OraclePlatform; -import org.eclipse.persistence.platform.database.oracle.Oracle8Platform; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle12Platform; public class OracleDBPlatformHelper extends org.eclipse.persistence.testing.framework.OracleDBPlatformHelper{ + @Override public OraclePlatform getOracle8Platform(){ - return new Oracle8Platform(); + return new Oracle11Platform(); } + @Override public OraclePlatform getOracle9Platform(){ - return new Oracle9Platform(); + return new Oracle12Platform(); } } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/CMAndPlatformWrapper.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/CMAndPlatformWrapper.java index aa26f8c6280..368b981aa72 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/CMAndPlatformWrapper.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/CMAndPlatformWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -17,7 +17,7 @@ import java.util.Vector; import org.eclipse.persistence.internal.helper.ConversionManager; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; // This works as a wrapper for CM and Oracle9Platform. It is used in DataTypesConvertedXX tests. public class CMAndPlatformWrapper { @@ -30,8 +30,8 @@ public CMAndPlatformWrapper(Object object) { public Vector getDataTypesConvertedFrom(Class aClass) { if (wrappedObj instanceof ConversionManager) { return ((ConversionManager)wrappedObj).getDataTypesConvertedFrom(aClass); - } else if (wrappedObj instanceof Oracle9Platform) { - return ((Oracle9Platform)wrappedObj).getDataTypesConvertedFrom(aClass); + } else if (wrappedObj instanceof Oracle11Platform) { + return ((Oracle11Platform)wrappedObj).getDataTypesConvertedFrom(aClass); } return new Vector(); } @@ -39,8 +39,8 @@ public Vector getDataTypesConvertedFrom(Class aClass) { public Vector getDataTypesConvertedTo(Class aClass) { if (wrappedObj instanceof ConversionManager) { return ((ConversionManager)wrappedObj).getDataTypesConvertedTo(aClass); - } else if (wrappedObj instanceof Oracle9Platform) { - return ((Oracle9Platform)wrappedObj).getDataTypesConvertedTo(aClass); + } else if (wrappedObj instanceof Oracle11Platform) { + return ((Oracle11Platform)wrappedObj).getDataTypesConvertedTo(aClass); } return new Vector(); } @@ -48,8 +48,8 @@ public Vector getDataTypesConvertedTo(Class aClass) { public Object convertObject(Object object, Class aClass) { if (wrappedObj instanceof ConversionManager) { return ((ConversionManager)wrappedObj).convertObject(object, aClass); - } else if (wrappedObj instanceof Oracle9Platform) { - return ((Oracle9Platform)wrappedObj).convertObject(object, aClass); + } else if (wrappedObj instanceof Oracle11Platform) { + return ((Oracle11Platform)wrappedObj).convertObject(object, aClass); } return null; } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedFromAClassForOracle9Test.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedFromAClassForOracle9Test.java index 887df627e9f..53c1c46d583 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedFromAClassForOracle9Test.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedFromAClassForOracle9Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,7 +14,7 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.conversion; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.testing.framework.TestWarningException; // This test retrieves all the classes that can be converted from a given class by @@ -25,6 +25,7 @@ public DataTypesConvertedFromAClassForOracle9Test() { setDescription("Test getDataTypesConvertedFrom() in Oracle9Platform."); } + @Override public void setup() { if(!getSession().getPlatform().isOracle()) { throw new TestWarningException("This test requires Oracle database"); @@ -32,8 +33,9 @@ public void setup() { cm = getSession().getPlatform(); } + @Override protected boolean isChar(Class aClass) { - return super.isChar(aClass) || aClass == Oracle9Platform.NCHAR || aClass == Oracle9Platform.NSTRING || - aClass == Oracle9Platform.NCLOB; + return super.isChar(aClass) || aClass == Oracle11Platform.NCHAR || aClass == Oracle11Platform.NSTRING || + aClass == Oracle11Platform.NCLOB; } } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedToAClassForOracle9Test.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedToAClassForOracle9Test.java index 54949241a24..6a0d003f549 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedToAClassForOracle9Test.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/conversion/DataTypesConvertedToAClassForOracle9Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,13 +14,13 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.conversion; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Time; +import java.sql.Timestamp; import java.util.Calendar; -import java.sql.*; - -import java.math.*; - -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.testing.framework.TestWarningException; //This test retrieves all the classes that can be converted to a given class by @@ -37,6 +37,7 @@ public DataTypesConvertedToAClassForOracle9Test() { setDescription("Test getDataTypesConvertedTo() in Oracle9Platform."); } + @Override public void setup() { if(!getSession().getPlatform().isOracle()) { throw new TestWarningException("This test requires Oracle database"); @@ -44,8 +45,9 @@ public void setup() { cm = getSession().getPlatform(); } + @Override protected boolean isChar(Class aClass) { - return super.isChar(aClass) || aClass == Oracle9Platform.NCHAR || aClass == Oracle9Platform.NSTRING || - aClass == Oracle9Platform.NCLOB; + return super.isChar(aClass) || aClass == Oracle11Platform.NCHAR || aClass == Oracle11Platform.NSTRING || + aClass == Oracle11Platform.NCLOB; } } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/proxyauthentication/ProxyAuthenticationTestSuite.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/proxyauthentication/ProxyAuthenticationTestSuite.java index b4caa4d3046..4b4912c82d0 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/proxyauthentication/ProxyAuthenticationTestSuite.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/jpa/proxyauthentication/ProxyAuthenticationTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -23,19 +23,12 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; -import junit.framework.Test; -import junit.framework.TestSuite; - -import oracle.jdbc.OracleConnection; -import oracle.jdbc.pool.OracleDataSource; - -import org.eclipse.persistence.config.PersistenceUnitProperties; import org.eclipse.persistence.config.ExclusiveConnectionMode; +import org.eclipse.persistence.config.PersistenceUnitProperties; import org.eclipse.persistence.internal.sessions.ExclusiveIsolatedClientSession; import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl; import org.eclipse.persistence.jpa.JpaEntityManagerFactory; - -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.sessions.SessionEvent; import org.eclipse.persistence.sessions.SessionEventAdapter; import org.eclipse.persistence.sessions.server.ConnectionPolicy; @@ -44,6 +37,11 @@ import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper; import org.eclipse.persistence.testing.tests.proxyauthentication.thin.ProxyAuthenticationUsersAndProperties; +import junit.framework.Test; +import junit.framework.TestSuite; +import oracle.jdbc.OracleConnection; +import oracle.jdbc.pool.OracleDataSource; + /** * TestSuite to verifying that connectionUser and proxyUser are used as expected. * To run this test suite several users should be setup in the Oracle database, @@ -66,6 +64,7 @@ public class ProxyAuthenticationTestSuite extends JUnitTestCase { // writeUser is set by an event risen by ModifyQuery. private static String writeUser; public static class Listener extends SessionEventAdapter { + @Override public void outputParametersDetected(SessionEvent event) { writeUser = (String)((Map)event.getResult()).get("OUT"); } @@ -97,6 +96,7 @@ public ProxyAuthenticationTestSuite(String name) { super(name); } + @Override public String getPersistenceUnitName() { return PU_NAME; } @@ -127,6 +127,7 @@ public static Test suite() { return suite; } + @Override public void setUp() { // runs for the first time - setup user names and properties used by the tests. if(setupErrorMsg == null) { @@ -134,7 +135,7 @@ public void setUp() { setupErrorMsg = "ProxyAuthentication tests currently can't run on server."; } else if(!getServerSession(PU_NAME).getPlatform().isOracle()) { setupErrorMsg = "ProxyAuthentication test has not run, it runs only on Oracle and Oracle9Platform or higher required."; - } else if (! (getServerSession(PU_NAME).getPlatform() instanceof Oracle9Platform)) { + } else if (! (getServerSession(PU_NAME).getPlatform() instanceof Oracle11Platform)) { setupErrorMsg = "ProxyAuthentication test has not run, Oracle9Platform or higher required."; } else { // sets up all user names and properties used by the tests. @@ -155,6 +156,7 @@ public void setUp() { } } + @Override public void tearDown() { // clean-up if(setupErrorMsg.length() > 0) { diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBSessionBrokerTestModel.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBSessionBrokerTestModel.java index cefb0fef63b..d4a071cf966 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBSessionBrokerTestModel.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBSessionBrokerTestModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -15,8 +15,11 @@ package org.eclipse.persistence.testing.tests.lob; import org.eclipse.persistence.internal.sessions.AbstractSession; +import org.eclipse.persistence.platform.database.OraclePlatform; import org.eclipse.persistence.sessions.broker.SessionBroker; -import org.eclipse.persistence.testing.framework.*; +import org.eclipse.persistence.testing.framework.TestModel; +import org.eclipse.persistence.testing.framework.TestSuite; +import org.eclipse.persistence.testing.framework.TestWarningException; public class LOBSessionBrokerTestModel extends TestModel { public LOBSessionBrokerTestModel() { @@ -24,16 +27,18 @@ public LOBSessionBrokerTestModel() { setDescription("This suite tests TopLink LOB support with Oracle thin driver and SessionBroker."); } + @Override public void addRequiredSystems() { if (!getSession().getPlatform().isOracle()) { throw new TestWarningException("WARNING: This model is not supposed to be run on databases other than Oracle."); } - if (!(getSession().getPlatform() instanceof org.eclipse.persistence.platform.database.oracle.Oracle8Platform)) { - throw new TestWarningException("WARNING: This model requires Oracle8Platform or higher"); + if (!(getSession().getPlatform() instanceof OraclePlatform)) { + throw new TestWarningException("WARNING: This model requires OraclePlatform or higher"); } addRequiredSystem(new LOBImageModelSystem()); } + @Override public void addTests() { addTest(getLOBInsertTestSuite()); addTest(getLOBUpdateTestSuite()); @@ -56,6 +61,7 @@ protected TestSuite getLOBUpdateTestSuite() { return suite; } + @Override public void setup() { if (!((AbstractSession)getSession()).isBroker()) { SessionBroker broker = new SessionBroker(); @@ -67,6 +73,7 @@ public void setup() { } } + @Override public void reset() { if (((AbstractSession)getSession()).isBroker()) { SessionBroker broker = (SessionBroker)getSession(); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBTestWrapper.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBTestWrapper.java index 59fc3f3e324..0f7cb2c0a57 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBTestWrapper.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/lob/LOBTestWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,9 +14,12 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.lob; -import org.eclipse.persistence.testing.framework.*; import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; -import org.eclipse.persistence.platform.database.oracle.Oracle8Platform; +import org.eclipse.persistence.platform.database.OraclePlatform; +import org.eclipse.persistence.testing.framework.AutoVerifyTestCase; +import org.eclipse.persistence.testing.framework.TestProblemException; +import org.eclipse.persistence.testing.framework.TestWarningException; +import org.eclipse.persistence.testing.framework.TestWrapper; public class LOBTestWrapper extends TestWrapper { protected boolean shouldSetUseLocatorForLOBWriteIntoPlatform; @@ -36,13 +39,14 @@ public LOBTestWrapper(AutoVerifyTestCase test, boolean shouldUseLocatorForLOBWri setName(getName() + " platform forced to "+(shouldUseLocatorForLOBWrite ? "use" : "NOT use")+" lob locators)"); } + @Override protected void setup() throws Throwable { DatabasePlatform platform = getSession().getPlatform(); if (!platform.isOracle()) { throw new TestWarningException("This test case works on Oracle only"); } - if(platform instanceof Oracle8Platform) { - Oracle8Platform platform8 = (Oracle8Platform)platform; + if(platform instanceof OraclePlatform) { + OraclePlatform platform8 = (OraclePlatform)platform; shouldUseLocatorForLOBWriteOriginal = platform8.shouldUseLocatorForLOBWrite(); if(shouldSetUseLocatorForLOBWriteIntoPlatform) { platform8.setShouldUseLocatorForLOBWrite(shouldUseLocatorForLOBWrite); @@ -65,14 +69,15 @@ protected void setup() throws Throwable { super.setup(); } + @Override public void reset() throws Throwable { super.reset(); DatabasePlatform platform = getSession().getPlatform(); if(!shouldUseLocatorForLOBWrite) { platform.setUsesStringBinding(usesStringBindingOriginal); } - if(platform instanceof Oracle8Platform) { - Oracle8Platform platform8 = (Oracle8Platform)platform; + if(platform instanceof OraclePlatform) { + OraclePlatform platform8 = (OraclePlatform)platform; if(shouldSetUseLocatorForLOBWriteIntoPlatform) { platform8.setShouldUseLocatorForLOBWrite(shouldUseLocatorForLOBWriteOriginal); } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nchar/BaseNcharTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nchar/BaseNcharTest.java index 92c5aa39d8a..a0851aa71e5 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nchar/BaseNcharTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nchar/BaseNcharTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,10 +14,13 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.nchar; -import org.eclipse.persistence.testing.framework.*; -import org.eclipse.persistence.sessions.UnitOfWork; import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.sessions.UnitOfWork; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestException; +import org.eclipse.persistence.testing.framework.TestProblemException; +import org.eclipse.persistence.testing.framework.TestWarningException; public abstract class BaseNcharTest extends TestCase { protected DatabasePlatform platformOriginal; @@ -25,10 +28,11 @@ public abstract class BaseNcharTest extends TestCase { protected CharNchar controlObject; protected boolean usesStringBindingOriginal; - protected Oracle9Platform getOracle9Platform() throws ClassCastException { - return (Oracle9Platform)getSession().getPlatform(); + protected Oracle11Platform getOracle9Platform() throws ClassCastException { + return (Oracle11Platform)getSession().getPlatform(); } + @Override protected void setup() { if (!getSession().getPlatform().isOracle()) { throw new TestWarningException("This test case works on Oracle only"); @@ -38,7 +42,7 @@ protected void setup() { } catch (ClassCastException ex) { DatabasePlatform platform = getSession().getPlatform(); try { - getSession().getLogin().usePlatform(new org.eclipse.persistence.platform.database.oracle.Oracle9Platform()); + getSession().getLogin().usePlatform(new org.eclipse.persistence.platform.database.oracle.Oracle11Platform()); getDatabaseSession().logout(); getDatabaseSession().login(); platformOriginal = platform; @@ -55,6 +59,7 @@ protected void setup() { } } + @Override protected void verify() { if (object == null) { throw new TestException("object is missing"); @@ -166,6 +171,7 @@ protected void verify() { } } + @Override public void reset() { if (object != null) { UnitOfWork uow = getSession().acquireUnitOfWork(); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nonJDBC/NonJDBCTestHelper.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nonJDBC/NonJDBCTestHelper.java index a77a9dc200a..7c6efe9f894 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nonJDBC/NonJDBCTestHelper.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/nonJDBC/NonJDBCTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,13 +12,13 @@ package org.eclipse.persistence.testing.tests.nonJDBC; +// JUnit imports +import static org.junit.Assert.fail; + // javase imports import java.lang.reflect.Field; import java.util.Properties; -// JUnit imports -import static org.junit.Assert.fail; - // EclipseLink imports import org.eclipse.persistence.descriptors.RelationalDescriptor; import org.eclipse.persistence.internal.descriptors.TransformerBasedFieldTransformation; @@ -26,7 +26,7 @@ import org.eclipse.persistence.mappings.DirectToFieldMapping; import org.eclipse.persistence.mappings.transformers.ConstantTransformer; import org.eclipse.persistence.oxm.mappings.XMLTransformationMapping; -import org.eclipse.persistence.platform.database.oracle.Oracle10Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.platform.xml.XMLComparer; import org.eclipse.persistence.platform.xml.XMLParser; import org.eclipse.persistence.platform.xml.XMLPlatformFactory; @@ -81,7 +81,7 @@ public static Project buildTestProject(Properties p) { login.setPassword(password); login.setConnectionString(url); login.setDriverClassName(driver); - login.setDatasourcePlatform(new Oracle10Platform()); + login.setDatasourcePlatform(new Oracle11Platform()); login.useBatchWriting(); project.setDatasourceLogin(login); return project; diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordTestHelper.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordTestHelper.java index 51f32525813..170215ac6cf 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordTestHelper.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,14 +12,14 @@ package org.eclipse.persistence.testing.tests.plsqlrecord; +// JUnit imports +import static org.junit.Assert.fail; + // javase imports import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.Properties; -// JUnit imports -import static org.junit.Assert.fail; - // EclipseLink imports import org.eclipse.persistence.internal.descriptors.TransformerBasedFieldTransformation; import org.eclipse.persistence.internal.sessions.factories.ObjectPersistenceWorkbenchXMLProject; @@ -27,7 +27,7 @@ import org.eclipse.persistence.mappings.structures.ObjectRelationalDataTypeDescriptor; import org.eclipse.persistence.mappings.transformers.ConstantTransformer; import org.eclipse.persistence.oxm.mappings.XMLTransformationMapping; -import org.eclipse.persistence.platform.database.oracle.Oracle10Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.platform.xml.XMLComparer; import org.eclipse.persistence.platform.xml.XMLParser; import org.eclipse.persistence.platform.xml.XMLPlatformFactory; @@ -132,7 +132,7 @@ public static Project buildTestProject(Properties p) { login.setPassword(password); login.setConnectionString(url); login.setDriverClassName(driver); - login.setDatasourcePlatform(new Oracle10Platform()); + login.setDatasourcePlatform(new Oracle11Platform()); project.setDatasourceLogin(login); return project; } diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInOutTestSet.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInOutTestSet.java index ef94384a600..1bd3645d4f8 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInOutTestSet.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInOutTestSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -38,8 +38,8 @@ import org.eclipse.persistence.internal.sessions.factories.ObjectPersistenceWorkbenchXMLProject; import org.eclipse.persistence.oxm.XMLContext; import org.eclipse.persistence.oxm.XMLMarshaller; +import org.eclipse.persistence.platform.database.OraclePlatform; import org.eclipse.persistence.platform.database.jdbc.JDBCTypes; -import org.eclipse.persistence.platform.database.oracle.Oracle8Platform; import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall; import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLrecord; import org.eclipse.persistence.queries.ReadObjectQuery; @@ -277,7 +277,7 @@ public void runQuery() { }; Struct struct = null; try { - struct = ((Oracle8Platform)s.getPlatform()).createStruct( + struct = ((OraclePlatform)s.getPlatform()).createStruct( "EMP_TYPE", attributes, ((DatabaseSessionImpl)s).getAccessor().getConnection()); } catch (SQLException e1) { diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInTestSet.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInTestSet.java index 584863a3e9f..17271bb3999 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInTestSet.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/plsqlrecord/PLSQLrecordWithCompatibleTypeInTestSet.java @@ -10,7 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -// Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved. package org.eclipse.persistence.testing.tests.plsqlrecord; @@ -36,8 +36,8 @@ import org.eclipse.persistence.internal.sessions.factories.ObjectPersistenceWorkbenchXMLProject; import org.eclipse.persistence.oxm.XMLContext; import org.eclipse.persistence.oxm.XMLMarshaller; +import org.eclipse.persistence.platform.database.OraclePlatform; import org.eclipse.persistence.platform.database.jdbc.JDBCTypes; -import org.eclipse.persistence.platform.database.oracle.Oracle8Platform; import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall; import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLrecord; import org.eclipse.persistence.queries.DataModifyQuery; @@ -269,7 +269,7 @@ public void runQuery() { }; Struct struct = null; try { - struct = ((Oracle8Platform)s.getPlatform()).createStruct( + struct = ((OraclePlatform)s.getPlatform()).createStruct( "EMP_TYPE", attributes, ((DatabaseSessionImpl)s).getAccessor().getConnection()); } catch (SQLException e) { diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarDaylightSavingsTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarDaylightSavingsTest.java index 406e7383e19..de13f1f80d9 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarDaylightSavingsTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarDaylightSavingsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,19 +14,27 @@ // dminsky - initial API and implementation package org.eclipse.persistence.testing.tests.types; -import java.text.*; -import java.util.*; - -import oracle.sql.*; - -import org.eclipse.persistence.sessions.*; -import org.eclipse.persistence.descriptors.*; -import org.eclipse.persistence.expressions.*; -import org.eclipse.persistence.queries.*; -import org.eclipse.persistence.tools.schemaframework.*; -import org.eclipse.persistence.platform.database.oracle.*; - -import org.eclipse.persistence.testing.framework.*; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; +import java.util.Vector; + +import org.eclipse.persistence.descriptors.RelationalDescriptor; +import org.eclipse.persistence.expressions.Expression; +import org.eclipse.persistence.expressions.ExpressionBuilder; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.queries.ReadObjectQuery; +import org.eclipse.persistence.sessions.UnitOfWork; +import org.eclipse.persistence.testing.framework.QuerySQLTracker; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestErrorException; +import org.eclipse.persistence.testing.framework.TestWarningException; +import org.eclipse.persistence.tools.schemaframework.TableDefinition; + +import oracle.sql.TIMESTAMPTZ; /** * EL Bug 249500 - Daylight savings time is not printed in native SQL run against Oracle 9i and above @@ -137,6 +145,7 @@ public static List getTestCalendars() { return testCalendars; } + @Override public String toString() { return "Test #: " + getTestId() + " -> " + formatCalendarAsString(this.calendar); } @@ -152,11 +161,12 @@ public static Vector testInstancesWithNoBindingAndNativeSql() { return tests; } + @Override public void setup() { - if (!(getSession().getPlatform() instanceof Oracle9Platform)) { + if (!(getSession().getPlatform() instanceof Oracle11Platform)) { throw new TestWarningException("Test is only supported on Oracle9 platform and above, as TIMESTAMPTZ is used"); } - Oracle9Platform platform = (Oracle9Platform) getSession().getPlatform(); + Oracle11Platform platform = (Oracle11Platform) getSession().getPlatform(); this.oldBindingValue = platform.shouldBindAllParameters(); this.oldNativeSqlValue = platform.usesNativeSQL(); @@ -183,6 +193,7 @@ public void setup() { sqlTracker = new QuerySQLTracker(getSession()); } + @Override public void test() { // write myself out to the database UnitOfWork uow = getSession().acquireUnitOfWork(); @@ -203,6 +214,7 @@ public void test() { result = (CalendarDaylightSavingsTest)getSession().executeQuery(query); } + @Override public void verify() { final String TZR = "TZR"; final String TZR_TZD = "TZR TZD"; @@ -232,9 +244,10 @@ public void verify() { } } + @Override public void reset() { // Compatibility for Oracle 9 and above is checked in the setup() method - Oracle9Platform platform = (Oracle9Platform) getSession().getPlatform(); + Oracle11Platform platform = (Oracle11Platform) getSession().getPlatform(); platform.setUsesNativeSQL(this.oldNativeSqlValue); platform.setShouldBindAllParameters(this.oldBindingValue); // reset the SQL tracker diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarToTSTZWithBindingTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarToTSTZWithBindingTest.java index f71c9f8ce72..03c4f2173c1 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarToTSTZWithBindingTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/CalendarToTSTZWithBindingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,17 +14,24 @@ // ailitchev ported the original test written by dminsky package org.eclipse.persistence.testing.tests.types; -import java.text.*; -import java.util.*; - -import oracle.sql.*; - -import org.eclipse.persistence.descriptors.*; -import org.eclipse.persistence.sessions.*; -import org.eclipse.persistence.tools.schemaframework.*; -import org.eclipse.persistence.platform.database.oracle.*; - -import org.eclipse.persistence.testing.framework.*; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; +import java.util.Vector; + +import org.eclipse.persistence.descriptors.RelationalDescriptor; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.sessions.DatabaseRecord; +import org.eclipse.persistence.sessions.UnitOfWork; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestErrorException; +import org.eclipse.persistence.testing.framework.TestWarningException; +import org.eclipse.persistence.tools.schemaframework.TableDefinition; + +import oracle.sql.TIMESTAMPTZ; /** * Testcase for resolution of issues with TIMESTAMPTZ compatibility and correctness. @@ -120,6 +127,7 @@ public String getOriginalCalendarString() { return this.originalCalendarString; } + @Override public String toString() { return "Test #: " + getTestId() + " -> " + getOriginalCalendarString(); } @@ -140,11 +148,12 @@ public static Vector testInstancesWithBindingAndNoCalendarPrinting() { return tests; } + @Override public void setup() { - if (!(getSession().getPlatform() instanceof Oracle9Platform)) { + if (!(getSession().getPlatform() instanceof Oracle11Platform)) { throw new TestWarningException("Test is only supported on Oracle9 platform and above, as TIMESTAMPTZ is used"); } - Oracle9Platform platform = (Oracle9Platform) getSession().getPlatform(); + Oracle11Platform platform = (Oracle11Platform) getSession().getPlatform(); // this.oldPrintingValue = platform.getPrintCalendarIntoTimestampTZ(); this.oldBindingValue = platform.shouldBindAllParameters(); @@ -158,6 +167,7 @@ public void setup() { uow.commit(); } + @Override public void test() { // read data back from database literally in order to check contents of database rather than the driver's TIMESTAMPTZ String sql = "select TEST_ID, to_char(TSTZ_DATA,'MM/DD/YYYY hh24:mi:ss TZR') as TSTZ_DATA FROM " + commonDescriptor().getTableName() + " where TEST_ID = " + getTestId(); @@ -167,6 +177,7 @@ public void test() { } } + @Override public void verify() throws Exception { String expectedResult = getOriginalCalendarString(); if (this.result == null) { @@ -179,9 +190,10 @@ public void verify() throws Exception { } } + @Override public void reset() { // Compatibility for Oracle 9 and above is checked in the setup() method - Oracle9Platform platform = (Oracle9Platform) getSession().getPlatform(); + Oracle11Platform platform = (Oracle11Platform) getSession().getPlatform(); // platform.setPrintCalendarIntoTimestampTZ(this.oldPrintingValue); platform.setShouldBindAllParameters(this.oldBindingValue); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestModel.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestModel.java index 982efff75c7..07e84e451b0 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestModel.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -19,10 +19,10 @@ import org.eclipse.persistence.internal.helper.Helper; import org.eclipse.persistence.internal.sessions.AbstractSession; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.sessions.DatabaseSession; -import org.eclipse.persistence.testing.framework.*; -import org.eclipse.persistence.testing.tests.types.CalendarToTSTZWithoutSessionTZTest; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestSuite; public class OracleTIMESTAMPTypeTestModel extends org.eclipse.persistence.testing.framework.TestModel { protected boolean useAccessors; @@ -47,13 +47,15 @@ public OracleTIMESTAMPTypeTestModel(boolean usingAccessors) { } } + @Override public void addRequiredSystems() { addRequiredSystem(new OracleTIMESTAMPTypeTestSystem()); } + @Override public void addTests() { - if (getSession().getPlatform() instanceof Oracle9Platform) { - Oracle9Platform platform = (Oracle9Platform)getSession().getPlatform(); + if (getSession().getPlatform() instanceof Oracle11Platform) { + Oracle11Platform platform = (Oracle11Platform)getSession().getPlatform(); ((AbstractSession)getSession()).getAccessor().incrementCallCount((AbstractSession)getSession()); // unwrap connection if it's wrapped String driverVersion= platform.getDriverVersion(); @@ -267,16 +269,17 @@ public static TestSuite getCalendarDaylightSavingsTestSuite() { return suite; } + @Override public void setup() { DatabaseSession session = (DatabaseSession)getSession(); if (useAccessors) { - if (getSession().getPlatform() instanceof Oracle9Platform) { + if (getSession().getPlatform() instanceof Oracle11Platform) { session.addDescriptor(TIMESTAMPDirectToFieldTester.descriptorWithAccessors()); session.addDescriptor(CalendarToTSTZWithBindingTest.descriptorWithAccessors()); session.addDescriptor(CalendarDaylightSavingsTest.descriptorWithAccessors()); } } else { - if (getSession().getPlatform() instanceof Oracle9Platform) { + if (getSession().getPlatform() instanceof Oracle11Platform) { session.addDescriptor(TIMESTAMPDirectToFieldTester.descriptor()); session.addDescriptor(TIMESTAMPTypeConversionTester.descriptor()); session.addDescriptor(CalendarToTSTZWithoutSessionTZTest.descriptor()); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestSystem.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestSystem.java index 0e416973b1c..f3ae6683a5f 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestSystem.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/types/OracleTIMESTAMPTypeTestSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,17 +14,18 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.types; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; import org.eclipse.persistence.sessions.DatabaseSession; import org.eclipse.persistence.testing.framework.TestSystem; import org.eclipse.persistence.tools.schemaframework.SchemaManager; public class OracleTIMESTAMPTypeTestSystem extends TestSystem { + @Override public void createTables(DatabaseSession session) { SchemaManager schemaManager = new SchemaManager(session); - if (session.getPlatform() instanceof Oracle9Platform) { + if (session.getPlatform() instanceof Oracle11Platform) { schemaManager.replaceObject(TIMESTAMPDirectToFieldTester.tableDefinition(session)); schemaManager.replaceObject(TIMESTAMPTypeConversionTester.tableDefinition(session)); schemaManager.replaceObject(CalendarToTSTZWithoutSessionTZTest.tableDefinition(session)); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/Employee_XMLProject.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/Employee_XMLProject.java index 7b94d383c9f..35187bf5e46 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/Employee_XMLProject.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/Employee_XMLProject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,11 +14,13 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.xdb; -import org.eclipse.persistence.mappings.*; import org.eclipse.persistence.descriptors.RelationalDescriptor; +import org.eclipse.persistence.mappings.DirectToFieldMapping; +import org.eclipse.persistence.mappings.OneToManyMapping; +import org.eclipse.persistence.mappings.OneToOneMapping; +import org.eclipse.persistence.mappings.xdb.DirectToXMLTypeMapping; import org.eclipse.persistence.sessions.DatabaseLogin; import org.eclipse.persistence.sessions.Project; -import org.eclipse.persistence.mappings.xdb.DirectToXMLTypeMapping; public class Employee_XMLProject extends Project { public Employee_XMLProject() { @@ -39,7 +41,7 @@ public void initializeProject() { private void initializeLogin() { DatabaseLogin login = new DatabaseLogin(); - login.setPlatform(new org.eclipse.persistence.platform.database.oracle.Oracle9Platform()); + login.setPlatform(new org.eclipse.persistence.platform.database.oracle.Oracle11Platform()); login.setConnectionString("jdbc:oracle:oci8:@matt"); login.setDriverClassName("oracle.jdbc.OracleDriver"); login.setUserName("System"); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExistsNodeWithJoinTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExistsNodeWithJoinTest.java index cbbc1fa0ff9..19a8e098354 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExistsNodeWithJoinTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExistsNodeWithJoinTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,9 +14,11 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.xdb; -import org.eclipse.persistence.expressions.*; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; -import org.eclipse.persistence.testing.framework.*; +import org.eclipse.persistence.expressions.ExpressionBuilder; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestErrorException; +import org.eclipse.persistence.testing.framework.TestWarningException; public class ExistsNodeWithJoinTest extends TestCase { Employee_XML employee = null; @@ -25,19 +27,23 @@ public ExistsNodeWithJoinTest() { setDescription("Tests the use of the existsNode() function as well as testing use of XMLType in a join"); } + @Override public void setup() { - if (!(getSession().getPlatform() instanceof Oracle9Platform)) { + if (!(getSession().getPlatform() instanceof Oracle11Platform)) { throw new TestWarningException("This test is intended for the Oracle9Platform"); } } + @Override public void reset() { } + @Override public void test() { employee = (Employee_XML)getSession().readObject(Employee_XML.class, new ExpressionBuilder().get("manager").get("resume").existsNode("//education/degree").greaterThan(0)); } + @Override public void verify() { if ((employee == null) || !employee.firstName.equals("Frank")) { throw new TestErrorException("Wrong Employee returned:" + employee); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExtractValueTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExtractValueTest.java index 0de50a71d75..8e4e1e86015 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExtractValueTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/ExtractValueTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,9 +14,11 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.xdb; -import org.eclipse.persistence.expressions.*; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; -import org.eclipse.persistence.testing.framework.*; +import org.eclipse.persistence.expressions.ExpressionBuilder; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestErrorException; +import org.eclipse.persistence.testing.framework.TestWarningException; public class ExtractValueTest extends TestCase { Employee_XML employee = null; @@ -25,19 +27,23 @@ public ExtractValueTest() { setDescription("Tests the use of the extractVale function"); } + @Override public void setup() { - if (!(getSession().getPlatform() instanceof Oracle9Platform)) { + if (!(getSession().getPlatform() instanceof Oracle11Platform)) { throw new TestWarningException("This test is intended for the Oracle 9 platform"); } } + @Override public void reset() { } + @Override public void test() { employee = (Employee_XML)getSession().readObject(Employee_XML.class, new ExpressionBuilder().get("resume").extractValue("/resume/first-name/text()").equal("Bob")); } + @Override public void verify() { if ((employee == null) || !(employee.firstName.equals("Bob"))) { throw new TestErrorException("Wrong or No Employee returned"); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/GetNumberValTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/GetNumberValTest.java index 71cabe464ed..d371f1de25d 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/GetNumberValTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/GetNumberValTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,9 +14,11 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.xdb; -import org.eclipse.persistence.expressions.*; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; -import org.eclipse.persistence.testing.framework.*; +import org.eclipse.persistence.expressions.ExpressionBuilder; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestErrorException; +import org.eclipse.persistence.testing.framework.TestWarningException; public class GetNumberValTest extends TestCase { Employee_XML employee = null; @@ -25,19 +27,23 @@ public GetNumberValTest() { setDescription("Tests the use of the getNumberVal() function"); } + @Override public void setup() { - if (!(getSession().getPlatform() instanceof Oracle9Platform)) { + if (!(getSession().getPlatform() instanceof Oracle11Platform)) { throw new TestWarningException("This test is intended for the Oracle 9 Platform"); } } + @Override public void reset() { } + @Override public void test() { employee = (Employee_XML)getSession().readObject(Employee_XML.class, new ExpressionBuilder().get("resume").extractXml("/resume/age/text()").getNumberVal().equal(27)); } + @Override public void verify() { if ((employee == null) || !(employee.firstName.equals("Frank"))) { throw new TestErrorException("Wrong or No Employee returned"); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/UpdateDocumentTest.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/UpdateDocumentTest.java index c7efd58a3b7..5e85a2e5eb2 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/UpdateDocumentTest.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/UpdateDocumentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -14,24 +14,29 @@ // Oracle - initial API and implementation from Oracle TopLink package org.eclipse.persistence.testing.tests.xdb; -import org.w3c.dom.*; - -import org.eclipse.persistence.expressions.*; -import org.eclipse.persistence.platform.database.oracle.Oracle9Platform; -import org.eclipse.persistence.sessions.*; -import org.eclipse.persistence.testing.framework.*; +import org.eclipse.persistence.expressions.ExpressionBuilder; +import org.eclipse.persistence.platform.database.oracle.Oracle11Platform; +import org.eclipse.persistence.sessions.UnitOfWork; +import org.eclipse.persistence.testing.framework.TestCase; +import org.eclipse.persistence.testing.framework.TestErrorException; +import org.eclipse.persistence.testing.framework.TestWarningException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; public class UpdateDocumentTest extends TestCase { public UpdateDocumentTest() { setDescription("Tests updating an XMLType instance"); } + @Override public void setup() { - if (!(getSession().getPlatform() instanceof Oracle9Platform)) { + if (!(getSession().getPlatform() instanceof Oracle11Platform)) { throw new TestWarningException("This test is intended for the Oracle 9 Platform"); } } + @Override public void test() { UnitOfWork uow = getSession().acquireUnitOfWork(); Employee_XML emp = (Employee_XML)uow.readObject(Employee_XML.class, new ExpressionBuilder().get("firstName").equal("Frank")); @@ -47,6 +52,7 @@ public void test() { uow.commit(); } + @Override public void verify() { getSession().getIdentityMapAccessor().initializeAllIdentityMaps(); Employee_XML emp = (Employee_XML)getSession().readObject(Employee_XML.class, new ExpressionBuilder().get("firstName").equal("Frank")); diff --git a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/XDBTestModelMWIntegration.java b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/XDBTestModelMWIntegration.java index 9535aac7852..bb92ace9698 100644 --- a/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/XDBTestModelMWIntegration.java +++ b/foundation/org.eclipse.persistence.oracle.test/src/it/java/org/eclipse/persistence/testing/tests/xdb/XDBTestModelMWIntegration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -16,7 +16,9 @@ import org.eclipse.persistence.platform.database.DatabasePlatform; import org.eclipse.persistence.platform.database.OraclePlatform; -import org.eclipse.persistence.testing.framework.*; +import org.eclipse.persistence.testing.framework.TestModel; +import org.eclipse.persistence.testing.framework.TestProblemException; +import org.eclipse.persistence.testing.framework.TestSuite; public class XDBTestModelMWIntegration extends TestModel { DatabasePlatform oldPlatform = null; @@ -25,10 +27,12 @@ public XDBTestModelMWIntegration() { setDescription("Tests Oracle XDB Specific features"); } + @Override public void addTests() { addTest(getXDBTestSuite()); } + @Override public void reset() { this.getSession().getLogin().setPlatform(oldPlatform); getDatabaseSession().logout(); @@ -49,13 +53,14 @@ public static TestSuite getXDBTestSuite() { return testSuite; } + @Override public void addForcedRequiredSystems() { addForcedRequiredSystem(new XMLTypeEmployeeSystemXML()); oldPlatform = getSession().getPlatform(); if (!(oldPlatform instanceof OraclePlatform)) { throw new TestProblemException("This model is intended for Oracle databases through OCI"); } - this.getSession().getLogin().setPlatform(new org.eclipse.persistence.platform.database.oracle.Oracle9Platform()); + this.getSession().getLogin().setPlatform(new org.eclipse.persistence.platform.database.oracle.Oracle11Platform()); getDatabaseSession().logout(); getDatabaseSession().login(); try { diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/module-info.java b/foundation/org.eclipse.persistence.oracle/src/main/java/module-info.java index 2b38e7ac07a..e1cc26e726f 100644 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/module-info.java +++ b/foundation/org.eclipse.persistence.oracle/src/main/java/module-info.java @@ -11,6 +11,9 @@ */ module org.eclipse.persistence.oracle { + requires java.sql; +// requires ojdbc8; + requires org.eclipse.persistence.core; exports org.eclipse.persistence.platform.database.oracle; diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/internal/platform/database/oracle/TIMESTAMPHelper.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/internal/platform/database/oracle/TIMESTAMPHelper.java index 22b0393f77b..7e1f3e1e245 100644 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/internal/platform/database/oracle/TIMESTAMPHelper.java +++ b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/internal/platform/database/oracle/TIMESTAMPHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -15,11 +15,17 @@ package org.eclipse.persistence.internal.platform.database.oracle; import java.io.StringWriter; -import java.sql.*; -import java.util.*; -import oracle.sql.*; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.TimeZone; + import org.eclipse.persistence.internal.helper.Helper; +import oracle.sql.TIMESTAMPTZ; +import oracle.sql.ZONEIDMAP; + /** * Used as a helper class for TIMESTAMP, TIMESTAMPTZ and TIMESTAMPLTZ in oracle9. */ diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle10Platform.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle10Platform.java deleted file mode 100644 index b97c762a57b..00000000000 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle10Platform.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -// Contributors: -// Oracle - initial API and implementation from Oracle TopLink -package org.eclipse.persistence.platform.database.oracle; - -import java.sql.Statement; - -import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; - -import oracle.jdbc.OraclePreparedStatement; - -/** - *

Purpose: - * Supports usage of certain Oracle JDBC specific APIs. - */ -public class Oracle10Platform extends Oracle9Platform { - - public Oracle10Platform(){ - super(); - } - - /** - * Build the hint string used for first rows. - * - * Allows it to be overridden - * @param max - * @return - */ - @Override - protected String buildFirstRowsHint(int max){ - //bug 374136: override setting the FIRST_ROWS hint as this is not needed on Oracle10g - return ""; - } - - /** - * Internal: This gets called on each batch statement execution - * Needs to be implemented so that it returns the number of rows successfully modified - * by this statement for optimistic locking purposes (if useNativeBatchWriting is enabled, and - * the call uses optimistic locking). - * - * @param isStatementPrepared - flag is set to true if this statement is prepared - * @return - number of rows modified/deleted by this statement - */ - @Override - public int executeBatch(Statement statement, boolean isStatementPrepared) throws java.sql.SQLException { - if (usesNativeBatchWriting() && isStatementPrepared) { - int rowCount = 0; - try { - rowCount = ((OraclePreparedStatement)statement).sendBatch(); - } finally { - ((OraclePreparedStatement) statement).setExecuteBatch(1); - } - return rowCount; - } else { - @SuppressWarnings("unused") - int[] results = statement.executeBatch(); - return statement.getUpdateCount(); - } - } - - /** - * INTERNAL: - * Indicate whether app. server should unwrap connection - * to use lob locator. - * No need to unwrap connection because - * writeLob method doesn't use oracle proprietary classes. - */ - @Override - public boolean isNativeConnectionRequiredForLobLocator() { - return false; - } - - /** - * INTERNAL: - * Supports Batch Writing with Optimistic Locking. - */ - @Override - public boolean canBatchWriteWithOptimisticLocking(DatabaseCall call){ - return true;//usesNativeBatchWriting || !call.hasParameters(); - } -} diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle11Platform.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle11Platform.java index 90c114f650d..6a78aaa33ae 100644 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle11Platform.java +++ b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle11Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -12,16 +12,996 @@ // Contributors: // Oracle - initial API and implementation from Oracle TopLink +// 09/14/2011-2.3.1 Guy Pelletier +// - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU package org.eclipse.persistence.platform.database.oracle; +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.Constructor; +import java.security.AccessController; +import java.sql.Array; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Struct; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Calendar; +import java.util.Date; +import java.util.Hashtable; +import java.util.Map; +import java.util.TimeZone; +import java.util.Vector; + +import org.eclipse.persistence.config.PersistenceUnitProperties; +import org.eclipse.persistence.exceptions.ConversionException; +import org.eclipse.persistence.exceptions.DatabaseException; +import org.eclipse.persistence.exceptions.QueryException; +import org.eclipse.persistence.internal.databaseaccess.Accessor; +import org.eclipse.persistence.internal.databaseaccess.BindCallCustomParameter; +import org.eclipse.persistence.internal.databaseaccess.ConnectionCustomizer; +import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; +import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; +import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition; +import org.eclipse.persistence.internal.databaseaccess.Platform; +import org.eclipse.persistence.internal.expressions.SpatialExpressionOperators; +import org.eclipse.persistence.internal.helper.ClassConstants; +import org.eclipse.persistence.internal.helper.DatabaseField; +import org.eclipse.persistence.internal.helper.Helper; +import org.eclipse.persistence.internal.platform.database.XMLTypePlaceholder; +import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPHelper; +import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPLTZWrapper; +import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPTZWrapper; +import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPTypes; +import org.eclipse.persistence.internal.platform.database.oracle.XMLTypeFactory; +import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; +import org.eclipse.persistence.internal.security.PrivilegedClassForName; +import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor; +import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor; +import org.eclipse.persistence.internal.sessions.AbstractSession; +import org.eclipse.persistence.platform.database.OraclePlatform; +import org.eclipse.persistence.queries.Call; +import org.eclipse.persistence.queries.ValueReadQuery; + +import oracle.jdbc.OracleBlob; +import oracle.jdbc.OracleClob; +import oracle.jdbc.OracleConnection; +import oracle.jdbc.OracleOpaque; +import oracle.jdbc.OraclePreparedStatement; +import oracle.jdbc.OracleTypes; +import oracle.sql.TIMESTAMP; +import oracle.sql.TIMESTAMPLTZ; +import oracle.sql.TIMESTAMPTZ; + /** *

Purpose: - * Supports usage of certain Oracle JDBC specific APIs for the Oracle 11 database. + * Supports usage of certain Oracle JDBC specific APIs. + *

Supports Oracle thin JDBC driver LOB >4k binding workaround. + *

Creates BLOB and CLOB type for byte[] and char[] for table creation. + *

Supports object-relational data-type creation. + *

Supports binding NCHAR, NVARCHAR, NCLOB types as required by Oracle JDBC drivers. + *

Supports Oracle JDBC TIMESTAMP, TIMESTAMPTZ, TIMESTAMPLTZ types. */ -public class Oracle11Platform extends Oracle10Platform { - public Oracle11Platform() { +public class Oracle11Platform extends OraclePlatform { + + public static final Class NCHAR = NCharacter.class; + public static final Class NSTRING = NString.class; + public static final Class NCLOB = NClob.class; + public static final Class XMLTYPE = XMLTypePlaceholder.class; + + /* Driver version set to connection.getMetaData.getDriverVersion() */ + protected transient String driverVersion; + /* Indicates whether printCalendar should be used when creating TIMESTAMPTZ. + * Bug5614674. It used to be a driver bug and Helper.printCalendar(cal, false) was used to make it work. + * It has been fixed in 11. Separate the newer version from the old ones. + * */ + protected transient boolean shouldPrintCalendar; + /* Indicates whether TIMESTAMPTZ.timestampValue returns Timestamp in GMT. + * The flag is set to false unless + * Oracle jdbc version is 11.1.0.7 or later and + * OracleConnection's "oracle.jdbc.timestampTzInGmt" property is set to "true". + * Though the property is defined per connection it is safe to assume that all connections + * used with the platform are identical because they all created by the same DatabaseLogin + * with the same properties. + * */ + protected transient boolean isTimestampInGmt; + /* Indicates whether TIMESTAMPLTZ.toTimestamp returns Timestamp in GMT. + * true for version 11.2.0.2 or later. + */ + protected transient boolean isLtzTimestampInGmt; + /* Indicates whether driverVersion, shouldPrintCalendar, isTimestampInGmt have been initialized. + * To re-initialize connection data call clearConnectionData method. + */ + protected transient boolean isConnectionDataInitialized; + + /** Indicates whether time component of java.sql.Date should be truncated (hours, minutes, seconds all set to zero) + * before been passed as a parameter to PreparedStatement. + * Starting with version 12.1 oracle jdbc Statement.setDate no longer zeroes sql.Date's entire time component (only milliseconds). + * Set this flag to true to make the platform to truncate days/hours/minutes before passing the date to Statement.setDate method. + */ + protected boolean shouldTruncateDate; + + private XMLTypeFactory xmlTypeFactory; + + /** User name retrieved from JDBC connection in {@link #initializeConnectionData(Connection)}. */ + private transient String connectionUserName; + + /** + * Please ensure that following declarations stay as it is. Having them ensures that oracle jdbc driver available + * in classpath when this class loaded. + * If driver is not available, this class will not be initialized and will fail fast instead of failing later on + * when classes from driver are utilized + */ + private static final Class ORACLE_SQL_TIMESTAMP = oracle.sql.TIMESTAMP.class; + private static final Class ORACLE_SQL_TIMESTAMPTZ = oracle.sql.TIMESTAMPTZ.class; + private static final Class ORACLE_SQL_TIMESTAMPLTZ = oracle.sql.TIMESTAMPLTZ.class; + + + public Oracle11Platform(){ super(); - // Locator is no longer required to write LOB values - usesLocatorForLOBWrite = false; + connectionUserName = null; + } + + /** + * INTERNAL: + * This class used for binding of NCHAR, NSTRING, NCLOB types. + */ + protected static class NTypeBindCallCustomParameter extends BindCallCustomParameter { + public NTypeBindCallCustomParameter(Object obj) { + super(obj); + } + //Bug5200836, use unwrapped connection if it is NType parameter. + @Override + public boolean shouldUseUnwrappedConnection() { + return true; + } + + /** + * INTERNAL: + * Binds the custom parameter (obj) into the passed PreparedStatement + * for the passed DatabaseCall. + * Note that parameter numeration for PreparedStatement starts with 1, + * therefore statement.set...(index + 1, ...) should be used. + * DatabaseCall will carry this object as its parameter: call.getParameters().elementAt(index). + * The reason for passing DatabaseCall and DatabasePlatform into this method + * is that this method may set obj as a new value of index parameter: + * call.getParameters().setElementAt(obj, index); + * and call again the method which has called it: + * platform.setParameterValueInDatabaseCall(call, statement, index); + * so obj will be bound. + * + * Called only by DatabasePlatform.setParameterValueInDatabaseCall method + */ + @Override + public void set(DatabasePlatform platform, PreparedStatement statement, int index, AbstractSession session) throws SQLException { + // Binding starts with a 1 not 0. Make sure that index > 0 + ((oracle.jdbc.OraclePreparedStatement)statement).setFormOfUse(index, oracle.jdbc.OraclePreparedStatement.FORM_NCHAR); + + super.set(platform, statement, index, session); + } + } + + /** + * Copy the state into the new platform. + */ + @Override + public void copyInto(Platform platform) { + super.copyInto(platform); + if (!(platform instanceof Oracle11Platform)) { + return; + } + Oracle11Platform oracle11Platform = (Oracle11Platform)platform; + oracle11Platform.setShouldTruncateDate(shouldTruncateDate()); + } + + /** + * INTERNAL: + * Get a timestamp value from a result set. + * Overrides the default behavior to specifically return a timestamp. Added + * to overcome an issue with the oracle 9.0.1.4 JDBC driver. + */ + @Override + public Object getObjectFromResultSet(ResultSet resultSet, int columnNumber, int type, AbstractSession session) throws java.sql.SQLException { + //Bug#3381652 10G Drivers return sql.Date instead of timestamp on DATE field + if ((type == Types.TIMESTAMP) || (type == Types.DATE)) { + return resultSet.getTimestamp(columnNumber); + } else if (type == oracle.jdbc.OracleTypes.TIMESTAMPTZ) { + return getTIMESTAMPTZFromResultSet(resultSet, columnNumber, type, session); + } else if (type == oracle.jdbc.OracleTypes.TIMESTAMPLTZ) { + return getTIMESTAMPLTZFromResultSet(resultSet, columnNumber, type, session); + } else if (type == OracleTypes.ROWID) { + return resultSet.getString(columnNumber); + } else if (type == Types.SQLXML) { + SQLXML sqlXml = resultSet.getSQLXML(columnNumber); + String str = null; + if (sqlXml != null) { + str = sqlXml.getString(); + sqlXml.free(); + } + // Oracle 12c appends a \n character to the xml string + return (str != null && str.endsWith("\n")) ? str.substring(0, str.length() - 1) : str; + } else if (type == OracleTypes.OPAQUE) { + try { + Object result = resultSet.getObject(columnNumber); + if (!(result instanceof OracleOpaque)) { + // Report Queries can cause result to not be an instance of OPAQUE. + return result; + } else { + return getXMLTypeFactory().getString((OracleOpaque) result); + } + } catch (SQLException ex) { + throw DatabaseException.sqlException(ex, null, session, false); + } + } else { + return super.getObjectFromResultSet(resultSet, columnNumber, type, session); + } + } + + /** + * INTERNAL: + * Get a TIMESTAMPTZ value from a result set. + */ + public Object getTIMESTAMPTZFromResultSet(ResultSet resultSet, int columnNumber, int type, AbstractSession session) throws java.sql.SQLException { + TIMESTAMPTZ tsTZ = (TIMESTAMPTZ)resultSet.getObject(columnNumber); + //Need to call timestampValue once here with the connection to avoid null point + //exception later when timestampValue is called in converObject() + if ((tsTZ != null) && (tsTZ.getLength() != 0)) { + Connection connection = getConnection(session, resultSet.getStatement().getConnection()); + //Bug#4364359 Add a wrapper to overcome TIMESTAMPTZ not serializable as of jdbc 9.2.0.5 and 10.1.0.2. + //It has been fixed in the next version for both streams + Timestamp timestampToWrap = tsTZ.timestampValue(connection); + TimeZone timezoneToWrap = TIMESTAMPHelper.extractTimeZone(tsTZ.toBytes()); + return new TIMESTAMPTZWrapper(timestampToWrap, timezoneToWrap, this.isTimestampInGmt); + } + return null; + } + + /** + * INTERNAL: + * Get a TIMESTAMPLTZ value from a result set. + */ + public Object getTIMESTAMPLTZFromResultSet(ResultSet resultSet, int columnNumber, int type, AbstractSession session) throws java.sql.SQLException { + //TIMESTAMPLTZ needs to be converted to Timestamp here because it requires the connection. + //However the java object is not know here. The solution is to store Timestamp and the + //session timezone in a wrapper class, which will be used later in converObject(). + TIMESTAMPLTZ tsLTZ = (TIMESTAMPLTZ)resultSet.getObject(columnNumber); + if ((tsLTZ != null) && (tsLTZ.getLength() != 0)) { + Connection connection = getConnection(session, resultSet.getStatement().getConnection()); + Timestamp timestampToWrap = TIMESTAMPLTZ.toTimestamp(connection, tsLTZ.toBytes()); + String sessionTimeZone = ((OracleConnection)connection).getSessionTimeZone(); + //Bug#4364359 Add a separate wrapper for TIMESTAMPLTZ. + return new TIMESTAMPLTZWrapper(timestampToWrap, sessionTimeZone, this.isLtzTimestampInGmt); + } + return null; + } + + /** + * INTERNAL + * Used by SQLCall.appendModify(..) + * If the field should be passed to customModifyInDatabaseCall, retun true, + * otherwise false. + * Methods shouldCustomModifyInDatabaseCall and customModifyInDatabaseCall should be + * kept in sync: shouldCustomModifyInDatabaseCall should return true if and only if the field + * is handled by customModifyInDatabaseCall. + */ + @Override + public boolean shouldUseCustomModifyForCall(DatabaseField field) { + Class type = field.getType(); + if ((type != null) && isOracle9Specific(type)) { + return true; + } + return super.shouldUseCustomModifyForCall(field); + } + + /** + * INTERNAL: + * Allow the use of XMLType operators on this platform. + */ + @Override + protected void initializePlatformOperators() { + super.initializePlatformOperators(); + addOperator(SpatialExpressionOperators.withinDistance()); + addOperator(SpatialExpressionOperators.relate()); + addOperator(SpatialExpressionOperators.filter()); + addOperator(SpatialExpressionOperators.nearestNeighbor()); + } + + /** + * INTERNAL: + * Add XMLType as the default database type for org.w3c.dom.Documents. + * Add TIMESTAMP, TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE + */ + @Override + protected Hashtable buildFieldTypes() { + Hashtable fieldTypes = super.buildFieldTypes(); + fieldTypes.put(org.w3c.dom.Document.class, new FieldTypeDefinition("sys.XMLType")); + //Bug#3381652 10g database does not accept Time for DATE field + fieldTypes.put(ORACLE_SQL_TIMESTAMP, new FieldTypeDefinition("TIMESTAMP", false)); + fieldTypes.put(ORACLE_SQL_TIMESTAMPTZ, new FieldTypeDefinition("TIMESTAMP WITH TIME ZONE", false)); + fieldTypes.put(ORACLE_SQL_TIMESTAMPLTZ, new FieldTypeDefinition("TIMESTAMP WITH LOCAL TIME ZONE", false)); + + return fieldTypes; + } + + /** + * INTERNAL: + * Add TIMESTAMP, TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE + */ + @Override + protected Map buildClassTypes() { + Map classTypeMapping = super.buildClassTypes(); + classTypeMapping.put("TIMESTAMP", ORACLE_SQL_TIMESTAMP); + classTypeMapping.put("TIMESTAMP WITH TIME ZONE", ORACLE_SQL_TIMESTAMPTZ); + classTypeMapping.put("TIMESTAMP WITH LOCAL TIME ZONE", ORACLE_SQL_TIMESTAMPLTZ); + return classTypeMapping; + } + + @Override + public Object clone() { + Oracle11Platform clone = (Oracle11Platform)super.clone(); + clone.clearConnectionData(); + return clone; + } + + /** + * INTERNAL: + * Allow for conversion from the Oracle type to the Java type. + */ + @Override + public Object convertObject(Object sourceObject, Class javaClass) throws ConversionException, DatabaseException { + if ((javaClass == null) || ((sourceObject != null) && (sourceObject.getClass() == javaClass))) { + return sourceObject; + } + if (sourceObject == null) { + return super.convertObject(sourceObject, javaClass); + } + + Object valueToConvert = sourceObject; + + //Used in Type Conversion Mapping on write + if ((javaClass == TIMESTAMPTypes.TIMESTAMP_CLASS) || (javaClass == TIMESTAMPTypes.TIMESTAMPLTZ_CLASS)) { + return sourceObject; + } + + if (javaClass == TIMESTAMPTypes.TIMESTAMPTZ_CLASS) { + if (sourceObject instanceof java.util.Date) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(((java.util.Date)sourceObject).getTime()); + return cal; + } else { + return sourceObject; + } + } + + if (javaClass == XMLTYPE) { + //Don't convert to XMLTypes. This will be done by the + //XMLTypeBindCallCustomParameter to ensure the correct + //Connection is used + return sourceObject; + } + + //Added to overcome an issue with the oracle 9.0.1.1.0 JDBC driver. + if (sourceObject instanceof TIMESTAMP) { + try { + valueToConvert = ((TIMESTAMP)sourceObject).timestampValue(); + } catch (SQLException exception) { + throw DatabaseException.sqlException(exception); + } + } else if (sourceObject instanceof TIMESTAMPTZWrapper) { + //Bug#4364359 Used when database type is TIMESTAMPTZ. Timestamp and session timezone are wrapped + //in TIMESTAMPTZWrapper. Separate Calendar from any other types. + if (((javaClass == ClassConstants.CALENDAR) || (javaClass == ClassConstants.GREGORIAN_CALENDAR))) { + try { + return TIMESTAMPHelper.buildCalendar((TIMESTAMPTZWrapper)sourceObject); + } catch (SQLException exception) { + throw DatabaseException.sqlException(exception); + } + } else { + //If not using native sql, Calendar will be converted to Timestamp just as + //other date time types + valueToConvert = ((TIMESTAMPTZWrapper)sourceObject).getTimestamp(); + } + } else if (sourceObject instanceof TIMESTAMPLTZWrapper) { + //Bug#4364359 Used when database type is TIMESTAMPLTZ. Timestamp and session timezone id are wrapped + //in TIMESTAMPLTZWrapper. Separate Calendar from any other types. + if (((javaClass == ClassConstants.CALENDAR) || (javaClass == ClassConstants.GREGORIAN_CALENDAR))) { + try { + return TIMESTAMPHelper.buildCalendar((TIMESTAMPLTZWrapper)sourceObject); + } catch (SQLException exception) { + throw DatabaseException.sqlException(exception); + } + } else { + //If not using native sql, Calendar will be converted to Timestamp just as + //other date time types + valueToConvert = ((TIMESTAMPLTZWrapper)sourceObject).getTimestamp(); + } + } + + return super.convertObject(valueToConvert, javaClass); + } + + /** + * INTERNAL: + * Appends an Oracle specific Timestamp with timezone and daylight time + * elements if usesNativeSQL is true, otherwise use the ODBC format. + * Native Format: + * (DST) to_timestamp_tz ('1997-11-06 10:35:45.345 America/Los_Angeles','yyyy-mm-dd hh:mm:ss.ff TZR TZD') + * (non-DST) to_timestamp_tz ('1997-11-06 10:35:45.345 America/Los_Angeles','yyyy-mm-dd hh:mm:ss.ff TZR') + */ + @Override + protected void appendCalendar(Calendar calendar, Writer writer) throws IOException { + if (usesNativeSQL()) { + writer.write("to_timestamp_tz('"); + writer.write(TIMESTAMPHelper.printCalendar(calendar)); + // append TZD element if the calendar's timezone is in daylight time + if (TIMESTAMPHelper.shouldAppendDaylightTime(calendar)) { + writer.write("','yyyy-mm-dd HH24:MI:SS.FF TZR TZD')"); + } else { + writer.write("','yyyy-mm-dd HH24:MI:SS.FF TZR')"); + } + } else { + super.appendCalendar(calendar, writer); + } + } + + /** + * INTERNAL: + */ + @Override + public void initializeConnectionData(Connection connection) throws SQLException { + if (this.isConnectionDataInitialized || (connection == null) || (connection.getMetaData() == null)) { + return; + } + this.driverVersion = connection.getMetaData().getDriverVersion(); + // printCalendar for versions greater or equal 9 and less than 10.2.0.4 + this.shouldPrintCalendar = Helper.compareVersions("9", this.driverVersion) <= 0 && Helper.compareVersions(this.driverVersion, "10.2.0.4") < 0; + if (Helper.compareVersions(this.driverVersion, "11.1.0.7") >= 0) { + if( connection instanceof OracleConnection ) { + final OracleConnection oraConn = (OracleConnection)connection; + String timestampTzInGmtPropStr = oraConn.getProperties().getProperty("oracle.jdbc.timestampTzInGmt", "true"); + this.connectionUserName = oraConn.getUserName(); + this.isTimestampInGmt = timestampTzInGmtPropStr.equalsIgnoreCase("true"); + } else { + this.connectionUserName = connection.getMetaData().getUserName(); + this.isTimestampInGmt = true; + } + if (Helper.compareVersions(this.driverVersion, "11.2.0.2") >= 0) { + this.isLtzTimestampInGmt = true; + } + } + this.isConnectionDataInitialized = true; + } + + public void clearConnectionData() { + this.driverVersion = null; + this.isConnectionDataInitialized = false; + } + + /** + * INTERNAL: + * Clears both implicit and explicit caches of OracleConnection + */ + @Override + public void clearOracleConnectionCache(Connection conn) { + if(conn instanceof OracleConnection){ + OracleConnection oracleConnection = (OracleConnection)conn; + try { + if(oracleConnection.getImplicitCachingEnabled()) { + oracleConnection.purgeImplicitCache(); + } + } catch(SQLException ex) { + // ignore + } + try { + if(oracleConnection.getExplicitCachingEnabled()) { + oracleConnection.purgeExplicitCache(); + } + } catch(SQLException ex) { + // ignore + } + } + } + + /** + * INTERNAL: + * Note that index (not index+1) is used in statement.setObject(index, parameter) + * Binding starts with a 1 not 0, so make sure that index > 0. + * Treat Calendar separately. Bind Calendar as TIMESTAMPTZ. + */ + @Override + public void setParameterValueInDatabaseCall(Object parameter, PreparedStatement statement, int index, AbstractSession session) throws SQLException { + if (parameter instanceof Calendar) { + Calendar calendar = (Calendar)parameter; + Connection conn = getConnection(session, statement.getConnection()); + TIMESTAMPTZ tsTZ = TIMESTAMPHelper.buildTIMESTAMPTZ(calendar, conn, this.shouldPrintCalendar); + statement.setObject(index, tsTZ); + } else if (this.shouldTruncateDate && parameter instanceof java.sql.Date) { + // hours, minutes, seconds all set to zero + statement.setDate(index, Helper.truncateDateIgnoreMilliseconds((java.sql.Date)parameter)); + } else { + super.setParameterValueInDatabaseCall(parameter, statement, index, session); + } + } + + /** + * INTERNAL: + * Answer the timestamp from the server. Convert TIMESTAMPTZ to Timestamp + */ + @Override + public java.sql.Timestamp getTimestampFromServer(AbstractSession session, String sessionName) { + if (getTimestampQuery() != null) { + getTimestampQuery().setSessionName(sessionName); + Object ob = session.executeQuery(getTimestampQuery()); + return ((TIMESTAMPTZWrapper)ob).getTimestamp(); + } + return super.getTimestampFromServer(session, sessionName); + } + + /** + * INTERNAL: + * This method returns the query to select the SYSTIMESTAMP as TIMESTAMPTZ + * from the server for Oracle9i. + */ + @Override + public ValueReadQuery getTimestampQuery() { + if (timestampQuery == null) { + timestampQuery = new ValueReadQuery(); + timestampQuery.setSQLString("SELECT SYSTIMESTAMP FROM DUAL"); + timestampQuery.setAllowNativeSQLQuery(true); + } + return timestampQuery; + } + + /** + * INTERNAL: + * Return the current SYSTIMESTAMP as TIMESTAMPTZ from the server. + */ + @Override + public String serverTimestampString() { + return "SYSTIMESTAMP"; + } + + protected Vector buildToTIMESTAMPVec() { + Vector vec = new Vector(); + vec.addElement(java.util.Date.class); + vec.addElement(Timestamp.class); + vec.addElement(Calendar.class); + vec.addElement(String.class); + vec.addElement(Long.class); + vec.addElement(Date.class); + vec.addElement(Time.class); + return vec; + } + + protected Vector buildToNStringCharVec() { + Vector vec = new Vector(); + vec.addElement(String.class); + vec.addElement(Character.class); + return vec; } + + protected Vector buildToNClobVec() { + Vector vec = new Vector(); + vec.addElement(String.class); + vec.addElement(Character[].class); + vec.addElement(char[].class); + return vec; + } + + /** + * INTERNAL: + * Return if the type is a special oracle type. + * bug 3325122 - just checking against the 4 classes is faster than isAssignableFrom MWN. + */ + protected boolean isOracle9Specific(Class type) { + return (type == NCHAR) || (type == NSTRING) || (type == NCLOB) || (type == XMLTYPE); + } + + /** + * INTERNAL: + * Used in write LOB method only to identify a CLOB. + */ + @Override + protected boolean isClob(Class type) { + return NCLOB.equals(type) || super.isClob(type); + } + + /** + * INTERNAL: + * Used by SQLCall.translate(..) + * The binding *must* be performed (NCHAR, NSTRING, NCLOB). + * In these special cases the method returns a wrapper object + * which knows whether it should be bound or appended and knows how to do that. + */ + @Override + public Object getCustomModifyValueForCall(Call call, Object value, DatabaseField field, boolean shouldBind) { + Class type = field.getType(); + if ((type != null) && isOracle9Specific(type)) { + if(value == null) { + return null; + } + if (NCHAR.equals(type) || NSTRING.equals(type)) { + return new NTypeBindCallCustomParameter(value); + } else if (NCLOB.equals(type)) { + value = convertToDatabaseType(value); + if (shouldUseLocatorForLOBWrite()) { + if (lobValueExceedsLimit(value)) { + ((DatabaseCall)call).addContext(field, value); + value = new String(" "); + } + } + return new NTypeBindCallCustomParameter(value); + } else if (XMLTYPE.equals(type)) { + return getXMLTypeFactory().createXMLTypeBindCallCustomParameter(value); + } + } + return super.getCustomModifyValueForCall(call, value, field, shouldBind); + } + + protected Vector buildFromStringCharVec(Class javaClass) { + Vector vec = getConversionManager().getDataTypesConvertedFrom(javaClass); + vec.addElement(NCHAR); + vec.addElement(NSTRING); + if (javaClass == String.class) { + vec.addElement(NCLOB); + } + return vec; + } + + /** + * INTERNAL: + * Return the list of Classes that can be converted to from the passed in javaClass. + * oracle.sql.TIMESTAMP and NCHAR types are added in some lists. + * @param javaClass - the class that is converted from + * @return - a vector of classes + */ + @Override + public Vector getDataTypesConvertedFrom(Class javaClass) { + if (dataTypesConvertedFromAClass == null) { + dataTypesConvertedFromAClass = new Hashtable(5); + } + Vector dataTypes = (Vector) dataTypesConvertedFromAClass.get(javaClass); + if (dataTypes != null) { + return dataTypes; + } + dataTypes = super.getDataTypesConvertedFrom(javaClass); + if ((javaClass == String.class) || (javaClass == Character.class)) { + dataTypes.addElement(NCHAR); + dataTypes.addElement(NSTRING); + if (javaClass == String.class) { + dataTypes.addElement(NCLOB); + } + } + if ((javaClass == char[].class) || (javaClass == Character[].class)) { + dataTypes.addElement(NCLOB); + } + dataTypesConvertedFromAClass.put(javaClass, dataTypes); + return dataTypes; + } + + /** + * INTERNAL: + * Return the list of Classes that can be converted from to the passed in javaClass. + * A list is added for oracle.sql.TIMESTAMP and NCHAR types. + * @param javaClass - the class that is converted to + * @return - a vector of classes + */ + @Override + public Vector getDataTypesConvertedTo(Class javaClass) { + if (dataTypesConvertedToAClass == null) { + dataTypesConvertedToAClass = new Hashtable(5); + } + Vector dataTypes = (Vector) dataTypesConvertedToAClass.get(javaClass); + if (dataTypes != null) { + return dataTypes; + } + if ((javaClass == NCHAR) || (javaClass == NSTRING)) { + dataTypes = buildToNStringCharVec(); + } else if (javaClass == NCLOB) { + dataTypes = buildToNClobVec(); + } else { + dataTypes = super.getDataTypesConvertedTo(javaClass); + } + dataTypesConvertedToAClass.put(javaClass, dataTypes); + return dataTypes; + } + + + /** + * Return the JDBC type for the given database field to be passed to Statement.setNull + * The Oracle driver does not like the OPAQUE type so VARCHAR must be used. + */ + @Override + public int getJDBCTypeForSetNull(DatabaseField field) { + int type = getJDBCType(field); + if (type == OracleTypes.OPAQUE || type == Types.SQLXML) { + // VARCHAR seems to work, driver does not like OPAQUE. + return java.sql.Types.VARCHAR; + } + return type; + } + + /** + * Return the JDBC type for the Java type. + * The Oracle driver does not like the OPAQUE type so VARCHAR must be used. + */ + @Override + public int getJDBCType(Class javaType) { + if (javaType == XMLTYPE) { + //return OracleTypes.OPAQUE; + // VARCHAR seems to work... + return java.sql.Types.VARCHAR; + } + return super.getJDBCType(javaType); + } + + /** + * INTERNAL: This gets called on each batch statement execution + * Needs to be implemented so that it returns the number of rows successfully modified + * by this statement for optimistic locking purposes (if useNativeBatchWriting is enabled, and + * the call uses optimistic locking). + * + * @param isStatementPrepared - flag is set to true if this statement is prepared + * @return - number of rows modified/deleted by this statement + */ + @Override + public int executeBatch(Statement statement, boolean isStatementPrepared) throws SQLException { + if (usesNativeBatchWriting() && isStatementPrepared) { + int rowCount = 0; + try { + rowCount = ((OraclePreparedStatement)statement).sendBatch(); + } finally { + ((OraclePreparedStatement) statement).setExecuteBatch(1); + } + return rowCount; + } else { + @SuppressWarnings("unused") + int[] results = statement.executeBatch(); + return statement.getUpdateCount(); + } + } + + /** + * INTERNAL: This gets called on each iteration to add parameters to the batch + * Needs to be implemented so that it returns the number of rows successfully modified + * by this statement for optimistic locking purposes (if useNativeBatchWriting is enabled, and + * the call uses optimistic locking). Is used with parameterized SQL + * + * @return - number of rows modified/deleted by this statement if it was executed (0 if it wasn't) + */ + @Override + public int addBatch(PreparedStatement statement) throws java.sql.SQLException { + if (usesNativeBatchWriting()){ + return statement.executeUpdate(); + }else{ + return super.addBatch(statement); + } + } + + /** + * INTERNAL: Allows setting the batch size on the statement + * Is used with parameterized SQL, and should only be passed in prepared statements + * + * @return - statement to be used for batch writing + */ + @Override + public Statement prepareBatchStatement(Statement statement, int maxBatchWritingSize) throws java.sql.SQLException { + if (usesNativeBatchWriting()){ + //add max statement setting + ((OraclePreparedStatement) statement).setExecuteBatch(maxBatchWritingSize); + } + return statement; + } + + /** + * INTERNAL: + * Lazy initialization of xmlTypeFactory allows to avoid loading xdb-dependent + * class XMLTypeFactoryImpl unless xdb is used. + * @return XMLTypeFactory + */ + protected XMLTypeFactory getXMLTypeFactory() { + if(xmlTypeFactory == null) { + String className = "org.eclipse.persistence.internal.platform.database.oracle.xdb.XMLTypeFactoryImpl"; + try { + if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ + Class xmlTypeFactoryClass = AccessController.doPrivileged(new PrivilegedClassForName(className, true, this.getClass().getClassLoader())); + Constructor xmlTypeFactoryConstructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor(xmlTypeFactoryClass, new Class[0], true)); + xmlTypeFactory = (XMLTypeFactory)AccessController.doPrivileged(new PrivilegedInvokeConstructor(xmlTypeFactoryConstructor, new Object[0])); + }else{ + Class xmlTypeFactoryClass = PrivilegedAccessHelper.getClassForName(className, true, this.getClass().getClassLoader()); + Constructor xmlTypeFactoryConstructor = PrivilegedAccessHelper.getConstructorFor(xmlTypeFactoryClass, new Class[0], true); + xmlTypeFactory = (XMLTypeFactory)PrivilegedAccessHelper.invokeConstructor(xmlTypeFactoryConstructor, new Object[0]); + } + } catch (Exception e) { + throw QueryException.reflectiveCallOnTopLinkClassFailed(className, e); + } + } + return xmlTypeFactory; + } + + /** + * INTERNAL: + * Indicates whether the passed object is an instance of XDBDocument. + * @return boolean + */ + @Override + public boolean isXDBDocument(Object obj) { + return getXMLTypeFactory().isXDBDocument(obj); + } + + /** + * INTERNAL: + * Indicates whether this Oracle platform can unwrap Oracle connection. + */ + @Override + public boolean canUnwrapOracleConnection() { + return true; + } + + /** + * INTERNAL: + * If can unwrap returns unwrapped Oracle connection, otherwise original connection. + */ + @Override + public Connection unwrapOracleConnection(Connection connection) { + //Bug#4607977 Use getPhysicalConnection() instead of physicalConnectionWithin() because it's not suppported in 9.2 driver + if(connection instanceof oracle.jdbc.internal.OracleConnection){ + return ((oracle.jdbc.internal.OracleConnection)connection).getPhysicalConnection(); + }else{ + return super.unwrapOracleConnection(connection); + } + } + + /** + * PUBLIC: + * Return is this is the Oracle 9 platform. + */ + @Override + public boolean isOracle9() { + return true; + } + + /** + * INTERNAL: + */ + @Override + public ConnectionCustomizer createConnectionCustomizer(Accessor accessor, AbstractSession session) { + Object proxyTypeValue = session.getProperty(PersistenceUnitProperties.ORACLE_PROXY_TYPE); + if (proxyTypeValue == null || ((proxyTypeValue instanceof String) && ((String)proxyTypeValue).length() == 0)) { + return null; + } else { + return new OracleJDBC_10_1_0_2ProxyConnectionCustomizer(accessor, session); + } + } + + /** + * INTERNAL: Return the driver version. + */ + public String getDriverVersion() { + return driverVersion; + } + + /** + * INTERNAL: Return if timestamps are returned in GMT by the driver. + */ + public boolean isTimestampInGmt() { + return isTimestampInGmt; + } + + /** + * INTERNAL: Return if ltz timestamps are returned in GMT by the driver. + */ + public boolean isLtzTimestampInGmt() { + return isLtzTimestampInGmt; + } + + /** + * PUBLIC: + * Indicates whether time component of java.sql.Date should be truncated (hours, minutes, seconds all set to zero) + * before been passed as a parameter to PreparedStatement. + * Starting with version 12.1 oracle jdbc Statement.setDate no longer zeroes sql.Date's entire time component (only milliseconds). + * "true" indicates that the platform truncates days/hours/minutes before passing the date to Statement.setDate method. + */ + public boolean shouldTruncateDate() { + return shouldTruncateDate; + } + + /** + * PUBLIC: + * Indicates whether time component of java.sql.Date should be truncated (hours, minutes, seconds all set to zero) + * before been passed as a parameter to PreparedStatement. + * Starting with version 12.1 oracle jdbc Statement.setDate no longer zeroes sql.Date's entire time component (only milliseconds). + * Set this flag to true to make the platform to truncate days/hours/minutes before passing the date to Statement.setDate method. + */ + public void setShouldTruncateDate(boolean shouldTruncateDate) { + this.shouldTruncateDate = shouldTruncateDate; + } + + /** + * INTERNAL: + * User name from JDBC connection is stored in {@link #initializeConnectionData(Connection)}. + * @return Always returns {@code true} + */ + @Override + public boolean supportsConnectionUserName() { + return true; + } + + /** + * INTERNAL: + * Returns user name retrieved from JDBC connection. {@link #initializeConnectionData(Connection)} shall be called + * before this method. + * @return User name retrieved from JDBC connection. + */ + @Override + public String getConnectionUserName() { + return this.connectionUserName; + } + + /** + * INTERNAL: + * This method is used to unwrap the oracle connection wrapped by + * the application server. TopLink needs this unwrapped connection for certain + * Oracle Specific support. (ie TIMESTAMPTZ, LOB) + * This is added as a workaround for bug 4565190 + */ + @Override + public Connection getConnection(AbstractSession session, Connection connection) { + if (session.getServerPlatform() != null && (session.getLogin()).shouldUseExternalConnectionPooling()){ + // This is added as a workaround for bug 4460996 + return session.getServerPlatform().unwrapConnection(connection); + } + return connection; + } + + /** + * INTERNAL: + * Platforms that support java.sql.Array may override this method. + * @return Array + */ + @Override + public Array createArray(String elementDataTypeName, Object[] elements, Connection connection) throws SQLException { + return new oracle.sql.ARRAY(new oracle.sql.ArrayDescriptor(elementDataTypeName, connection), connection, elements); + } + + /** + * INTERNAL: + * Platforms that support java.sql.Struct may override this method. + * @return Struct + */ + @Override + public Struct createStruct(String structTypeName, Object[] attributes, Connection connection) throws SQLException { + return new oracle.sql.STRUCT(new oracle.sql.StructDescriptor(structTypeName, connection), connection, attributes); + } + + /** + * INTERNAL: + * Overrides DatabasePlatform method. + * @return String + */ + @Override + public Object getRefValue(Ref ref,Connection connection) throws SQLException { + ((oracle.sql.REF)ref).setPhysicalConnectionOf(connection); + return ((oracle.sql.REF)ref).getValue(); + } + + /** + * INTERNAL: + * Used by Oracle platforms during reading of ResultSet to free temporary LOBs. + */ + @Override + public void freeTemporaryObject(Object value) throws SQLException { + if (value instanceof OracleClob && ((OracleClob) value).isTemporary()) { + ((OracleClob) value).free(); + } else if (value instanceof OracleBlob && ((OracleBlob) value).isTemporary()) { + ((OracleBlob) value).free(); + } + } + } diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java index af6022b1364..9f8bb3692ec 100644 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java +++ b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle12Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -45,6 +45,7 @@ public class Oracle12Platform extends Oracle11Platform { public Oracle12Platform() { super(); + usesNativeBatchWriting = false; supportsIdentity = true; identitySequences = new ConcurrentHashMap<>(); } diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle8Platform.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle8Platform.java deleted file mode 100644 index aab1c4b5a5e..00000000000 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle8Platform.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -// Contributors: -// Oracle - initial API and implementation from Oracle TopLink -// Vikram Bhatia - added method for releasing temporary LOBs after conversion -package org.eclipse.persistence.platform.database.oracle; - -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Struct; -import java.util.Hashtable; - -import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; -import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition; -import org.eclipse.persistence.internal.databaseaccess.Platform; -import org.eclipse.persistence.internal.databaseaccess.SimpleAppendCallCustomParameter; -import org.eclipse.persistence.internal.helper.ClassConstants; -import org.eclipse.persistence.internal.helper.DatabaseField; -import org.eclipse.persistence.internal.sessions.AbstractSession; -import org.eclipse.persistence.logging.SessionLog; -import org.eclipse.persistence.platform.database.OraclePlatform; -import org.eclipse.persistence.queries.Call; - -import oracle.jdbc.OracleBlob; -import oracle.jdbc.OracleClob; - - -/** - *

Purpose: - * Supports certain new Oracle 8 data types, and usage of certain Oracle JDBC specific APIs. - *

Supports Oracle thin JDBC driver LOB >4k binding workaround. - *

Creates BLOB and CLOB type for byte[] and char[] for table creation. - *

Supports object-relational data-type creation. - */ -public class Oracle8Platform extends OraclePlatform { - - /** Locator is required for Oracle thin driver to write LOB value exceeds the limits */ - protected boolean usesLocatorForLOBWrite = true; - - /** The LOB value limits when the Locator is required for the writing */ - protected int lobValueLimits = 0; - - /** - * INTERNAL: - */ - @Override - protected Hashtable buildFieldTypes() { - Hashtable fieldTypeMapping = super.buildFieldTypes(); - - fieldTypeMapping.put(Byte[].class, new FieldTypeDefinition("BLOB", false)); - fieldTypeMapping.put(Character[].class, new FieldTypeDefinition("CLOB", false)); - - return fieldTypeMapping; - } - - /** - * INTERNAL: - * Allow for conversion from the Oralce type to the Java type. - */ - @Override - public void copyInto(Platform platform) { - super.copyInto(platform); - if (!(platform instanceof Oracle8Platform)) { - return; - } - Oracle8Platform oracle8Platform = (Oracle8Platform)platform; - oracle8Platform.setShouldUseLocatorForLOBWrite(shouldUseLocatorForLOBWrite()); - oracle8Platform.setLobValueLimits(getLobValueLimits()); - } - - /** - * INTERNAL: - * Return if the LOB value size is larger than the limit, i.e. 4k. - */ - protected boolean lobValueExceedsLimit(Object value) { - if (value == null) { - return false; - } - int limit = getLobValueLimits(); - if (value instanceof byte[]) {//blob - return ((byte[])value).length >= limit; - } else if (value instanceof String) {//clob - return ((String)value).length() >= limit; - } else { - return false; - } - } - - /** - * INTERNAL: - * This method is used to unwrap the oracle connection wrapped by - * the application server. TopLink needs this unwrapped connection for certain - * Oracle Specific support. (ie TIMESTAMPTZ, LOB) - * This is added as a workaround for bug 4565190 - */ - @Override - public Connection getConnection(AbstractSession session, Connection connection) { - if (session.getServerPlatform() != null && (session.getLogin()).shouldUseExternalConnectionPooling()){ - // This is added as a workaround for bug 4460996 - return session.getServerPlatform().unwrapConnection(connection); - } - return connection; - } - - /** - * INTERNAL - * Used by SQLCall.translate(..) - * Typically there is no field translation (and this is default implementation). - * However on different platforms (Oracle) there are cases such that the values for - * binding and appending may be different (BLOB, CLOB). - * In these special cases the method returns a wrapper object - * which knows whether it should be bound or appended and knows how to do that. - */ - @Override - public Object getCustomModifyValueForCall(Call call, Object value, DatabaseField field, boolean shouldBind) { - Class type = field.getType(); - if (ClassConstants.BLOB.equals(type) || ClassConstants.CLOB.equals(type)) { - if(value == null) { - return null; - } - value = convertToDatabaseType(value); - if (shouldUseLocatorForLOBWrite()) { - if (lobValueExceedsLimit(value)) { - ((DatabaseCall)call).addContext(field, value); - if (ClassConstants.BLOB.equals(type)) { - if (shouldBind) { - value = new byte[1]; - } else { - value = new SimpleAppendCallCustomParameter("empty_blob()"); - } - } else { - if (shouldBind) { - value = new String(" "); - } else { - value = new SimpleAppendCallCustomParameter("empty_clob()"); - } - } - } - } - return value; - } - return super.getCustomModifyValueForCall(call, value, field, shouldBind); - } - - /** - * INTERNAL - * Used by SQLCall.appendModify(..) - * If the field should be passed to customModifyInDatabaseCall, retun true, - * otherwise false. - * Methods shouldCustomModifyInDatabaseCall and customModifyInDatabaseCall should be - * kept in sync: shouldCustomModifyInDatabaseCall should return true if and only if the field - * is handled by customModifyInDatabaseCall. - */ - @Override - public boolean shouldUseCustomModifyForCall(DatabaseField field) { - if (shouldUseLocatorForLOBWrite()) { - Class type = field.getType(); - if (ClassConstants.BLOB.equals(type) || ClassConstants.CLOB.equals(type)) { - return true; - } - } - return super.shouldUseCustomModifyForCall(field); - } - - /** - * INTERNAL: - * Write LOB value - works on Oracle 10 and newer - */ - @Override - public void writeLOB(DatabaseField field, Object value, ResultSet resultSet, AbstractSession session) throws SQLException { - if (isBlob(field.getType())) { - //change for 338585 to use getName instead of getNameDelimited - Blob blob = (Blob) resultSet.getObject(field.getName()); - blob.setBytes(1, (byte[]) value); - //impose the localization - session.log(SessionLog.FINEST, SessionLog.SQL, "write_BLOB", Long.valueOf(blob.length()), field.getName()); - } else if (isClob(field.getType())) { - //change for 338585 to use getName instead of getNameDelimited - Clob clob = (Clob) resultSet.getObject(field.getName()); - clob.setString(1, (String) value); - //impose the localization - session.log(SessionLog.FINEST, SessionLog.SQL, "write_CLOB", Long.valueOf(clob.length()), field.getName()); - } else { - //do nothing for now, open to BFILE or NCLOB types - } - } - - /** - * INTERNAL: - * Used in writeLOB method only to identify a BLOB - */ - protected boolean isBlob(Class type) { - return ClassConstants.BLOB.equals(type); - } - - /** - * INTERNAL: - * Used in writeLOB method only to identify a CLOB - */ - protected boolean isClob(Class type) { - return ClassConstants.CLOB.equals(type); - } - - /** - * INTERNAL: - * Indicates whether app. server should unwrap connection - * to use lob locator. - */ - @Override - public boolean isNativeConnectionRequiredForLobLocator() { - return true; - } - - /** - * PUBLIC: - * Set if the locator is required for the LOB write. The default is true. - * For Oracle thin driver, the locator is recommended for large size - * ( >4k for Oracle8, >5.9K for Oracle9) BLOB/CLOB value write. - */ - public void setShouldUseLocatorForLOBWrite(boolean usesLocatorForLOBWrite) { - this.usesLocatorForLOBWrite = usesLocatorForLOBWrite; - } - - /** - * PUBLIC: - * Return if the locator is required for the LOB write. The default is true. - * For Oracle thin driver, the locator is recommended for large size - * ( >4k for Oracle8, >5.9K for Oracle9) BLOB/CLOB value write. - */ - public boolean shouldUseLocatorForLOBWrite() { - return usesLocatorForLOBWrite; - } - - /** - * PUBLIC: - * Return the BLOB/CLOB value limits on thin driver. The default value is 0. - * If usesLocatorForLOBWrite is true, locator will be used in case the - * lob's size is larger than lobValueLimit. - */ - public int getLobValueLimits() { - return lobValueLimits; - } - - /** - * PUBLIC: - * Set the BLOB/CLOB value limits on thin driver. The default value is 0. - * If usesLocatorForLOBWrite is true, locator will be used in case the - * lob's size is larger than lobValueLimit. - */ - public void setLobValueLimits(int lobValueLimits) { - this.lobValueLimits = lobValueLimits; - } - - /** - * INTERNAL: - * Platforms that support java.sql.Array may override this method. - * @return Array - */ - @Override - public Array createArray(String elementDataTypeName, Object[] elements, Connection connection) throws SQLException { - return new oracle.sql.ARRAY(new oracle.sql.ArrayDescriptor(elementDataTypeName, connection), connection, elements); - } - - /** - * INTERNAL: - * Platforms that support java.sql.Struct may override this method. - * @return Struct - */ - @Override - public Struct createStruct(String structTypeName, Object[] attributes, Connection connection) throws SQLException { - return new oracle.sql.STRUCT(new oracle.sql.StructDescriptor(structTypeName, connection), connection, attributes); - } - - /** - * INTERNAL: - * Overrides DatabasePlatform method. - * @return String - */ - @Override - public Object getRefValue(Ref ref,Connection connection) throws SQLException { - ((oracle.sql.REF)ref).setPhysicalConnectionOf(connection); - return ((oracle.sql.REF)ref).getValue(); - } - - /** - * INTERNAL: - * Used by Oracle platforms during reading of ResultSet to free temporary LOBs. - */ - @Override - public void freeTemporaryObject(Object value) throws SQLException { - if (value instanceof OracleClob && ((OracleClob) value).isTemporary()) { - ((OracleClob) value).free(); - } else if (value instanceof OracleBlob && ((OracleBlob) value).isTemporary()) { - ((OracleBlob) value).free(); - } - } -} diff --git a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle9Platform.java b/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle9Platform.java deleted file mode 100644 index 900019bbdb6..00000000000 --- a/foundation/org.eclipse.persistence.oracle/src/main/java/org/eclipse/persistence/platform/database/oracle/Oracle9Platform.java +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, - * or the Eclipse Distribution License v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -// Contributors: -// Oracle - initial API and implementation from Oracle TopLink -// 09/14/2011-2.3.1 Guy Pelletier -// - 357533: Allow DDL queries to execute even when Multitenant entities are part of the PU -package org.eclipse.persistence.platform.database.oracle; - -import java.io.IOException; -import java.io.Writer; -import java.lang.reflect.Constructor; -import java.security.AccessController; -import java.sql.CallableStatement; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.Calendar; -import java.util.Date; -import java.util.Hashtable; -import java.util.Map; -import java.util.TimeZone; -import java.util.Vector; - -import org.eclipse.persistence.config.PersistenceUnitProperties; -import org.eclipse.persistence.exceptions.ConversionException; -import org.eclipse.persistence.exceptions.DatabaseException; -import org.eclipse.persistence.exceptions.QueryException; -import org.eclipse.persistence.expressions.ExpressionOperator; -import org.eclipse.persistence.internal.databaseaccess.Accessor; -import org.eclipse.persistence.internal.databaseaccess.BindCallCustomParameter; -import org.eclipse.persistence.internal.databaseaccess.ConnectionCustomizer; -import org.eclipse.persistence.internal.databaseaccess.DatabaseCall; -import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform; -import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition; -import org.eclipse.persistence.internal.databaseaccess.Platform; -import org.eclipse.persistence.internal.expressions.SpatialExpressionOperators; -import org.eclipse.persistence.internal.helper.ClassConstants; -import org.eclipse.persistence.internal.helper.DatabaseField; -import org.eclipse.persistence.internal.helper.Helper; -import org.eclipse.persistence.internal.platform.database.XMLTypePlaceholder; -import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPHelper; -import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPLTZWrapper; -import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPTZWrapper; -import org.eclipse.persistence.internal.platform.database.oracle.TIMESTAMPTypes; -import org.eclipse.persistence.internal.platform.database.oracle.XMLTypeFactory; -import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; -import org.eclipse.persistence.internal.security.PrivilegedClassForName; -import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor; -import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor; -import org.eclipse.persistence.internal.sessions.AbstractSession; -import org.eclipse.persistence.queries.Call; -import org.eclipse.persistence.queries.ValueReadQuery; - -import oracle.jdbc.OracleConnection; -import oracle.jdbc.OracleOpaque; -import oracle.jdbc.OraclePreparedStatement; -import oracle.jdbc.OracleTypes; -import oracle.sql.TIMESTAMP; -import oracle.sql.TIMESTAMPLTZ; -import oracle.sql.TIMESTAMPTZ; - -/** - *

Purpose: - * Supports usage of certain Oracle JDBC specific APIs. - *

Supports binding NCHAR, NVARCHAR, NCLOB types as required by Oracle JDBC drivers. - *

Supports Oracle JDBC TIMESTAMP, TIMESTAMPTZ, TIMESTAMPLTZ types. - */ -public class Oracle9Platform extends Oracle8Platform { - - public static final Class NCHAR = NCharacter.class; - public static final Class NSTRING = NString.class; - public static final Class NCLOB = NClob.class; - public static final Class XMLTYPE = XMLTypePlaceholder.class; - - /* Driver version set to connection.getMetaData.getDriverVersion() */ - protected transient String driverVersion; - /* Indicates whether printCalendar should be used when creating TIMESTAMPTZ. - * Bug5614674. It used to be a driver bug and Helper.printCalendar(cal, false) was used to make it work. - * It has been fixed in 11. Separate the newer version from the old ones. - * */ - protected transient boolean shouldPrintCalendar; - /* Indicates whether TIMESTAMPTZ.timestampValue returns Timestamp in GMT. - * The flag is set to false unless - * Oracle jdbc version is 11.1.0.7 or later and - * OracleConnection's "oracle.jdbc.timestampTzInGmt" property is set to "true". - * Though the property is defined per connection it is safe to assume that all connections - * used with the platform are identical because they all created by the same DatabaseLogin - * with the same properties. - * */ - protected transient boolean isTimestampInGmt; - /* Indicates whether TIMESTAMPLTZ.toTimestamp returns Timestamp in GMT. - * true for version 11.2.0.2 or later. - */ - protected transient boolean isLtzTimestampInGmt; - /* Indicates whether driverVersion, shouldPrintCalendar, isTimestampInGmt have been initialized. - * To re-initialize connection data call clearConnectionData method. - */ - protected transient boolean isConnectionDataInitialized; - - /** Indicates whether time component of java.sql.Date should be truncated (hours, minutes, seconds all set to zero) - * before been passed as a parameter to PreparedStatement. - * Starting with version 12.1 oracle jdbc Statement.setDate no longer zeroes sql.Date's entire time component (only milliseconds). - * Set this flag to true to make the platform to truncate days/hours/minutes before passing the date to Statement.setDate method. - */ - protected boolean shouldTruncateDate; - - private XMLTypeFactory xmlTypeFactory; - - /** User name retrieved from JDBC connection in {@link #initializeConnectionData(Connection)}. */ - private transient String connectionUserName; - - /** - * Please ensure that following declarations stay as it is. Having them ensures that oracle jdbc driver available - * in classpath when this class loaded. - * If driver is not available, this class will not be initialized and will fail fast instead of failing later on - * when classes from driver are utilized - */ - private static final Class ORACLE_SQL_TIMESTAMP = oracle.sql.TIMESTAMP.class; - private static final Class ORACLE_SQL_TIMESTAMPTZ = oracle.sql.TIMESTAMPTZ.class; - private static final Class ORACLE_SQL_TIMESTAMPLTZ = oracle.sql.TIMESTAMPLTZ.class; - - - public Oracle9Platform(){ - super(); - connectionUserName = null; - } - - /** - * INTERNAL: - * This class used for binding of NCHAR, NSTRING, NCLOB types. - */ - protected static class NTypeBindCallCustomParameter extends BindCallCustomParameter { - public NTypeBindCallCustomParameter(Object obj) { - super(obj); - } - //Bug5200836, use unwrapped connection if it is NType parameter. - @Override - public boolean shouldUseUnwrappedConnection() { - return true; - } - - /** - * INTERNAL: - * Binds the custom parameter (obj) into the passed PreparedStatement - * for the passed DatabaseCall. - * Note that parameter numeration for PreparedStatement starts with 1, - * therefore statement.set...(index + 1, ...) should be used. - * DatabaseCall will carry this object as its parameter: call.getParameters().elementAt(index). - * The reason for passing DatabaseCall and DatabasePlatform into this method - * is that this method may set obj as a new value of index parameter: - * call.getParameters().setElementAt(obj, index); - * and call again the method which has called it: - * platform.setParameterValueInDatabaseCall(call, statement, index); - * so obj will be bound. - * - * Called only by DatabasePlatform.setParameterValueInDatabaseCall method - */ - @Override - public void set(DatabasePlatform platform, PreparedStatement statement, int index, AbstractSession session) throws SQLException { - // Binding starts with a 1 not 0. Make sure that index > 0 - ((oracle.jdbc.OraclePreparedStatement)statement).setFormOfUse(index, oracle.jdbc.OraclePreparedStatement.FORM_NCHAR); - - super.set(platform, statement, index, session); - } - } - - /** - * Copy the state into the new platform. - */ - @Override - public void copyInto(Platform platform) { - super.copyInto(platform); - if (!(platform instanceof Oracle9Platform)) { - return; - } - Oracle9Platform oracle9Platform = (Oracle9Platform)platform; - oracle9Platform.setShouldTruncateDate(shouldTruncateDate()); - } - - /** - * INTERNAL: - * Get a timestamp value from a result set. - * Overrides the default behavior to specifically return a timestamp. Added - * to overcome an issue with the oracle 9.0.1.4 JDBC driver. - */ - @Override - public Object getObjectFromResultSet(ResultSet resultSet, int columnNumber, int type, AbstractSession session) throws java.sql.SQLException { - //Bug#3381652 10G Drivers return sql.Date instead of timestamp on DATE field - if ((type == Types.TIMESTAMP) || (type == Types.DATE)) { - return resultSet.getTimestamp(columnNumber); - } else if (type == oracle.jdbc.OracleTypes.TIMESTAMPTZ) { - return getTIMESTAMPTZFromResultSet(resultSet, columnNumber, type, session); - } else if (type == oracle.jdbc.OracleTypes.TIMESTAMPLTZ) { - return getTIMESTAMPLTZFromResultSet(resultSet, columnNumber, type, session); - } else if (type == OracleTypes.ROWID) { - return resultSet.getString(columnNumber); - } else if (type == Types.SQLXML) { - SQLXML sqlXml = resultSet.getSQLXML(columnNumber); - String str = null; - if (sqlXml != null) { - str = sqlXml.getString(); - sqlXml.free(); - } - // Oracle 12c appends a \n character to the xml string - return (str != null && str.endsWith("\n")) ? str.substring(0, str.length() - 1) : str; - } else if (type == OracleTypes.OPAQUE) { - try { - Object result = resultSet.getObject(columnNumber); - if (!(result instanceof OracleOpaque)) { - // Report Queries can cause result to not be an instance of OPAQUE. - return result; - } else { - return getXMLTypeFactory().getString((OracleOpaque) result); - } - } catch (SQLException ex) { - throw DatabaseException.sqlException(ex, null, session, false); - } - } else { - return super.getObjectFromResultSet(resultSet, columnNumber, type, session); - } - } - - /** - * INTERNAL: - * Get a TIMESTAMPTZ value from a result set. - */ - public Object getTIMESTAMPTZFromResultSet(ResultSet resultSet, int columnNumber, int type, AbstractSession session) throws java.sql.SQLException { - TIMESTAMPTZ tsTZ = (TIMESTAMPTZ)resultSet.getObject(columnNumber); - //Need to call timestampValue once here with the connection to avoid null point - //exception later when timestampValue is called in converObject() - if ((tsTZ != null) && (tsTZ.getLength() != 0)) { - Connection connection = getConnection(session, resultSet.getStatement().getConnection()); - //Bug#4364359 Add a wrapper to overcome TIMESTAMPTZ not serializable as of jdbc 9.2.0.5 and 10.1.0.2. - //It has been fixed in the next version for both streams - Timestamp timestampToWrap = tsTZ.timestampValue(connection); - TimeZone timezoneToWrap = TIMESTAMPHelper.extractTimeZone(tsTZ.toBytes()); - return new TIMESTAMPTZWrapper(timestampToWrap, timezoneToWrap, this.isTimestampInGmt); - } - return null; - } - - /** - * INTERNAL: - * Get a TIMESTAMPLTZ value from a result set. - */ - public Object getTIMESTAMPLTZFromResultSet(ResultSet resultSet, int columnNumber, int type, AbstractSession session) throws java.sql.SQLException { - //TIMESTAMPLTZ needs to be converted to Timestamp here because it requires the connection. - //However the java object is not know here. The solution is to store Timestamp and the - //session timezone in a wrapper class, which will be used later in converObject(). - TIMESTAMPLTZ tsLTZ = (TIMESTAMPLTZ)resultSet.getObject(columnNumber); - if ((tsLTZ != null) && (tsLTZ.getLength() != 0)) { - Connection connection = getConnection(session, resultSet.getStatement().getConnection()); - Timestamp timestampToWrap = TIMESTAMPLTZ.toTimestamp(connection, tsLTZ.toBytes()); - String sessionTimeZone = ((OracleConnection)connection).getSessionTimeZone(); - //Bug#4364359 Add a separate wrapper for TIMESTAMPLTZ. - return new TIMESTAMPLTZWrapper(timestampToWrap, sessionTimeZone, this.isLtzTimestampInGmt); - } - return null; - } - - /** - * INTERNAL - * Used by SQLCall.appendModify(..) - * If the field should be passed to customModifyInDatabaseCall, retun true, - * otherwise false. - * Methods shouldCustomModifyInDatabaseCall and customModifyInDatabaseCall should be - * kept in sync: shouldCustomModifyInDatabaseCall should return true if and only if the field - * is handled by customModifyInDatabaseCall. - */ - @Override - public boolean shouldUseCustomModifyForCall(DatabaseField field) { - Class type = field.getType(); - if ((type != null) && isOracle9Specific(type)) { - return true; - } - return super.shouldUseCustomModifyForCall(field); - } - - /** - * INTERNAL: - * Allow the use of XMLType operators on this platform. - */ - @Override - protected void initializePlatformOperators() { - super.initializePlatformOperators(); - addOperator(ExpressionOperator.extractXml()); - addOperator(ExpressionOperator.extractValue()); - addOperator(ExpressionOperator.existsNode()); - addOperator(ExpressionOperator.isFragment()); - addOperator(ExpressionOperator.getStringVal()); - addOperator(ExpressionOperator.getNumberVal()); - addOperator(SpatialExpressionOperators.withinDistance()); - addOperator(SpatialExpressionOperators.relate()); - addOperator(SpatialExpressionOperators.filter()); - addOperator(SpatialExpressionOperators.nearestNeighbor()); - } - - /** - * INTERNAL: - * Add XMLType as the default database type for org.w3c.dom.Documents. - * Add TIMESTAMP, TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE - */ - @Override - protected Hashtable buildFieldTypes() { - Hashtable fieldTypes = super.buildFieldTypes(); - fieldTypes.put(org.w3c.dom.Document.class, new FieldTypeDefinition("sys.XMLType")); - //Bug#3381652 10g database does not accept Time for DATE field - fieldTypes.put(java.sql.Time.class, new FieldTypeDefinition("TIMESTAMP", false)); - fieldTypes.put(java.sql.Timestamp.class, new FieldTypeDefinition("TIMESTAMP", false)); - fieldTypes.put(ORACLE_SQL_TIMESTAMP, new FieldTypeDefinition("TIMESTAMP", false)); - fieldTypes.put(ORACLE_SQL_TIMESTAMPTZ, new FieldTypeDefinition("TIMESTAMP WITH TIME ZONE", false)); - fieldTypes.put(ORACLE_SQL_TIMESTAMPLTZ, new FieldTypeDefinition("TIMESTAMP WITH LOCAL TIME ZONE", false)); - - fieldTypes.put(java.time.LocalDate.class, new FieldTypeDefinition("DATE")); - fieldTypes.put(java.time.LocalDateTime.class, new FieldTypeDefinition("TIMESTAMP")); - fieldTypes.put(java.time.LocalTime.class, new FieldTypeDefinition("TIMESTAMP")); - fieldTypes.put(java.time.OffsetDateTime.class, new FieldTypeDefinition("TIMESTAMP")); //TIMESTAMP WITH TIME ZONE ??? - fieldTypes.put(java.time.OffsetTime.class, new FieldTypeDefinition("TIMESTAMP")); //TIMESTAMP WITH TIME ZONE ??? - return fieldTypes; - } - - /** - * Build the hint string used for first rows. - * - * Allows it to be overridden - * @param max - * @return - */ - @Override - protected String buildFirstRowsHint(int max){ - return HINT_START + '(' + max + ')'+ HINT_END; - } - - /** - * INTERNAL: - * Add TIMESTAMP, TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE - */ - @Override - protected Map buildClassTypes() { - Map classTypeMapping = super.buildClassTypes(); - classTypeMapping.put("TIMESTAMP", ORACLE_SQL_TIMESTAMP); - classTypeMapping.put("TIMESTAMP WITH TIME ZONE", ORACLE_SQL_TIMESTAMPTZ); - classTypeMapping.put("TIMESTAMP WITH LOCAL TIME ZONE", ORACLE_SQL_TIMESTAMPLTZ); - return classTypeMapping; - } - - @Override - public Object clone() { - Oracle9Platform clone = (Oracle9Platform)super.clone(); - clone.clearConnectionData(); - return clone; - } - - /** - * INTERNAL: - * Allow for conversion from the Oracle type to the Java type. - */ - @Override - public Object convertObject(Object sourceObject, Class javaClass) throws ConversionException, DatabaseException { - if ((javaClass == null) || ((sourceObject != null) && (sourceObject.getClass() == javaClass))) { - return sourceObject; - } - if (sourceObject == null) { - return super.convertObject(sourceObject, javaClass); - } - - Object valueToConvert = sourceObject; - - //Used in Type Conversion Mapping on write - if ((javaClass == TIMESTAMPTypes.TIMESTAMP_CLASS) || (javaClass == TIMESTAMPTypes.TIMESTAMPLTZ_CLASS)) { - return sourceObject; - } - - if (javaClass == TIMESTAMPTypes.TIMESTAMPTZ_CLASS) { - if (sourceObject instanceof java.util.Date) { - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(((java.util.Date)sourceObject).getTime()); - return cal; - } else { - return sourceObject; - } - } - - if (javaClass == XMLTYPE) { - //Don't convert to XMLTypes. This will be done by the - //XMLTypeBindCallCustomParameter to ensure the correct - //Connection is used - return sourceObject; - } - - //Added to overcome an issue with the oracle 9.0.1.1.0 JDBC driver. - if (sourceObject instanceof TIMESTAMP) { - try { - valueToConvert = ((TIMESTAMP)sourceObject).timestampValue(); - } catch (SQLException exception) { - throw DatabaseException.sqlException(exception); - } - } else if (sourceObject instanceof TIMESTAMPTZWrapper) { - //Bug#4364359 Used when database type is TIMESTAMPTZ. Timestamp and session timezone are wrapped - //in TIMESTAMPTZWrapper. Separate Calendar from any other types. - if (((javaClass == ClassConstants.CALENDAR) || (javaClass == ClassConstants.GREGORIAN_CALENDAR))) { - try { - return TIMESTAMPHelper.buildCalendar((TIMESTAMPTZWrapper)sourceObject); - } catch (SQLException exception) { - throw DatabaseException.sqlException(exception); - } - } else { - //If not using native sql, Calendar will be converted to Timestamp just as - //other date time types - valueToConvert = ((TIMESTAMPTZWrapper)sourceObject).getTimestamp(); - } - } else if (sourceObject instanceof TIMESTAMPLTZWrapper) { - //Bug#4364359 Used when database type is TIMESTAMPLTZ. Timestamp and session timezone id are wrapped - //in TIMESTAMPLTZWrapper. Separate Calendar from any other types. - if (((javaClass == ClassConstants.CALENDAR) || (javaClass == ClassConstants.GREGORIAN_CALENDAR))) { - try { - return TIMESTAMPHelper.buildCalendar((TIMESTAMPLTZWrapper)sourceObject); - } catch (SQLException exception) { - throw DatabaseException.sqlException(exception); - } - } else { - //If not using native sql, Calendar will be converted to Timestamp just as - //other date time types - valueToConvert = ((TIMESTAMPLTZWrapper)sourceObject).getTimestamp(); - } - } - - return super.convertObject(valueToConvert, javaClass); - } - - /** - * INTERNAL: - * Appends an Oracle specific Timestamp, if usesNativeSQL is true otherwise use the ODBC format. - * Native Format: to_timestamp ('1997-11-06 10:35:45.656' , 'yyyy-mm-dd hh:mm:ss.ff') - */ - @Override - protected void appendTimestamp(java.sql.Timestamp timestamp, Writer writer) throws IOException { - if (usesNativeSQL()) { - writer.write("to_timestamp('"); - writer.write(Helper.printTimestamp(timestamp)); - writer.write("','yyyy-mm-dd HH24:MI:SS.FF')"); - } else { - super.appendTimestamp(timestamp, writer); - } - } - - /** - * INTERNAL: - * Appends an Oracle specific Timestamp with timezone and daylight time - * elements if usesNativeSQL is true, otherwise use the ODBC format. - * Native Format: - * (DST) to_timestamp_tz ('1997-11-06 10:35:45.345 America/Los_Angeles','yyyy-mm-dd hh:mm:ss.ff TZR TZD') - * (non-DST) to_timestamp_tz ('1997-11-06 10:35:45.345 America/Los_Angeles','yyyy-mm-dd hh:mm:ss.ff TZR') - */ - @Override - protected void appendCalendar(Calendar calendar, Writer writer) throws IOException { - if (usesNativeSQL()) { - writer.write("to_timestamp_tz('"); - writer.write(TIMESTAMPHelper.printCalendar(calendar)); - // append TZD element if the calendar's timezone is in daylight time - if (TIMESTAMPHelper.shouldAppendDaylightTime(calendar)) { - writer.write("','yyyy-mm-dd HH24:MI:SS.FF TZR TZD')"); - } else { - writer.write("','yyyy-mm-dd HH24:MI:SS.FF TZR')"); - } - } else { - super.appendCalendar(calendar, writer); - } - } - - /** - * INTERNAL: - */ - @Override - public void initializeConnectionData(Connection connection) throws SQLException { - if (this.isConnectionDataInitialized || (connection == null) || (connection.getMetaData() == null)) { - return; - } - this.driverVersion = connection.getMetaData().getDriverVersion(); - // printCalendar for versions greater or equal 9 and less than 10.2.0.4 - this.shouldPrintCalendar = Helper.compareVersions("9", this.driverVersion) <= 0 && Helper.compareVersions(this.driverVersion, "10.2.0.4") < 0; - if (Helper.compareVersions(this.driverVersion, "11.1.0.7") >= 0) { - if( connection instanceof OracleConnection ) { - final OracleConnection oraConn = (OracleConnection)connection; - String timestampTzInGmtPropStr = oraConn.getProperties().getProperty("oracle.jdbc.timestampTzInGmt", "true"); - this.connectionUserName = oraConn.getUserName(); - this.isTimestampInGmt = timestampTzInGmtPropStr.equalsIgnoreCase("true"); - } else { - this.connectionUserName = connection.getMetaData().getUserName(); - this.isTimestampInGmt = true; - } - if (Helper.compareVersions(this.driverVersion, "11.2.0.2") >= 0) { - this.isLtzTimestampInGmt = true; - } - } - this.isConnectionDataInitialized = true; - } - - public void clearConnectionData() { - this.driverVersion = null; - this.isConnectionDataInitialized = false; - } - - /** - * INTERNAL: - * Clears both implicit and explicit caches of OracleConnection - */ - @Override - public void clearOracleConnectionCache(Connection conn) { - if(conn instanceof OracleConnection){ - OracleConnection oracleConnection = (OracleConnection)conn; - try { - if(oracleConnection.getImplicitCachingEnabled()) { - oracleConnection.purgeImplicitCache(); - } - } catch(SQLException ex) { - // ignore - } - try { - if(oracleConnection.getExplicitCachingEnabled()) { - oracleConnection.purgeExplicitCache(); - } - } catch(SQLException ex) { - // ignore - } - } - } - - /** - * INTERNAL: - * Note that index (not index+1) is used in statement.setObject(index, parameter) - * Binding starts with a 1 not 0, so make sure that index > 0. - * Treat Calendar separately. Bind Calendar as TIMESTAMPTZ. - */ - @Override - public void setParameterValueInDatabaseCall(Object parameter, PreparedStatement statement, int index, AbstractSession session) throws SQLException { - if (parameter instanceof Calendar) { - Calendar calendar = (Calendar)parameter; - Connection conn = getConnection(session, statement.getConnection()); - TIMESTAMPTZ tsTZ = TIMESTAMPHelper.buildTIMESTAMPTZ(calendar, conn, this.shouldPrintCalendar); - statement.setObject(index, tsTZ); - } else if (this.shouldTruncateDate && parameter instanceof java.sql.Date) { - // hours, minutes, seconds all set to zero - statement.setDate(index, Helper.truncateDateIgnoreMilliseconds((java.sql.Date)parameter)); - } else { - super.setParameterValueInDatabaseCall(parameter, statement, index, session); - } - } - - /** - * INTERNAL: - * Note that index (not index+1) is used in statement.setObject(index, parameter) - * Binding starts with a 1 not 0, so make sure that index > 0. - * Treat Calendar separately. Bind Calendar as TIMESTAMPTZ. - */ - @Override - public void setParameterValueInDatabaseCall(Object parameter, CallableStatement statement, String name, AbstractSession session) throws SQLException { - if (parameter instanceof Calendar) { - Calendar calendar = (Calendar)parameter; - Connection conn = getConnection(session, statement.getConnection()); - TIMESTAMPTZ tsTZ = TIMESTAMPHelper.buildTIMESTAMPTZ(calendar, conn, this.shouldPrintCalendar); - statement.setObject(name, tsTZ); - } else if (this.shouldTruncateDate && parameter instanceof java.sql.Date) { - // hours, minutes, seconds all set to zero - statement.setDate(name, Helper.truncateDateIgnoreMilliseconds((java.sql.Date)parameter)); - } else { - super.setParameterValueInDatabaseCall(parameter, statement, name, session); - } - } - - /** - * INTERNAL: - * Answer the timestamp from the server. Convert TIMESTAMPTZ to Timestamp - */ - @Override - public java.sql.Timestamp getTimestampFromServer(AbstractSession session, String sessionName) { - if (getTimestampQuery() != null) { - getTimestampQuery().setSessionName(sessionName); - Object ob = session.executeQuery(getTimestampQuery()); - return ((TIMESTAMPTZWrapper)ob).getTimestamp(); - } - return super.getTimestampFromServer(session, sessionName); - } - - /** - * INTERNAL: - * This method returns the query to select the SYSTIMESTAMP as TIMESTAMPTZ - * from the server for Oracle9i. - */ - @Override - public ValueReadQuery getTimestampQuery() { - if (timestampQuery == null) { - timestampQuery = new ValueReadQuery(); - timestampQuery.setSQLString("SELECT SYSTIMESTAMP FROM DUAL"); - timestampQuery.setAllowNativeSQLQuery(true); - } - return timestampQuery; - } - - /** - * INTERNAL: - * Return the current SYSTIMESTAMP as TIMESTAMPTZ from the server. - */ - @Override - public String serverTimestampString() { - return "SYSTIMESTAMP"; - } - - protected Vector buildToTIMESTAMPVec() { - Vector vec = new Vector(); - vec.addElement(java.util.Date.class); - vec.addElement(Timestamp.class); - vec.addElement(Calendar.class); - vec.addElement(String.class); - vec.addElement(Long.class); - vec.addElement(Date.class); - vec.addElement(Time.class); - return vec; - } - - protected Vector buildToNStringCharVec() { - Vector vec = new Vector(); - vec.addElement(String.class); - vec.addElement(Character.class); - return vec; - } - - protected Vector buildToNClobVec() { - Vector vec = new Vector(); - vec.addElement(String.class); - vec.addElement(Character[].class); - vec.addElement(char[].class); - return vec; - } - - /** - * PUBLIC: - * Return the BLOB/CLOB value limits on thin driver. The default value is 0. - * If usesLocatorForLOBWrite is true, locator will be used in case the - * lob's size is larger than lobValueLimit. - */ - @Override - public int getLobValueLimits() { - return lobValueLimits; - } - - /** - * PUBLIC: - * Set the BLOB/CLOB value limits on thin driver. The default value is 0. - * If usesLocatorForLOBWrite is true, locator will be used in case the - * lob's size is larger than lobValueLimit. - */ - @Override - public void setLobValueLimits(int lobValueLimits) { - this.lobValueLimits = lobValueLimits; - } - - /** - * INTERNAL: - * Return if the type is a special oracle type. - * bug 3325122 - just checking against the 4 classes is faster than isAssignableFrom MWN. - */ - protected boolean isOracle9Specific(Class type) { - return (type == NCHAR) || (type == NSTRING) || (type == NCLOB) || (type == XMLTYPE); - } - - /** - * INTERNAL: - * Used in write LOB method only to identify a CLOB. - */ - @Override - protected boolean isClob(Class type) { - return NCLOB.equals(type) || super.isClob(type); - } - - /** - * INTERNAL: - * Used by SQLCall.translate(..) - * The binding *must* be performed (NCHAR, NSTRING, NCLOB). - * In these special cases the method returns a wrapper object - * which knows whether it should be bound or appended and knows how to do that. - */ - @Override - public Object getCustomModifyValueForCall(Call call, Object value, DatabaseField field, boolean shouldBind) { - Class type = field.getType(); - if ((type != null) && isOracle9Specific(type)) { - if(value == null) { - return null; - } - if (NCHAR.equals(type) || NSTRING.equals(type)) { - return new NTypeBindCallCustomParameter(value); - } else if (NCLOB.equals(type)) { - value = convertToDatabaseType(value); - if (shouldUseLocatorForLOBWrite()) { - if (lobValueExceedsLimit(value)) { - ((DatabaseCall)call).addContext(field, value); - value = new String(" "); - } - } - return new NTypeBindCallCustomParameter(value); - } else if (XMLTYPE.equals(type)) { - return getXMLTypeFactory().createXMLTypeBindCallCustomParameter(value); - } - } - return super.getCustomModifyValueForCall(call, value, field, shouldBind); - } - - protected Vector buildFromStringCharVec(Class javaClass) { - Vector vec = getConversionManager().getDataTypesConvertedFrom(javaClass); - vec.addElement(NCHAR); - vec.addElement(NSTRING); - if (javaClass == String.class) { - vec.addElement(NCLOB); - } - return vec; - } - - /** - * INTERNAL: - * Return the list of Classes that can be converted to from the passed in javaClass. - * oracle.sql.TIMESTAMP and NCHAR types are added in some lists. - * @param javaClass - the class that is converted from - * @return - a vector of classes - */ - @Override - public Vector getDataTypesConvertedFrom(Class javaClass) { - if (dataTypesConvertedFromAClass == null) { - dataTypesConvertedFromAClass = new Hashtable(5); - } - Vector dataTypes = (Vector) dataTypesConvertedFromAClass.get(javaClass); - if (dataTypes != null) { - return dataTypes; - } - dataTypes = super.getDataTypesConvertedFrom(javaClass); - if ((javaClass == String.class) || (javaClass == Character.class)) { - dataTypes.addElement(NCHAR); - dataTypes.addElement(NSTRING); - if (javaClass == String.class) { - dataTypes.addElement(NCLOB); - } - } - if ((javaClass == char[].class) || (javaClass == Character[].class)) { - dataTypes.addElement(NCLOB); - } - dataTypesConvertedFromAClass.put(javaClass, dataTypes); - return dataTypes; - } - - /** - * INTERNAL: - * Return the list of Classes that can be converted from to the passed in javaClass. - * A list is added for oracle.sql.TIMESTAMP and NCHAR types. - * @param javaClass - the class that is converted to - * @return - a vector of classes - */ - @Override - public Vector getDataTypesConvertedTo(Class javaClass) { - if (dataTypesConvertedToAClass == null) { - dataTypesConvertedToAClass = new Hashtable(5); - } - Vector dataTypes = (Vector) dataTypesConvertedToAClass.get(javaClass); - if (dataTypes != null) { - return dataTypes; - } - if ((javaClass == NCHAR) || (javaClass == NSTRING)) { - dataTypes = buildToNStringCharVec(); - } else if (javaClass == NCLOB) { - dataTypes = buildToNClobVec(); - } else { - dataTypes = super.getDataTypesConvertedTo(javaClass); - } - dataTypesConvertedToAClass.put(javaClass, dataTypes); - return dataTypes; - } - - - /** - * Return the JDBC type for the given database field to be passed to Statement.setNull - * The Oracle driver does not like the OPAQUE type so VARCHAR must be used. - */ - @Override - public int getJDBCTypeForSetNull(DatabaseField field) { - int type = getJDBCType(field); - if (type == OracleTypes.OPAQUE || type == Types.SQLXML) { - // VARCHAR seems to work, driver does not like OPAQUE. - return Types.VARCHAR; - } - return type; - } - - /** - * Return the JDBC type for the Java type. - * The Oracle driver does not like the OPAQUE type so VARCHAR must be used. - */ - @Override - public int getJDBCType(Class javaType) { - if (javaType == XMLTYPE) { - //return OracleTypes.OPAQUE; - // VARCHAR seems to work... - return Types.VARCHAR; - } - return super.getJDBCType(javaType); - } - - /** - * INTERNAL: This gets called on each batch statement execution - * Needs to be implemented so that it returns the number of rows successfully modified - * by this statement for optimistic locking purposes (if useNativeBatchWriting is enabled, and - * the call uses optimistic locking). - * - * @param isStatementPrepared - flag is set to true if this statement is prepared - * @return - number of rows modified/deleted by this statement - */ - @Override - public int executeBatch(Statement statement, boolean isStatementPrepared) throws SQLException { - if (usesNativeBatchWriting() && isStatementPrepared) { - int rowCount = 0; - try { - rowCount = ((OraclePreparedStatement)statement).sendBatch(); - } finally { - ((OraclePreparedStatement) statement).setExecuteBatch(1); - } - return rowCount; - } else { - return super.executeBatch(statement, isStatementPrepared); - } - } - - /** - * INTERNAL: This gets called on each iteration to add parameters to the batch - * Needs to be implemented so that it returns the number of rows successfully modified - * by this statement for optimistic locking purposes (if useNativeBatchWriting is enabled, and - * the call uses optimistic locking). Is used with parameterized SQL - * - * @return - number of rows modified/deleted by this statement if it was executed (0 if it wasn't) - */ - @Override - public int addBatch(PreparedStatement statement) throws java.sql.SQLException { - if (usesNativeBatchWriting()){ - return statement.executeUpdate(); - }else{ - return super.addBatch(statement); - } - } - - /** - * INTERNAL: Allows setting the batch size on the statement - * Is used with parameterized SQL, and should only be passed in prepared statements - * - * @return - statement to be used for batch writing - */ - @Override - public Statement prepareBatchStatement(Statement statement, int maxBatchWritingSize) throws java.sql.SQLException { - if (usesNativeBatchWriting()){ - //add max statement setting - ((OraclePreparedStatement) statement).setExecuteBatch(maxBatchWritingSize); - } - return statement; - } - - /** - * INTERNAL: - * Lazy initialization of xmlTypeFactory allows to avoid loading xdb-dependent - * class XMLTypeFactoryImpl unless xdb is used. - * @return XMLTypeFactory - */ - protected XMLTypeFactory getXMLTypeFactory() { - if(xmlTypeFactory == null) { - String className = "org.eclipse.persistence.internal.platform.database.oracle.xdb.XMLTypeFactoryImpl"; - try { - if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ - Class xmlTypeFactoryClass = AccessController.doPrivileged(new PrivilegedClassForName(className, true, this.getClass().getClassLoader())); - Constructor xmlTypeFactoryConstructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor(xmlTypeFactoryClass, new Class[0], true)); - xmlTypeFactory = (XMLTypeFactory)AccessController.doPrivileged(new PrivilegedInvokeConstructor(xmlTypeFactoryConstructor, new Object[0])); - }else{ - Class xmlTypeFactoryClass = PrivilegedAccessHelper.getClassForName(className, true, this.getClass().getClassLoader()); - Constructor xmlTypeFactoryConstructor = PrivilegedAccessHelper.getConstructorFor(xmlTypeFactoryClass, new Class[0], true); - xmlTypeFactory = (XMLTypeFactory)PrivilegedAccessHelper.invokeConstructor(xmlTypeFactoryConstructor, new Object[0]); - } - } catch (Exception e) { - throw QueryException.reflectiveCallOnTopLinkClassFailed(className, e); - } - } - return xmlTypeFactory; - } - - /** - * INTERNAL: - * Indicates whether the passed object is an instance of XDBDocument. - * @return boolean - */ - @Override - public boolean isXDBDocument(Object obj) { - return getXMLTypeFactory().isXDBDocument(obj); - } - - /** - * INTERNAL: - * Indicates whether this Oracle platform can unwrap Oracle connection. - */ - @Override - public boolean canUnwrapOracleConnection() { - return true; - } - - /** - * INTERNAL: - * If can unwrap returns unwrapped Oracle connection, otherwise original connection. - */ - @Override - public Connection unwrapOracleConnection(Connection connection) { - //Bug#4607977 Use getPhysicalConnection() instead of physicalConnectionWithin() because it's not suppported in 9.2 driver - if(connection instanceof oracle.jdbc.internal.OracleConnection){ - return ((oracle.jdbc.internal.OracleConnection)connection).getPhysicalConnection(); - }else{ - return super.unwrapOracleConnection(connection); - } - } - - /** - * PUBLIC: - * Return is this is the Oracle 9 platform. - */ - @Override - public boolean isOracle9() { - return true; - } - - /** - * INTERNAL: - */ - @Override - public ConnectionCustomizer createConnectionCustomizer(Accessor accessor, AbstractSession session) { - Object proxyTypeValue = session.getProperty(PersistenceUnitProperties.ORACLE_PROXY_TYPE); - if (proxyTypeValue == null || ((proxyTypeValue instanceof String) && ((String)proxyTypeValue).length() == 0)) { - return null; - } else { - return new OracleJDBC_10_1_0_2ProxyConnectionCustomizer(accessor, session); - } - } - - /** - * INTERNAL: Return the driver version. - */ - public String getDriverVersion() { - return driverVersion; - } - - /** - * INTERNAL: Return if timestamps are returned in GMT by the driver. - */ - public boolean isTimestampInGmt() { - return isTimestampInGmt; - } - - /** - * INTERNAL: Return if ltz timestamps are returned in GMT by the driver. - */ - public boolean isLtzTimestampInGmt() { - return isLtzTimestampInGmt; - } - - /** - * PUBLIC: - * Indicates whether time component of java.sql.Date should be truncated (hours, minutes, seconds all set to zero) - * before been passed as a parameter to PreparedStatement. - * Starting with version 12.1 oracle jdbc Statement.setDate no longer zeroes sql.Date's entire time component (only milliseconds). - * "true" indicates that the platform truncates days/hours/minutes before passing the date to Statement.setDate method. - */ - public boolean shouldTruncateDate() { - return shouldTruncateDate; - } - - /** - * PUBLIC: - * Indicates whether time component of java.sql.Date should be truncated (hours, minutes, seconds all set to zero) - * before been passed as a parameter to PreparedStatement. - * Starting with version 12.1 oracle jdbc Statement.setDate no longer zeroes sql.Date's entire time component (only milliseconds). - * Set this flag to true to make the platform to truncate days/hours/minutes before passing the date to Statement.setDate method. - */ - public void setShouldTruncateDate(boolean shouldTruncateDate) { - this.shouldTruncateDate = shouldTruncateDate; - } - - /** - * INTERNAL: - * User name from JDBC connection is stored in {@link #initializeConnectionData(Connection)}. - * @return Always returns {@code true} - */ - @Override - public boolean supportsConnectionUserName() { - return true; - } - - /** - * INTERNAL: - * Returns user name retrieved from JDBC connection. {@link #initializeConnectionData(Connection)} shall be called - * before this method. - * @return User name retrieved from JDBC connection. - */ - @Override - public String getConnectionUserName() { - return this.connectionUserName; - } - -}