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

[master] SQL Struct with @Lob (BLOB, CLOB) used as stored procedure parameter type - fix #1302

Merged
merged 3 commits into from
Sep 21, 2021
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
Expand Up @@ -3389,6 +3389,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, 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
Expand Down Expand Up @@ -189,17 +189,17 @@ public void buildOutDeclare(StringBuilder sb, PLSQLargument outArg) {// Validate

@Override
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, 2019 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 @@ -339,7 +339,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
Expand Up @@ -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, 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
Expand All @@ -18,12 +18,22 @@

import java.io.IOException;
import java.io.Writer;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Struct;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.ConversionException;
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;
import org.eclipse.persistence.internal.sessions.EmptyRecord;
import org.eclipse.persistence.logging.SessionLog;
Expand Down Expand Up @@ -151,4 +161,29 @@ public void printFieldIdentityClause(final Writer writer) throws ValidationExcep
}
}

/**
* 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 super.createStruct(structTypeName, attributes, session, connection);
}
}
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 jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.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 jakarta.persistence.Column;
import jakarta.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 +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.eclipse.persistence.annotations.Direction;
import org.eclipse.persistence.platform.database.oracle.annotations.*;

@Entity
@NamedPLSQLStoredFunctionQueries(value = {
@NamedPLSQLStoredFunctionQuery(name = "PLSQL_BLOB_REC_IN", functionName = "PLSQL_P.PLSQL_BLOB_REC_IN",
parameters = {@PLSQLParameter(name = "P_BLOB_REC", direction = Direction.IN, databaseType = "PLSQL_P_PLSQL_INNER_BLOB_REC"),
@PLSQLParameter(name = "P_CITY", direction = Direction.IN, databaseType = "VARCHAR_TYPE")},
returnParameter = @PLSQLParameter(name = "RESULT", direction = Direction.OUT, databaseType = "VARCHAR_TYPE")),
@NamedPLSQLStoredFunctionQuery(name = "PLSQL_STRUCT_INSTRUCT_REC_IN", functionName = "PLSQL_P.PLSQL_STRUCT_INSTRUCT_REC_IN",
parameters = {@PLSQLParameter(name = "P_BLOB_REC", databaseType = "PLSQL_P_PLSQL_INNER_BLOB_REC"),
@PLSQLParameter(name = "P_STRUCT_REC", databaseType = "PLSQL_P_PLSQL_OUTER_STRUCT_REC"),
@PLSQLParameter(name = "P_CITY", databaseType = "VARCHAR_TYPE")},
returnParameter = @PLSQLParameter(name = "RESULT", direction = Direction.OUT, databaseType = "VARCHAR_TYPE"))
}
)
@PLSQLRecords(value = {
@PLSQLRecord(name = "PLSQL_P_PLSQL_INNER_BLOB_REC", compatibleType = "PLSQL_P_PLSQL_INNER_BLOB_REC", javaType = InnerObjBlob.class,
fields = {
@PLSQLParameter(name = "BLOB_ID", databaseType = "NUMERIC_TYPE"),
@PLSQLParameter(name = "BLOB_CONTENT", databaseType = "BLOB_TYPE"),
@PLSQLParameter(name = "CLOB_CONTENT", databaseType = "CLOB_TYPE")
}
),
@PLSQLRecord(name = "PLSQL_P_PLSQL_OUTER_STRUCT_REC", compatibleType = "PLSQL_P_PLSQL_OUTER_STRUCT_REC", javaType = OuterObjBlob.class,
fields = {
@PLSQLParameter(name = "STRUCT_ID", databaseType = "NUMERIC_TYPE"),
@PLSQLParameter(name = "STRUCT_CONTENT", databaseType = "PLSQL_P_PLSQL_INNER_BLOB_REC")
}

)
}
)
public class SaveComplexBlob {

@Id
@Column(name = "RESULT")
private String result;

public String getResult() {
return result;
}

public void setResult(String result) {
this.result = result;
}
}
Loading