List:Commits« Previous MessageNext Message »
From:mmatthews Date:March 9 2006 9:00pm
Subject:Connector/J commit: r5035 - in branches: branch_3_1/connector-j/src/com/mysql/jdbc branch_3_1/connector-j/src/testsuite/regression branch_5_0/connecto...
View as plain text  
Modified:
   branches/branch_3_1/connector-j/src/com/mysql/jdbc/CallableStatement.java
   branches/branch_3_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/CallableStatement.java
   branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java
   branches/branch_5_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
Log:
Fixed BUG#17898 - registerOutParameter not working when some 
	  parameters pre-populated. Still waiting for feedback from JDBC experts
	  group to determine what correct parameter count from getMetaData() 
	  should be, however.

Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- branches/branch_3_1/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-03-09 20:56:13 UTC (rev 5034)
+++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-03-09 21:00:13 UTC (rev 5035)
@@ -377,8 +377,52 @@
 		super(conn, catalog, null);
 
 		determineParameterTypes();
+		generateParameterMap();
 	}
 
+	private int[] placeholderToParameterIndexMap;
+	
+	private void generateParameterMap() throws SQLException {
+		// if the user specified some parameters as literals, we need to
+		// provide a map from the specified placeholders to the actual
+		// parameter numbers
+		
+		if (this.parameterCount != this.paramInfo.getParameterCount()) {
+			this.placeholderToParameterIndexMap = new int[this.parameterCount];
+			
+			int startPos = StringUtils.indexOfIgnoreCase(this.originalSql, 
+					"CALL");
+			if (startPos != -1) {
+				int parenOpenPos = this.originalSql.indexOf('(', startPos + 4);
+				
+				if (parenOpenPos != -1) {
+					int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, 
+							this.originalSql, ")", '\'', true);
+					
+					if (parenClosePos != -1) {
+						List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true);
+						
+						int numParsedParameters = parsedParameters.size();
+						
+						// sanity check
+						
+						if (numParsedParameters != this.parameterCount) {
+							// bail?
+						}
+						
+						int placeholderCount = 0;
+						
+						for (int i = 0; i < numParsedParameters; i++) {
+							if (((String)parsedParameters.get(i)).equals("?")) {
+								this.placeholderToParameterIndexMap[placeholderCount++] = i;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
 	/**
 	 * Creates a new CallableStatement
 	 * 
@@ -399,6 +443,7 @@
 		this.callingStoredFunction = isFunctionCall;
 
 		determineParameterTypes();
+		generateParameterMap();
 	}
 
 	/*
@@ -436,6 +481,10 @@
 
 		int localParamIndex = paramIndex - 1;
 
+		if (this.placeholderToParameterIndexMap != null) {
+			localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
+		}
+		
 		CallableStatementParam paramDescriptor = this.paramInfo
 				.getParameter(localParamIndex);
 
@@ -1114,7 +1163,19 @@
 					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 		}
 
-		return namedParamInfo.index + 1; // JDBC indices are 1-based
+		
+		if (this.placeholderToParameterIndexMap == null) {
+			return namedParamInfo.index + 1; // JDBC indices are 1-based
+		} 
+		
+		for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) {
+			if (this.placeholderToParameterIndexMap[i] == namedParamInfo.index) {
+				return i + 1;
+			}
+		}
+		
+		throw new SQLException("Can't find local placeholder mapping for parameter named \"" + 
+				paramName + "\".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 	}
 
 	/**
@@ -1180,6 +1241,11 @@
 
 		return retValue;
 	}
+	
+	public synchronized ParameterMetaData getParameterMetaData()
+			throws SQLException {
+		return (CallableStatementParamInfoJDBC3) this.paramInfo;
+	}
 
 	/**
 	 * Returns the ResultSet that holds the output parameters, or throws an
@@ -1459,6 +1525,10 @@
 		checkParameterIndexBounds(paramIndex);
 
 		int localParamIndex = paramIndex - 1;
+		
+		if (this.placeholderToParameterIndexMap != null) {
+			localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
+		}
 
 		int rsIndex = this.parameterIndexToRsIndex[localParamIndex];
 
@@ -1831,7 +1901,15 @@
 				if (outParamInfo.isOut) {
 					String outParameterName = mangleParameterName(outParamInfo.paramName);
 
-					this.setBytesNoEscapeNoQuotes(outParamInfo.index + 1,
+					int outParamIndex;
+					
+					if (this.placeholderToParameterIndexMap == null) { 
+							outParamIndex = outParamInfo.index + 1;
+					} else {
+							outParamIndex = this.placeholderToParameterIndexMap[outParamInfo.index - 1 /* JDBC is 1-based */];
+					}
+					
+					this.setBytesNoEscapeNoQuotes(outParamIndex,
 							StringUtils.getBytes(outParameterName,
 									this.charConverter, this.charEncoding,
 									this.connection

Modified: branches/branch_3_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
--- branches/branch_3_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-03-09 20:56:13 UTC (rev 5034)
+++ branches/branch_3_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-03-09 21:00:13 UTC (rev 5035)
@@ -623,4 +623,29 @@
 			}
 		}
 	}
+	
+	/**
+	 * Tests fix for BUG#17898 - registerOutParameter not working when some 
+	 * parameters pre-populated. Still waiting for feedback from JDBC experts
+	 * group to determine what correct parameter count from getMetaData() 
+	 * should be, however.
+	 * 
+	 * @throws Exception if the test fails
+	 */
+	public void testBug17898() throws Exception {
+		if (versionMeetsMinimum(5, 0)) {
+			this.stmt.executeUpdate("DROP PROCEDURE IF EXISTS testBug17898");
+			this.stmt.executeUpdate("CREATE PROCEDURE testBug17898(param1 VARCHAR(50), OUT param2 INT)\nBEGIN\nDECLARE rtn INT;\nSELECT 1 INTO rtn;\nSET param2=rtn;\nEND");
+			
+			CallableStatement cstmt = this.conn.prepareCall("{CALL testBug17898('foo', ?)}");
+			cstmt.registerOutParameter(1, Types.INTEGER);
+			cstmt.execute();
+			assertEquals(1, cstmt.getInt(1));
+			
+			cstmt.clearParameters();
+			cstmt.registerOutParameter("param2", Types.INTEGER);
+			cstmt.execute();
+			assertEquals(1, cstmt.getInt(1));
+		}
+	}
 }

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-03-09 20:56:13 UTC (rev 5034)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-03-09 21:00:13 UTC (rev 5035)
@@ -379,8 +379,52 @@
 		super(conn, catalog, null);
 
 		determineParameterTypes();
+		generateParameterMap();
 	}
 
+	private int[] placeholderToParameterIndexMap;
+	
+	private void generateParameterMap() throws SQLException {
+		// if the user specified some parameters as literals, we need to
+		// provide a map from the specified placeholders to the actual
+		// parameter numbers
+		
+		if (this.parameterCount != this.paramInfo.getParameterCount()) {
+			this.placeholderToParameterIndexMap = new int[this.parameterCount];
+			
+			int startPos = StringUtils.indexOfIgnoreCase(this.originalSql, 
+					"CALL");
+			if (startPos != -1) {
+				int parenOpenPos = this.originalSql.indexOf('(', startPos + 4);
+				
+				if (parenOpenPos != -1) {
+					int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, 
+							this.originalSql, ")", '\'', true);
+					
+					if (parenClosePos != -1) {
+						List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true);
+						
+						int numParsedParameters = parsedParameters.size();
+						
+						// sanity check
+						
+						if (numParsedParameters != this.parameterCount) {
+							// bail?
+						}
+						
+						int placeholderCount = 0;
+						
+						for (int i = 0; i < numParsedParameters; i++) {
+							if (((String)parsedParameters.get(i)).equals("?")) {
+								this.placeholderToParameterIndexMap[placeholderCount++] = i;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
 	/**
 	 * Creates a new CallableStatement
 	 * 
@@ -401,6 +445,7 @@
 		this.callingStoredFunction = isFunctionCall;
 
 		determineParameterTypes();
+		generateParameterMap();
 	}
 
 	/*
@@ -438,6 +483,10 @@
 
 		int localParamIndex = paramIndex - 1;
 
+		if (this.placeholderToParameterIndexMap != null) {
+			localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
+		}
+		
 		CallableStatementParam paramDescriptor = this.paramInfo
 				.getParameter(localParamIndex);
 
@@ -1094,14 +1143,14 @@
 	}
 
 	private int getNamedParamIndex(String paramName, boolean forOut)
-			throws SQLException {
+	throws SQLException {
 		if ((paramName == null) || (paramName.length() == 0)) {
 			throw SQLError.createSQLException(Messages.getString("CallableStatement.2"), //$NON-NLS-1$
 					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 		}
 
 		CallableStatementParam namedParamInfo = this.paramInfo
-				.getParameter(paramName);
+		.getParameter(paramName);
 
 		if (this.paramInfo == null) {
 			throw SQLError.createSQLException(
@@ -1112,11 +1161,23 @@
 		if (forOut && !namedParamInfo.isOut) {
 			throw SQLError.createSQLException(
 					Messages.getString("CallableStatement.5") + paramName //$NON-NLS-1$
-							+ Messages.getString("CallableStatement.6"), //$NON-NLS-1$
+					+ Messages.getString("CallableStatement.6"), //$NON-NLS-1$
 					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 		}
 
-		return namedParamInfo.index + 1; // JDBC indices are 1-based
+
+		if (this.placeholderToParameterIndexMap == null) {
+			return namedParamInfo.index + 1; // JDBC indices are 1-based
+		} 
+
+		for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) {
+			if (this.placeholderToParameterIndexMap[i] == namedParamInfo.index) {
+				return i + 1;
+			}
+		}
+
+		throw SQLError.createSQLException("Can't find local placeholder mapping for parameter named \"" + 
+				paramName + "\".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 	}
 
 	/**
@@ -1467,6 +1528,10 @@
 
 		int localParamIndex = paramIndex - 1;
 
+		if (this.placeholderToParameterIndexMap != null) {
+			localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
+		}
+
 		int rsIndex = this.parameterIndexToRsIndex[localParamIndex];
 
 		if (rsIndex == NOT_OUTPUT_PARAMETER_INDICATOR) {
@@ -1827,7 +1892,15 @@
 				if (outParamInfo.isOut) {
 					String outParameterName = mangleParameterName(outParamInfo.paramName);
 
-					this.setBytesNoEscapeNoQuotes(outParamInfo.index + 1,
+					int outParamIndex;
+					
+					if (this.placeholderToParameterIndexMap == null) { 
+							outParamIndex = outParamInfo.index + 1;
+					} else {
+							outParamIndex = this.placeholderToParameterIndexMap[outParamInfo.index - 1 /* JDBC is 1-based */];
+					}
+					
+					this.setBytesNoEscapeNoQuotes(outParamIndex,
 							StringUtils.getBytes(outParameterName,
 									this.charConverter, this.charEncoding,
 									this.connection

Modified: branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-03-09 20:56:13 UTC (rev 5034)
+++ branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-03-09 21:00:13 UTC (rev 5035)
@@ -590,4 +590,29 @@
 			}
 		}
 	}
+
+	/**
+	 * Tests fix for BUG#17898 - registerOutParameter not working when some 
+	 * parameters pre-populated. Still waiting for feedback from JDBC experts
+	 * group to determine what correct parameter count from getMetaData() 
+	 * should be, however.
+	 * 
+	 * @throws Exception if the test fails
+	 */
+	public void testBug17898() throws Exception {
+		if (versionMeetsMinimum(5, 0)) {
+			this.stmt.executeUpdate("DROP PROCEDURE IF EXISTS testBug17898");
+			this.stmt.executeUpdate("CREATE PROCEDURE testBug17898(param1 VARCHAR(50), OUT param2 INT)\nBEGIN\nDECLARE rtn INT;\nSELECT 1 INTO rtn;\nSET param2=rtn;\nEND");
+			
+			CallableStatement cstmt = this.conn.prepareCall("{CALL testBug17898('foo', ?)}");
+			cstmt.registerOutParameter(1, Types.INTEGER);
+			cstmt.execute();
+			assertEquals(1, cstmt.getInt(1));
+			
+			cstmt.clearParameters();
+			cstmt.registerOutParameter("param2", Types.INTEGER);
+			cstmt.execute();
+			assertEquals(1, cstmt.getInt(1));
+		}
+	}
 }

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-03-09 20:56:13 UTC (rev 5034)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/CallableStatement.java	2006-03-09 21:00:13 UTC (rev 5035)
@@ -396,8 +396,52 @@
 		super(conn, catalog, null);
 
 		determineParameterTypes();
+		generateParameterMap();
 	}
 
+	private int[] placeholderToParameterIndexMap;
+	
+	private void generateParameterMap() throws SQLException {
+		// if the user specified some parameters as literals, we need to
+		// provide a map from the specified placeholders to the actual
+		// parameter numbers
+		
+		if (this.parameterCount != this.paramInfo.getParameterCount()) {
+			this.placeholderToParameterIndexMap = new int[this.parameterCount];
+			
+			int startPos = StringUtils.indexOfIgnoreCase(this.originalSql, 
+					"CALL");
+			if (startPos != -1) {
+				int parenOpenPos = this.originalSql.indexOf('(', startPos + 4);
+				
+				if (parenOpenPos != -1) {
+					int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, 
+							this.originalSql, ")", '\'', true);
+					
+					if (parenClosePos != -1) {
+						List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true);
+						
+						int numParsedParameters = parsedParameters.size();
+						
+						// sanity check
+						
+						if (numParsedParameters != this.parameterCount) {
+							// bail?
+						}
+						
+						int placeholderCount = 0;
+						
+						for (int i = 0; i < numParsedParameters; i++) {
+							if (((String)parsedParameters.get(i)).equals("?")) {
+								this.placeholderToParameterIndexMap[placeholderCount++] = i;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
 	/**
 	 * Creates a new CallableStatement
 	 * 
@@ -418,6 +462,7 @@
 		this.callingStoredFunction = isFunctionCall;
 
 		determineParameterTypes();
+		generateParameterMap();
 	}
 
 	/*
@@ -455,6 +500,10 @@
 
 		int localParamIndex = paramIndex - 1;
 
+		if (this.placeholderToParameterIndexMap != null) {
+			localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
+		}
+		
 		CallableStatementParam paramDescriptor = this.paramInfo
 				.getParameter(localParamIndex);
 
@@ -1178,7 +1227,18 @@
 					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 		}
 
-		return namedParamInfo.index + 1; // JDBC indices are 1-based
+		if (this.placeholderToParameterIndexMap == null) {
+			return namedParamInfo.index + 1; // JDBC indices are 1-based
+		} 
+
+		for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) {
+			if (this.placeholderToParameterIndexMap[i] == namedParamInfo.index) {
+				return i + 1;
+			}
+		}
+
+		throw SQLError.createSQLException("Can't find local placeholder mapping for parameter named \"" + 
+				paramName + "\".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
 	}
 
     /**
@@ -1642,6 +1702,10 @@
 
 		int localParamIndex = paramIndex - 1;
 
+		if (this.placeholderToParameterIndexMap != null) {
+			localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
+		}
+
 		int rsIndex = this.parameterIndexToRsIndex[localParamIndex];
 
 		if (rsIndex == NOT_OUTPUT_PARAMETER_INDICATOR) {
@@ -1987,7 +2051,9 @@
 	/**
 	 * @see java.sql.CallableStatement#setLong(java.lang.String, long)
 	 */
-	public void setLong(String parameterName, long x) throws SQLException {
+	public void setNCharacterStream(int parameterIndex, Reader value,
+			long length) throws SQLException {
+		throw new ToBeImplementedException();
         setLong(getNamedParamIndex(parameterName, false), x);
 	}
 
@@ -2030,6 +2096,7 @@
 	 * @see java.sql.CallableStatement#setNull(java.lang.String, int)
 	 */
 	public void setNull(String parameterName, int sqlType) throws SQLException {
+		setNull(getNamedParamIndex(parameterName, false), sqlType);
 	}
 
 	/**
@@ -2038,6 +2105,7 @@
 	 */
 	public void setNull(String parameterName, int sqlType, String typeName)
 			throws SQLException {
+		setNull(getNamedParamIndex(parameterName, false), sqlType, typeName);
 	}
 
 	/**
@@ -2075,7 +2143,15 @@
 				if (outParamInfo.isOut) {
 					String outParameterName = mangleParameterName(outParamInfo.paramName);
 
-					this.setBytesNoEscapeNoQuotes(outParamInfo.index + 1,
+					int outParamIndex;
+					
+					if (this.placeholderToParameterIndexMap == null) { 
+							outParamIndex = outParamInfo.index + 1;
+					} else {
+							outParamIndex = this.placeholderToParameterIndexMap[outParamInfo.index - 1 /* JDBC is 1-based */];
+					}
+					
+					this.setBytesNoEscapeNoQuotes(outParamIndex,
 							StringUtils.getBytes(outParameterName,
 									this.charConverter, this.charEncoding,
 									this.connection

Modified: branches/branch_5_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
--- branches/branch_5_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-03-09 20:56:13 UTC (rev 5034)
+++ branches/branch_5_1/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2006-03-09 21:00:13 UTC (rev 5035)
@@ -590,4 +590,29 @@
 			}
 		}
 	}
+
+	/**
+	 * Tests fix for BUG#17898 - registerOutParameter not working when some 
+	 * parameters pre-populated. Still waiting for feedback from JDBC experts
+	 * group to determine what correct parameter count from getMetaData() 
+	 * should be, however.
+	 * 
+	 * @throws Exception if the test fails
+	 */
+	public void testBug17898() throws Exception {
+		if (versionMeetsMinimum(5, 0)) {
+			this.stmt.executeUpdate("DROP PROCEDURE IF EXISTS testBug17898");
+			this.stmt.executeUpdate("CREATE PROCEDURE testBug17898(param1 VARCHAR(50), OUT param2 INT)\nBEGIN\nDECLARE rtn INT;\nSELECT 1 INTO rtn;\nSET param2=rtn;\nEND");
+			
+			CallableStatement cstmt = this.conn.prepareCall("{CALL testBug17898('foo', ?)}");
+			cstmt.registerOutParameter(1, Types.INTEGER);
+			cstmt.execute();
+			assertEquals(1, cstmt.getInt(1));
+			
+			cstmt.clearParameters();
+			cstmt.registerOutParameter("param2", Types.INTEGER);
+			cstmt.execute();
+			assertEquals(1, cstmt.getInt(1));
+		}
+	}
 }

Thread
Connector/J commit: r5035 - in branches: branch_3_1/connector-j/src/com/mysql/jdbc branch_3_1/connector-j/src/testsuite/regression branch_5_0/connecto...mmatthews9 Mar