Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2.7] SQL Struct with @Lob (BLOB, CLOB) used as stored procedure parameter type - backport from 2.6 #1339

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2019 IBM Corporation. All rights reserved.
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021 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
Expand Down Expand Up @@ -3425,6 +3425,16 @@ public Struct createStruct(String structTypeName, Object[] attributes, AbstractS
return createStruct(structTypeName,attributes,unwrappedConnection);
}

/**
* INTERNAL:
* This method builds a Struct using the unwrapped connection within the session
* @return Struct
*/
public Struct createStruct(String structTypeName, Object[] attributes, AbstractRecord row, Vector orderedFields, AbstractSession session, Connection connection) throws SQLException {
java.sql.Connection unwrappedConnection = getConnection(session, connection);
return createStruct(structTypeName,attributes,unwrappedConnection);
}

/**
* INTERNAL:
* Platforms that support java.sql.Array may override this method.
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, 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
Expand Down Expand Up @@ -181,17 +181,17 @@ public void buildOutDeclare(StringBuilder sb, PLSQLargument outArg) {// Validate
}

public void buildBeginBlock(StringBuilder sb, PLSQLargument arg, PLSQLStoredProcedureCall call) {
String sql2PlName = call.getSQL2PlName(this);
if (sql2PlName == null) {
String conversionRoutine = ((this.getTypeName().equals(this.getCompatibleType()))) ? call.getPl2SQLName(this) : call.getSQL2PlName(this);
if (conversionRoutine == null) {
// TODO exception
throw new NullPointerException("no SQL2Pl conversion routine for " + typeName);
throw new NullPointerException("no SQL2Pl or Pl2SQL conversion routine for " + typeName);
}
String target = databaseTypeHelper.buildTarget(arg);
String compat = databaseTypeHelper.buildCompatible(arg);
sb.append(" ");
sb.append(target);
sb.append(" := ");
sb.append(sql2PlName);
sb.append(conversionRoutine);
sb.append("(");
sb.append(compat);
sb.append(");");
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, 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
Expand Down Expand Up @@ -340,7 +340,7 @@ public Struct buildStructureFromRow(AbstractRecord row, AbstractSession session,
fields[index] = row.get(field);
}

structure = session.getPlatform().createStruct(getStructureName(), fields, session, connection);
structure = session.getPlatform().createStruct(getStructureName(), fields, row, getOrderedFields(), session, connection);
} catch (java.sql.SQLException exception) {
throw DatabaseException.sqlException(exception, session, false);
} finally {
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, 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
Expand Down Expand Up @@ -641,12 +641,12 @@ protected void buildDeclareBlock(StringBuilder sb, List<PLSQLargument> arguments
* must be added in inverse order to resolve dependencies.
*/
protected void addNestedFunctionsForArgument(List functions, PLSQLargument argument,
DatabaseType databaseType, Set<DatabaseType> processed) {
DatabaseType databaseType, Set<DatabaseType> processed) {
if ((databaseType == null)
|| !databaseType.isComplexDatabaseType()
|| databaseType.isJDBCType()
|| argument.cursorOutput
|| processed.contains(databaseType)) {
|| !databaseType.isComplexDatabaseType()
|| databaseType.isJDBCType()
|| argument.cursorOutput
|| processed.contains(databaseType)) {
return;
}
ComplexDatabaseType type = (ComplexDatabaseType)databaseType;
Expand All @@ -670,20 +670,26 @@ protected void addNestedFunctionsForArgument(List functions, PLSQLargument argum
if (info == null) {
info = generateNestedFunction(type, isNestedTable);
}
if (argument.direction == IN) {
if (!functions.contains(info.sql2PlConv)) {
functions.add(info.sql2PlConv);
}
} else if (argument.direction == INOUT) {
if (!functions.contains(info.sql2PlConv)) {
functions.add(info.sql2PlConv);
}
if (type.getTypeName().equals(type.getCompatibleType())) {
if (!functions.contains(info.pl2SqlConv)) {
functions.add(info.pl2SqlConv);
}
} else if (argument.direction == OUT) {
if (!functions.contains(info.pl2SqlConv)) {
functions.add(info.pl2SqlConv);
} else {
if (argument.direction == IN) {
if (!functions.contains(info.sql2PlConv)) {
functions.add(info.sql2PlConv);
}
} else if (argument.direction == INOUT) {
if (!functions.contains(info.sql2PlConv)) {
functions.add(info.sql2PlConv);
}
if (!functions.contains(info.pl2SqlConv)) {
functions.add(info.pl2SqlConv);
}
} else if (argument.direction == OUT) {
if (!functions.contains(info.pl2SqlConv)) {
functions.add(info.pl2SqlConv);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2018 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
Expand All @@ -16,6 +16,19 @@
// - 426852: @GeneratedValue(strategy=GenerationType.IDENTITY) support in Oracle 12c
package org.eclipse.persistence.platform.database.oracle;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Struct;
import java.util.Vector;

import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
* <p><b>Purpose:</b>
* Supports usage of certain Oracle JDBC specific APIs for the Oracle 12 database.
Expand All @@ -24,4 +37,42 @@ public class Oracle12Platform extends Oracle11Platform {
public Oracle12Platform() {
super();
}

/**
* INTERNAL:
* This method builds a Struct using the unwrapped connection within the session
* @return Struct
*/
@Override
public Struct createStruct(String structTypeName, Object[] attributes, AbstractRecord row, Vector orderedFields, AbstractSession session, Connection connection) throws SQLException {
for (int index = 0; index < orderedFields.size(); index++) {
DatabaseField field = (DatabaseField)orderedFields.elementAt(index);
if (row.getField(field) != null && row.getField(field).getTypeName() != null) {
if (ClassConstants.BLOB.getTypeName().equals(row.getField(field).getTypeName())) {
Blob blob = connection.createBlob();
blob.setBytes(1L, (byte[]) row.get(field));
attributes[index] = blob;
} else if (ClassConstants.CLOB.getTypeName().equals(row.getField(field).getTypeName())) {
Clob clob = connection.createClob();
clob.setString(1L, (String) attributes[index]);
attributes[index] = clob;
}
} else {
attributes[index] = row.get(field);
}
}
return createStruct(structTypeName, attributes, connection);
}

/**
* Create java.sql.Struct from given parameters.
* @param structTypeName - the SQL type name of the SQL structured type that this Struct object maps to.
* @param attributes - the attributes that populate the returned object
* @param connection - DB connection
* @return Struct
*/
@Override
public Struct createStruct(String structTypeName, Object[] attributes, Connection connection) throws SQLException {
return connection.createStruct(structTypeName, attributes);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 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
* 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 implementation
package org.eclipse.persistence.testing.models.jpa.plsql;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Lob;
import org.eclipse.persistence.annotations.Struct;

import java.util.Arrays;

@Embeddable
@Struct(name="PLSQL_P_PLSQL_INNER_BLOB_REC", fields={"BLOB_ID", "BLOB_CONTENT", "CLOB_CONTENT"})
public class InnerObjBlob {

public InnerObjBlob() {
}

public InnerObjBlob(int blobId, byte[] blobContent, String clobContent) {
this.blobId = blobId;
this.blobContent = blobContent;
this.clobContent = clobContent;
}

@Column(name="BLOB_ID")
private int blobId;

@Column(name="BLOB_CONTENT")
@Lob
private byte[] blobContent;

@Column(name="CLOB_CONTENT")
@Lob
private String clobContent;

public int getBlobId() {
return blobId;
}

public void setBlobId(int blobId) {
this.blobId = blobId;
}

public byte[] getBlobContent() {
return blobContent;
}

public void setBlobContent(byte[] blobContent) {
this.blobContent = blobContent;
}

public String getClobContent() {
return clobContent;
}

public void setClobContent(String clobContent) {
this.clobContent = clobContent;
}

@Override
public String toString() {
return "InnerObjBlob{" +
"blobId=" + blobId +
", blobContent=" + Arrays.toString(blobContent) +
", clobContent='" + clobContent + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 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
* 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 implementation
package org.eclipse.persistence.testing.models.jpa.plsql;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import org.eclipse.persistence.annotations.Struct;

@Embeddable
@Struct(name="PLSQL_P_PLSQL_OUTER_STRUCT_REC", fields={"STRUCT_ID", "STRUCT_CONTENT"})
public class OuterObjBlob {

public OuterObjBlob() {
}

public OuterObjBlob(int structId, InnerObjBlob structContent) {
this.structId = structId;
this.structContent = structContent;
}

@Column(name="STRUCT_ID")
private int structId;

@Column(name="STRUCT_CONTENT")
private InnerObjBlob structContent;

public int getStructId() {
return structId;
}

public void setStructId(int structId) {
this.structId = structId;
}

public InnerObjBlob getStructContent() {
return structContent;
}

public void setStructContent(InnerObjBlob structContent) {
this.structContent = structContent;
}

@Override
public String toString() {
return "OuterObjBBlob{" +
"structId=" + structId +
", structContent=" + structContent +
'}';
}
}
Loading