List:Commits« Previous MessageNext Message »
From:mmatthews Date:March 9 2007 10:14pm
Subject:Connector/J commit: r6341 - branches/branch_5_0/connector-j branches/branch_5_0/connector-j/src/com/mysql/jdbc branches/branch_5_0/connector-j/src/tes...
View as plain text  
Modified:
   branches/branch_5_0/connector-j/CHANGES
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java
  
branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
   trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
   trunk/connector-j/src/com/mysql/jdbc/StringUtils.java
   trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
Log:
Fixed BUG#26959 - comments in DDL of stored procedures/functions confuse 
	  procedure parser, and thus metadata about them can not be created, leading to
	  inability to retrieve said metadata, or execute procedures that have certain
	  comments in them.

(also, in 5.1, changed visibility of one member for some re-factoring going on elsewhere)

Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES	2007-03-08 02:28:23 UTC (rev 6340)
+++ branches/branch_5_0/connector-j/CHANGES	2007-03-09 21:13:57 UTC (rev 6341)
@@ -20,7 +20,12 @@
 	  statement that enables this functionality, which the driver ignored (using
 	  the original metadata returned during prepare()), causing corrupt reading
 	  of data due to type mismatch when the actual rows were returned.
-	  	   	  
+
+	- Fixed BUG#26959 - comments in DDL of stored procedures/functions confuse 
+	  procedure parser, and thus metadata about them can not be created, leading to
+	  inability to retrieve said metadata, or execute procedures that have certain
+	  comments in them.
+	  	  	   	  
 03-01-07 - Version 5.0.5
 
     - Fixed BUG#23645 - Some collations/character sets reported as "unknown"

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-03-08
02:28:23 UTC (rev 6340)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-03-09
21:13:57 UTC (rev 6341)
@@ -1507,11 +1507,12 @@
 
 		String quoteChar = getIdentifierQuoteString();
 
-		String storageDefnDelims = "(" + quoteChar;
-		String storageDefnClosures = ")" + quoteChar;
-
 		String parameterDef = null;
 
+		boolean isProcedureInAnsiMode = false;
+		String storageDefnDelims = null;
+		String storageDefnClosures = null;
+		
 		try {
 			paramRetrievalStmt = this.conn.getMetadataSafeStatement();
 
@@ -1620,6 +1621,25 @@
 									SQLError.SQL_STATE_GENERAL_ERROR);
 				}
 
+				try {
+					String sqlMode = paramRetrievalRs.getString("sql_mode");
+					
+					if (StringUtils.indexOfIgnoreCase(sqlMode, "ANSI") != -1) {
+						isProcedureInAnsiMode = true;
+					}
+				} catch (SQLException sqlEx) {
+					// doesn't exist
+				}
+
+				String identifierMarkers = isProcedureInAnsiMode ? "`\"" : "`";
+				String identifierAndStringMarkers = "'" + identifierMarkers;
+				storageDefnDelims = "(" + identifierMarkers;
+				storageDefnClosures = ")" + identifierMarkers;
+				
+				// sanitize/normalize by stripping out comments
+				procedureDef = StringUtils.stripComments(procedureDef, 
+						identifierAndStringMarkers, identifierAndStringMarkers, true, false, true, true);
+				
 				int openParenIndex = StringUtils
 						.indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(",
 								quoteChar.charAt(0), !this.conn
@@ -1703,6 +1723,7 @@
 		}
 
 		if (parameterDef != null) {
+
 			List parseList = StringUtils.split(parameterDef, ",",
 					storageDefnDelims, storageDefnClosures, true);
 
@@ -1789,6 +1810,11 @@
 										SQLError.SQL_STATE_GENERAL_ERROR);
 					}
 
+					if ((paramName.startsWith("`") && paramName.endsWith("`")) || 
+							(isProcedureInAnsiMode && paramName.startsWith("\"") &&
paramName.endsWith("\""))) {
+						paramName = paramName.substring(1, paramName.length() - 1);
+					}
+					
 					int wildCompareRes = StringUtils.wildCompare(paramName,
 							parameterNamePattern);
 

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java	2007-03-08
02:28:23 UTC (rev 6340)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/StringUtils.java	2007-03-09
21:13:57 UTC (rev 6341)
@@ -25,6 +25,8 @@
 package com.mysql.jdbc;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -929,7 +931,7 @@
 			boolean allowBackslashEscapes) {
 		char contextMarker = Character.MIN_VALUE;
 		boolean escaped = false;
-		int markerTypeFound = 0;
+		int markerTypeFound = -1;
 		int srcLength = src.length();
 		int ind = 0;
 
@@ -938,8 +940,9 @@
 
 			if (allowBackslashEscapes && c == '\\') {
 				escaped = !escaped;
-			} else if (c == markerCloses.charAt(markerTypeFound) && !escaped) {
+			} else if (markerTypeFound != -1 && c == markerCloses.charAt(markerTypeFound)
&& !escaped) {
 				contextMarker = Character.MIN_VALUE;
+				markerTypeFound = -1;
 			} else if ((ind = marker.indexOf(c)) != -1 && !escaped
 					&& contextMarker == Character.MIN_VALUE) {
 				markerTypeFound = ind;
@@ -1482,4 +1485,133 @@
 		
 		return -1;
 	}
+	
+	/**
+	 * Returns the given string, with comments removed
+	 * 
+	 * @param src
+	 *            the source string
+	 * @param stringOpens
+	 *            characters which delimit the "open" of a string
+	 * @param stringCloses
+	 *            characters which delimit the "close" of a string, in
+	 *            counterpart order to <code>stringOpens</code>
+	 * @param slashStarComments
+	 *            strip slash-star type "C" style comments
+	 * @param slashSlashComments
+	 *            strip slash-slash C++ style comments to end-of-line
+	 * @param hashComments
+	 *            strip #-style comments to end-of-line
+	 * @param dashDashComments
+	 *            strip "--" style comments to end-of-line
+	 * @return the input string with all comment-delimited data removed
+	 */
+	public static String stripComments(String src, String stringOpens,
+			String stringCloses, boolean slashStarComments,
+			boolean slashSlashComments, boolean hashComments,
+			boolean dashDashComments) {
+		if (src == null) {
+			return null;
+		}
+
+		StringBuffer buf = new StringBuffer(src.length());
+
+		// It's just more natural to deal with this as a stream
+		// when parsing..This code is currently only called when
+		// parsing the kind of metadata that developers are strongly
+		// recommended to cache anyways, so we're not worried
+		// about the _1_ extra object allocation if it cleans
+		// up the code
+
+		StringReader sourceReader = new StringReader(src);
+
+		int contextMarker = Character.MIN_VALUE;
+		boolean escaped = false;
+		int markerTypeFound = -1;
+
+		int ind = 0;
+
+		int currentChar = 0;
+
+		try {
+			while ((currentChar = sourceReader.read()) != -1) {
+
+				if (false && currentChar == '\\') {
+					escaped = !escaped;
+				} else if (markerTypeFound != -1 && currentChar ==
stringCloses.charAt(markerTypeFound)
+						&& !escaped) {
+					contextMarker = Character.MIN_VALUE;
+					markerTypeFound = -1;
+				} else if ((ind = stringOpens.indexOf(currentChar)) != -1
+						&& !escaped && contextMarker == Character.MIN_VALUE) {
+					markerTypeFound = ind;
+					contextMarker = currentChar;
+				}
+
+				if (contextMarker == Character.MIN_VALUE && currentChar == '/'
+						&& (slashSlashComments || slashStarComments)) {
+					currentChar = sourceReader.read();
+					if (currentChar == '*' && slashStarComments) {
+						int prevChar = 0;
+						while ((currentChar = sourceReader.read()) != '/'
+								|| prevChar != '*') {
+							if (currentChar == '\r') {
+
+								currentChar = sourceReader.read();
+								if (currentChar == '\n') {
+									currentChar = sourceReader.read();
+								}
+							} else {
+								if (currentChar == '\n') {
+
+									currentChar = sourceReader.read();
+								}
+							}
+							if (currentChar < 0)
+								break;
+							prevChar = currentChar;
+						}
+						continue;
+					} else if (currentChar == '/' && slashSlashComments) {
+						while ((currentChar = sourceReader.read()) != '\n'
+								&& currentChar != '\r' && currentChar >= 0)
+							;
+					}
+				} else if (contextMarker == Character.MIN_VALUE
+						&& currentChar == '#' && hashComments) {
+					// Slurp up everything until the newline
+					while ((currentChar = sourceReader.read()) != '\n'
+							&& currentChar != '\r' && currentChar >= 0)
+						;
+				} else if (contextMarker == Character.MIN_VALUE
+						&& currentChar == '-' && dashDashComments) {
+					currentChar = sourceReader.read();
+
+					if (currentChar == -1 || currentChar != '-') {
+						buf.append('-');
+
+						if (currentChar != -1) {
+							buf.append(currentChar);
+						}
+
+						continue;
+					}
+
+					// Slurp up everything until the newline
+
+					while ((currentChar = sourceReader.read()) != '\n'
+							&& currentChar != '\r' && currentChar >= 0)
+						;
+				}
+
+				if (currentChar != -1) {
+					buf.append((char) currentChar);
+				}
+			}
+		} catch (IOException ioEx) {
+			// we'll never see this from a StringReader
+		}
+
+		return buf.toString();
+	}
 }

Modified:
branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
---
branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2007-03-08
02:28:23 UTC (rev 6340)
+++
branches/branch_5_0/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2007-03-09
21:13:57 UTC (rev 6341)
@@ -30,11 +30,13 @@
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Types;
+import java.util.List;
 import java.util.Properties;
 
 import com.mysql.jdbc.DatabaseMetaData;
 import com.mysql.jdbc.NonRegisteringDriver;
 import com.mysql.jdbc.SQLError;
+import com.mysql.jdbc.StringUtils;
 
 import testsuite.BaseTestCase;
 
@@ -950,4 +952,117 @@
 		
 		this.conn.prepareCall("{call testBug26143(?)").close();
 	}
+	
+	/**
+	 * Tests fix for BUG#26959 - comments confuse procedure parser.
+	 * 
+	 * @throws Exception if the test fails
+	 */
+	public void testBug26959() throws Exception {
+		if (!versionMeetsMinimum(5, 0)) {
+			return;
+		}
+
+		createProcedure(
+				"testBug26959",
+				"(_ACTION varchar(20),"
+						+ "\n`/*dumb-identifier-1*/` int,"
+						+ "\n`#dumb-identifier-2` int,"
+						+ "\n`--dumb-identifier-3` int,"
+						+ "\n_CLIENT_ID int, -- ABC"
+						+ "\n_LOGIN_ID  int, # DEF"
+						+ "\n_WHERE varchar(2000),"
+						+ "\n_SORT varchar(2000),"
+						+ "\n out _SQL varchar(/* inline right here - oh my gosh! */ 8000),"
+						+ "\n _SONG_ID int,"
+						+ "\n  _NOTES varchar(2000),"
+						+ "\n out _RESULT varchar(10)"
+						+ "\n /*"
+						+ "\n ,    -- Generic result parameter"
+						+ "\n out _PERIOD_ID int,         -- Returns the period_id. Useful when using
@PREDEFLINK to return which is the last period"
+						+ "\n   _SONGS_LIST varchar(8000),"
+						+ "\n  _COMPOSERID int,"
+						+ "\n  _PUBLISHERID int,"
+						+ "\n   _PREDEFLINK int        -- If the user is accessing through a predefined
link: 0=none  1=last period"
+						+ "\n */) BEGIN SELECT 1; END");
+
+		createProcedure(
+				"testBug26959_1",
+				"(`/*id*/` /* before type 1 */ varchar(20),"
+						+ "/* after type 1 */ OUT result2 DECIMAL(/*size1*/10,/*size2*/2) /* p2 */)"
+						+ "BEGIN SELECT action, result; END");
+
+		try {
+			this.conn.prepareCall(
+					"{call testBug26959(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}")
+					.close();
+			this.rs = this.conn.getMetaData().getProcedureColumns(
+					this.conn.getCatalog(), null, "testBug26959", "%");
+
+			String[] parameterNames = new String[] { "_ACTION",
+					"/*dumb-identifier-1*/", "#dumb-identifier-2",
+					"--dumb-identifier-3", "_CLIENT_ID", "_LOGIN_ID", "_WHERE",
+					"_SORT", "_SQL", "_SONG_ID", "_NOTES", "_RESULT" };
+
+			int[] parameterTypes = new int[] { Types.VARCHAR, Types.INTEGER,
+					Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER,
+					Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER,
+					Types.VARCHAR, Types.VARCHAR };
+
+			int[] direction = new int[] { DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnOut,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnOut };
+
+			int[] precision = new int[] { 20, 10, 10, 10, 10, 10, 2000, 2000,
+					8000, 10, 2000, 10 };
+
+			int index = 0;
+
+			while (this.rs.next()) {
+				assertEquals(parameterNames[index], this.rs
+						.getString("COLUMN_NAME"));
+				assertEquals(parameterTypes[index], this.rs.getInt("DATA_TYPE"));
+				assertEquals(precision[index], this.rs.getInt("PRECISION"));
+				assertEquals(direction[index], this.rs.getInt("COLUMN_TYPE"));
+				index++;
+			}
+
+			this.rs.close();
+
+			index = 0;
+			parameterNames = new String[] { "/*id*/", "result2" };
+			parameterTypes = new int[] { Types.VARCHAR, Types.DECIMAL };
+			precision = new int[] { 20, 10 };
+			direction = new int[] { DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnOut };
+			int[] scale = new int[] { 0, 2 };
+
+			this.conn.prepareCall("{call testBug26959_1(?, ?)}").close();
+
+			this.rs = this.conn.getMetaData().getProcedureColumns(
+					this.conn.getCatalog(), null, "testBug26959_1", "%");
+
+			while (this.rs.next()) {
+				assertEquals(parameterNames[index], this.rs
+						.getString("COLUMN_NAME"));
+				assertEquals(parameterTypes[index], this.rs.getInt("DATA_TYPE"));
+				assertEquals(precision[index], this.rs.getInt("PRECISION"));
+				assertEquals(scale[index], this.rs.getInt("SCALE"));
+				assertEquals(direction[index], this.rs.getInt("COLUMN_TYPE"));
+
+				index++;
+			}
+		} finally {
+			closeMemberJDBCResources();
+		}
+	}
 }

Modified: trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-03-08 02:28:23 UTC
(rev 6340)
+++ trunk/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-03-09 21:13:57 UTC
(rev 6341)
@@ -431,7 +431,7 @@
 	
 	private static String mysqlKeywordsThatArentSQL92;
 	
-	private static final int MAX_IDENTIFIER_LENGTH = 64;
+	protected static final int MAX_IDENTIFIER_LENGTH = 64;
 	
 	private static final int DEFERRABILITY = 13;
 
@@ -1431,11 +1431,11 @@
 
 		String quoteChar = getIdentifierQuoteString();
 
-		String storageDefnDelims = "(" + quoteChar;
-		String storageDefnClosures = ")" + quoteChar;
+		String parameterDef = null;
 
-		// First try 'select from mysql.proc, as this is easier to parse...
-		String parameterDef = null;
+		boolean isProcedureInAnsiMode = false;
+		String storageDefnDelims = null;
+		String storageDefnClosures = null;
 		
 		try {
 			paramRetrievalStmt = this.conn.getMetadataSafeStatement();
@@ -1542,7 +1542,26 @@
 							"to have driver generate parameters that represent INOUT strings irregardless of
actual parameter types.",
 							SQLError.SQL_STATE_GENERAL_ERROR);		
 				}
+
+				try {
+					String sqlMode = paramRetrievalRs.getString("sql_mode");
+					
+					if (StringUtils.indexOfIgnoreCase(sqlMode, "ANSI") != -1) {
+						isProcedureInAnsiMode = true;
+					}
+				} catch (SQLException sqlEx) {
+					// doesn't exist
+				}
+
+				String identifierMarkers = isProcedureInAnsiMode ? "`\"" : "`";
+				String identifierAndStringMarkers = "'" + identifierMarkers;
+				storageDefnDelims = "(" + identifierMarkers;
+				storageDefnClosures = ")" + identifierMarkers;
 				
+				// sanitize/normalize by stripping out comments
+				procedureDef = StringUtils.stripComments(procedureDef, 
+						identifierAndStringMarkers, identifierAndStringMarkers, true, false, true, true);
+				
 				int openParenIndex = StringUtils
 				.indexOfIgnoreCaseRespectQuotes(0, procedureDef, "(",
 						quoteChar.charAt(0), !this.conn
@@ -1707,6 +1726,11 @@
 								SQLError.SQL_STATE_GENERAL_ERROR);
 					}
 
+					if ((paramName.startsWith("`") && paramName.endsWith("`")) || 
+							(isProcedureInAnsiMode && paramName.startsWith("\"") &&
paramName.endsWith("\""))) {
+						paramName = paramName.substring(1, paramName.length() - 1);
+					}
+
 					int wildCompareRes = StringUtils.wildCompare(paramName,
 							parameterNamePattern);
 

Modified: trunk/connector-j/src/com/mysql/jdbc/StringUtils.java
===================================================================
--- trunk/connector-j/src/com/mysql/jdbc/StringUtils.java	2007-03-08 02:28:23 UTC (rev
6340)
+++ trunk/connector-j/src/com/mysql/jdbc/StringUtils.java	2007-03-09 21:13:57 UTC (rev
6341)
@@ -25,6 +25,8 @@
 package com.mysql.jdbc;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -1486,4 +1488,133 @@
 	public static boolean isNullOrEmpty(String toTest) {
 		return (toTest == null || toTest.length() == 0);
 	}
+	
+	/**
+	 * Returns the given string, with comments removed
+	 * 
+	 * @param src
+	 *            the source string
+	 * @param stringOpens
+	 *            characters which delimit the "open" of a string
+	 * @param stringCloses
+	 *            characters which delimit the "close" of a string, in
+	 *            counterpart order to <code>stringOpens</code>
+	 * @param slashStarComments
+	 *            strip slash-star type "C" style comments
+	 * @param slashSlashComments
+	 *            strip slash-slash C++ style comments to end-of-line
+	 * @param hashComments
+	 *            strip #-style comments to end-of-line
+	 * @param dashDashComments
+	 *            strip "--" style comments to end-of-line
+	 * @return the input string with all comment-delimited data removed
+	 */
+	public static String stripComments(String src, String stringOpens,
+			String stringCloses, boolean slashStarComments,
+			boolean slashSlashComments, boolean hashComments,
+			boolean dashDashComments) {
+		if (src == null) {
+			return null;
+		}
+
+		StringBuffer buf = new StringBuffer(src.length());
+
+		// It's just more natural to deal with this as a stream
+		// when parsing..This code is currently only called when
+		// parsing the kind of metadata that developers are strongly
+		// recommended to cache anyways, so we're not worried
+		// about the _1_ extra object allocation if it cleans
+		// up the code
+
+		StringReader sourceReader = new StringReader(src);
+
+		int contextMarker = Character.MIN_VALUE;
+		boolean escaped = false;
+		int markerTypeFound = -1;
+
+		int ind = 0;
+
+		int currentChar = 0;
+
+		try {
+			while ((currentChar = sourceReader.read()) != -1) {
+
+				if (false && currentChar == '\\') {
+					escaped = !escaped;
+				} else if (markerTypeFound != -1 && currentChar ==
stringCloses.charAt(markerTypeFound)
+						&& !escaped) {
+					contextMarker = Character.MIN_VALUE;
+					markerTypeFound = -1;
+				} else if ((ind = stringOpens.indexOf(currentChar)) != -1
+						&& !escaped && contextMarker == Character.MIN_VALUE) {
+					markerTypeFound = ind;
+					contextMarker = currentChar;
+				}
+
+				if (contextMarker == Character.MIN_VALUE && currentChar == '/'
+						&& (slashSlashComments || slashStarComments)) {
+					currentChar = sourceReader.read();
+					if (currentChar == '*' && slashStarComments) {
+						int prevChar = 0;
+						while ((currentChar = sourceReader.read()) != '/'
+								|| prevChar != '*') {
+							if (currentChar == '\r') {
+
+								currentChar = sourceReader.read();
+								if (currentChar == '\n') {
+									currentChar = sourceReader.read();
+								}
+							} else {
+								if (currentChar == '\n') {
+
+									currentChar = sourceReader.read();
+								}
+							}
+							if (currentChar < 0)
+								break;
+							prevChar = currentChar;
+						}
+						continue;
+					} else if (currentChar == '/' && slashSlashComments) {
+						while ((currentChar = sourceReader.read()) != '\n'
+								&& currentChar != '\r' && currentChar >= 0)
+							;
+					}
+				} else if (contextMarker == Character.MIN_VALUE
+						&& currentChar == '#' && hashComments) {
+					// Slurp up everything until the newline
+					while ((currentChar = sourceReader.read()) != '\n'
+							&& currentChar != '\r' && currentChar >= 0)
+						;
+				} else if (contextMarker == Character.MIN_VALUE
+						&& currentChar == '-' && dashDashComments) {
+					currentChar = sourceReader.read();
+
+					if (currentChar == -1 || currentChar != '-') {
+						buf.append('-');
+
+						if (currentChar != -1) {
+							buf.append(currentChar);
+						}
+
+						continue;
+					}
+
+					// Slurp up everything until the newline
+
+					while ((currentChar = sourceReader.read()) != '\n'
+							&& currentChar != '\r' && currentChar >= 0)
+						;
+				}
+
+				if (currentChar != -1) {
+					buf.append((char) currentChar);
+				}
+			}
+		} catch (IOException ioEx) {
+			// we'll never see this from a StringReader
+		}
+
+		return buf.toString();
+	}
 }

Modified: trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java
===================================================================
---
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2007-03-08
02:28:23 UTC (rev 6340)
+++
trunk/connector-j/src/testsuite/regression/CallableStatementRegressionTest.java	2007-03-09
21:13:57 UTC (rev 6341)
@@ -950,4 +950,117 @@
 		
 		this.conn.prepareCall("{call testBug26143(?)").close();
 	}
+	
+	/**
+	 * Tests fix for BUG#26959 - comments confuse procedure parser.
+	 * 
+	 * @throws Exception if the test fails
+	 */
+	public void testBug26959() throws Exception {
+		if (!versionMeetsMinimum(5, 0)) {
+			return;
+		}
+
+		createProcedure(
+				"testBug26959",
+				"(_ACTION varchar(20),"
+						+ "\n`/*dumb-identifier-1*/` int,"
+						+ "\n`#dumb-identifier-2` int,"
+						+ "\n`--dumb-identifier-3` int,"
+						+ "\n_CLIENT_ID int, -- ABC"
+						+ "\n_LOGIN_ID  int, # DEF"
+						+ "\n_WHERE varchar(2000),"
+						+ "\n_SORT varchar(2000),"
+						+ "\n out _SQL varchar(/* inline right here - oh my gosh! */ 8000),"
+						+ "\n _SONG_ID int,"
+						+ "\n  _NOTES varchar(2000),"
+						+ "\n out _RESULT varchar(10)"
+						+ "\n /*"
+						+ "\n ,    -- Generic result parameter"
+						+ "\n out _PERIOD_ID int,         -- Returns the period_id. Useful when using
@PREDEFLINK to return which is the last period"
+						+ "\n   _SONGS_LIST varchar(8000),"
+						+ "\n  _COMPOSERID int,"
+						+ "\n  _PUBLISHERID int,"
+						+ "\n   _PREDEFLINK int        -- If the user is accessing through a predefined
link: 0=none  1=last period"
+						+ "\n */) BEGIN SELECT 1; END");
+
+		createProcedure(
+				"testBug26959_1",
+				"(`/*id*/` /* before type 1 */ varchar(20),"
+						+ "/* after type 1 */ OUT result2 DECIMAL(/*size1*/10,/*size2*/2) /* p2 */)"
+						+ "BEGIN SELECT action, result; END");
+
+		try {
+			this.conn.prepareCall(
+					"{call testBug26959(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}")
+					.close();
+			this.rs = this.conn.getMetaData().getProcedureColumns(
+					this.conn.getCatalog(), null, "testBug26959", "%");
+
+			String[] parameterNames = new String[] { "_ACTION",
+					"/*dumb-identifier-1*/", "#dumb-identifier-2",
+					"--dumb-identifier-3", "_CLIENT_ID", "_LOGIN_ID", "_WHERE",
+					"_SORT", "_SQL", "_SONG_ID", "_NOTES", "_RESULT" };
+
+			int[] parameterTypes = new int[] { Types.VARCHAR, Types.INTEGER,
+					Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER,
+					Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER,
+					Types.VARCHAR, Types.VARCHAR };
+
+			int[] direction = new int[] { DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnOut,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnOut };
+
+			int[] precision = new int[] { 20, 10, 10, 10, 10, 10, 2000, 2000,
+					8000, 10, 2000, 10 };
+
+			int index = 0;
+
+			while (this.rs.next()) {
+				assertEquals(parameterNames[index], this.rs
+						.getString("COLUMN_NAME"));
+				assertEquals(parameterTypes[index], this.rs.getInt("DATA_TYPE"));
+				assertEquals(precision[index], this.rs.getInt("PRECISION"));
+				assertEquals(direction[index], this.rs.getInt("COLUMN_TYPE"));
+				index++;
+			}
+
+			this.rs.close();
+
+			index = 0;
+			parameterNames = new String[] { "/*id*/", "result2" };
+			parameterTypes = new int[] { Types.VARCHAR, Types.DECIMAL };
+			precision = new int[] { 20, 10 };
+			direction = new int[] { DatabaseMetaData.procedureColumnIn,
+					DatabaseMetaData.procedureColumnOut };
+			int[] scale = new int[] { 0, 2 };
+
+			this.conn.prepareCall("{call testBug26959_1(?, ?)}").close();
+
+			this.rs = this.conn.getMetaData().getProcedureColumns(
+					this.conn.getCatalog(), null, "testBug26959_1", "%");
+
+			while (this.rs.next()) {
+				assertEquals(parameterNames[index], this.rs
+						.getString("COLUMN_NAME"));
+				assertEquals(parameterTypes[index], this.rs.getInt("DATA_TYPE"));
+				assertEquals(precision[index], this.rs.getInt("PRECISION"));
+				assertEquals(scale[index], this.rs.getInt("SCALE"));
+				assertEquals(direction[index], this.rs.getInt("COLUMN_TYPE"));
+
+				index++;
+			}
+		} finally {
+			closeMemberJDBCResources();
+		}
+	}
 }

Thread
Connector/J commit: r6341 - branches/branch_5_0/connector-j branches/branch_5_0/connector-j/src/com/mysql/jdbc branches/branch_5_0/connector-j/src/tes...mmatthews9 Mar