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... | mmatthews | 9 Mar |