Skip to content

Commit

Permalink
Oracle 23C platform
Browse files Browse the repository at this point in the history
Adds support for Oracle 23c database.
There are following changes
- Oracle23Platform.java platform classes added
- New Oracle JDBC driver 23.x.x.x has, in some cases, different behaviour for boolean type. There are changes in PL/SQL calls.
- When empty String ("") is inserted into table column like ...CLOBDATA CLOB NOT NULL...
    Solution is based on conversion into java.sql.Clob, because solution based on SimpleAppendCallCustomParameter("empty_clob()") and DatabasePlatform.appendParameter() leads into another test failures.
- Fix for loss of precision if DB table is automatically created if entity using java.time.LocalDateTime, java.time.LocalTime.
- JDBC Driver update

Signed-off-by: Radek Felcman <[email protected]>
  • Loading branch information
rfelcman committed Nov 16, 2023
1 parent c332ea3 commit 307a58f
Show file tree
Hide file tree
Showing 13 changed files with 270 additions and 20 deletions.
4 changes: 2 additions & 2 deletions buildsystem/compdeps/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@
<!-- CQ #21122 -->
<org.jgroups.version>4.1.8.Final</org.jgroups.version>
<!-- CQ #21154 -->
<oracle.jdbc.version>21.7.0.0</oracle.jdbc.version>
<oracle.apapi.version>21.3.0.0</oracle.apapi.version>
<oracle.jdbc.version>23.3.0.23.09</oracle.jdbc.version>
<oracle.apapi.version>23.2.0.0</oracle.apapi.version>
<!-- CQ #21141 -->
<oracle.nosql.version>18.3.10</oracle.nosql.version>
<!-- CQ #22994 -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1998, 2023 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1998, 2019 IBM Corporation. All rights reserved.
#
# This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -36,13 +36,15 @@
# to platform class entries should be placed before less specific entries. Each
# platform entry must be on its own line, an entry cannot span multiple lines.

(?is)oracle.*23.*=org.eclipse.persistence.platform.database.oracle.Oracle23Platform
(?is)oracle.*21.*=org.eclipse.persistence.platform.database.oracle.Oracle21Platform
(?is)oracle.*19.*=org.eclipse.persistence.platform.database.oracle.Oracle19Platform
(?is)oracle.*18.*=org.eclipse.persistence.platform.database.oracle.Oracle18Platform
(?is)oracle.*12.*=org.eclipse.persistence.platform.database.oracle.Oracle12Platform
(?is)oracle.*11.*=org.eclipse.persistence.platform.database.oracle.Oracle11Platform
(?is)oracle.*10.*=org.eclipse.persistence.platform.database.oracle.Oracle10Platform
(?is)oracle.*9.*=org.eclipse.persistence.platform.database.oracle.Oracle9Platform
(?is)core.oracle.*23.*=org.eclipse.persistence.platform.database.Oracle23Platform
(?is)core.oracle.*21.*=org.eclipse.persistence.platform.database.Oracle21Platform
(?is)core.oracle.*19.*=org.eclipse.persistence.platform.database.Oracle19Platform
(?is)core.oracle.*18.*=org.eclipse.persistence.platform.database.Oracle18Platform
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2023 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
Expand All @@ -14,7 +14,9 @@
// Blaise Doughan - 2.5 - initial implementation
package org.eclipse.persistence.internal.core.databaseaccess;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.internal.core.helper.CoreConversionManager;
import org.eclipse.persistence.internal.sessions.AbstractSession;

public interface CorePlatform<CONVERSION_MANAGER extends CoreConversionManager> {

Expand All @@ -28,6 +30,17 @@ public interface CorePlatform<CONVERSION_MANAGER extends CoreConversionManager>
*/
Object convertObject(Object sourceObject, Class javaClass);

/**
* Convert the object to the appropriate type by invoking the appropriate
* ConversionManager method.
* @param sourceObject the object that must be converted
* @param javaClass the class that the object must be converted to
* @param session current database session
* @exception ConversionException all exceptions will be thrown as this type.
* @return the newly converted object
*/
Object convertObject(Object sourceObject, Class javaClass, AbstractSession session) throws ConversionException;

/**
* The platform hold its own instance of conversion manager to allow customization.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,20 @@ public Object convertObject(Object sourceObject, Class javaClass) throws Convers
return getConversionManager().convertObject(sourceObject, javaClass);
}

/**
* Convert the object to the appropriate type by invoking the appropriate
* ConversionManager method.
* @param sourceObject the object that must be converted
* @param javaClass the class that the object must be converted to
* @param session current database session
* @exception ConversionException all exceptions will be thrown as this type.
* @return the newly converted object
*/
@Override
public Object convertObject(Object sourceObject, Class javaClass, AbstractSession session) throws ConversionException {
return convertObject(sourceObject, javaClass);
}

/**
* Copy the state into the new platform.
*/
Expand Down Expand Up @@ -286,6 +300,13 @@ public void setConversionManager(ConversionManager conversionManager) {
this.conversionManager = conversionManager;
}

/**
* Return the driver version.
*/
public String getDriverVersion() {
return "";
}

/**
* Delimiter to use for fields and tables using spaces or other special values.
*
Expand Down Expand Up @@ -645,6 +666,11 @@ public boolean isOracle9() {
return false;
}

@Override
public boolean isOracle23() {
return false;
}

public boolean isPervasive(){
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023 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
Expand Down Expand Up @@ -47,6 +47,17 @@ public interface Platform extends CorePlatform<ConversionManager>, Serializable,
*/
public Object convertObject(Object sourceObject, Class javaClass) throws ConversionException;

/**
* Convert the object to the appropriate type by invoking the appropriate
* ConversionManager method.
* @param sourceObject the object that must be converted
* @param javaClass the class that the object must be converted to
* @param session current database session
* @exception ConversionException all exceptions will be thrown as this type.
* @return the newly converted object
*/
public Object convertObject(Object sourceObject, Class javaClass, AbstractSession session) throws ConversionException;

/**
* Copy the state into the new platform.
*/
Expand All @@ -63,6 +74,11 @@ public interface Platform extends CorePlatform<ConversionManager>, Serializable,
*/
public void setConversionManager(ConversionManager conversionManager);

/**
* Return the driver version.
*/
public String getDriverVersion();

/**
* Return the qualifier for the table. Required by some
* databases such as Oracle and DB2
Expand Down Expand Up @@ -113,6 +129,8 @@ public interface Platform extends CorePlatform<ConversionManager>, Serializable,

public boolean isOracle9();

public boolean isOracle23();

public boolean isPointBase();

public boolean isSQLAnywhere();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023 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
Expand Down Expand Up @@ -207,7 +207,12 @@ public void setObjectClassName(String objectClassName) {
*/
public Object convertObjectValueToDataValue(Object attributeValue, Session session) {
try {
return ((AbstractSession)session).getDatasourcePlatform().convertObject(attributeValue, getDataClass());
if (session.isConnected()) {
//Should handle conversions where DB connection is needed like String -> java.sql.Clob
return session.getDatasourcePlatform().convertObject(attributeValue, getDataClass(), (AbstractSession)session);
} else {
return session.getDatasourcePlatform().convertObject(attributeValue, getDataClass());
}
} catch (ConversionException e) {
throw ConversionException.couldNotBeConverted(mapping, mapping.getDescriptor(), e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2023 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
package org.eclipse.persistence.platform.database;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.sessions.AbstractSession;

import java.sql.Clob;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;

import static org.eclipse.persistence.internal.helper.StringHelper.EMPTY_STRING;

public class Oracle23Platform extends Oracle21Platform {
public Oracle23Platform() {
super();
}

@Override
protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
Hashtable<Class<?>, FieldTypeDefinition> fieldTypes = super.buildFieldTypes();
fieldTypes.put(java.time.LocalDateTime.class, new FieldTypeDefinition("TIMESTAMP", 9));
fieldTypes.put(java.time.LocalTime.class, new FieldTypeDefinition("TIMESTAMP", 9));
return fieldTypes;
}

/**
* INTERNAL:
* Check whether current platform is Oracle 23c or later.
* @return Always returns {@code true} for instances of Oracle 23c platform.
* @since 2.7.14
*/
@Override
public boolean isOracle23() {
return true;
}

/**
* INTERNAL:
* Allow for conversion from the Oracle type to the Java type. Used in cases when DB connection is needed like BLOB, CLOB.
*/
@Override
public Object convertObject(Object sourceObject, Class javaClass, AbstractSession session) throws ConversionException, DatabaseException {
//Handle special case when empty String ("") is passed from the entity into CLOB type column
if (ClassConstants.CLOB.equals(javaClass) && sourceObject instanceof String && EMPTY_STRING.equals(sourceObject)) {
Connection connection = session.getAccessor().getConnection();
Clob clob = null;
try {
clob = connection.createClob();
clob.setString(1, (String)sourceObject);
} catch (SQLException e) {
throw ConversionException.couldNotBeConvertedToClass(sourceObject, ClassConstants.CLOB, e);
}
return clob;
}
return super.convertObject(sourceObject, javaClass);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -56,6 +56,8 @@
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.database.jdbc.JDBCTypes;
import org.eclipse.persistence.platform.database.oracle.jdbc.OracleArrayType;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
Expand Down Expand Up @@ -488,6 +490,7 @@ public void useNamedCursorOutputAsResultSet(String argumentName, DatabaseType da
protected void assignIndices() {
List<PLSQLargument> inArguments = getArguments(arguments, ParameterType.IN);
List<PLSQLargument> inOutArguments = getArguments(arguments, ParameterType.INOUT);
DatabasePlatform platform = this.getQuery().getSession().getPlatform();
inArguments.addAll(inOutArguments);
int newIndex = 1;
List<PLSQLargument> expandedArguments = new ArrayList<PLSQLargument>();
Expand All @@ -509,6 +512,10 @@ protected void assignIndices() {
}
for (PLSQLargument inArg : inArguments) {
DatabaseType type = inArg.databaseType;
if (platform.isOracle23() && type == OraclePLSQLTypes.PLSQLBoolean && Helper.compareVersions(platform.getDriverVersion(), "23.0.0") >= 0) {
type = JDBCTypes.BOOLEAN_TYPE;
inArg.databaseType = JDBCTypes.BOOLEAN_TYPE;
}
String inArgName = inArg.name;
if (!type.isComplexDatabaseType()) {
// for XMLType, we need to set type name parameter (will be "XMLTYPE")
Expand Down Expand Up @@ -562,6 +569,10 @@ protected void assignIndices() {
super.useNamedCursorOutputAsResultSet(outArgName);
} else {
DatabaseType type = outArg.databaseType;
if (platform.isOracle23() && type == OraclePLSQLTypes.PLSQLBoolean && Helper.compareVersions(platform.getDriverVersion(), "23.0.0") >= 0) {
type = JDBCTypes.BOOLEAN_TYPE;
outArg.databaseType = JDBCTypes.BOOLEAN_TYPE;
}
if (!type.isComplexDatabaseType()) {
// for XMLType, we need to set type name parameter (will be "XMLTYPE")
if (type == XMLType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2023 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
package org.eclipse.persistence.platform.database.oracle;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.sessions.AbstractSession;

import java.sql.Clob;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Hashtable;

import static org.eclipse.persistence.internal.helper.StringHelper.EMPTY_STRING;

/**
* <p><b>Purpose:</b>
* Supports certain new Oracle 23c data types, and usage of certain Oracle JDBC specific APIs.
* <p> Supports Oracle JSON data type.
* <p> Supports Oracle OracleJsonValue derived Java types.
*/
public class Oracle23Platform extends Oracle21Platform {

/**
* Creates an instance of Oracle 23c database platform.
*/
public Oracle23Platform() {
super();
}

/**
* INTERNAL:
* Check whether current platform is Oracle 23c or later.
* @return Always returns {@code true} for instances of Oracle 23c platform.
* @since 4.0.2
*/
@Override
public boolean isOracle23() {
return true;
}

@Override
protected Hashtable<Class<?>, FieldTypeDefinition> buildFieldTypes() {
Hashtable<Class<?>, FieldTypeDefinition> fieldTypes = super.buildFieldTypes();
fieldTypes.put(java.time.LocalDateTime.class, new FieldTypeDefinition("TIMESTAMP", 9));
fieldTypes.put(java.time.LocalTime.class, new FieldTypeDefinition("TIMESTAMP", 9));
return fieldTypes;
}

/**
* INTERNAL:
* Allow for conversion from the Oracle type to the Java type. Used in cases when DB connection is needed like BLOB, CLOB.
*/
@Override
public Object convertObject(Object sourceObject, Class javaClass, AbstractSession session) throws ConversionException, DatabaseException {
//Handle special case when empty String ("") is passed from the entity into CLOB type column
if (ClassConstants.CLOB.equals(javaClass) && sourceObject instanceof String && EMPTY_STRING.equals(sourceObject)) {
Connection connection = session.getAccessor().getConnection();
Clob clob = null;
try {
clob = connection.createClob();
clob.setString(1, (String)sourceObject);
} catch (SQLException e) {
throw ConversionException.couldNotBeConvertedToClass(sourceObject, ClassConstants.CLOB, e);
}
return clob;
}
return super.convertObject(sourceObject, javaClass);
}
}
Loading

0 comments on commit 307a58f

Please sign in to comment.