blob: a7e8a93c78a8b1a0fa3d8c1614adec9ccf664dc1 [file] [log] [blame]
/*
* 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
* 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.plsql;
import static java.sql.Types.OTHER;
import static java.sql.Types.STRUCT;
import static org.eclipse.persistence.internal.databaseaccess.DatasourceCall.IN;
import static org.eclipse.persistence.internal.databaseaccess.DatasourceCall.INOUT;
import static org.eclipse.persistence.internal.databaseaccess.DatasourceCall.OUT;
import static org.eclipse.persistence.internal.helper.DatabaseType.DatabaseTypeHelper.databaseTypeHelper;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.helper.ComplexDatabaseType;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseType;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
/**
* <b>PUBLIC</b>: describe an Oracle PL/SQL Record type
* @author Mike Norman - michael.norman@oracle.com
* @since Oracle TopLink 11.x.x
*/
public class PLSQLrecord extends ComplexDatabaseType implements OraclePLSQLType, Cloneable {
protected List<PLSQLargument> fields = new ArrayList<>();
public PLSQLrecord() {
super();
}
@Override
public PLSQLrecord clone() {
PLSQLrecord clone = (PLSQLrecord)super.clone();
clone.fields = new ArrayList<>(fields.size());
for (PLSQLargument f : fields) {
clone.fields.add(f.clone());
}
return clone;
}
@Override
public boolean isRecord() {
return true;
}
/**
* Return the record's fields defined as PLSQLargument.
*/
public List<PLSQLargument> getFields() {
return fields;
}
@Override
public int getSqlCode() {
if (hasCompatibleType()) {
return STRUCT;
} else {
return OTHER;
}
}
public void addField(PLSQLargument field) {
fields.add(field);
}
public void addField(String fieldName, DatabaseType databaseType) {
fields.add(new PLSQLargument(fieldName, -1, IN, databaseType));
}
public void addField(String fieldName, DatabaseType databaseType, int precision, int scale) {
fields.add(new PLSQLargument(fieldName, -1, IN, databaseType, precision, scale));
}
public void addField(String fieldName, DatabaseType databaseType, int length) {
fields.add(new PLSQLargument(fieldName, -1, IN, databaseType, length));
}
@Override
public int computeInIndex(PLSQLargument inArg, int newIndex, ListIterator<PLSQLargument> iterator) {
if (hasCompatibleType()) {
return super.computeInIndex(inArg, newIndex, iterator);
}
else {
iterator.remove();
inArg.inIndex = newIndex;
for (PLSQLargument argument : fields) {
argument.inIndex = newIndex++;
iterator.add(argument);
}
return newIndex;
}
}
@Override
public int computeOutIndex(PLSQLargument outArg, int newIndex,
ListIterator<PLSQLargument> iterator) {
if (hasCompatibleType()) {
return super.computeOutIndex(outArg, newIndex, iterator);
}
else {
iterator.remove();
outArg.outIndex = newIndex;
for (PLSQLargument argument : fields) {
argument.outIndex = newIndex++;
argument.direction = OUT;
iterator.add(argument);
}
return newIndex;
}
}
@Override
public void buildInDeclare(StringBuilder sb, PLSQLargument inArg) {
if (hasCompatibleType()) {
super.buildInDeclare(sb, inArg);
} else {
if ((getTypeName() == null) || getTypeName().equals("")) {
throw QueryException.typeNameNotSet(this);
}
sb.append(" ");
sb.append(databaseTypeHelper.buildTarget(inArg));
sb.append(" ");
sb.append(getTypeName());
sb.append(";\n");
}
}
@Override
public void buildOutDeclare(StringBuilder sb, PLSQLargument outArg) {
if (hasCompatibleType()) {
super.buildOutDeclare(sb, outArg);
} else {
if ((getTypeName() == null) || getTypeName().equals("")) {
throw QueryException.typeNameNotSet(this);
}
sb.append(" ");
sb.append(databaseTypeHelper.buildTarget(outArg));
sb.append(" ");
sb.append(getTypeName());
sb.append(";\n");
}
}
@Override
public void buildBeginBlock(StringBuilder sb, PLSQLargument arg, PLSQLStoredProcedureCall call) {
if (hasCompatibleType()) {
super.buildBeginBlock(sb, arg, call);
} else {
String target = databaseTypeHelper.buildTarget(arg);
if (arg.direction == IN || arg.direction == INOUT) {
for (PLSQLargument f : fields) {
sb.append(" ");
sb.append(target);
sb.append('.');
sb.append(f.name);
sb.append(" := ");
sb.append(":");
sb.append(f.inIndex);
sb.append(";\n");
}
}
}
}
@Override
public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call) {
if (hasCompatibleType()) {
super.buildOutAssignment(sb, outArg, call);
} else {
String target = databaseTypeHelper.buildTarget(outArg);
for (PLSQLargument f : fields) {
sb.append(" ");
sb.append(":");
sb.append(f.outIndex);
sb.append(" := ");
sb.append(target);
sb.append('.');
sb.append(f.name);
sb.append(";\n");
}
}
}
@Override
public void translate(PLSQLargument arg, AbstractRecord translationRow,
AbstractRecord copyOfTranslationRow, List<DatabaseField> copyOfTranslationFields,
List<DatabaseField> translationRowFields, List translationRowValues,
StoredProcedureCall call) {
if (hasCompatibleType()) {
super.translate(arg, translationRow, copyOfTranslationRow,
copyOfTranslationFields, translationRowFields, translationRowValues, call);
} else {
for (PLSQLargument argument : fields) {
databaseTypeHelper.translate(argument, translationRow, copyOfTranslationRow,
copyOfTranslationFields, translationRowFields, translationRowValues, call);
}
}
}
@Override
public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow,
DatabaseRecord newOutputRow, List<DatabaseField> outputRowFields, List outputRowValues) {
if (hasCompatibleType()) {
super.buildOutputRow(outArg, outputRow, newOutputRow, outputRowFields, outputRowValues);
} else {
for (PLSQLargument field : fields) {
databaseTypeHelper.buildOutputRow(field, outputRow, newOutputRow,
outputRowFields, outputRowValues);
}
}
}
@Override
public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg,
AbstractRecord translationRow, DatabasePlatform platform) {
if (hasCompatibleType()) {
super.logParameter(sb, direction, arg, translationRow, platform);
} else {
for (Iterator<PLSQLargument> iterator = fields.iterator(); iterator.hasNext(); ) {
PLSQLargument argument = iterator.next();
argument.databaseType.logParameter(sb, direction, argument, translationRow,
platform);
if (iterator.hasNext()) {
sb.append(", ");
}
}
}
}
}