org.eclipse.persistence.queries.StoredProcedureCall Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* 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
* 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
// 09/27/2012-2.5 Guy Pelletier
// - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
package org.eclipse.persistence.queries;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.structures.ObjectRelationalDatabaseField;
/**
* Purpose: Used to define a platform independent procedure call.
* This supports output parameters.
* Procedures can also be called through custom SQL.
*/
public class StoredProcedureCall extends DatabaseCall {
protected String procedureName;
protected List procedureArgumentNames;
protected List optionalArguments;
public StoredProcedureCall() {
super();
}
/**
* PUBLIC:
* Define the argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterAndArgumentFieldName is the name of the procedure argument expected,
* and is the field or argument name to be used to pass to the procedure.
* These names are assumed to be the same, if not this method can be called with two arguments.
*/
public void addNamedArgument(String procedureParameterAndArgumentFieldName) {
addNamedArgument(procedureParameterAndArgumentFieldName, procedureParameterAndArgumentFieldName);
}
/**
* PUBLIC:
* Define the argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName) {
getProcedureArgumentNames().add(procedureParameterName);
appendIn(new DatabaseField(argumentFieldName));
}
/**
* PUBLIC:
* Define the argument to the stored procedure and the value to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentValue is the value of the argument to be used to pass to the procedure.
*/
public void addNamedArgumentValue(String procedureParameterName, Object argumentValue) {
getProcedureArgumentNames().add(procedureParameterName);
appendIn(argumentValue);
}
/**
* PUBLIC:
* Define the input argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the user.
* The type is the type of Java class for the field, and is dependent on the type required by the procedure. This is used
* to set the type in case null is passed in.
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, Class> type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setType(type);
appendIn(field);
}
/**
* PUBLIC:
* Define the input argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the user.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, int type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setSqlType(type);
appendIn(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, int type,
String typeName) {
addNamedArgument(procedureParameterName, argumentFieldName, type, typeName, (Class)null);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
* The javaType is the mapped Class that has an ObjectRelationalDataTypeDescriptor for the ARRAY
* or STRUCT type typeName
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, int type,
String typeName, Class> javaType) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setType(javaType);
field.setSqlTypeName(typeName);
appendIn(field);
}
/**
* PUBLIC:
* Define the inout argument to the stored procedure and the field/argument name to be substituted for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
* The javaType is the mapped Class that has an ObjectRelationalDataTypeDescriptor for the ARRAY
* or STRUCT type typeName
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, int type, String typeName, Class> javaType, DatabaseField nestedType) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setType(javaType);
field.setSqlTypeName(typeName);
field.setNestedTypeField(nestedType);
appendIn(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
* The javaType is the name of the mapped Class that has an ObjectRelationalDataTypeDescriptor
* for the ARRAY or STRUCT type typeName
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, int type,
String typeName, String javaTypeName) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setTypeName(javaTypeName);
field.setSqlTypeName(typeName);
appendIn(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, as required for STRUCT and ARRAY types.
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addNamedArgument(String procedureParameterName, String argumentFieldName, int type, String typeName, DatabaseField nestedType) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setSqlTypeName(typeName);
field.setNestedTypeField(nestedType);
appendIn(field);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterAndArgumentFieldName is the name of the procedure argument expected,
* the field or argument name to be used to pass to the procedure and,
* the field or argument name to be used is the result of the output row.
*/
public void addNamedInOutputArgument(String procedureParameterAndArgumentFieldName) {
getProcedureArgumentNames().add(procedureParameterAndArgumentFieldName);
appendInOut(new DatabaseField(procedureParameterAndArgumentFieldName));
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure and
* is the result of the output row.
*/
public void addNamedInOutputArgument(String procedureParameterName, String argumentFieldName) {
addNamedInOutputArgument(procedureParameterName, argumentFieldName, argumentFieldName, null);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure and
* is the result of the output row.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addNamedInOutputArgument(String procedureParameterName, String argumentFieldName, Class> type) {
addNamedInOutputArgument(procedureParameterName, argumentFieldName, argumentFieldName, type);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The inArgumentFieldName is the field or argument name to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type the Java class desired back from the procedure, if a struct is returned and the class has an ObjectRelationalDataTypeDescriptor defined .
*/
public void addNamedInOutputArgument(String procedureParameterName, String inArgumentFieldName, String outArgumentFieldName, Class> type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField inField = new DatabaseField(inArgumentFieldName);
inField.setType(type);
if (inArgumentFieldName.equals(outArgumentFieldName)) {
appendInOut(inField);
} else {
DatabaseField outField = new DatabaseField(outArgumentFieldName);
outField.setType(type);
appendInOut(inField, outField);
}
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The inArgumentFieldName is the field or argument name to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this dependent on the type returned from the procedure.
*/
public void addNamedInOutputArgument(String procedureParameterName, String inArgumentFieldName, String outArgumentFieldName, int type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField inField = new DatabaseField(inArgumentFieldName);
inField.setSqlType(type);
if (inArgumentFieldName.equals(outArgumentFieldName)) {
appendInOut(inField);
} else {
DatabaseField outField = new DatabaseField(outArgumentFieldName);
outField.setSqlType(type);
appendInOut(inField, outField);
}
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The inArgumentFieldName is the field or argument name to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
*/
public void addNamedInOutputArgument(String procedureParameterName, String inArgumentFieldName, String outArgumentFieldName, int type, String typeName) {
addNamedInOutputArgument(procedureParameterName, inArgumentFieldName, outArgumentFieldName, type, typeName, null, null);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The inArgumentFieldName is the field or argument name to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for STRUCT and ARRAY types.
* The classType is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addNamedInOutputArgument(String procedureParameterName, String inArgumentFieldName, String outArgumentFieldName, int type, String typeName, Class> classType) {
addNamedInOutputArgument(procedureParameterName, inArgumentFieldName, outArgumentFieldName, type, typeName, classType, null);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The inArgumentFieldName is the field or argument name to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY types.
* The javaType is the java class to return instead of the ARRAY and STRUCT types if a conversion is possible.
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addNamedInOutputArgument(String procedureParameterName, String inArgumentFieldName, String outArgumentFieldName, int type, String typeName, Class> javaType, DatabaseField nestedType) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField inField = new ObjectRelationalDatabaseField(inArgumentFieldName);
inField.setSqlType(type);
inField.setSqlTypeName(typeName);
inField.setType(javaType);//needed for out, less necessary for in. maybe use containerPolicy instead?
inField.setNestedTypeField(nestedType);
if (inArgumentFieldName.equals(outArgumentFieldName)) {
appendInOut(inField);
} else {
ObjectRelationalDatabaseField outField = new ObjectRelationalDatabaseField(outArgumentFieldName);
outField.setSqlType(type);
outField.setSqlTypeName(typeName);
outField.setType(javaType);//needed for out, less necessary for in. maybe use containerPolicy instead?
outField.setNestedTypeField(nestedType);
appendInOut(inField, outField);
}
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure and the field/argument name to be substitute for it on the way in and out.
* The procedureParameterName is the name of the procedure argument expected.
* The inArgumentValue is the value of the argument to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addNamedInOutputArgumentValue(String procedureParameterName, Object inArgumentValue, String outArgumentFieldName, Class> type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField outField = new DatabaseField(outArgumentFieldName);
outField.setType(type);
appendInOut(inArgumentValue, outField);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterAndArgumentFieldName is the name of the procedure argument expected,
* and is the field or argument name to be used to pass to the procedure.
* These names are assumed to be the same, if not this method can be called with two arguments.
*/
public void addNamedOutputArgument(String procedureParameterAndArgumentFieldName) {
addNamedOutputArgument(procedureParameterAndArgumentFieldName, procedureParameterAndArgumentFieldName);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
*/
public void addNamedOutputArgument(String procedureParameterName, String argumentFieldName) {
getProcedureArgumentNames().add(procedureParameterName);
appendOut(new DatabaseField(argumentFieldName));
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addNamedOutputArgument(String procedureParameterName, String argumentFieldName, Class> type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setType(type);
appendOut(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type returned from the procedure.
*/
public void addNamedOutputArgument(String procedureParameterName, String argumentFieldName, int type) {
getProcedureArgumentNames().add(procedureParameterName);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setSqlType(type);
appendOut(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
*/
public void addNamedOutputArgument(String procedureParameterName, String argumentFieldName, int type, String typeName) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setSqlTypeName(typeName);
appendOut(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used is the result of the output row.
* The jdbcType is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY and STRUCT types.
* The javaType is the java class to return instead of the ARRAY and STRUCT types if a conversion is possible.
*/
public void addNamedOutputArgument(String procedureParameterName, String argumentFieldName, int jdbcType, String typeName, Class> javaType) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(jdbcType);
field.setSqlTypeName(typeName);
field.setType(javaType);
appendOut(field);
}
/**
* PUBLIC:
* Define the output argument to the stored procedure and the field/argument name to be substitute for it.
* The procedureParameterName is the name of the procedure argument expected.
* The argumentFieldName is the field or argument name to be used is the result of the output row.
* The jdbcType is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY and STRUCT types.
* The javaType is the java class to return instead of the ARRAY and STRUCT types if a conversion is possible.
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addNamedOutputArgument(String procedureParameterName, String argumentFieldName, int jdbcType, String typeName, Class> javaType, DatabaseField nestedType) {
getProcedureArgumentNames().add(procedureParameterName);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(jdbcType);
field.setSqlTypeName(typeName);
field.setType(javaType);
field.setNestedTypeField(nestedType);
appendOut(field);
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
*/
public void addUnamedArgument(String argumentFieldName) {
getProcedureArgumentNames().add(null);
DatabaseField field = new DatabaseField(argumentFieldName);
appendIn(field);
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentValue is the value of the argument to be used to pass to the procedure.
*/
public void addUnamedArgumentValue(Object argumentValue) {
getProcedureArgumentNames().add(null);
appendIn(argumentValue);
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the user.
* The type is the type of Java class for the field, and is dependent on the type required by the procedure. This is used
* to set the type in case null is passed in.
*/
public void addUnamedArgument(String argumentFieldName, Class> type) {
getProcedureArgumentNames().add(null);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setType(type);
appendIn(field);
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the user.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
*/
public void addUnamedArgument(String argumentFieldName, int type) {
getProcedureArgumentNames().add(null);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setSqlType(type);
appendIn(field);
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
*/
public void addUnamedArgument(String argumentFieldName, int type, String typeName) {
getProcedureArgumentNames().add(null);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setSqlTypeName(typeName);
appendIn(field);
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type required by the procedure.
* The typeName is the JDBC type name, as required for STRUCT and ARRAY types.
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addUnamedArgument(String argumentFieldName, int type, String typeName, DatabaseField nestedType) {
getProcedureArgumentNames().add(null);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setSqlTypeName(typeName);
field.setNestedTypeField(nestedType);
appendIn(field);
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The inArgumentFieldName is the field name of the argument to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addUnamedInOutputArgument(String inArgumentFieldName, String outArgumentFieldName, Class> type) {
getProcedureArgumentNames().add(null);
DatabaseField inField = new DatabaseField(inArgumentFieldName);
inField.setType(type);
if (inArgumentFieldName.equals(outArgumentFieldName)) {
appendInOut(inField);
} else {
DatabaseField outField = new DatabaseField(outArgumentFieldName);
outField.setType(type);
appendInOut(inField, outField);
}
}
/**
* PUBLIC:
* Define the argument to the stored procedure for the index argument.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The inArgumentFieldName is the field name of the argument to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type returned from the procedure.
*/
public void addUnamedInOutputArgument(String inArgumentFieldName, String outArgumentFieldName, int type) {
getProcedureArgumentNames().add(null);
DatabaseField inField = new DatabaseField(inArgumentFieldName);
inField.setSqlType(type);
if (inArgumentFieldName.equals(outArgumentFieldName)) {
appendInOut(inField);
} else {
DatabaseField outField = new DatabaseField(outArgumentFieldName);
outField.setSqlType(type);
appendInOut(inField, outField);
}
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure for the index argument and the field/argument name to be substitute for it on the way in and out.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The inArgumentFieldName is the field name of the argument to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this is dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
*/
public void addUnamedInOutputArgument(String inArgumentFieldName, String outArgumentFieldName, int type, String typeName) {
getProcedureArgumentNames().add(null);
ObjectRelationalDatabaseField inField = new ObjectRelationalDatabaseField(inArgumentFieldName);
inField.setSqlType(type);
inField.setSqlTypeName(typeName);
if (inArgumentFieldName.equals(outArgumentFieldName)) {
appendInOut(inField);
} else {
ObjectRelationalDatabaseField outField = new ObjectRelationalDatabaseField(outArgumentFieldName);
outField.setSqlType(type);
outField.setSqlTypeName(typeName);
appendInOut(inField, outField);
}
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure for the index argument and the field/argument name to be substitute for it on the way in and out.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field name of the argument to be used to pass to the procedure
* and to be used is the result of the output row.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addUnamedInOutputArgument(String argumentFieldName, Class> type) {
addUnamedInOutputArgument(argumentFieldName, argumentFieldName, type);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure for the index argument and the field/argument name to be substitute for it on the way in and out.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field name of the argument to be used to pass to the procedure
* and to be used is the result of the output row.
*/
public void addUnamedInOutputArgument(String argumentFieldName) {
addUnamedInOutputArgument(argumentFieldName, argumentFieldName, null);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure for the index argument and the field/argument name to be substitute for it on the way in and out.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The inArgumentFieldName is the field or argument name to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY types.
* The collectionClass is the java class to return instead of the ARRAY type.
*/
public void addUnamedInOutputArgument( String inArgumentFieldName, String outArgumentFieldName, int type, String typeName, Class> collection ) {
addNamedInOutputArgument( null, inArgumentFieldName, outArgumentFieldName, type, typeName, collection, null);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure for the index argument and the field/argument name to be substitute for it on the way in and out.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The argumentFieldName is the field or argument name to be used is the result of the output row.
* The jdbcType is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY and STRUCT types.
* The javaType is the java class to return instead of the ARRAY and STRUCT types if a conversion is possible.
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addUnamedInOutputArgument(String inArgumentFieldName, String outArgumentFieldName, int type, String typeName, Class> collection, DatabaseField nestedType) {
addNamedInOutputArgument(null, inArgumentFieldName, outArgumentFieldName, type, typeName, collection, nestedType);
}
/**
* PUBLIC:
* Define the inoutput argument to the stored procedure for the index argument and the field/argument name to be substitute for it on the way in and out.
* This method is used if the procedure is not named and the order is explicit, arguments must be added in the correct order.
* The inArgumentValue is the value of the argument to be used to pass to the procedure.
* The outArgumentFieldName is the field or argument name to be used is the result of the output row.
* If these names are the same (as they normally are) this method can be called with a single argument.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addUnamedInOutputArgumentValue(Object inArgumentValue, String outArgumentFieldName, Class> type) {
getProcedureArgumentNames().add(null);
DatabaseField outField = new DatabaseField(outArgumentFieldName);
outField.setType(type);
appendInOut(inArgumentValue, outField);
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index output argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addUnamedOutputArgument(String argumentFieldName) {
getProcedureArgumentNames().add(null);
appendOut(new DatabaseField(argumentFieldName));
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index output argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* The type is the type of Java class desired back from the procedure, this is dependent on the type returned from the procedure.
*/
public void addUnamedOutputArgument(String argumentFieldName, Class> type) {
getProcedureArgumentNames().add(null);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setType(type);
appendOut(field);
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index output argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* The type is the JDBC type code, this is dependent on the type returned from the procedure.
*/
public void addUnamedOutputArgument(String argumentFieldName, int type) {
getProcedureArgumentNames().add(null);
DatabaseField field = new DatabaseField(argumentFieldName);
field.setSqlType(type);
appendOut(field);
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index output argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used to pass to the procedure.
* The type is the JDBC type code, this is dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY or STRUCT types.
*/
public void addUnamedOutputArgument(String argumentFieldName, int type, String typeName) {
getProcedureArgumentNames().add(null);
ObjectRelationalDatabaseField field = new ObjectRelationalDatabaseField(argumentFieldName);
field.setSqlType(type);
field.setSqlTypeName(typeName);
appendOut(field);
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index output argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used is the result of the output row.
* The jdbcType is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY and STRUCT types.
* The javaType is the java class to return instead of the ARRAY and STRUCT types if a conversion is possible.
*/
public void addUnamedOutputArgument(String argumentFieldName, int jdbcType, String typeName, Class> javaType) {
addNamedOutputArgument(null, argumentFieldName, jdbcType, typeName, javaType, null);
}
/**
* PUBLIC:
* Define the field/argument name to be substitute for the index output argument.
* This method is used if the procedure is not named and the order is explicit, names must be added in the correct order.
* The argumentFieldName is the field or argument name to be used is the result of the output row.
* The jdbcType is the JDBC type code, this dependent on the type returned from the procedure.
* The typeName is the JDBC type name, this may be required for ARRAY and STRUCT types.
* The javaType is the java class to return instead of the ARRAY and STRUCT types if a conversion is possible.
* The nestedType is a DatabaseField with type information set to match the VARRAYs object types
*/
public void addUnamedOutputArgument(String argumentFieldName, int jdbcType, String typeName, Class> javaType, DatabaseField nestedType) {
addNamedOutputArgument(null, argumentFieldName, jdbcType, typeName, javaType, nestedType);
}
/**
* INTERNAL:
* Return call header for the call string.
*/
public String getCallHeader(DatabasePlatform platform) {
return platform.getProcedureCallHeader();
}
/**
* INTERNAL:
* Return the first index of parameter to be placed inside brackets
* in the call string
*/
public int getFirstParameterIndexForCallString() {
return 0;
}
/**
* INTERNAL:
* The if the names are provide the order is not required to match the call def.
* This is lazy initialized to conserve space on calls that have no parameters.
* If the argument name is null, then it is a positional parameter.
*/
public List getProcedureArgumentNames() {
if (procedureArgumentNames == null) {
procedureArgumentNames = new ArrayList<>();
}
return procedureArgumentNames;
}
/**
* PUBLIC:
* Return the name of the store procedure on the database.
*/
public String getProcedureName() {
return procedureName;
}
/**
* Callable statements are used for StoredProcedures that have argument names (named parameters)
*/
@Override
protected boolean isCallableStatementRequired() {
return super.isCallableStatementRequired() || (getProcedureArgumentNames().size() > 0 && getProcedureArgumentNames().get(0) != null);
}
@Override
public boolean isStoredProcedureCall() {
return true;
}
/**
* INTERNAL:
* Called by prepare method only.
*/
@Override
protected void prepareInternal(AbstractSession session) {
setSQLStringInternal(session.getPlatform().buildProcedureCallString(this, session, getQuery().getTranslationRow()));
super.prepareInternal(session);
}
/**
* INTERNAL:
* Prepare the JDBC statement, this may be parameterize or a call statement.
* If caching statements this must check for the pre-prepared statement and re-bind to it.
*/
@Override
public Statement prepareStatement(DatabaseAccessor accessor,
AbstractRecord translationRow, AbstractSession session) throws SQLException {
List procedureArgs = getProcedureArgumentNames();
if(procedureArgs.size() == 0 || procedureArgs.get(0) == null) {
return super.prepareStatement(accessor, translationRow, session);
}
//#Bug5200836 pass shouldUnwrapConnection flag to indicate whether or not using unwrapped connection.
Statement statement = accessor.prepareStatement(this, session);
// Setup the max rows returned and query timeout limit.
if (this.queryTimeout > 0 && this.queryTimeoutUnit != null) {
long timeout = TimeUnit.SECONDS.convert(this.queryTimeout, this.queryTimeoutUnit);
if(timeout > Integer.MAX_VALUE){
timeout = Integer.MAX_VALUE;
}
//Round up the timeout if SECONDS are larger than the given units
if(TimeUnit.SECONDS.compareTo(this.queryTimeoutUnit) > 0 && this.queryTimeout % 1000 > 0){
timeout += 1;
}
statement.setQueryTimeout((int)timeout);
}
if (!this.ignoreMaxResultsSetting && this.maxRows > 0) {
statement.setMaxRows(this.maxRows);
}
if (this.resultSetFetchSize > 0) {
statement.setFetchSize(this.resultSetFetchSize);
}
if (this.parameters == null) {
return statement;
}
List parameters = getParameters();
int size = parameters.size();
DatabasePlatform platform = session.getPlatform();
//Both lists should be the same size
for (int index = 0; index < size; index++) {
if (session.getProject().namingIntoIndexed()) {
platform.setParameterValueInDatabaseCall(parameters.get(index), (PreparedStatement) statement, index+1, session);
} else {
platform.setParameterValueInDatabaseCall(parameters.get(index), (CallableStatement) statement, procedureArgs.get(index), session);
}
}
return statement;
}
/**
* INTERNAL:
* The if the names are provide the order is not required to match the call def.
* This is lazy initialized to conserve space on calls that have no parameters.
*/
public void setProcedureArgumentNames(List procedureArgumentNames) {
this.procedureArgumentNames = procedureArgumentNames;
}
/**
* PUBLIC: (REQUIRED)
* Set the name of the store procedure on the database.
*/
public void setProcedureName(String procedureName) {
this.procedureName = procedureName;
}
@Override
public String toString() {
return Helper.getShortClassName(getClass()) + "(" + getProcedureName() + ")";
}
/**
* ADVANCED:
* Add the cursor output parameter to the procedure.
* This is used for procedures that have multiple cursor output parameters.
* If the procedure has a single cursor output parameter, then useNamedCursorOutputAsResultSet() should be used.
*/
public void addNamedCursorOutputArgument(String argumentName) {
getProcedureArgumentNames().add(argumentName);
appendOutCursor(new DatabaseField(argumentName));
}
/**
* ADVANCED:
* Add the cursor output parameter to the procedure.
* This is used for procedures that have multiple cursor output parameters.
* If the procedure has a single cursor output parameter, then useNamedCursorOutputAsResultSet() should be used.
*/
public void addUnnamedCursorOutputArgument(String outputRowFieldName) {
getProcedureArgumentNames().add(null);
appendOutCursor(new DatabaseField(outputRowFieldName));
}
/**
* INTERNAL:
* Add the unnamed output cursor to return the result.
*/
protected void useCursorOutputResultSet(String argumentName, String outputFieldName) {
// Set the isCursorOutputProcedure first based on the outputCursor list.
// Should be true if there is one and only one, once a second is added,
// the flag must be false.
setIsCursorOutputProcedure(!hasOutputCursors());
setIsMultipleCursorOutputProcedure(hasOutputCursors());
getProcedureArgumentNames().add(argumentName);
appendOutCursor(new DatabaseField(outputFieldName));
}
/**
* PUBLIC:
* Used for Oracle result sets through procedures.
* This can only be used if the arguments are not named but ordered.
*/
public void useNamedCursorOutputAsResultSet(String argumentName) {
useCursorOutputResultSet(argumentName, argumentName);
}
/**
* PUBLIC:
* Used for Oracle result sets through procedures.
* This can only be used if the arguments are not named but ordered.
*/
@Override
public void useUnnamedCursorOutputAsResultSet() {
useCursorOutputResultSet(null, "CURSOR");
}
/**
* PUBLIC:
* Used for Oracle result sets through procedures.
* This can only be used if the arguments are not named but ordered.
*/
public void useUnnamedCursorOutputAsResultSet(int position) {
String positionName = String.valueOf(position);
useCursorOutputResultSet(null, positionName);
}
/**
* PUBLIC:
* Set if the call returns multiple result sets.
* Some databases support having stored procedures that return multiple result set.
* This can be used by data queries, if an object query is used, all of the result sets must return
* the required data to build the resulting class.
*/
@Override
public void setHasMultipleResultSets(boolean hasMultipleResultSets) {
super.setHasMultipleResultSets(hasMultipleResultSets);
}
/**
* PUBLIC:
* Some database support stored procedures returning result sets.
* This default to true in the call has no output parameters, otherwise false.
* If the call returns a result set, and has output parameters, this can be set to true.
* If the call is used in a modify query, it is assumed to not have a result set,
* result sets can only be used by read queries.
* For Oracle a cursored output parameter can be used instead of a result set.
*/
@Override
public void setReturnsResultSet(boolean returnsResultSet) {
super.setReturnsResultSet(returnsResultSet);
}
/**
* PUBLIC:
* Add the optional argument.
* This will be ignored if null and defaulted by the database.
*/
public void addOptionalArgument(String argument) {
getOptionalArguments().add(new DatabaseField(argument));
}
/**
* INTERNAL:
* Return if there are any optional arguments.
*/
public boolean hasOptionalArguments() {
return (this.optionalArguments != null) && !this.optionalArguments.isEmpty();
}
/**
* INTERNAL:
* Return the list of optional arguments.
* These will be ignored if null and defaulted by the database.
*/
public List getOptionalArguments() {
if (this.optionalArguments == null) {
this.optionalArguments = new ArrayList<>();
}
return this.optionalArguments;
}
/**
* INTERNAL:
* Set the list of optional arguments.
* These will be ignored if null and defaulted by the database.
*/
public void setOptionalArguments(List optionalArguments) {
this.optionalArguments = optionalArguments;
}
@Override
public Object getOutputParameterValue(CallableStatement statement, int index, AbstractSession session) throws SQLException {
List procedureArgs = getProcedureArgumentNames();
if(procedureArgs.size() == 0 || procedureArgs.get(0) == null) {
return super.getOutputParameterValue(statement, index, session);
}
String name = procedureArgs.get(index);
return getOutputParameterValue(statement, name, session);
}
/**
* Bind the parameter. Binding is determined by the call and second the platform.
*/
@Override
public void bindParameter(Writer writer, Object parameter) {
if (parameter instanceof Collection) {
throw QueryException.inCannotBeParameterized(getQuery());
}
try {
writer.write("?");
} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
getParameters().add(parameter);
}
/**
* Return the SQL string for logging purposes.
*/
@Override
public String getLogString(Accessor accessor) {
if (hasParameters()) {
StringWriter writer = new StringWriter();
writer.write(getSQLString());
writer.write(Helper.cr());
if (hasParameters()) {
AbstractSession session = null;
if (getQuery() != null) {
session = getQuery().getSession();
}
List procedureArgs = getProcedureArgumentNames();
boolean indexBased = isIndexBased(procedureArgs, session);
Collection parameters = new ArrayList<>();
for (int index = 0; index < getParameters().size(); index++) {
if (indexBased) {
parameters.add(String.valueOf(getParameters().get(index)));
} else {
parameters.add(procedureArgs.get(index) + "=>" + getParameters().get(index));
}
}
appendLogParameters(parameters, accessor, writer, session);
}
return writer.toString();
} else {
return getSQLString();
}
}
private boolean isIndexBased(List procedureArgs, AbstractSession session) {
boolean hasNoArgs = procedureArgs.size() == 0 || procedureArgs.get(0) == null;
boolean isNamingIntoIndexed = false;
if (session != null && session.getProject() != null) {
isNamingIntoIndexed = session.getProject().namingIntoIndexed();
}
return hasNoArgs || isNamingIntoIndexed;
}
}