Modified:
branches/branch_5_0/connector-j/CHANGES
branches/branch_5_0/connector-j/src/com/mysql/jdbc/CallableStatement.java
branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
branches/branch_5_0/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
branches/branch_5_0/connector-j/src/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java
branches/branch_5_0/connector-j/src/testsuite/BaseTestCase.java
branches/branch_5_0/connector-j/src/testsuite/simple/CallableStatementTest.java
trunk/connector-j/CHANGES
trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
trunk/connector-j/src/com/mysql/jdbc/Connection.java
trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
trunk/connector-j/src/testsuite/BaseTestCase.java
trunk/connector-j/src/testsuite/simple/CallableStatementTest.java
Log:
- Removed non-short-circuited logical ORs from "if" statements.
- Re-worked stored procedure parameter parser to be more robust. Driver no
longer requires "BEGIN" in stored procedure definition, but does have
requirement that if a stored function begins with a label directly after the
"returns" clause, that the label is not a quoted identifier.
Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/CHANGES 2007-01-23 21:42:00 UTC (rev 6299)
@@ -74,6 +74,13 @@
- Fixed BUG#25379 - INOUT parameters in CallableStatements get
doubly-escaped.
+
+ - Removed non-short-circuited logical ORs from "if" statements.
+
+ - Re-worked stored procedure parameter parser to be more robust. Driver no
+ longer requires "BEGIN" in stored procedure definition, but does have
+ requirement that if a stored function begins with a label directly after the
+ "returns" clause, that the label is not a quoted identifier.
10-20-06 - Version 5.0.4
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 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/CallableStatement.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2005 MySQL AB
+ Copyright (C) 2002-2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -701,7 +701,7 @@
paramTypesRs = dbmd.getProcedureColumns(this.connection
.versionMeetsMinimum(5, 0, 2)
- & useCatalog ? this.currentCatalog : null, null, procName,
+ && useCatalog ? this.currentCatalog : null, null, procName,
"%"); //$NON-NLS-1$
convertGetProcedureColumnsToInternalDescriptors(paramTypesRs);
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/Connection.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -4303,7 +4303,7 @@
if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) {
directCompare = false;
- } else if (otherHost != null & otherHost.indexOf(",") == -1 &&
+ } else if (otherHost != null && otherHost.indexOf(",") == -1 &&
otherHost.indexOf(":") == -1) {
// need to check port numbers
directCompare = (otherConnection.origPortToConnectTo ==
@@ -5125,7 +5125,7 @@
*/
public void resetServerState() throws SQLException {
if (!getParanoid()
- && ((this.io != null) & versionMeetsMinimum(4, 0, 6))) {
+ && ((this.io != null) && versionMeetsMinimum(4, 0, 6))) {
changeUser(this.user, this.password);
}
}
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -243,8 +243,9 @@
while (tokenizer.hasMoreTokens()) {
String setMember = tokenizer.nextToken().trim();
-
- if (setMember.startsWith("'") && setMember.endsWith("'")) {
+
+ if (setMember.startsWith("'")
+ && setMember.endsWith("'")) {
maxLength += setMember.length() - 2;
} else {
maxLength += setMember.length();
@@ -255,22 +256,23 @@
this.decimalDigits = null;
} else if (typeInfo.indexOf(",") != -1) {
// Numeric with decimals
- this.columnSize = new Integer(typeInfo.substring(
- (typeInfo.indexOf("(") + 1),
- (typeInfo.indexOf(","))));
+ this.columnSize = new Integer(typeInfo.substring((typeInfo
+ .indexOf("(") + 1), (typeInfo.indexOf(","))));
this.decimalDigits = new Integer(typeInfo.substring(
(typeInfo.indexOf(",") + 1),
(typeInfo.indexOf(")"))));
} else {
this.columnSize = null;
this.decimalDigits = null;
-
+
/* If the size is specified with the DDL, use that */
- if ((StringUtils.indexOfIgnoreCase(typeInfo, "char") != -1 ||
- StringUtils.indexOfIgnoreCase(typeInfo, "text") != -1 ||
- StringUtils.indexOfIgnoreCase(typeInfo, "blob") != -1 ||
- StringUtils.indexOfIgnoreCase(typeInfo, "binary") != -1 ||
- StringUtils.indexOfIgnoreCase(typeInfo, "bit") != -1) && typeInfo.indexOf("(") != -1) {
+ if ((StringUtils.indexOfIgnoreCase(typeInfo, "char") != -1
+ || StringUtils.indexOfIgnoreCase(typeInfo, "text") != -1
+ || StringUtils.indexOfIgnoreCase(typeInfo, "blob") != -1
+ || StringUtils
+ .indexOfIgnoreCase(typeInfo, "binary") != -1 || StringUtils
+ .indexOfIgnoreCase(typeInfo, "bit") != -1)
+ && typeInfo.indexOf("(") != -1) {
int endParenIndex = typeInfo.indexOf(")");
if (endParenIndex == -1) {
@@ -293,68 +295,96 @@
this.typeName = "BIT";
}
}
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "tinyint")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "tinyint")) {
this.columnSize = new Integer(3);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "smallint")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "smallint")) {
this.columnSize = new Integer(5);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "mediumint")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "mediumint")) {
this.columnSize = new Integer(7);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "int")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "int")) {
this.columnSize = new Integer(10);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "integer")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "integer")) {
this.columnSize = new Integer(10);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "bigint")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "bigint")) {
this.columnSize = new Integer(19);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "int24")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "int24")) {
this.columnSize = new Integer(19);
this.decimalDigits = new Integer(0);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "real")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "real")) {
this.columnSize = new Integer(12);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "float")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "float")) {
this.columnSize = new Integer(12);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "decimal")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "decimal")) {
this.columnSize = new Integer(12);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "numeric")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "numeric")) {
this.columnSize = new Integer(12);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "double")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "double")) {
this.columnSize = new Integer(22);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "char")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "char")) {
this.columnSize = new Integer(1);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "varchar")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "varchar")) {
this.columnSize = new Integer(255);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "date")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "date")) {
this.columnSize = null;
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "time")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "time")) {
this.columnSize = null;
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "timestamp")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "timestamp")) {
this.columnSize = null;
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "datetime")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "datetime")) {
this.columnSize = null;
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "tinyblob")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "tinyblob")) {
this.columnSize = new Integer(255);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "blob")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "blob")) {
this.columnSize = new Integer(65535);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "mediumblob")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "mediumblob")) {
this.columnSize = new Integer(16777215);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "longblob")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "longblob")) {
this.columnSize = new Integer(Integer.MAX_VALUE);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "tinytext")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "tinytext")) {
this.columnSize = new Integer(255);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "text")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "text")) {
this.columnSize = new Integer(65535);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "mediumtext")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "mediumtext")) {
this.columnSize = new Integer(16777215);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "longtext")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "longtext")) {
this.columnSize = new Integer(Integer.MAX_VALUE);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "enum")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "enum")) {
this.columnSize = new Integer(255);
- } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo, "set")) {
+ } else if (StringUtils.startsWithIgnoreCaseAndWs(typeInfo,
+ "set")) {
this.columnSize = new Integer(255);
}
@@ -486,7 +516,7 @@
java.util.ArrayList rows) throws SQLException {
return buildResultSet(fields, rows, this.conn);
}
-
+
static java.sql.ResultSet buildResultSet(com.mysql.jdbc.Field[] fields,
java.util.ArrayList rows, Connection c) throws SQLException {
int fieldsLength = fields.length;
@@ -513,7 +543,7 @@
if (db == null && procDb == null) {
shouldAdd = true;
- } else if (db != null & db.equals(procDb)) {
+ } else if (db != null && db.equals(procDb)) {
shouldAdd = true;
}
}
@@ -548,7 +578,7 @@
if (db == null && procDb == null) {
shouldAdd = true;
- } else if (db != null & db.equals(procDb)) {
+ } else if (db != null && db.equals(procDb)) {
shouldAdd = true;
}
}
@@ -599,9 +629,11 @@
}
row[5] = s2b(Short.toString(typeDesc.dataType)); // DATA_TYPE
row[6] = s2b(typeDesc.typeName); // TYPE_NAME
- row[7] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize.toString()); // PRECISION
+ row[7] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize
+ .toString()); // PRECISION
row[8] = s2b(Integer.toString(typeDesc.bufferLength)); // LENGTH
- row[9] = typeDesc.decimalDigits == null ? null : s2b(typeDesc.decimalDigits.toString()); // SCALE
+ row[9] = typeDesc.decimalDigits == null ? null
+ : s2b(typeDesc.decimalDigits.toString()); // SCALE
row[10] = s2b(Integer.toString(typeDesc.numPrecRadix)); // RADIX
// Map 'column****' to 'procedure****'
switch (typeDesc.nullability) {
@@ -621,9 +653,10 @@
break;
default:
- throw SQLError.createSQLException(
- "Internal error while parsing callable statement metadata (unknown nullability value fount)",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error while parsing callable statement metadata (unknown nullability value fount)",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
row[12] = null;
return row;
@@ -698,117 +731,134 @@
byte[][] row = new byte[3][];
row[0] = rs.getBytes(1);
row[1] = s2b(SUPPORTS_FK);
-
+
String createTableString = rs.getString(2);
StringTokenizer lineTokenizer = new StringTokenizer(createTableString,
"\n");
StringBuffer commentBuf = new StringBuffer("comment; ");
boolean firstTime = true;
-
+
String quoteChar = getIdentifierQuoteString();
-
+
if (quoteChar == null) {
quoteChar = "`";
}
-
+
while (lineTokenizer.hasMoreTokens()) {
String line = lineTokenizer.nextToken().trim();
-
+
String constraintName = null;
-
+
if (StringUtils.startsWithIgnoreCase(line, "CONSTRAINT")) {
boolean usingBackTicks = true;
int beginPos = line.indexOf(quoteChar);
-
+
if (beginPos == -1) {
beginPos = line.indexOf("\"");
usingBackTicks = false;
}
-
+
if (beginPos != -1) {
int endPos = -1;
-
+
if (usingBackTicks) {
endPos = line.indexOf(quoteChar, beginPos + 1);
} else {
endPos = line.indexOf("\"", beginPos + 1);
}
-
+
if (endPos != -1) {
constraintName = line.substring(beginPos + 1, endPos);
line = line.substring(endPos + 1, line.length()).trim();
}
}
}
-
-
+
if (line.startsWith("FOREIGN KEY")) {
if (line.endsWith(",")) {
line = line.substring(0, line.length() - 1);
}
-
+
char quote = this.quotedId.charAt(0);
-
+
int indexOfFK = line.indexOf("FOREIGN KEY");
-
+
String localColumnName = null;
- String referencedCatalogName = this.quotedId + catalog + this.quotedId;
+ String referencedCatalogName = this.quotedId + catalog
+ + this.quotedId;
String referencedTableName = null;
String referencedColumnName = null;
-
-
+
if (indexOfFK != -1) {
int afterFk = indexOfFK + "FOREIGN KEY".length();
-
- int indexOfRef = StringUtils.indexOfIgnoreCaseRespectQuotes(afterFk, line, "REFERENCES", quote, true);
-
+
+ int indexOfRef = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(afterFk, line,
+ "REFERENCES", quote, true);
+
if (indexOfRef != -1) {
-
+
int indexOfParenOpen = line.indexOf('(', afterFk);
- int indexOfParenClose = StringUtils.indexOfIgnoreCaseRespectQuotes(indexOfParenOpen, line, ")", quote, true);
-
+ int indexOfParenClose = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(
+ indexOfParenOpen, line, ")", quote,
+ true);
+
if (indexOfParenOpen == -1 || indexOfParenClose == -1) {
// throw SQLError.createSQLException();
}
-
- localColumnName = line.substring(indexOfParenOpen + 1, indexOfParenClose);
-
+
+ localColumnName = line.substring(indexOfParenOpen + 1,
+ indexOfParenClose);
+
int afterRef = indexOfRef + "REFERENCES".length();
-
- int referencedColumnBegin = StringUtils.indexOfIgnoreCaseRespectQuotes(afterRef, line, "(", quote, true);
-
+
+ int referencedColumnBegin = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(afterRef, line,
+ "(", quote, true);
+
if (referencedColumnBegin != -1) {
- referencedTableName = line.substring(afterRef, referencedColumnBegin);
-
- int referencedColumnEnd = StringUtils.indexOfIgnoreCaseRespectQuotes(referencedColumnBegin + 1, line, ")", quote, true);
-
+ referencedTableName = line.substring(afterRef,
+ referencedColumnBegin);
+
+ int referencedColumnEnd = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(
+ referencedColumnBegin + 1, line,
+ ")", quote, true);
+
if (referencedColumnEnd != -1) {
- referencedColumnName = line.substring(referencedColumnBegin + 1, referencedColumnEnd);
+ referencedColumnName = line.substring(
+ referencedColumnBegin + 1,
+ referencedColumnEnd);
}
-
- int indexOfCatalogSep = StringUtils.indexOfIgnoreCaseRespectQuotes(0, referencedTableName, ".", quote, true);
-
+
+ int indexOfCatalogSep = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(0,
+ referencedTableName, ".", quote,
+ true);
+
if (indexOfCatalogSep != -1) {
- referencedCatalogName = referencedTableName.substring(0, indexOfCatalogSep);
- referencedTableName = referencedTableName.substring(indexOfCatalogSep + 1);
+ referencedCatalogName = referencedTableName
+ .substring(0, indexOfCatalogSep);
+ referencedTableName = referencedTableName
+ .substring(indexOfCatalogSep + 1);
}
}
}
}
-
-
+
if (!firstTime) {
commentBuf.append("; ");
} else {
firstTime = false;
}
-
+
if (constraintName != null) {
commentBuf.append(constraintName);
} else {
commentBuf.append("not_available");
}
-
+
commentBuf.append("(");
commentBuf.append(localColumnName);
commentBuf.append(") REFER ");
@@ -818,9 +868,9 @@
commentBuf.append("(");
commentBuf.append(referencedColumnName);
commentBuf.append(")");
-
+
int lastParenIndex = line.lastIndexOf(")");
-
+
if (lastParenIndex != (line.length() - 1)) {
String cascadeOptions = cascadeOptions = line
.substring(lastParenIndex + 1);
@@ -829,10 +879,10 @@
}
}
}
-
+
row[2] = s2b(commentBuf.toString());
rows.add(row);
-
+
return rows;
}
@@ -1181,9 +1231,10 @@
if (this.conn.getNullNamePatternMatchesAll()) {
parameterNamePattern = "%";
} else {
- throw SQLError.createSQLException(
- "Parameter/Column name pattern can not be NULL or empty.",
- SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+ throw SQLError
+ .createSQLException(
+ "Parameter/Column name pattern can not be NULL or empty.",
+ SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
@@ -1193,8 +1244,6 @@
procNameAsBytes = procName.getBytes("UTF-8");
} catch (UnsupportedEncodingException ueEx) {
procNameAsBytes = s2b(procName);
-
- // Set all fields to connection encoding
}
String quoteChar = getIdentifierQuoteString();
@@ -1202,38 +1251,37 @@
String storageDefnDelims = "(" + quoteChar;
String storageDefnClosures = ")" + quoteChar;
- // First try 'select from mysql.proc, as this is easier to parse...
String parameterDef = null;
-
+
try {
paramRetrievalStmt = this.conn.getMetadataSafeStatement();
-
- if (this.conn.lowerCaseTableNames() && catalog != null
+
+ if (this.conn.lowerCaseTableNames() && catalog != null
&& catalog.length() != 0) {
- // Workaround for bug in server wrt. to
+ // Workaround for bug in server wrt. to
// SHOW CREATE PROCEDURE not respecting
// lower-case table names
-
+
String oldCatalog = this.conn.getCatalog();
ResultSet rs = null;
-
+
try {
this.conn.setCatalog(catalog);
rs = paramRetrievalStmt.executeQuery("SELECT DATABASE()");
rs.next();
-
+
catalog = rs.getString(1);
-
+
} finally {
-
+
this.conn.setCatalog(oldCatalog);
-
+
if (rs != null) {
rs.close();
}
}
}
-
+
if (paramRetrievalStmt.getMaxRows() != 0) {
paramRetrievalStmt.setMaxRows(0);
}
@@ -1305,98 +1353,67 @@
.getString("Create Procedure");
if (procedureDef == null || procedureDef.length() == 0) {
- throw SQLError.createSQLException("User does not have access to metadata required to determine " +
- "stored procedure parameter types. If rights can not be granted, configure connection with \"noAccessToProcedureBodies=true\" " +
- "to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "User does not have access to metadata required to determine "
+ + "stored procedure parameter types. If rights can not be granted, configure connection with \"noAccessToProcedureBodies=true\" "
+ + "to have driver generate parameters that represent INOUT strings irregardless of actual parameter types.",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
-
+
int openParenIndex = StringUtils
.indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(",
quoteChar.charAt(0), !this.conn
.isNoBackslashEscapesSet());
+ int endOfParamDeclarationIndex = 0;
- String beforeBegin = null;
+ endOfParamDeclarationIndex = endPositionOfParameterDeclaration(
+ openParenIndex, procedureDef, quoteChar);
- // Try and fudge this with the 'begin' statement
- int beginIndex = 0;
+ if (parsingFunction) {
- if (!parsingFunction) {
- beginIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(0,
- procedureDef, "\nbegin", quoteChar.charAt(0),
- !this.conn.isNoBackslashEscapesSet());
- } else {
- // Grab the return column first, since it needs
+ // Grab the return column since it needs
// to go first in the output result set
int returnsIndex = StringUtils
.indexOfIgnoreCaseRespectQuotes(0, procedureDef,
" RETURNS ", quoteChar.charAt(0),
!this.conn.isNoBackslashEscapesSet());
- beginIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(
- returnsIndex, procedureDef, "\nbegin", quoteChar
- .charAt(0), !this.conn
- .isNoBackslashEscapesSet());
+ int endReturnsDef = findEndOfReturnsClause(procedureDef,
+ quoteChar, returnsIndex);
- if (beginIndex == -1) {
- beginIndex = StringUtils
- .indexOfIgnoreCaseRespectQuotes(0,
- procedureDef, "\n",
- quoteChar.charAt(0), !this.conn
- .isNoBackslashEscapesSet());
+ // Trim off whitespace after "RETURNS"
+
+ int declarationStart = returnsIndex + "RETURNS ".length();
+
+ while (declarationStart < procedureDef.length()) {
+ if (Character.isWhitespace(procedureDef.charAt(declarationStart))) {
+ declarationStart++;
+ } else {
+ break;
+ }
}
-
- // Okay, give up...
-
- if (beginIndex == -1) {
- throw SQLError.createSQLException(
- "Driver requires declaration of procedure to either contain a '\\nbegin' or '\\n' to follow argument declaration, or SELECT privilege on mysql.proc to parse column types.",
- SQLError.SQL_STATE_GENERAL_ERROR);
- }
-
- String returnsDefn = procedureDef.substring(returnsIndex
- + "RETURNS ".length(), beginIndex);
+
+ String returnsDefn = procedureDef.substring(declarationStart, endReturnsDef).trim();
TypeDescriptor returnDescriptor = new TypeDescriptor(
returnsDefn, null);
resultRows.add(convertTypeDescriptorToProcedureRow(
procNameAsBytes, "", false, false, true,
returnDescriptor));
-
- beginIndex = returnsIndex; // further processing needs to
- // look before "RETURNS" token
}
- // Bah, we _really_ need information schema here
-
- if (beginIndex != -1) {
- beforeBegin = procedureDef.substring(0, beginIndex);
- } else {
- beginIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(0,
- procedureDef, "\n", quoteChar.charAt(0), !this.conn
- .isNoBackslashEscapesSet());
-
- if (beginIndex != -1) {
- beforeBegin = procedureDef.substring(0, beginIndex);
- } else {
- throw SQLError.createSQLException(
- "Driver requires declaration of procedure to either contain a '\\nbegin' or '\\n' to follow argument declaration, or SELECT privilege on mysql.proc to parse column types.",
- SQLError.SQL_STATE_GENERAL_ERROR);
- }
-
- }
-
- int endParenIndex = beforeBegin.lastIndexOf(')');
-
- if ((openParenIndex == -1) || (endParenIndex == -1)) {
+ if ((openParenIndex == -1)
+ || (endOfParamDeclarationIndex == -1)) {
// parse error?
- throw SQLError.createSQLException(
- "Internal error when parsing callable statement metadata",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
parameterDef = procedureDef.substring(openParenIndex + 1,
- endParenIndex);
+ endOfParamDeclarationIndex);
}
} finally {
SQLException sqlExRethrow = null;
@@ -1436,9 +1453,10 @@
String declaration = (String) parseList.get(i);
if (declaration.trim().length() == 0) {
- break; // no parameters actually declared, but whitespace spans lines
+ break; // no parameters actually declared, but whitespace
+ // spans lines
}
-
+
StringTokenizer declarationTok = new StringTokenizer(
declaration, " \t");
@@ -1455,9 +1473,10 @@
if (declarationTok.hasMoreTokens()) {
paramName = declarationTok.nextToken();
} else {
- throw SQLError.createSQLException(
- "Internal error when parsing callable statement metadata (missing parameter name)",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata (missing parameter name)",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
} else if (possibleParamName.equalsIgnoreCase("INOUT")) {
isOutParam = true;
@@ -1466,9 +1485,10 @@
if (declarationTok.hasMoreTokens()) {
paramName = declarationTok.nextToken();
} else {
- throw SQLError.createSQLException(
- "Internal error when parsing callable statement metadata (missing parameter name)",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata (missing parameter name)",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
} else if (possibleParamName.equalsIgnoreCase("IN")) {
isOutParam = false;
@@ -1477,9 +1497,10 @@
if (declarationTok.hasMoreTokens()) {
paramName = declarationTok.nextToken();
} else {
- throw SQLError.createSQLException(
- "Internal error when parsing callable statement metadata (missing parameter name)",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata (missing parameter name)",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
} else {
isOutParam = false;
@@ -1503,9 +1524,10 @@
typeDesc = new TypeDescriptor(typeInfo, null);
} else {
- throw SQLError.createSQLException(
- "Internal error when parsing callable statement metadata (missing parameter type)",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata (missing parameter type)",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
int wildCompareRes = StringUtils.wildCompare(paramName,
@@ -1519,9 +1541,10 @@
resultRows.add(row);
}
} else {
- throw SQLError.createSQLException(
- "Internal error when parsing callable statement metadata (unknown output from 'SHOW CREATE PROCEDURE')",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata (unknown output from 'SHOW CREATE PROCEDURE')",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
}
} else {
@@ -1532,6 +1555,120 @@
}
/**
+ * Finds the end of the parameter declaration from the output of "SHOW
+ * CREATE PROCEDURE".
+ *
+ * @param beginIndex
+ * should be the index of the procedure body that contains the
+ * first "(".
+ * @param procedureDef
+ * the procedure body
+ * @param quoteChar
+ * the identifier quote character in use
+ * @return the ending index of the parameter declaration, not including the
+ * closing ")"
+ * @throws SQLException
+ * if a parse error occurs.
+ */
+ private int endPositionOfParameterDeclaration(int beginIndex,
+ String procedureDef, String quoteChar) throws SQLException {
+ int currentPos = beginIndex + 1;
+ int parenDepth = 1; // counting the first openParen
+
+ while (parenDepth > 0 && currentPos < procedureDef.length()) {
+ int closedParenIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(
+ currentPos, procedureDef, ")", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
+
+ if (closedParenIndex != -1) {
+ int nextOpenParenIndex = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(currentPos,
+ procedureDef, "(", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
+
+ if (nextOpenParenIndex != -1
+ && nextOpenParenIndex < closedParenIndex) {
+ parenDepth++;
+ currentPos = closedParenIndex + 1; // set after closed
+ // paren that increases
+ // depth
+ } else {
+ parenDepth--;
+ currentPos = closedParenIndex; // start search from same
+ // position
+ }
+ } else {
+ // we should always get closed paren of some sort
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ }
+
+ return currentPos;
+ }
+
+ /**
+ * Finds the end of the RETURNS clause for SQL Functions by using any of the
+ * keywords allowed after the RETURNS clause, or a label.
+ *
+ * @param procedureDefn
+ * the function body containing the definition of the function
+ * @param quoteChar
+ * the identifier quote string in use
+ * @param positionOfReturnKeyword
+ * the position of "RETRUNS" in the definition
+ * @return the end of the returns clause
+ * @throws SQLException
+ * if a parse error occurs
+ */
+ private int findEndOfReturnsClause(String procedureDefn, String quoteChar,
+ int positionOfReturnKeyword) throws SQLException {
+ /*
+ * characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL |
+ * NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY {
+ * DEFINER | INVOKER } | COMMENT 'string'
+ */
+
+ String[] tokens = new String[] { "LANGUAGE", "NOT", "DETERMINISTIC",
+ "CONTAINS", "NO", "READ", "MODIFIES", "SQL", "COMMENT", "BEGIN",
+ "RETURN" };
+
+ int startLookingAt = positionOfReturnKeyword + "RETURNS".length() + 1;
+
+ for (int i = 0; i < tokens.length; i++) {
+ int endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes(
+ startLookingAt, procedureDefn, tokens[i], quoteChar
+ .charAt(0), !this.conn.isNoBackslashEscapesSet());
+
+ if (endOfReturn != -1) {
+ return endOfReturn;
+ }
+ }
+
+ // Label?
+ int endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes(
+ startLookingAt, procedureDefn, ":", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
+
+ if (endOfReturn != -1) {
+ // seek back until whitespace
+ for (int i = endOfReturn; i > 0; i--) {
+ if (Character.isWhitespace(procedureDefn.charAt(i))) {
+ return i;
+ }
+ }
+ }
+
+ // We can't parse it.
+
+ throw SQLError.createSQLException(
+ "Internal error when parsing callable statement metadata",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+
+ /**
* Parses the cascade option string and returns the DBMD constant that
* represents it (for deletes)
*
@@ -2094,9 +2231,12 @@
// DATA_TYPE (jdbc)
rowVal[5] = s2b(typeDesc.typeName); // TYPE_NAME
// (native)
- rowVal[6] = typeDesc.columnSize == null ? null : s2b(typeDesc.columnSize.toString());
- rowVal[7] = s2b(Integer.toString(typeDesc.bufferLength));
- rowVal[8] = typeDesc.decimalDigits == null ? null : s2b(typeDesc.decimalDigits.toString());
+ rowVal[6] = typeDesc.columnSize == null ? null
+ : s2b(typeDesc.columnSize.toString());
+ rowVal[7] = s2b(Integer
+ .toString(typeDesc.bufferLength));
+ rowVal[8] = typeDesc.decimalDigits == null ? null
+ : s2b(typeDesc.decimalDigits.toString());
rowVal[9] = s2b(Integer
.toString(typeDesc.numPrecRadix));
rowVal[10] = s2b(Integer
@@ -2125,11 +2265,15 @@
rowVal[13] = new byte[] { (byte) '0' }; // SQL_DATA_TYPE
rowVal[14] = new byte[] { (byte) '0' }; // SQL_DATE_TIME_SUB
-
- if (StringUtils.indexOfIgnoreCase(typeDesc.typeName, "CHAR") != -1 ||
- StringUtils.indexOfIgnoreCase(typeDesc.typeName, "BLOB") != -1 ||
- StringUtils.indexOfIgnoreCase(typeDesc.typeName, "TEXT") != -1 ||
- StringUtils.indexOfIgnoreCase(typeDesc.typeName, "BINARY") != -1) {
+
+ if (StringUtils.indexOfIgnoreCase(
+ typeDesc.typeName, "CHAR") != -1
+ || StringUtils.indexOfIgnoreCase(
+ typeDesc.typeName, "BLOB") != -1
+ || StringUtils.indexOfIgnoreCase(
+ typeDesc.typeName, "TEXT") != -1
+ || StringUtils.indexOfIgnoreCase(
+ typeDesc.typeName, "BINARY") != -1) {
rowVal[15] = rowVal[6]; // CHAR_OCTET_LENGTH
} else {
rowVal[15] = null;
@@ -2149,9 +2293,10 @@
rowVal[16] = realOrdinal.toString()
.getBytes();
} else {
- throw SQLError.createSQLException(
- "Can not find column in full column list to determine true ordinal position.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Can not find column in full column list to determine true ordinal position.",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
}
@@ -3649,7 +3794,7 @@
&& (procedureNamePattern.indexOf("?") == -1)) {
proceduresToExtractList.add(procedureNamePattern);
} else {
-
+
ResultSet procedureNameRs = null;
try {
@@ -3677,7 +3822,7 @@
rethrowSqlEx = sqlEx;
}
}
-
+
if (rethrowSqlEx != null) {
throw rethrowSqlEx;
}
@@ -3743,13 +3888,11 @@
return getProceduresAndOrFunctions(catalog, schemaPattern,
procedureNamePattern, true, true);
}
-
- protected java.sql.ResultSet getProceduresAndOrFunctions(
- String catalog,
- String schemaPattern,
- String procedureNamePattern,
- final boolean returnProcedures,
- final boolean returnFunctions) throws SQLException {
+
+ protected java.sql.ResultSet getProceduresAndOrFunctions(String catalog,
+ String schemaPattern, String procedureNamePattern,
+ final boolean returnProcedures, final boolean returnFunctions)
+ throws SQLException {
if ((procedureNamePattern == null)
|| (procedureNamePattern.length() == 0)) {
if (this.conn.getNullNamePatternMatchesAll()) {
@@ -3846,8 +3989,8 @@
if (returnProcedures) {
convertToJdbcProcedureList(fromSelect, db,
- proceduresRs, needsClientFiltering, db,
- procedureRowsOrderedByName, nameIndex);
+ proceduresRs, needsClientFiltering, db,
+ procedureRowsOrderedByName, nameIndex);
}
if (!hasTypeColumn) {
@@ -3869,8 +4012,8 @@
if (returnFunctions) {
convertToJdbcFunctionList(db, proceduresRs,
- needsClientFiltering, db,
- procedureRowsOrderedByName, nameIndex);
+ needsClientFiltering, db,
+ procedureRowsOrderedByName, nameIndex);
}
}
@@ -3942,10 +4085,11 @@
if (parsedInfo.localColumnsList.size() != parsedInfo.referencedColumnsList
.size()) {
- throw SQLError.createSQLException(
- "Error parsing foreign keys definition,"
- + "number of local and referenced columns is not the same.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Error parsing foreign keys definition,"
+ + "number of local and referenced columns is not the same.",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
Iterator localColumnNames = parsedInfo.localColumnsList.iterator();
@@ -4000,8 +4144,8 @@
*/
public java.sql.ResultSet getSchemas() throws SQLException {
Field[] fields = new Field[2];
- fields[0] = new Field("", "TABLE_SCHEM", java.sql.Types.CHAR, 0);
- fields[1] = new Field("", "TABLE_CATALOG", java.sql.Types.CHAR, 0);
+ fields[0] = new Field("", "TABLE_SCHEM", java.sql.Types.CHAR, 0);
+ fields[1] = new Field("", "TABLE_CATALOG", java.sql.Types.CHAR, 0);
ArrayList tuples = new ArrayList();
java.sql.ResultSet results = buildResultSet(fields, tuples);
@@ -4386,30 +4530,32 @@
if (!conn.versionMeetsMinimum(5, 0, 2)) {
try {
- results = stmt
- .executeQuery("SHOW TABLES FROM "
- + quotedId + catalogStr.toString()
- + quotedId + " LIKE '"
- + tableNamePat + "'");
+ results = stmt.executeQuery("SHOW TABLES FROM "
+ + quotedId + catalogStr.toString()
+ + quotedId + " LIKE '" + tableNamePat
+ + "'");
} catch (SQLException sqlEx) {
- if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE.equals(sqlEx.getSQLState())) {
+ if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
+ .equals(sqlEx.getSQLState())) {
throw sqlEx;
}
-
+
return;
}
} else {
try {
results = stmt
- .executeQuery("SHOW FULL TABLES FROM "
- + quotedId + catalogStr.toString()
- + quotedId + " LIKE '"
- + tableNamePat + "'");
+ .executeQuery("SHOW FULL TABLES FROM "
+ + quotedId
+ + catalogStr.toString()
+ + quotedId + " LIKE '"
+ + tableNamePat + "'");
} catch (SQLException sqlEx) {
- if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE.equals(sqlEx.getSQLState())) {
+ if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
+ .equals(sqlEx.getSQLState())) {
throw sqlEx;
}
-
+
return;
}
}
@@ -6224,8 +6370,9 @@
true);
if (indexOfOpenParenLocalColumns == -1) {
- throw SQLError.createSQLException("Error parsing foreign keys definition,"
- + " couldn't find start of local columns list.",
+ throw SQLError.createSQLException(
+ "Error parsing foreign keys definition,"
+ + " couldn't find start of local columns list.",
SQLError.SQL_STATE_GENERAL_ERROR);
}
@@ -6241,8 +6388,9 @@
quoteChar, true);
if (indexOfCloseParenLocalColumns == -1) {
- throw SQLError.createSQLException("Error parsing foreign keys definition,"
- + " couldn't find end of local columns list.",
+ throw SQLError.createSQLException(
+ "Error parsing foreign keys definition,"
+ + " couldn't find end of local columns list.",
SQLError.SQL_STATE_GENERAL_ERROR);
}
@@ -6253,9 +6401,11 @@
keysCommentTrimmed, "REFER ", this.quotedId.charAt(0), true);
if (indexOfRefer == -1) {
- throw SQLError.createSQLException("Error parsing foreign keys definition,"
- + " couldn't find start of referenced tables list.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Error parsing foreign keys definition,"
+ + " couldn't find start of referenced tables list.",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
int indexOfOpenParenReferCol = StringUtils
@@ -6263,9 +6413,11 @@
keysCommentTrimmed, "(", quoteChar, false);
if (indexOfOpenParenReferCol == -1) {
- throw SQLError.createSQLException("Error parsing foreign keys definition,"
- + " couldn't find start of referenced columns list.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ throw SQLError
+ .createSQLException(
+ "Error parsing foreign keys definition,"
+ + " couldn't find start of referenced columns list.",
+ SQLError.SQL_STATE_GENERAL_ERROR);
}
String referCatalogTableString = keysCommentTrimmed.substring(
@@ -6275,8 +6427,9 @@
referCatalogTableString, "/", this.quotedId.charAt(0), false);
if (indexOfSlash == -1) {
- throw SQLError.createSQLException("Error parsing foreign keys definition,"
- + " couldn't find name of referenced catalog.",
+ throw SQLError.createSQLException(
+ "Error parsing foreign keys definition,"
+ + " couldn't find name of referenced catalog.",
SQLError.SQL_STATE_GENERAL_ERROR);
}
@@ -6290,8 +6443,9 @@
keysCommentTrimmed, ")", quoteChar, true);
if (indexOfCloseParenRefer == -1) {
- throw SQLError.createSQLException("Error parsing foreign keys definition,"
- + " couldn't find end of referenced columns list.",
+ throw SQLError.createSQLException(
+ "Error parsing foreign keys definition,"
+ + " couldn't find end of referenced columns list.",
SQLError.SQL_STATE_GENERAL_ERROR);
}
@@ -6344,7 +6498,6 @@
private byte[] s2b(String s) throws SQLException {
return StringUtils.s2b(s, this.conn);
}
-
/**
* Does the database store mixed case unquoted SQL identifiers in lower
@@ -6624,16 +6777,16 @@
return false;
}
- /*
- * We don't handle the BIT type yet.
- */
+ /*
+ * We don't handle the BIT type yet.
+ */
case java.sql.Types.BIT:
return false;
- /*
- * The numeric types. Basically they can convert among themselves, and
- * with char/binary types.
- */
+ /*
+ * The numeric types. Basically they can convert among themselves,
+ * and with char/binary types.
+ */
case java.sql.Types.DECIMAL:
case java.sql.Types.NUMERIC:
case java.sql.Types.REAL:
@@ -6666,14 +6819,14 @@
return false;
}
- /* MySQL doesn't support a NULL type. */
+ /* MySQL doesn't support a NULL type. */
case java.sql.Types.NULL:
return false;
- /*
- * With this driver, this will always be a serialized object, so the
- * char/binary types will work.
- */
+ /*
+ * With this driver, this will always be a serialized object, so the
+ * char/binary types will work.
+ */
case java.sql.Types.OTHER:
switch (toType) {
@@ -6689,7 +6842,7 @@
return false;
}
- /* Dates can be converted to char/binary types. */
+ /* Dates can be converted to char/binary types. */
case java.sql.Types.DATE:
switch (toType) {
@@ -6705,7 +6858,7 @@
return false;
}
- /* Time can be converted to char/binary types */
+ /* Time can be converted to char/binary types */
case java.sql.Types.TIME:
switch (toType) {
@@ -6721,10 +6874,10 @@
return false;
}
- /*
- * Timestamp can be converted to char/binary types and date/time types
- * (with loss of precision).
- */
+ /*
+ * Timestamp can be converted to char/binary types and date/time
+ * types (with loss of precision).
+ */
case java.sql.Types.TIMESTAMP:
switch (toType) {
@@ -6742,7 +6895,7 @@
return false;
}
- /* We shouldn't get here! */
+ /* We shouldn't get here! */
default:
return false; // not sure
}
@@ -6895,8 +7048,8 @@
public boolean supportsIntegrityEnhancementFacility() throws SQLException {
if (!this.conn.getOverrideSupportsIntegrityEnhancementFacility()) {
return false;
- }
-
+ }
+
return true;
}
Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/integration/jboss/MysqlValidConnectionChecker.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -109,6 +109,8 @@
Statement pingStatement = null;
try {
+ pingStatement = conn.createStatement();
+
pingStatement.executeQuery("SELECT 1").close();
return null;
Modified: branches/branch_5_0/connector-j/src/testsuite/BaseTestCase.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/BaseTestCase.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/src/testsuite/BaseTestCase.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -49,13 +49,14 @@
* closes them.
*
* @author Mark Matthews
- * @version $Id$
+ * @version $Id: BaseTestCase.java 5440 2006-06-27 17:00:53 +0000 (Tue, 27 Jun
+ * 2006) mmatthews $
*/
public abstract class BaseTestCase extends TestCase {
private final static String ADMIN_CONNECTION_PROPERTY_NAME = "com.mysql.jdbc.testsuite.admin-url";
private final static String NO_MULTI_HOST_PROPERTY_NAME = "com.mysql.jdbc.testsuite.no-multi-hosts-tests";
-
+
/**
* JDBC URL, initialized from com.mysql.jdbc.testsuite.url system property,
* or defaults to jdbc:mysql:///test
@@ -68,8 +69,8 @@
/** Connection to server, initialized in setUp() Cleaned up in tearDown(). */
protected Connection conn = null;
- /** list of Tables to be dropped in tearDown */
- private List createdTables;
+ /** list of schema objects to be dropped in tearDown */
+ private List createdObjects;
/** The driver to use */
protected String dbClass = "com.mysql.jdbc.Driver";
@@ -95,7 +96,7 @@
protected Statement stmt = null;
private boolean runningOnJdk131 = false;
-
+
/**
* Creates a new BaseTestCase object.
*
@@ -111,8 +112,9 @@
if ((newDbUrl != null) && (newDbUrl.trim().length() != 0)) {
dbUrl = newDbUrl;
} else {
- String defaultDbUrl = System.getProperty("com.mysql.jdbc.testsuite.url.default");
-
+ String defaultDbUrl = System
+ .getProperty("com.mysql.jdbc.testsuite.url.default");
+
if ((defaultDbUrl != null) && (defaultDbUrl.trim().length() != 0)) {
dbUrl = defaultDbUrl;
}
@@ -124,33 +126,64 @@
if ((newDriver != null) && (newDriver.trim().length() != 0)) {
this.dbClass = newDriver;
}
-
+
try {
- Blob.class.getMethod("truncate", new Class[] {Long.TYPE});
+ Blob.class.getMethod("truncate", new Class[] { Long.TYPE });
this.runningOnJdk131 = false;
} catch (NoSuchMethodException nsme) {
this.runningOnJdk131 = true;
}
}
- protected void createTable(String tableName, String columnsAndOtherStuff)
- throws SQLException {
- createdTables.add(tableName);
- dropTable(tableName);
+ protected void createSchemaObject(String objectType, String objectName,
+ String columnsAndOtherStuff) throws SQLException {
+ this.createdObjects.add(new String[] {objectType, objectName});
+ dropSchemaObject(objectType, objectName);
- StringBuffer createSql = new StringBuffer(tableName.length()
- + columnsAndOtherStuff.length() + 10);
- createSql.append("CREATE TABLE ");
- createSql.append(tableName);
+ StringBuffer createSql = new StringBuffer(objectName.length()
+ + objectType.length() + columnsAndOtherStuff.length() + 10);
+ createSql.append("CREATE ");
+ createSql.append(objectType);
createSql.append(" ");
+ createSql.append(objectName);
+ createSql.append(" ");
createSql.append(columnsAndOtherStuff);
this.stmt.executeUpdate(createSql.toString());
}
+ protected void createFunction(String functionName, String functionDefn)
+ throws SQLException {
+ createSchemaObject("FUNCTION", functionName, functionDefn);
+ }
+
+ protected void dropFunction(String functionName) throws SQLException {
+ dropSchemaObject("FUNCTION", functionName);
+ }
+
+ protected void createProcedure(String procedureName, String procedureDefn)
+ throws SQLException {
+ createSchemaObject("PROCEDURE", procedureName, procedureDefn);
+ }
+
+ protected void dropProcedure(String procedureName) throws SQLException {
+ dropSchemaObject("PROCEDURE", procedureName);
+ }
+
+ protected void createTable(String tableName, String columnsAndOtherStuff)
+ throws SQLException {
+ createSchemaObject("TABLE", tableName, columnsAndOtherStuff);
+ }
+
protected void dropTable(String tableName) throws SQLException {
- this.stmt.executeUpdate("DROP TABLE IF EXISTS " + tableName);
+ dropSchemaObject("TABLE", tableName);
}
+ protected void dropSchemaObject(String objectType, String objectName)
+ throws SQLException {
+ this.stmt.executeUpdate("DROP " + objectType + " IF EXISTS "
+ + objectName);
+ }
+
protected Connection getAdminConnection() throws SQLException {
return getAdminConnectionWithProps(new Properties());
}
@@ -203,13 +236,12 @@
Object value = getSingleIndexedValueWithQuery(c, 2,
"SHOW VARIABLES LIKE '" + variableName + "'");
-
if (value != null) {
if (value instanceof byte[]) {
// workaround for bad 4.1.x bugfix
- return new String((byte[])value);
+ return new String((byte[]) value);
}
-
+
return value.toString();
}
@@ -387,10 +419,8 @@
System.out.println("Loading JDBC driver '" + this.dbClass + "'");
Class.forName(this.dbClass).newInstance();
System.out.println("Done.\n");
- createdTables = new ArrayList();
+ this.createdObjects = new ArrayList();
- // System.out.println("Establishing connection to database '" + dbUrl
- // + "'");
if (this.dbClass.equals("gwe.sql.gweMysqlDriver")) {
try {
@@ -412,11 +442,18 @@
this.stmt = this.conn.createStatement();
try {
- this.rs = this.stmt.executeQuery("SELECT VERSION()");
- this.rs.next();
- logDebug("Connected to " + this.rs.getString(1));
- this.rs.close();
- this.rs = null;
+ if (dbUrl.indexOf("mysql") != -1) {
+ this.rs = this.stmt.executeQuery("SELECT VERSION()");
+ this.rs.next();
+ logDebug("Connected to " + this.rs.getString(1));
+ this.rs.close();
+ this.rs = null;
+ } else {
+ logDebug("Connected to "
+ + this.conn.getMetaData().getDatabaseProductName()
+ + " / "
+ + this.conn.getMetaData().getDatabaseProductVersion());
+ }
} finally {
if (this.rs != null) {
this.rs.close();
@@ -439,9 +476,11 @@
}
}
- for (int i = 0; i < createdTables.size(); i++) {
+ for (int i = 0; i < this.createdObjects.size(); i++) {
try {
- dropTable((String) createdTables.get(i));
+ String[] objectInfo = (String[])this.createdObjects.get(i);
+
+ dropSchemaObject(objectInfo[0], objectInfo[1]);
} catch (SQLException SQLE) {
;
}
@@ -510,36 +549,36 @@
return (((com.mysql.jdbc.Connection) this.conn).versionMeetsMinimum(
major, minor, subminor));
}
-
+
protected boolean isRunningOnJdk131() {
return this.runningOnJdk131;
}
-
+
protected boolean isClassAvailable(String classname) {
try {
Class.forName(classname);
return true;
} catch (ClassNotFoundException e) {
return false;
- }
+ }
}
protected void closeMemberJDBCResources() {
if (this.rs != null) {
ResultSet toClose = this.rs;
this.rs = null;
-
+
try {
toClose.close();
} catch (SQLException sqlEx) {
// ignore
}
}
-
+
if (this.pstmt != null) {
PreparedStatement toClose = this.pstmt;
this.pstmt = null;
-
+
try {
toClose.close();
} catch (SQLException sqlEx) {
@@ -547,10 +586,11 @@
}
}
}
-
+
protected boolean isRunningOnJRockit() {
String vmVendor = System.getProperty("java.vm.vendor");
-
- return (vmVendor != null && vmVendor.toUpperCase(Locale.US).startsWith("BEA"));
+
+ return (vmVendor != null && vmVendor.toUpperCase(Locale.US).startsWith(
+ "BEA"));
}
}
Modified: branches/branch_5_0/connector-j/src/testsuite/simple/CallableStatementTest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/simple/CallableStatementTest.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ branches/branch_5_0/connector-j/src/testsuite/simple/CallableStatementTest.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -30,6 +30,7 @@
import java.sql.CallableStatement;
import java.sql.Connection;
+import java.sql.ParameterMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
@@ -496,4 +497,56 @@
public static void main(String[] args) {
junit.textui.TestRunner.run(CallableStatementTest.class);
}
+
+ /** Tests the new parameter parser that doesn't require "BEGIN" or "\n" at end
+ * of parameter declaration
+ * @throws Exception
+ */
+ public void testParameterParser() throws Exception {
+
+ if (!versionMeetsMinimum(5, 0)) {
+ return;
+ }
+
+ CallableStatement cstmt = null;
+
+ try {
+
+ createTable("t1",
+ "(id char(16) not null default '', data int not null)");
+ createTable("t2", "(s char(16), i int, d double)");
+
+ createProcedure("foo42",
+ "() insert into test.t1 values ('foo', 42);");
+ this.conn.prepareCall("{CALL foo42()}");
+ this.conn.prepareCall("{CALL foo42}");
+
+ createProcedure("bar",
+ "(x char(16), y int, z DECIMAL(10)) insert into test.t1 values (x, y);");
+ cstmt = this.conn.prepareCall("{CALL bar(?, ?, ?)}");
+
+ if (!isRunningOnJdk131()) {
+ ParameterMetaData md = cstmt.getParameterMetaData();
+ assertEquals(3, md.getParameterCount());
+ assertEquals(Types.CHAR, md.getParameterType(1));
+ assertEquals(Types.INTEGER, md.getParameterType(2));
+ assertEquals(Types.DECIMAL, md.getParameterType(3));
+ }
+
+ createProcedure("p", "() label1: WHILE @a=0 DO SET @a=1; END WHILE");
+ this.conn.prepareCall("{CALL p()}");
+
+ createFunction("f", "() RETURNS INT return 1; ");
+ cstmt = this.conn.prepareCall("{? = CALL f()}");
+
+ if (!isRunningOnJdk131()) {
+ ParameterMetaData md = cstmt.getParameterMetaData();
+ assertEquals(Types.INTEGER, md.getParameterType(1));
+ }
+ } finally {
+ if (cstmt != null) {
+ cstmt.close();
+ }
+ }
+ }
}
Modified: trunk/connector-j/CHANGES
===================================================================
--- trunk/connector-j/CHANGES 2007-01-11 21:05:22 UTC (rev 6298)
+++ trunk/connector-j/CHANGES 2007-01-23 21:42:00 UTC (rev 6299)
@@ -72,6 +72,13 @@
- Fixed BUG#25379 - INOUT parameters in CallableStatements get
doubly-escaped.
+ - Removed non-short-circuited logical ORs from "if" statements.
+
+ - Re-worked stored procedure parameter parser to be more robust. Driver no
+ longer requires "BEGIN" in stored procedure definition, but does have
+ requirement that if a stored function begins with a label directly after the
+ "returns" clause, that the label is not a quoted identifier.
+
10-20-06 - Version 5.0.4
- Fixed BUG#21379 - column names don't match metadata in cases
Modified: trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ trunk/connector-j/src/com/mysql/jdbc/CallableStatement.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -727,7 +727,7 @@
paramTypesRs = dbmd.getProcedureColumns(this.connection
.versionMeetsMinimum(5, 0, 2)
- & useCatalog ? this.currentCatalog : null, null, procName,
+ && useCatalog ? this.currentCatalog : null, null, procName,
"%"); //$NON-NLS-1$
convertGetProcedureColumnsToInternalDescriptors(paramTypesRs);
Modified: trunk/connector-j/src/com/mysql/jdbc/Connection.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/Connection.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ trunk/connector-j/src/com/mysql/jdbc/Connection.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -3422,7 +3422,7 @@
if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) {
directCompare = false;
- } else if (otherHost != null & otherHost.indexOf(",") == -1 &&
+ } else if (otherHost != null && otherHost.indexOf(",") == -1 &&
otherHost.indexOf(":") == -1) {
// need to check port numbers
directCompare = (otherConnection.origPortToConnectTo ==
@@ -4249,7 +4249,7 @@
*/
public void resetServerState() throws SQLException {
if (!getParanoid()
- && ((this.io != null) & versionMeetsMinimum(4, 0, 6))) {
+ && ((this.io != null) && versionMeetsMinimum(4, 0, 6))) {
changeUser(this.user, this.password);
}
}
Modified: trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -549,7 +549,7 @@
if (db == null && procDb == null) {
shouldAdd = true;
- } else if (db != null & db.equals(procDb)) {
+ } else if (db != null && db.equals(procDb)) {
shouldAdd = true;
}
}
@@ -604,7 +604,7 @@
if (db == null && procDb == null) {
shouldAdd = true;
- } else if (db != null & db.equals(procDb)) {
+ } else if (db != null && db.equals(procDb)) {
shouldAdd = true;
}
}
@@ -1368,91 +1368,58 @@
}
int openParenIndex = StringUtils
- .indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(",
- quoteChar.charAt(0), !this.conn
- .isNoBackslashEscapesSet());
+ .indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(",
+ quoteChar.charAt(0), !this.conn
+ .isNoBackslashEscapesSet());
+ int endOfParamDeclarationIndex = 0;
- String beforeBegin = null;
+ endOfParamDeclarationIndex = endPositionOfParameterDeclaration(
+ openParenIndex, procedureDef, quoteChar);
- // Try and fudge this with the 'begin' statement
- int beginIndex = 0;
+ if (parsingFunction) {
- if (!parsingFunction) {
- beginIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(0,
- procedureDef, "\nbegin", quoteChar.charAt(0),
- !this.conn.isNoBackslashEscapesSet());
- } else {
- // Grab the return column first, since it needs
+ // Grab the return column since it needs
// to go first in the output result set
int returnsIndex = StringUtils
- .indexOfIgnoreCaseRespectQuotes(0, procedureDef,
- " RETURNS ", quoteChar.charAt(0),
- !this.conn.isNoBackslashEscapesSet());
+ .indexOfIgnoreCaseRespectQuotes(0, procedureDef,
+ " RETURNS ", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
- beginIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(
- returnsIndex, procedureDef, "\nbegin", quoteChar
- .charAt(0), !this.conn
- .isNoBackslashEscapesSet());
+ int endReturnsDef = findEndOfReturnsClause(procedureDef,
+ quoteChar, returnsIndex);
- if (beginIndex == -1) {
- beginIndex = StringUtils
- .indexOfIgnoreCaseRespectQuotes(0,
- procedureDef, "\n",
- quoteChar.charAt(0), !this.conn
- .isNoBackslashEscapesSet());
- }
+ // Trim off whitespace after "RETURNS"
- // Okay, give up...
+ int declarationStart = returnsIndex + "RETURNS ".length();
- if (beginIndex == -1) {
- throw SQLError.createSQLException(
- "Driver requires declaration of procedure to either contain a '\\nbegin' or '\\n' to follow argument declaration, or SELECT privilege on mysql.proc to parse column types.",
- SQLError.SQL_STATE_GENERAL_ERROR);
+ while (declarationStart < procedureDef.length()) {
+ if (Character.isWhitespace(procedureDef.charAt(declarationStart))) {
+ declarationStart++;
+ } else {
+ break;
+ }
}
- String returnsDefn = procedureDef.substring(returnsIndex
- + "RETURNS ".length(), beginIndex);
+ String returnsDefn = procedureDef.substring(declarationStart, endReturnsDef).trim();
TypeDescriptor returnDescriptor = new TypeDescriptor(
returnsDefn, null);
resultRows.add(convertTypeDescriptorToProcedureRow(
procNameAsBytes, "", false, false, true,
returnDescriptor));
-
- beginIndex = returnsIndex; // further processing needs to
- // look before "RETURNS" token
}
- // Bah, we _really_ need information schema here
-
- if (beginIndex != -1) {
- beforeBegin = procedureDef.substring(0, beginIndex);
- } else {
- beginIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(0,
- procedureDef, "\n", quoteChar.charAt(0), !this.conn
- .isNoBackslashEscapesSet());
-
- if (beginIndex != -1) {
- beforeBegin = procedureDef.substring(0, beginIndex);
- } else {
- throw SQLError.createSQLException(
- "Driver requires declaration of procedure to either contain a '\\nbegin' or '\\n' to follow argument declaration, or SELECT privilege on mysql.proc to parse column types.",
- SQLError.SQL_STATE_GENERAL_ERROR);
- }
-
- }
-
- int endParenIndex = beforeBegin.lastIndexOf(')');
-
- if ((openParenIndex == -1) || (endParenIndex == -1)) {
+ if ((openParenIndex == -1)
+ || (endOfParamDeclarationIndex == -1)) {
// parse error?
- throw SQLError.createSQLException(
+ throw SQLError
+ .createSQLException(
"Internal error when parsing callable statement metadata",
SQLError.SQL_STATE_GENERAL_ERROR);
}
parameterDef = procedureDef.substring(openParenIndex + 1,
- endParenIndex);
+ endOfParamDeclarationIndex);
}
} finally {
SQLException sqlExRethrow = null;
@@ -1586,8 +1553,121 @@
// exist, is it an error....
}
}
+ /**
+ * Finds the end of the parameter declaration from the output of "SHOW
+ * CREATE PROCEDURE".
+ *
+ * @param beginIndex
+ * should be the index of the procedure body that contains the
+ * first "(".
+ * @param procedureDef
+ * the procedure body
+ * @param quoteChar
+ * the identifier quote character in use
+ * @return the ending index of the parameter declaration, not including the
+ * closing ")"
+ * @throws SQLException
+ * if a parse error occurs.
+ */
+ private int endPositionOfParameterDeclaration(int beginIndex,
+ String procedureDef, String quoteChar) throws SQLException {
+ int currentPos = beginIndex + 1;
+ int parenDepth = 1; // counting the first openParen
+ while (parenDepth > 0 && currentPos < procedureDef.length()) {
+ int closedParenIndex = StringUtils.indexOfIgnoreCaseRespectQuotes(
+ currentPos, procedureDef, ")", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
+
+ if (closedParenIndex != -1) {
+ int nextOpenParenIndex = StringUtils
+ .indexOfIgnoreCaseRespectQuotes(currentPos,
+ procedureDef, "(", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
+
+ if (nextOpenParenIndex != -1
+ && nextOpenParenIndex < closedParenIndex) {
+ parenDepth++;
+ currentPos = closedParenIndex + 1; // set after closed
+ // paren that increases
+ // depth
+ } else {
+ parenDepth--;
+ currentPos = closedParenIndex; // start search from same
+ // position
+ }
+ } else {
+ // we should always get closed paren of some sort
+ throw SQLError
+ .createSQLException(
+ "Internal error when parsing callable statement metadata",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+ }
+
+ return currentPos;
+ }
+
/**
+ * Finds the end of the RETURNS clause for SQL Functions by using any of the
+ * keywords allowed after the RETURNS clause, or a label.
+ *
+ * @param procedureDefn
+ * the function body containing the definition of the function
+ * @param quoteChar
+ * the identifier quote string in use
+ * @param positionOfReturnKeyword
+ * the position of "RETRUNS" in the definition
+ * @return the end of the returns clause
+ * @throws SQLException
+ * if a parse error occurs
+ */
+ private int findEndOfReturnsClause(String procedureDefn, String quoteChar,
+ int positionOfReturnKeyword) throws SQLException {
+ /*
+ * characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL |
+ * NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY {
+ * DEFINER | INVOKER } | COMMENT 'string'
+ */
+
+ String[] tokens = new String[] { "LANGUAGE", "NOT", "DETERMINISTIC",
+ "CONTAINS", "NO", "READ", "MODIFIES", "SQL", "COMMENT", "BEGIN",
+ "RETURN" };
+
+ int startLookingAt = positionOfReturnKeyword + "RETURNS".length() + 1;
+
+ for (int i = 0; i < tokens.length; i++) {
+ int endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes(
+ startLookingAt, procedureDefn, tokens[i], quoteChar
+ .charAt(0), !this.conn.isNoBackslashEscapesSet());
+
+ if (endOfReturn != -1) {
+ return endOfReturn;
+ }
+ }
+
+ // Label?
+ int endOfReturn = StringUtils.indexOfIgnoreCaseRespectQuotes(
+ startLookingAt, procedureDefn, ":", quoteChar.charAt(0),
+ !this.conn.isNoBackslashEscapesSet());
+
+ if (endOfReturn != -1) {
+ // seek back until whitespace
+ for (int i = endOfReturn; i > 0; i--) {
+ if (Character.isWhitespace(procedureDefn.charAt(i))) {
+ return i;
+ }
+ }
+ }
+
+ // We can't parse it.
+
+ throw SQLError.createSQLException(
+ "Internal error when parsing callable statement metadata",
+ SQLError.SQL_STATE_GENERAL_ERROR);
+ }
+
+ /**
* Parses the cascade option string and returns the DBMD constant that
* represents it (for deletes)
*
Modified: trunk/connector-j/src/testsuite/BaseTestCase.java
===================================================================
--- trunk/connector-j/src/testsuite/BaseTestCase.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ trunk/connector-j/src/testsuite/BaseTestCase.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -49,13 +49,14 @@
* closes them.
*
* @author Mark Matthews
- * @version $Id$
+ * @version $Id: BaseTestCase.java 5440 2006-06-27 17:00:53 +0000 (Tue, 27 Jun
+ * 2006) mmatthews $
*/
public abstract class BaseTestCase extends TestCase {
private final static String ADMIN_CONNECTION_PROPERTY_NAME = "com.mysql.jdbc.testsuite.admin-url";
private final static String NO_MULTI_HOST_PROPERTY_NAME = "com.mysql.jdbc.testsuite.no-multi-hosts-tests";
-
+
/**
* JDBC URL, initialized from com.mysql.jdbc.testsuite.url system property,
* or defaults to jdbc:mysql:///test
@@ -68,8 +69,8 @@
/** Connection to server, initialized in setUp() Cleaned up in tearDown(). */
protected Connection conn = null;
- /** list of Tables to be dropped in tearDown */
- private List createdTables;
+ /** list of schema objects to be dropped in tearDown */
+ private List createdObjects;
/** The driver to use */
protected String dbClass = "com.mysql.jdbc.Driver";
@@ -95,7 +96,7 @@
protected Statement stmt = null;
private boolean runningOnJdk131 = false;
-
+
/**
* Creates a new BaseTestCase object.
*
@@ -111,8 +112,9 @@
if ((newDbUrl != null) && (newDbUrl.trim().length() != 0)) {
dbUrl = newDbUrl;
} else {
- String defaultDbUrl = System.getProperty("com.mysql.jdbc.testsuite.url.default");
-
+ String defaultDbUrl = System
+ .getProperty("com.mysql.jdbc.testsuite.url.default");
+
if ((defaultDbUrl != null) && (defaultDbUrl.trim().length() != 0)) {
dbUrl = defaultDbUrl;
}
@@ -124,33 +126,64 @@
if ((newDriver != null) && (newDriver.trim().length() != 0)) {
this.dbClass = newDriver;
}
-
+
try {
- Blob.class.getMethod("truncate", new Class[] {Long.TYPE});
+ Blob.class.getMethod("truncate", new Class[] { Long.TYPE });
this.runningOnJdk131 = false;
} catch (NoSuchMethodException nsme) {
this.runningOnJdk131 = true;
}
}
- protected void createTable(String tableName, String columnsAndOtherStuff)
- throws SQLException {
- createdTables.add(tableName);
- dropTable(tableName);
+ protected void createSchemaObject(String objectType, String objectName,
+ String columnsAndOtherStuff) throws SQLException {
+ this.createdObjects.add(new String[] {objectType, objectName});
+ dropSchemaObject(objectType, objectName);
- StringBuffer createSql = new StringBuffer(tableName.length()
- + columnsAndOtherStuff.length() + 10);
- createSql.append("CREATE TABLE ");
- createSql.append(tableName);
+ StringBuffer createSql = new StringBuffer(objectName.length()
+ + objectType.length() + columnsAndOtherStuff.length() + 10);
+ createSql.append("CREATE ");
+ createSql.append(objectType);
createSql.append(" ");
+ createSql.append(objectName);
+ createSql.append(" ");
createSql.append(columnsAndOtherStuff);
this.stmt.executeUpdate(createSql.toString());
}
+ protected void createFunction(String functionName, String functionDefn)
+ throws SQLException {
+ createSchemaObject("FUNCTION", functionName, functionDefn);
+ }
+
+ protected void dropFunction(String functionName) throws SQLException {
+ dropSchemaObject("FUNCTION", functionName);
+ }
+
+ protected void createProcedure(String procedureName, String procedureDefn)
+ throws SQLException {
+ createSchemaObject("PROCEDURE", procedureName, procedureDefn);
+ }
+
+ protected void dropProcedure(String procedureName) throws SQLException {
+ dropSchemaObject("PROCEDURE", procedureName);
+ }
+
+ protected void createTable(String tableName, String columnsAndOtherStuff)
+ throws SQLException {
+ createSchemaObject("TABLE", tableName, columnsAndOtherStuff);
+ }
+
protected void dropTable(String tableName) throws SQLException {
- this.stmt.executeUpdate("DROP TABLE IF EXISTS " + tableName);
+ dropSchemaObject("TABLE", tableName);
}
+ protected void dropSchemaObject(String objectType, String objectName)
+ throws SQLException {
+ this.stmt.executeUpdate("DROP " + objectType + " IF EXISTS "
+ + objectName);
+ }
+
protected Connection getAdminConnection() throws SQLException {
return getAdminConnectionWithProps(new Properties());
}
@@ -203,13 +236,12 @@
Object value = getSingleIndexedValueWithQuery(c, 2,
"SHOW VARIABLES LIKE '" + variableName + "'");
-
if (value != null) {
if (value instanceof byte[]) {
// workaround for bad 4.1.x bugfix
- return new String((byte[])value);
+ return new String((byte[]) value);
}
-
+
return value.toString();
}
@@ -387,10 +419,8 @@
System.out.println("Loading JDBC driver '" + this.dbClass + "'");
Class.forName(this.dbClass).newInstance();
System.out.println("Done.\n");
- createdTables = new ArrayList();
+ this.createdObjects = new ArrayList();
- // System.out.println("Establishing connection to database '" + dbUrl
- // + "'");
if (this.dbClass.equals("gwe.sql.gweMysqlDriver")) {
try {
@@ -412,11 +442,18 @@
this.stmt = this.conn.createStatement();
try {
- this.rs = this.stmt.executeQuery("SELECT VERSION()");
- this.rs.next();
- logDebug("Connected to " + this.rs.getString(1));
- this.rs.close();
- this.rs = null;
+ if (dbUrl.indexOf("mysql") != -1) {
+ this.rs = this.stmt.executeQuery("SELECT VERSION()");
+ this.rs.next();
+ logDebug("Connected to " + this.rs.getString(1));
+ this.rs.close();
+ this.rs = null;
+ } else {
+ logDebug("Connected to "
+ + this.conn.getMetaData().getDatabaseProductName()
+ + " / "
+ + this.conn.getMetaData().getDatabaseProductVersion());
+ }
} finally {
if (this.rs != null) {
this.rs.close();
@@ -439,9 +476,11 @@
}
}
- for (int i = 0; i < createdTables.size(); i++) {
+ for (int i = 0; i < this.createdObjects.size(); i++) {
try {
- dropTable((String) createdTables.get(i));
+ String[] objectInfo = (String[])this.createdObjects.get(i);
+
+ dropSchemaObject(objectInfo[0], objectInfo[1]);
} catch (SQLException SQLE) {
;
}
@@ -510,36 +549,36 @@
return (((com.mysql.jdbc.Connection) this.conn).versionMeetsMinimum(
major, minor, subminor));
}
-
+
protected boolean isRunningOnJdk131() {
return this.runningOnJdk131;
}
-
+
protected boolean isClassAvailable(String classname) {
try {
Class.forName(classname);
return true;
} catch (ClassNotFoundException e) {
return false;
- }
+ }
}
protected void closeMemberJDBCResources() {
if (this.rs != null) {
ResultSet toClose = this.rs;
this.rs = null;
-
+
try {
toClose.close();
} catch (SQLException sqlEx) {
// ignore
}
}
-
+
if (this.pstmt != null) {
PreparedStatement toClose = this.pstmt;
this.pstmt = null;
-
+
try {
toClose.close();
} catch (SQLException sqlEx) {
@@ -547,10 +586,11 @@
}
}
}
-
+
protected boolean isRunningOnJRockit() {
String vmVendor = System.getProperty("java.vm.vendor");
-
- return (vmVendor != null && vmVendor.toUpperCase(Locale.US).startsWith("BEA"));
+
+ return (vmVendor != null && vmVendor.toUpperCase(Locale.US).startsWith(
+ "BEA"));
}
}
Modified: trunk/connector-j/src/testsuite/simple/CallableStatementTest.java
===================================================================
--- trunk/connector-j/src/testsuite/simple/CallableStatementTest.java 2007-01-11 21:05:22 UTC (rev 6298)
+++ trunk/connector-j/src/testsuite/simple/CallableStatementTest.java 2007-01-23 21:42:00 UTC (rev 6299)
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2002-2004 MySQL AB
+ Copyright (C) 2002-2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -488,6 +488,58 @@
}
}
+ /** Tests the new parameter parser that doesn't require "BEGIN" or "\n" at end
+ * of parameter declaration
+ * @throws Exception
+ */
+ public void testParameterParser() throws Exception {
+
+ if (!versionMeetsMinimum(5, 0)) {
+ return;
+ }
+
+ CallableStatement cstmt = null;
+
+ try {
+
+ createTable("t1",
+ "(id char(16) not null default '', data int not null)");
+ createTable("t2", "(s char(16), i int, d double)");
+
+ createProcedure("foo42",
+ "() insert into test.t1 values ('foo', 42);");
+ this.conn.prepareCall("{CALL foo42()}");
+ this.conn.prepareCall("{CALL foo42}");
+
+ createProcedure("bar",
+ "(x char(16), y int, z DECIMAL(10)) insert into test.t1 values (x, y);");
+ cstmt = this.conn.prepareCall("{CALL bar(?, ?, ?)}");
+
+ if (!isRunningOnJdk131()) {
+ ParameterMetaData md = cstmt.getParameterMetaData();
+ assertEquals(3, md.getParameterCount());
+ assertEquals(Types.CHAR, md.getParameterType(1));
+ assertEquals(Types.INTEGER, md.getParameterType(2));
+ assertEquals(Types.DECIMAL, md.getParameterType(3));
+ }
+
+ createProcedure("p", "() label1: WHILE @a=0 DO SET @a=1; END WHILE");
+ this.conn.prepareCall("{CALL p()}");
+
+ createFunction("f", "() RETURNS INT return 1; ");
+ cstmt = this.conn.prepareCall("{? = CALL f()}");
+
+ if (!isRunningOnJdk131()) {
+ ParameterMetaData md = cstmt.getParameterMetaData();
+ assertEquals(Types.INTEGER, md.getParameterType(1));
+ }
+ } finally {
+ if (cstmt != null) {
+ cstmt.close();
+ }
+ }
+ }
+
/**
* Runs all test cases in this test suite
*
| Thread |
|---|
| • Connector/J commit: r6299 - branches/branch_5_0/connector-j branches/branch_5_0/connector-j/src/com/mysql/jdbc branches/branch_5_0/connector-j/src/com... | mmatthews | 23 Jan |