Author: sebb Date: Thu Oct 4 12:30:48 2007 New Revision: 581992 URL: http://svn.apache.org/viewvc?rev=581992&view=rev Log: JDBC Sampler now allows INOUT and OUT parameters for Called procedures
Modified: jakarta/jmeter/trunk/docs/changes.html jakarta/jmeter/trunk/docs/usermanual/component_reference.html jakarta/jmeter/trunk/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java jakarta/jmeter/trunk/xdocs/changes.xml jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Modified: jakarta/jmeter/trunk/docs/changes.html URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/docs/changes.html?rev=581992&r1=581991&r2=581992&view=diff ============================================================================== --- jakarta/jmeter/trunk/docs/changes.html (original) +++ jakarta/jmeter/trunk/docs/changes.html Thu Oct 4 12:30:48 2007 @@ -206,6 +206,11 @@ </li> + <li > + JDBC Sampler now allows INOUT and OUT parameters for Called procedures + </li> + + </ul> <h4 > Non-functional Improvements Modified: jakarta/jmeter/trunk/docs/usermanual/component_reference.html URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/docs/usermanual/component_reference.html?rev=581992&r1=581991&r2=581992&view=diff ============================================================================== --- jakarta/jmeter/trunk/docs/usermanual/component_reference.html (original) +++ jakarta/jmeter/trunk/docs/usermanual/component_reference.html Thu Oct 4 12:30:48 2007 @@ -1005,7 +1005,9 @@ <td> SQL query. Do not enter a trailing semi-colon. - There is no need to use { and } to enclose Callable statements. + There is generally no need to use { and } to enclose Callable statements; + however they mey be used if the database uses a non-standard syntax. + [The JDBC driver automatically converts the statement if necessary when it is enclosed in {}]. For example: <ul > @@ -1067,6 +1069,9 @@ <td>Parameter types</td> <td> Comma-separated list of SQL parameter types (e.g. INTEGER, DATE, VARCHAR, DOUBLE). + If the callable statement has INOUT or OUT parameters, then these must be indicated by prefixing the + appropriate parameter types, e.g. instead of "INTEGER", use "INOUT INTEGER". + If not specified, "IN" is assumed, i.e. "DATE" is the same as "IN DATE". <br > </br> Modified: jakarta/jmeter/trunk/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java?rev=581992&r1=581991&r2=581992&view=diff ============================================================================== --- jakarta/jmeter/trunk/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java (original) +++ jakarta/jmeter/trunk/src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java Thu Oct 4 12:30:48 2007 @@ -26,10 +26,12 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import org.apache.jmeter.protocol.jdbc.config.DataSourceElement; @@ -47,6 +49,10 @@ * */ public class JDBCSampler extends AbstractSampler implements TestBean { + private static final String INOUT = "INOUT"; + + private static final String OUT = "OUT"; + private static final Logger log = LoggingManager.getLoggerForClass(); // This value is used for both the connection (perConnCache) and statement (preparedStatementMap) caches. @@ -160,11 +166,11 @@ } } else if (CALLABLE.equals(_queryType)) { CallableStatement cstmt = getCallableStatement(conn); - setArguments(cstmt); + int out[]=setArguments(cstmt); // A CallableStatement can return more than 1 ResultSets // plus a number of update counts. boolean hasResultSet = cstmt.execute(); - String sb = resultSetsToString(cstmt,hasResultSet); + String sb = resultSetsToString(cstmt,hasResultSet, out); res.setResponseData(sb.toString().getBytes()); } else if (UPDATE.equals(_queryType)) { stmt = conn.createStatement(); @@ -176,13 +182,13 @@ PreparedStatement pstmt = getPreparedStatement(conn); setArguments(pstmt); pstmt.executeQuery(); - String sb = resultSetsToString(pstmt,true); + String sb = resultSetsToString(pstmt,true,null); res.setResponseData(sb.toString().getBytes()); } else if (PREPARED_UPDATE.equals(_queryType)) { PreparedStatement pstmt = getPreparedStatement(conn); setArguments(pstmt); pstmt.executeUpdate(); - String sb = resultSetsToString(pstmt,false); + String sb = resultSetsToString(pstmt,false,null); res.setResponseData(sb.toString().getBytes()); } else if (ROLLBACK.equals(_queryType)){ conn.rollback(); @@ -220,7 +226,7 @@ return res; } - private String resultSetsToString(PreparedStatement pstmt, boolean result) throws SQLException { + private String resultSetsToString(PreparedStatement pstmt, boolean result, int[] out) throws SQLException { StringBuffer sb = new StringBuffer(); sb.append("\n"); // $NON-NLS-1$ int updateCount = 0; @@ -245,33 +251,63 @@ updateCount = pstmt.getUpdateCount(); } } while (result || (updateCount != -1)); + if (out!=null && pstmt instanceof CallableStatement){ + 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){ + sb.append("["); + sb.append(i+1); + sb.append("] "); + sb.append(cs.getObject(i+1)); + sb.append("\n"); + } + } + } return sb.toString(); } - private void setArguments(PreparedStatement pstmt) throws SQLException { + private int[] setArguments(PreparedStatement pstmt) throws SQLException { if (getQueryArguments().trim().length()==0) { - return; + return new int[]{}; } String[] arguments = getQueryArguments().split(","); // $NON-NLS-1$ String[] argumentsTypes = getQueryArgumentsTypes().split(","); // $NON-NLS-1$ 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 (argument.equals(NULL_MARKER)){ - pstmt.setNull(i+1, targetSqlType); + if (!OUT.equalsIgnoreCase(inputOutput)){ + if (argument.equals(NULL_MARKER)){ + pstmt.setNull(i+1, targetSqlType); + } else { + pstmt.setObject(i+1, argument, targetSqlType); + } + } + if (OUT.equalsIgnoreCase(inputOutput)||INOUT.equalsIgnoreCase(inputOutput)) { + CallableStatement cs = (CallableStatement) pstmt; + cs.registerOutParameter(i+1, targetSqlType); + outputs[i]=targetSqlType; } else { - pstmt.setObject(i+1, argument, targetSqlType); + 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?"); } } + return outputs; } Modified: jakarta/jmeter/trunk/xdocs/changes.xml URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=581992&r1=581991&r2=581992&view=diff ============================================================================== --- jakarta/jmeter/trunk/xdocs/changes.xml (original) +++ jakarta/jmeter/trunk/xdocs/changes.xml Thu Oct 4 12:30:48 2007 @@ -47,6 +47,7 @@ <li>Test Plan items can now only be dropped/pasted into parts of the tree where they are allowed</li> <li>Property Display to show the value of System and JMeter properties and allow them to be changed</li> <li>Bug 43451 - Allow Regex Extractor to operate on Response Code/Message</li> +<li>JDBC Sampler now allows INOUT and OUT parameters for Called procedures</li> </ul> <h4>Non-functional Improvements</h4> Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=581992&r1=581991&r2=581992&view=diff ============================================================================== --- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original) +++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Thu Oct 4 12:30:48 2007 @@ -281,7 +281,9 @@ <property name="SQL Query" required="Yes"> SQL query. Do not enter a trailing semi-colon. - There is no need to use { and } to enclose Callable statements. + There is generally no need to use { and } to enclose Callable statements; + however they mey be used if the database uses a non-standard syntax. + [The JDBC driver automatically converts the statement if necessary when it is enclosed in {}]. For example: <ul> <li>select * from t_customers where id=23</li> @@ -302,6 +304,9 @@ </property> <property name="Parameter types" required="Yes, if a prepared or callable statement has parameters"> Comma-separated list of SQL parameter types (e.g. INTEGER, DATE, VARCHAR, DOUBLE). + If the callable statement has INOUT or OUT parameters, then these must be indicated by prefixing the + appropriate parameter types, e.g. instead of "INTEGER", use "INOUT INTEGER". + If not specified, "IN" is assumed, i.e. "DATE" is the same as "IN DATE". <br></br> There must be as many values as there are placeholders in the statement. </property> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]