org.eclipse.persistence.internal.helper.DatabaseType Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.persistence.core Show documentation
Show all versions of org.eclipse.persistence.core Show documentation
EclipseLink build based upon Git transaction ecdf3c32c4
/*
* Copyright (c) 1998, 2018 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.internal.helper;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import static java.lang.Integer.MIN_VALUE;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
import static org.eclipse.persistence.internal.databaseaccess.DatasourceCall.IN;
import static org.eclipse.persistence.internal.databaseaccess.DatasourceCall.OUT;
import static org.eclipse.persistence.internal.helper.Helper.NL;
import static org.eclipse.persistence.internal.helper.Helper.buildHexStringFromBytes;
/**
* PUBLIC: Interface used to categorize arguments to Stored Procedures as either
* 'simple' (use subclass SimpleDatabaseType) or 'complex' (use subclass ComplexDatabaseType)
*
* @author Mike Norman - [email protected]
* @since Oracle TopLink 11.x.x
*/
@SuppressWarnings("unchecked")
public interface DatabaseType {
public static final String TARGET_SHORT_PREFIX = "T_";
public static final String TARGET_SUFFIX = "TARGET";
public static final String COMPAT_SHORT_PREFIX = "C_";
public static final String COMPAT_SUFFIX = "COMPAT";
public static final int ARGNAME_SIZE_LIMIT = 30 - TARGET_SUFFIX.length();
public boolean isComplexDatabaseType();
public boolean isJDBCType();
public int getSqlCode();
public int getConversionCode();
public String getTypeName();
public int computeInIndex(PLSQLargument inArg, int newIndex,
ListIterator i);
public int computeOutIndex(PLSQLargument outArg, int newIndex,
ListIterator i);
public void buildInDeclare(StringBuilder sb, PLSQLargument inArg);
public void buildOutDeclare(StringBuilder sb, PLSQLargument outArg);
public void buildBeginBlock(StringBuilder sb, PLSQLargument arg, PLSQLStoredProcedureCall call);
public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call);
public void translate(PLSQLargument arg, AbstractRecord translationRow,
AbstractRecord copyOfTranslationRow, List copyOfTranslationFields,
List translationRowFields, List translationRowValues,
StoredProcedureCall call);
public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow,
DatabaseRecord newOutputRow, List outputRowFields, List outputRowValues);
public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg,
AbstractRecord translationRow, DatabasePlatform platform);
public enum DatabaseTypeHelper {
databaseTypeHelper;
static String getTruncatedSHA1Hash(String s) {
StringBuilder sb = new StringBuilder(28);
try {
byte[] longIdentifierBytes = s.getBytes();
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(longIdentifierBytes, 0, longIdentifierBytes.length);
byte[] digest = md.digest(); //produces a 160-bit hash
//truncate to 112 bits, which is about the same java.util.UUID;
//HMAC-SHA1-96 is only 96 bits and that's good enough for IPSEC work
//TL;DR - probability of collision quite small
byte[] truncDigest = new byte[14];
System.arraycopy(digest, 0, truncDigest, 0, 14);
sb.append(buildHexStringFromBytes(truncDigest));
}
catch (NoSuchAlgorithmException e) {
//ignore: should never happen
}
return sb.toString();
}
protected String getTruncatedSHA1Name(String argName, String prefix) {
if (argName.length() >= ARGNAME_SIZE_LIMIT) {
StringBuilder sb = new StringBuilder();
//the truncated SHA is great, but a PL/SQL identifier
//can't start with a number, so use prefix
sb.append(prefix);
sb.append(getTruncatedSHA1Hash(argName));
return sb.toString();
}
return argName;
}
public String buildTarget(PLSQLargument arg) {
StringBuilder sb = new StringBuilder();
if (arg.name.length() >= ARGNAME_SIZE_LIMIT) {
sb.append(getTruncatedSHA1Name(arg.name, TARGET_SHORT_PREFIX));
}
else {
sb.append(arg.name);
sb.append(TARGET_SUFFIX);
}
return sb.toString();
}
public String buildCompatible(PLSQLargument arg) {
StringBuilder sb = new StringBuilder();
if (arg.name.length() >= ARGNAME_SIZE_LIMIT) {
sb.append(getTruncatedSHA1Name(arg.name, COMPAT_SHORT_PREFIX));
}
else {
sb.append(arg.name);
sb.append(COMPAT_SUFFIX);
}
return sb.toString();
}
public void declareTarget(StringBuilder sb, PLSQLargument arg,
DatabaseType databaseType) {
sb.append(" ");
sb.append(buildTarget(arg));
sb.append(" ");
sb.append(databaseType.getTypeName());
}
public int computeInIndex(PLSQLargument inArg, int newIndex) {
inArg.inIndex = newIndex;
return ++newIndex;
}
public int computeOutIndex(PLSQLargument outArg, int newIndex) {
outArg.outIndex = newIndex;
return ++newIndex;
}
public void buildOutAssignment(StringBuilder sb, PLSQLargument outArg, PLSQLStoredProcedureCall call) {
sb.append(" :");
sb.append(outArg.outIndex);
sb.append(" := ");
sb.append(buildTarget(outArg));
sb.append(";");
sb.append(NL);
}
public void translate(PLSQLargument arg, AbstractRecord translationRow,
AbstractRecord copyOfTranslationRow, List copyOfTranslationFields,
List translationRowFields, List translationRowValues,
StoredProcedureCall call) {
DatabaseField field = null;
for (Iterator i = copyOfTranslationFields.iterator(); i.hasNext(); ) {
DatabaseField f = (DatabaseField)i.next();
if (f.getName().equals(arg.name)) {
field = f;
break;
}
}
if (arg.length != MIN_VALUE) {
field.setLength(arg.length);
}
if (arg.precision != MIN_VALUE) {
field.setPrecision(arg.precision);
}
if (arg.scale != MIN_VALUE) {
field.setScale(arg.scale);
}
translationRowFields.set(arg.inIndex - 1, field);
Object value = copyOfTranslationRow.get(field);
translationRowValues.set(arg.inIndex - 1, value);
}
public void buildOutputRow(PLSQLargument outArg, AbstractRecord outputRow,
DatabaseRecord newOutputRow, List outputRowFields, List outputRowValues) {
DatabaseField field = null;
for (Iterator i = outputRowFields.iterator(); i.hasNext(); ) {
DatabaseField f = (DatabaseField)i.next();
if (f.getName().equals(outArg.name)) {
field = f;
break;
}
}
Object value = outputRow.get(field);
newOutputRow.add(field, value);
}
public void logParameter(StringBuilder sb, Integer direction, PLSQLargument arg,
AbstractRecord translationRow, DatabasePlatform platform) {
if (direction == IN && arg.inIndex != MIN_VALUE) {
sb.append(":");
sb.append(arg.inIndex);
sb.append(" => ");
sb.append(platform.convertToDatabaseType(translationRow.get(arg.name)));
}
if (direction == OUT && arg.outIndex != MIN_VALUE) {
sb.append(arg.name);
sb.append(" => :");
sb.append(arg.outIndex);
}
}
}
}