You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2007/10/04 21:30:49 UTC

svn commit: r581992 - in /jakarta/jmeter/trunk: docs/changes.html docs/usermanual/component_reference.html src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java xdocs/changes.xml xdocs/usermanual/component_reference.xml

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: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org