From: Date: July 19 2006 3:33am Subject: Connector/J commit: r5530 - in branches: branch_3_1/connector-j branch_3_1/connector-j/src/com/mysql/jdbc branch_3_1/connector-j/src/testsuite/regression branch_5_0/connector-j branch_5_0/connector-j/src/com/mysql/jdbc branch_5_0/connector-j/src/testsuite/regression List-Archive: http://lists.mysql.com/commits/9314 X-Bug: 20888 Message-Id: <200607190133.k6J1XFot018006@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/branch_3_1/connector-j/CHANGES branches/branch_3_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 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#20888 - escape of quotes in client-side prepared statements parsing not respected. Patch covers more than bug report, including NO_BACKSLASH_ESCAPES being set, and stacked quote characters forms of escaping (i.e. '' or ""). Modified: branches/branch_3_1/connector-j/CHANGES =================================================================== --- branches/branch_3_1/connector-j/CHANGES 2006-07-19 00:01:36 UTC (rev 5529) +++ branches/branch_3_1/connector-j/CHANGES 2006-07-19 01:33:13 UTC (rev 5530) @@ -28,6 +28,11 @@ - Fixed BUG#18880 - ResultSet.getFloatFromString() can't retrieve values near Float.MIN/MAX_VALUE. + - Fixed BUG#20888 - escape of quotes in client-side prepared + statements parsing not respected. Patch covers more than bug report, + including NO_BACKSLASH_ESCAPES being set, and stacked quote characters + forms of escaping (i.e. '' or ""). + 05-26-06 - Version 3.1.13 - Fixed BUG#15464 - INOUT parameter does not store IN value. Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java =================================================================== --- branches/branch_3_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2006-07-19 00:01:36 UTC (rev 5529) +++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2006-07-19 01:33:13 UTC (rev 5530) @@ -169,13 +169,12 @@ int lastParmEnd = 0; int i; - int pre1 = 0; - int pre2 = 0; - int stopLookingForLimitClause = this.statementLength - 5; this.foundLimitClause = false; + boolean noBackslashEscapes = connection.isNoBackslashEscapesSet(); + for (i = 0; i < this.statementLength; ++i) { char c = sql.charAt(i); @@ -185,6 +184,12 @@ this.firstStmtChar = Character.toUpperCase(c); } + if (!noBackslashEscapes && + c == '\\' && i < (this.statementLength - 1)) { + i++; + continue; // next character is escaped + } + // are we in a quoted identifier? // (only valid when the id is not inside a 'string') if (!inQuotes && (quotedIdentifierChar != 0) @@ -194,22 +199,23 @@ // only respect quotes when not in a quoted identifier if (inQuotes) { - if ((((c == '\'') || (c == '"')) && c == quoteChar) - && (pre1 == '\\') && (pre2 != '\\')) { + if (((c == '\'') || (c == '"')) && c == quoteChar) { + if (i < (this.statementLength - 1) && sql.charAt(i + 1) == quoteChar) { + i++; + continue; // inline quote escape + } + inQuotes = !inQuotes; quoteChar = 0; - } else if ((((c == '\'') || (c == '"')) && c == quoteChar) - && (pre1 != '\\')) { + } else if (((c == '\'') || (c == '"')) && c == quoteChar) { inQuotes = !inQuotes; quoteChar = 0; } } else { - if (((c == '\'') || (c == '"')) && (pre1 == '\\') - && (pre2 != '\\')) { + if ((c == '\'') || (c == '"')) { inQuotes = true; quoteChar = c; - } else if (((c == '\'') || (c == '"')) - && (pre1 != '\\')) { + } else if ((c == '\'') || (c == '"')) { inQuotes = true; quoteChar = c; } @@ -242,9 +248,6 @@ } } } - - pre2 = pre1; - pre1 = c; } if (this.firstStmtChar == 'L') { Modified: branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java =================================================================== --- branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-07-19 00:01:36 UTC (rev 5529) +++ branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-07-19 01:33:13 UTC (rev 5530) @@ -3276,14 +3276,24 @@ Properties props = new Properties(); props.setProperty("cachePrepStmts", "true"); + props.setProperty("prepStmtCacheSqlLimit", "5000"); + StringBuffer queryBuf = new StringBuffer("SELECT field1 FROM testBug20687 /*"); + for (int i = 0; i < 1000; i++) { + queryBuf.append("a"); + } + + queryBuf.append(" */"); + + String query = queryBuf.toString(); + try { poolingConn = getConnectionWithProps(props); - PreparedStatement pstmt1 = poolingConn.prepareStatement("SELECT field1 FROM testBug20687"); + PreparedStatement pstmt1 = poolingConn.prepareStatement(query); pstmt1.executeQuery(); pstmt1.close(); - PreparedStatement pstmt2 = poolingConn.prepareStatement("SELECT field1 FROM testBug20687"); + PreparedStatement pstmt2 = poolingConn.prepareStatement(query); pstmt2.executeQuery(); assertSame(pstmt1, pstmt2); pstmt2.close(); @@ -3291,4 +3301,25 @@ } } + + /** + * Tests fix for BUG#20888 - escape of quotes in client-side prepared + * statements parsing not respected. + * + * @throws Exception if the test fails. + */ + public void testBug20888() throws Exception { + + try { + String s = "SELECT 'What do you think about D\\'Artanian''?', \"What do you think about D\\\"Artanian\"\"?\""; + this.pstmt = ((com.mysql.jdbc.Connection)this.conn).clientPrepareStatement(s); + + this.rs = this.pstmt.executeQuery(); + this.rs.next(); + assertEquals(this.rs.getString(1), "What do you think about D'Artanian'?"); + assertEquals(this.rs.getString(2), "What do you think about D\"Artanian\"?"); + } finally { + closeMemberJDBCResources(); + } + } } Modified: branches/branch_5_0/connector-j/CHANGES =================================================================== --- branches/branch_5_0/connector-j/CHANGES 2006-07-19 00:01:36 UTC (rev 5529) +++ branches/branch_5_0/connector-j/CHANGES 2006-07-19 01:33:13 UTC (rev 5530) @@ -194,7 +194,12 @@ - Fixed BUG#18880 - ResultSet.getFloatFromString() can't retrieve values near Float.MIN/MAX_VALUE. - + + - Fixed BUG#20888 - escape of quotes in client-side prepared + statements parsing not respected. Patch covers more than bug report, + including NO_BACKSLASH_ESCAPES being set, and stacked quote characters + forms of escaping (i.e. '' or ""). + 05-26-06 - Version 3.1.13 - Fixed BUG#15464 - INOUT parameter does not store IN value. 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 2006-07-19 00:01:36 UTC (rev 5529) +++ branches/branch_5_0/connector-j/src/com/mysql/jdbc/PreparedStatement.java 2006-07-19 01:33:13 UTC (rev 5530) @@ -171,13 +171,12 @@ int lastParmEnd = 0; int i; - int pre1 = 0; - int pre2 = 0; - int stopLookingForLimitClause = this.statementLength - 5; this.foundLimitClause = false; - + + boolean noBackslashEscapes = connection.isNoBackslashEscapesSet(); + for (i = 0; i < this.statementLength; ++i) { char c = sql.charAt(i); @@ -187,6 +186,12 @@ this.firstStmtChar = Character.toUpperCase(c); } + if (!noBackslashEscapes && + c == '\\' && i < (this.statementLength - 1)) { + i++; + continue; // next character is escaped + } + // are we in a quoted identifier? // (only valid when the id is not inside a 'string') if (!inQuotes && (quotedIdentifierChar != 0) @@ -196,22 +201,23 @@ // only respect quotes when not in a quoted identifier if (inQuotes) { - if ((((c == '\'') || (c == '"')) && c == quoteChar) - && (pre1 == '\\') && (pre2 != '\\')) { + if (((c == '\'') || (c == '"')) && c == quoteChar) { + if (i < (this.statementLength - 1) && sql.charAt(i + 1) == quoteChar) { + i++; + continue; // inline quote escape + } + inQuotes = !inQuotes; quoteChar = 0; - } else if ((((c == '\'') || (c == '"')) && c == quoteChar) - && (pre1 != '\\')) { + } else if (((c == '\'') || (c == '"')) && c == quoteChar) { inQuotes = !inQuotes; quoteChar = 0; } } else { - if (((c == '\'') || (c == '"')) && (pre1 == '\\') - && (pre2 != '\\')) { + if ((c == '\'') || (c == '"')) { inQuotes = true; quoteChar = c; - } else if (((c == '\'') || (c == '"')) - && (pre1 != '\\')) { + } else if ((c == '\'') || (c == '"')) { inQuotes = true; quoteChar = c; } @@ -244,9 +250,6 @@ } } } - - pre2 = pre1; - pre1 = c; } if (this.firstStmtChar == 'L') { Modified: branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java =================================================================== --- branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-07-19 00:01:36 UTC (rev 5529) +++ branches/branch_5_0/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-07-19 01:33:13 UTC (rev 5530) @@ -3361,4 +3361,25 @@ } } } + + /** + * Tests fix for BUG#20888 - escape of quotes in client-side prepared + * statements parsing not respected. + * + * @throws Exception if the test fails. + */ + public void testBug20888() throws Exception { + + try { + String s = "SELECT 'What do you think about D\\'Artanian''?', \"What do you think about D\\\"Artanian\"\"?\""; + this.pstmt = ((com.mysql.jdbc.Connection)this.conn).clientPrepareStatement(s); + + this.rs = this.pstmt.executeQuery(); + this.rs.next(); + assertEquals(this.rs.getString(1), "What do you think about D'Artanian'?"); + assertEquals(this.rs.getString(2), "What do you think about D\"Artanian\"?"); + } finally { + closeMemberJDBCResources(); + } + } }