MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:mmatthews Date:January 4 2007 6:22pm
Subject:Connector/J commit: r6254 - in branches/branch_5_0/connector-j: . src/com/mysql/jdbc src/testsuite/regression
View as plain text  
Modified:
   branches/branch_5_0/connector-j/CHANGES
   branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
   branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java
Log:
Fixed BUG#25025 - Client-side prepared statement parser gets confused by
	  in-line (/* ... */) comments and therefore can't rewrite batched statements 
	  or reliably detect type of statements when they're used.

Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES	2007-01-04 01:03:01 UTC (rev 6253)
+++ branches/branch_5_0/connector-j/CHANGES	2007-01-04 18:22:41 UTC (rev 6254)
@@ -39,7 +39,11 @@
 	  INFORMATION_SCHEMA didn't have references to current connections,
 	  sometimes leading to NullPointerExceptions when intropsecting them via
 	  ResultSetMetaData.       
-	   
+
+	- Fixed BUG#25025 - Client-side prepared statement parser gets confused by
+	  in-line (/* ... */) comments and therefore can't rewrite batched statements 
+	  or reliably detect type of statements when they're used.
+	  
 10-20-06 - Version 5.0.4
 
     - Fixed BUG#21379 - column names don't match metadata in cases 

Modified: branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-01-04 01:03:01 UTC (rev 6253)
+++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-01-04 18:22:41 UTC (rev 6254)
@@ -135,6 +135,8 @@
 		long lastUsed = 0;
 
 		int statementLength = 0;
+		
+		int statementStartPos = 0;
 
 		byte[][] staticSql = null;
 
@@ -177,7 +179,22 @@
 			
 			boolean noBackslashEscapes = connection.isNoBackslashEscapesSet();
 			
-			for (i = 0; i < this.statementLength; ++i) {
+			// we're not trying to be real pedantic here, but we'd like to 
+			// skip comments at the beginning of statements, as frameworks
+			// such as Hibernate use them to aid in debugging
+			
+			if (StringUtils.startsWithIgnoreCaseAndWs(sql, "/*")) {
+				statementStartPos = sql.indexOf("*/");
+				
+				if (statementStartPos == -1) {
+					statementStartPos = 0;
+				} else {
+					statementStartPos += 2;
+				}
+			}
+			
+			
+			for (i = statementStartPos; i < this.statementLength; ++i) {
 				char c = sql.charAt(i);
 
 				if ((this.firstStmtChar == 0) && !Character.isWhitespace(c)) {
@@ -401,7 +418,22 @@
 
 	private String batchedValuesClause;
 
+	/** Where does the statement text actually start? */
+	
+	private int statementAfterCommentsPos;
+
 	/**
+	 * have we checked whether we can rewrite this statement as a multi-value
+	 * insert?
+	 */
+
+	private boolean hasCheckedForRewrite = false;
+
+	/** Can we actually rewrite this statement as a multi-value insert? */
+
+	private boolean canRewrite = false;
+	
+	/**
 	 * Constructor used by server-side prepared statements
 	 * 
 	 * @param conn
@@ -844,8 +876,9 @@
 
 				if (!this.batchHasPlainStatements
 						&& this.connection.getRewriteBatchedStatements()) {
-					if (StringUtils.startsWithIgnoreCaseAndWs(this.originalSql,
-							"INSERT")) {
+					
+					
+					if (canRewriteAsMultivalueInsertStatement()) {
 						return executeBatchedInserts();
 					}
 				}
@@ -857,6 +890,16 @@
 		}
 	}
 
+	public synchronized boolean canRewriteAsMultivalueInsertStatement() {
+		if (!this.hasCheckedForRewrite) {
+			this.canRewrite = StringUtils.startsWithIgnoreCaseAndWs(
+					this.originalSql, "INSERT", this.statementAfterCommentsPos);
+			this.hasCheckedForRewrite = true;
+		}
+
+		return this.canRewrite;
+	}
+
 	/**
 	 * Rewrites the already prepared statement into a multi-value insert
 	 * statement of 'statementsPerBatch' values and executes the entire batch
@@ -1450,10 +1493,12 @@
 			int indexOfValues = -1;
 	
 			if (quoteCharStr.length() > 0) {
-				indexOfValues = StringUtils.indexOfIgnoreCaseRespectQuotes(0,
+				indexOfValues = StringUtils.indexOfIgnoreCaseRespectQuotes(
+						this.statementAfterCommentsPos,
 						this.originalSql, "VALUES ", quoteCharStr.charAt(0), false);
 			} else {
-				indexOfValues = StringUtils.indexOfIgnoreCase(0, this.originalSql,
+				indexOfValues = StringUtils.indexOfIgnoreCase(this.statementAfterCommentsPos, 
+						this.originalSql,
 						"VALUES ");
 			}
 	
@@ -1932,6 +1977,8 @@
 		for (int j = 0; j < this.parameterCount; j++) {
 			this.isStream[j] = false;
 		}
+		
+		this.statementAfterCommentsPos = this.parseInfo.statementStartPos;
 	}
 
 	boolean isNull(int paramIndex) {

Modified: branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java	2007-01-04 01:03:01 UTC (rev 6253)
+++ branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java	2007-01-04 18:22:41 UTC (rev 6254)
@@ -3689,4 +3689,49 @@
 		
 		assertEquals(beforeOpenStatementCount, afterOpenStatementCount);
 	}
+	
+	/**
+	 * Tests fix for BUG#25025 - Client-side prepared statement parser gets confused by
+	 * in-line (slash-star) comments and therefore can't rewrite batched statements or
+	 * reliably detect type of statements when they're used.
+	 * 
+	 * @throws Exception if the test fails.
+	 */
+	public void testBug25025() throws Exception {
+		
+		Connection multiConn = null;
+		
+		createTable("testBug25025", "(field1 INT)");
+		
+		try {
+			Properties props = new Properties();
+			props.setProperty("rewriteBatchedStatements", "true");
+			props.setProperty("useServerPrepStmts", "false");
+			
+			multiConn = getConnectionWithProps(props);
+			
+			this.pstmt = multiConn.prepareStatement("/* insert foo.bar.baz INSERT INTO foo VALUES (?,?,?,?) to trick parser */ INSERT into testBug25025 VALUES (?)");
+			this.pstmt.setInt(1, 1);
+			this.pstmt.addBatch();
+			this.pstmt.setInt(1, 2);
+			this.pstmt.addBatch();
+			this.pstmt.setInt(1, 3);
+			this.pstmt.addBatch();
+			
+			int[] counts = this.pstmt.executeBatch();
+			
+			assertEquals(3, counts.length);
+			assertEquals(1, counts[0]);
+			assertEquals(1, counts[1]);
+			assertEquals(1, counts[2]);
+			assertEquals(true, 
+					((com.mysql.jdbc.PreparedStatement)this.pstmt).canRewriteAsMultivalueInsertStatement());
+		} finally {
+			closeMemberJDBCResources();
+			
+			if (multiConn != null) {
+				multiConn.close();
+			}
+		}
+	}
 }

Thread
Connector/J commit: r6254 - in branches/branch_5_0/connector-j: . src/com/mysql/jdbc src/testsuite/regressionmmatthews4 Jan