blob: 0680cf52e7d942211299a946172c5314dcafb8c3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jmeter.protocol.jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.save.CSVSaveService;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jmeter.util.JMeterUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A base class for all JDBC test elements handling the basics of a SQL request.
*
*/
public abstract class AbstractJDBCTestElement extends AbstractTestElement {
private static final long serialVersionUID = 235L;
private static final Logger log = LoggerFactory.getLogger(AbstractJDBCTestElement.class);
private static final String COMMA = ","; // $NON-NLS-1$
private static final char COMMA_CHAR = ',';
private static final String UNDERSCORE = "_"; // $NON-NLS-1$
// String used to indicate a null value
private static final String NULL_MARKER =
JMeterUtils.getPropDefault("jdbcsampler.nullmarker","]NULL["); // $NON-NLS-1$
private static final String INOUT = "INOUT"; // $NON-NLS-1$
private static final String OUT = "OUT"; // $NON-NLS-1$
// TODO - should the encoding be configurable?
protected static final String ENCODING = StandardCharsets.UTF_8.name();
// key: name (lowercase) from java.sql.Types; entry: corresponding int value
private static final Map<String, Integer> mapJdbcNameToInt;
// read-only after class init
static {
// based on e291. Getting the Name of a JDBC Type from javaalmanac.com
// http://javaalmanac.com/egs/java.sql/JdbcInt2Str.html
mapJdbcNameToInt = new HashMap<>();
//Get all fields in java.sql.Types and store the corresponding int values
Field[] fields = java.sql.Types.class.getFields();
for (Field field : fields) {
try {
String name = field.getName();
Integer value = (Integer) field.get(null);
mapJdbcNameToInt.put(name.toLowerCase(java.util.Locale.ENGLISH), value);
} catch (IllegalAccessException e) {
throw new RuntimeException(e); // should not happen
}
}
}
// Query types (used to communicate with GUI)
// N.B. These must not be changed, as they are used in the JMX files
static final String SELECT = "Select Statement"; // $NON-NLS-1$
static final String UPDATE = "Update Statement"; // $NON-NLS-1$
static final String CALLABLE = "Callable Statement"; // $NON-NLS-1$
static final String PREPARED_SELECT = "Prepared Select Statement"; // $NON-NLS-1$
static final String PREPARED_UPDATE = "Prepared Update Statement"; // $NON-NLS-1$
static final String COMMIT = "Commit"; // $NON-NLS-1$
static final String ROLLBACK = "Rollback"; // $NON-NLS-1$
static final String AUTOCOMMIT_FALSE = "AutoCommit(false)"; // $NON-NLS-1$
static final String AUTOCOMMIT_TRUE = "AutoCommit(true)"; // $NON-NLS-1$
static final String RS_STORE_AS_STRING = "Store as String"; // $NON-NLS-1$
static final String RS_STORE_AS_OBJECT = "Store as Object"; // $NON-NLS-1$
static final String RS_COUNT_RECORDS = "Count Records"; // $NON-NLS-1$
private String query = ""; // $NON-NLS-1$
private String dataSource = ""; // $NON-NLS-1$
private String queryType = SELECT;
private String queryArguments = ""; // $NON-NLS-1$
private String queryArgumentsTypes = ""; // $NON-NLS-1$
private String variableNames = ""; // $NON-NLS-1$
private String resultSetHandler = RS_STORE_AS_STRING;
private String resultVariable = ""; // $NON-NLS-1$
private String queryTimeout = ""; // $NON-NLS-1$
private String resultSetMaxRows = ""; // $NON-NLS-1$
private static final int MAX_RETAIN_SIZE = JMeterUtils.getPropDefault("jdbcsampler.max_retain_result_size", 64 * 1024);
/**
* Creates a JDBCSampler.
*/
protected AbstractJDBCTestElement() {
}
/**
* Execute the test element.
*
* @param conn a {@link Connection}
* @return the result of the execute command
* @throws SQLException if a database error occurs
* @throws IOException when I/O error occurs
* @throws UnsupportedOperationException if the user provided incorrect query type
*/
protected byte[] execute(Connection conn) throws SQLException, IOException, UnsupportedOperationException { // NOSONAR
return execute(conn, new SampleResult());
}
/**
* Execute the test element.
* Use the sample given as argument to set time to first byte in the "latency" field of the SampleResult.
*
* @param conn a {@link Connection}
* @param sample a {@link SampleResult} to save the latency
* @return the result of the execute command
* @throws SQLException if a database error occurs
* @throws IOException when I/O error occurs
* @throws UnsupportedOperationException if the user provided incorrect query type
*/
protected byte[] execute(Connection conn, SampleResult sample) throws SQLException, IOException, UnsupportedOperationException {
log.debug("executing jdbc:{}", getQuery());
// Based on query return value, get results
String currentQueryType = getQueryType();
if (SELECT.equals(currentQueryType)) {
try (Statement stmt = conn.createStatement()) {
setQueryTimeout(stmt, getIntegerQueryTimeout());
configureMaxRows(stmt);
ResultSet rs = null;
try {
rs = stmt.executeQuery(getQuery());
sample.latencyEnd();
return getStringFromResultSet(rs).getBytes(ENCODING);
} finally {
close(rs);
}
}
} else if (CALLABLE.equals(currentQueryType)) {
try (CallableStatement cstmt = getCallableStatement(conn)) {
int[] out = setArguments(cstmt);
// A CallableStatement can return more than 1 ResultSets
// plus a number of update counts.
boolean hasResultSet = cstmt.execute();
sample.latencyEnd();
String sb = resultSetsToString(cstmt,hasResultSet, out);
return sb.getBytes(ENCODING);
}
} else if (UPDATE.equals(currentQueryType)) {
try (Statement stmt = conn.createStatement()) {
setQueryTimeout(stmt, getIntegerQueryTimeout());
stmt.executeUpdate(getQuery());
sample.latencyEnd();
int updateCount = stmt.getUpdateCount();
String results = updateCount + " updates";
return results.getBytes(ENCODING);
}
} else if (PREPARED_SELECT.equals(currentQueryType)) {
try (PreparedStatement pstmt = getPreparedStatement(conn)) {
setArguments(pstmt);
configureMaxRows(pstmt);
ResultSet rs = null;
try {
rs = pstmt.executeQuery();
sample.latencyEnd();
return getStringFromResultSet(rs).getBytes(ENCODING);
} finally {
close(rs);
}
}
} else if (PREPARED_UPDATE.equals(currentQueryType)) {
try (PreparedStatement pstmt = getPreparedStatement(conn)) {
setArguments(pstmt);
pstmt.executeUpdate();
sample.latencyEnd();
String sb = resultSetsToString(pstmt,false,null);
return sb.getBytes(ENCODING);
}
} else if (ROLLBACK.equals(currentQueryType)){
conn.rollback();
sample.latencyEnd();
return ROLLBACK.getBytes(ENCODING);
} else if (COMMIT.equals(currentQueryType)){
conn.commit();
sample.latencyEnd();
return COMMIT.getBytes(ENCODING);
} else if (AUTOCOMMIT_FALSE.equals(currentQueryType)){
conn.setAutoCommit(false);
sample.latencyEnd();
return AUTOCOMMIT_FALSE.getBytes(ENCODING);
} else if (AUTOCOMMIT_TRUE.equals(currentQueryType)){
conn.setAutoCommit(true);
sample.latencyEnd();
return AUTOCOMMIT_TRUE.getBytes(ENCODING);
} else { // User provided incorrect query type
throw new UnsupportedOperationException("Unexpected query type: "+currentQueryType);
}
}
private void configureMaxRows(Statement stmt) throws SQLException {
int maxRows = getIntegerResultSetMaxRows();
if (maxRows >= 0) {
stmt.setMaxRows(maxRows);
}
}
private String resultSetsToString(PreparedStatement pstmt, boolean result, int[] out) throws SQLException, UnsupportedEncodingException {
configureMaxRows(pstmt);
StringBuilder sb = new StringBuilder();
int updateCount = 0;
boolean currentResult = result;
if (!currentResult) {
updateCount = pstmt.getUpdateCount();
}
do {
if (currentResult) {
ResultSet rs = null;
try {
rs = pstmt.getResultSet();
sb.append(getStringFromResultSet(rs)).append("\n"); // $NON-NLS-1$
} finally {
close(rs);
}
} else {
sb.append(updateCount).append(" updates.\n");
}
currentResult = pstmt.getMoreResults();
if (!currentResult) {
updateCount = pstmt.getUpdateCount();
}
} while (currentResult || (updateCount != -1));
if (out!=null && pstmt instanceof CallableStatement){
List<Object> outputValues = new ArrayList<>();
CallableStatement cs = (CallableStatement) pstmt;
sb.append("Output variables by position:\n");
for(int i=0; i < out.length; i++){
if (out[i]!=java.sql.Types.NULL){
Object o = cs.getObject(i+1);
outputValues.add(o);
sb.append("[");
sb.append(i+1);
sb.append("] ");
sb.append(o);
if( o instanceof java.sql.ResultSet && RS_COUNT_RECORDS.equals(resultSetHandler)) {
sb.append(" ").append(countRows((ResultSet) o)).append(" rows");
}
sb.append("\n");
}
}
String[] varnames = getVariableNames().split(COMMA);
if(varnames.length > 0) {
JMeterVariables jmvars = getThreadContext().getVariables();
for(int i = 0; i < varnames.length && i < outputValues.size(); i++) {
String name = varnames[i].trim();
if (name.length()>0){ // Save the value in the variable if present
Object o = outputValues.get(i);
if( o instanceof java.sql.ResultSet ) {
putIntoVar(jmvars, name, (java.sql.ResultSet) o);
} else if (o instanceof java.sql.Clob) {
putIntoVar(jmvars, name, (java.sql.Clob) o);
} else if (o instanceof java.sql.Blob) {
putIntoVar(jmvars, name, (java.sql.Blob) o);
}
else {
jmvars.put(name, o == null ? null : o.toString());
}
}
}
}
}
return sb.toString();
}
private void putIntoVar(final JMeterVariables jmvars, final String name,
final ResultSet resultSet) throws SQLException {
if (RS_STORE_AS_OBJECT.equals(resultSetHandler)) {
jmvars.putObject(name, resultSet);
} else if (RS_COUNT_RECORDS.equals(resultSetHandler)) {
jmvars.put(name, resultSet.toString() + " " + countRows(resultSet)
+ " rows");
} else {
jmvars.put(name, resultSet.toString());
}
}
private static void putIntoVar(final JMeterVariables jmvars, final String name,
final Clob clob) throws SQLException {
try {
if (clob.length() > MAX_RETAIN_SIZE) {
try (Reader reader = clob.getCharacterStream(0,MAX_RETAIN_SIZE)) {
jmvars.put(
name,
IOUtils.toString(reader)
+ "<result cut off, it is too big>");
}
} else {
try (Reader reader = clob.getCharacterStream()) {
jmvars.put(name, IOUtils.toString(reader));
}
}
} catch (IOException e) {
log.warn("Could not read CLOB into {}", name, e);
}
}
private void putIntoVar(final JMeterVariables jmvars, final String name,
final Blob blob) throws SQLException {
if (RS_STORE_AS_OBJECT.equals(resultSetHandler)) {
try {
long length = Math.max(blob.length(), MAX_RETAIN_SIZE);
jmvars.putObject(name,
IOUtils.toByteArray(blob.getBinaryStream(0, length)));
} catch (IOException e) {
log.warn("Could not read BLOB into {} as object.", name, e);
}
} else if (RS_COUNT_RECORDS.equals(resultSetHandler)) {
jmvars.put(name, blob.length() + " bytes");
} else {
try {
long length = Math.max(blob.length(), MAX_RETAIN_SIZE);
try (InputStream is = blob.getBinaryStream(0, length)) {
jmvars.put(name, IOUtils.toString(is, ENCODING));
}
} catch (IOException e) {
log.warn("Can't convert BLOB to String using {}", ENCODING, e);
}
}
}
/**
* Count rows in result set
* @param resultSet {@link ResultSet}
* @return number of rows in resultSet
* @throws SQLException
*/
private int countRows(ResultSet resultSet) throws SQLException {
int resultSetMaxRows = getIntegerResultSetMaxRows();
if (resultSetMaxRows >= 0) {
resultSet.absolute(resultSetMaxRows);
if (!resultSet.isAfterLast()) {
return resultSet.getRow();
}
}
return resultSet.last() ? resultSet.getRow() : 0;
}
private int[] setArguments(PreparedStatement pstmt) throws SQLException, IOException {
if (getQueryArguments().trim().length()==0) {
return new int[]{};
}
String[] arguments = CSVSaveService.csvSplitString(getQueryArguments(), COMMA_CHAR);
String[] argumentsTypes = getQueryArgumentsTypes().split(COMMA);
if (arguments.length != argumentsTypes.length) {
throw new SQLException("number of arguments ("+arguments.length+") and number of types ("+argumentsTypes.length+") are not equal");
}
int[] outputs= new int[arguments.length];
for (int i = 0; i < arguments.length; i++) {
String argument = arguments[i];
String argumentType = argumentsTypes[i];
String[] arg = argumentType.split(" ");
String inputOutput="";
if (arg.length > 1) {
argumentType = arg[1];
inputOutput=arg[0];
}
int targetSqlType = getJdbcType(argumentType);
try {
if (!OUT.equalsIgnoreCase(inputOutput)){
if (argument.equals(NULL_MARKER)){
pstmt.setNull(i+1, targetSqlType);
} else {
setArgument(pstmt, argument, targetSqlType, i+1);
}
}
if (OUT.equalsIgnoreCase(inputOutput)||INOUT.equalsIgnoreCase(inputOutput)) {
CallableStatement cs = (CallableStatement) pstmt;
cs.registerOutParameter(i+1, targetSqlType);
outputs[i]=targetSqlType;
} else {
outputs[i]=java.sql.Types.NULL; // can't have an output parameter type null
}
} catch (NullPointerException e) { // thrown by Derby JDBC (at least) if there are no "?" markers in statement
throw new SQLException("Could not set argument no: "+(i+1)+" - missing parameter marker?", e);
}
}
return outputs;
}
private static void setArgument(PreparedStatement pstmt, String argument, int targetSqlType, int index) throws SQLException {
switch (targetSqlType) {
case Types.INTEGER:
pstmt.setInt(index, Integer.parseInt(argument));
break;
case Types.DECIMAL:
case Types.NUMERIC:
pstmt.setBigDecimal(index, new BigDecimal(argument));
break;
case Types.DOUBLE:
case Types.FLOAT:
pstmt.setDouble(index, Double.parseDouble(argument));
break;
case Types.CHAR:
case Types.LONGVARCHAR:
case Types.VARCHAR:
pstmt.setString(index, argument);
break;
case Types.BIT:
case Types.BOOLEAN:
pstmt.setBoolean(index, Boolean.parseBoolean(argument));
break;
case Types.BIGINT:
pstmt.setLong(index, Long.parseLong(argument));
break;
case Types.DATE:
pstmt.setDate(index, Date.valueOf(argument));
break;
case Types.REAL:
pstmt.setFloat(index, Float.parseFloat(argument));
break;
case Types.TINYINT:
pstmt.setByte(index, Byte.parseByte(argument));
break;
case Types.SMALLINT:
pstmt.setShort(index, Short.parseShort(argument));
break;
case Types.TIMESTAMP:
pstmt.setTimestamp(index, Timestamp.valueOf(argument));
break;
case Types.TIME:
pstmt.setTime(index, Time.valueOf(argument));
break;
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
pstmt.setBytes(index, argument.getBytes(StandardCharsets.UTF_8));
break;
case Types.NULL:
pstmt.setNull(index, targetSqlType);
break;
default:
pstmt.setObject(index, argument, targetSqlType);
}
}
private static int getJdbcType(String jdbcType) throws SQLException {
Integer entry = mapJdbcNameToInt.get(jdbcType.toLowerCase(java.util.Locale.ENGLISH));
if (entry == null) {
try {
entry = Integer.decode(jdbcType);
} catch (NumberFormatException e) {
throw new SQLException("Invalid data type: "+jdbcType, e);
}
}
return entry;
}
private CallableStatement getCallableStatement(Connection conn) throws SQLException {
return (CallableStatement) getPreparedStatement(conn,true);
}
private PreparedStatement getPreparedStatement(Connection conn) throws SQLException {
return getPreparedStatement(conn,false);
}
private PreparedStatement getPreparedStatement(Connection conn, boolean callable) throws SQLException {
PreparedStatement pstmt;
if (callable) {
pstmt = conn.prepareCall(getQuery()); // NOSONAR closed by caller
} else {
pstmt = conn.prepareStatement(getQuery()); // NOSONAR closed by caller
}
setQueryTimeout(pstmt, getIntegerQueryTimeout());
return pstmt;
}
/**
* @param stmt {@link Statement} Statement for which we want to set timeout
* @param timeout int timeout value in seconds, if < 0 setQueryTimeout will not be called
* @throws SQLException
*/
private static void setQueryTimeout(Statement stmt, int timeout) throws SQLException {
if(timeout >= 0) {
stmt.setQueryTimeout(timeout);
}
}
/**
* Gets a Data object from a ResultSet.
*
* @param rs
* ResultSet passed in from a database query
* @return a Data object
* @throws java.sql.SQLException
* @throws UnsupportedEncodingException
*/
private String getStringFromResultSet(ResultSet rs) throws SQLException, UnsupportedEncodingException {
ResultSetMetaData meta = rs.getMetaData();
StringBuilder sb = new StringBuilder();
int numColumns = meta.getColumnCount();
for (int i = 1; i <= numColumns; i++) {
sb.append(meta.getColumnLabel(i));
if (i==numColumns){
sb.append('\n');
} else {
sb.append('\t');
}
}
JMeterVariables jmvars = getThreadContext().getVariables();
String[] varNames = getVariableNames().split(COMMA);
String currentResultVariable = getResultVariable().trim();
List<Map<String, Object> > results = null;
if(!currentResultVariable.isEmpty()) {
results = new ArrayList<>();
jmvars.putObject(currentResultVariable, results);
}
int currentIterationIndex = 0;
int resultSetMaxRows = getIntegerResultSetMaxRows();
if (resultSetMaxRows < 0) {
while (rs.next()) {
currentIterationIndex = processRow(rs, meta, sb, numColumns, jmvars, varNames, results, currentIterationIndex);
}
} else {
while (currentIterationIndex < resultSetMaxRows && rs.next()) {
currentIterationIndex = processRow(rs, meta, sb, numColumns, jmvars, varNames, results, currentIterationIndex);
}
}
// Remove any additional values from previous sample
for (String varName : varNames) {
String name = varName.trim();
if (name.length() > 0 && jmvars != null) {
final String varCount = name + "_#"; // $NON-NLS-1$
// Get the previous count
String prevCount = jmvars.get(varCount);
if (prevCount != null) {
int prev = Integer.parseInt(prevCount);
for (int n = currentIterationIndex + 1; n <= prev; n++) {
jmvars.remove(name + UNDERSCORE + n);
}
}
jmvars.put(varCount, Integer.toString(currentIterationIndex)); // save the current count
}
}
return sb.toString();
}
private static int processRow(ResultSet rs, ResultSetMetaData meta, StringBuilder sb, int numColumns,
JMeterVariables jmvars, String[] varNames, List<? super Map<String, Object>> results, int currentIterationIndex)
throws SQLException, UnsupportedEncodingException {
Map<String, Object> row = null;
currentIterationIndex++;
for (int i = 1; i <= numColumns; i++) {
Object o = rs.getObject(i);
if(results != null) {
if(row == null) {
row = new HashMap<>(numColumns);
results.add(row);
}
row.put(meta.getColumnLabel(i), o);
}
if (o instanceof byte[]) {
o = new String((byte[]) o, ENCODING);
}
sb.append(o);
if (i==numColumns){
sb.append('\n');
} else {
sb.append('\t');
}
if (i <= varNames.length) { // i starts at 1
String name = varNames[i - 1].trim();
if (name.length()>0){ // Save the value in the variable if present
jmvars.put(name+UNDERSCORE+currentIterationIndex, o == null ? null : o.toString());
}
}
}
return currentIterationIndex;
}
public static void close(Connection c) {
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
log.warn("Error closing Connection", e);
}
}
public static void close(Statement s) {
try {
if (s != null) {
s.close();
}
} catch (SQLException e) {
log.warn("Error closing Statement {}", s, e);
}
}
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
log.warn("Error closing ResultSet", e);
}
}
/**
* @return the integer representation queryTimeout
*/
public int getIntegerQueryTimeout() {
int timeout;
if(StringUtils.isEmpty(queryTimeout)) {
return 0;
} else {
try {
timeout = Integer.parseInt(queryTimeout);
} catch (NumberFormatException nfe) {
timeout = 0;
}
}
return timeout;
}
/**
* @return the queryTimeout
*/
public String getQueryTimeout() {
return queryTimeout ;
}
/**
* @param queryTimeout query timeout in seconds
*/
public void setQueryTimeout(String queryTimeout) {
this.queryTimeout = queryTimeout;
}
/**
* @return the integer representation resultSetMaxRows
*/
public int getIntegerResultSetMaxRows() {
int maxrows;
if(StringUtils.isEmpty(resultSetMaxRows)) {
return -1;
} else {
try {
maxrows = Integer.parseInt(resultSetMaxRows);
} catch (NumberFormatException nfe) {
maxrows = -1;
}
}
return maxrows;
}
/**
* @return the resultSetMaxRows
*/
public String getResultSetMaxRows() {
return resultSetMaxRows ;
}
/**
* @param resultSetMaxRows max number of rows to iterate through the ResultSet
*/
public void setResultSetMaxRows(String resultSetMaxRows) {
this.resultSetMaxRows = resultSetMaxRows;
}
public String getQuery() {
return query;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(80);
sb.append("["); // $NON-NLS-1$
sb.append(getQueryType());
sb.append("] "); // $NON-NLS-1$
sb.append(getQuery());
sb.append("\n");
sb.append(getQueryArguments());
sb.append("\n");
sb.append(getQueryArgumentsTypes());
return sb.toString();
}
/**
* @param query
* The query to set.
*/
public void setQuery(String query) {
this.query = query;
}
/**
* @return Returns the dataSource.
*/
public String getDataSource() {
return dataSource;
}
/**
* @param dataSource
* The dataSource to set.
*/
public void setDataSource(String dataSource) {
this.dataSource = dataSource;
}
/**
* @return Returns the queryType.
*/
public String getQueryType() {
return queryType;
}
/**
* @param queryType The queryType to set.
*/
public void setQueryType(String queryType) {
this.queryType = queryType;
}
public String getQueryArguments() {
return queryArguments;
}
public void setQueryArguments(String queryArguments) {
this.queryArguments = queryArguments;
}
public String getQueryArgumentsTypes() {
return queryArgumentsTypes;
}
public void setQueryArgumentsTypes(String queryArgumentsType) {
this.queryArgumentsTypes = queryArgumentsType;
}
/**
* @return the variableNames
*/
public String getVariableNames() {
return variableNames;
}
/**
* @param variableNames the variableNames to set
*/
public void setVariableNames(String variableNames) {
this.variableNames = variableNames;
}
/**
* @return the resultSetHandler
*/
public String getResultSetHandler() {
return resultSetHandler;
}
/**
* @param resultSetHandler the resultSetHandler to set
*/
public void setResultSetHandler(String resultSetHandler) {
this.resultSetHandler = resultSetHandler;
}
/**
* @return the resultVariable
*/
public String getResultVariable() {
return resultVariable ;
}
/**
* @param resultVariable the variable name in which results will be stored
*/
public void setResultVariable(String resultVariable) {
this.resultVariable = resultVariable;
}
}