--- src/com/mysql/jdbc/PreparedStatement.java +++ src/com/mysql/jdbc/PreparedStatement.java @@ -181,7 +181,9 @@ byte[][] staticSql = null; - boolean isOnDuplicateKeyUpdate = false; + int onDuplicateKeyUpdateIndex = -1; + + boolean isOnDuplicateKeyUpdateWithArgs = false; /** * Represents the "parsed" state of a client-side @@ -199,7 +201,8 @@ SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } - this.isOnDuplicateKeyUpdate = containsOnDuplicateKeyInString(sql); + this.onDuplicateKeyUpdateIndex = containsOnDuplicateKeyInString(sql); + this.isOnDuplicateKeyUpdateWithArgs = this.onDuplicateKeyUpdateIndex == -1; this.lastUsed = System.currentTimeMillis(); @@ -321,6 +324,11 @@ if ((c == '?') && !inQuotes && !inQuotedId) { endpointList.add(new int[] { lastParmEnd, i }); lastParmEnd = i + 1; + if (!this.isOnDuplicateKeyUpdateWithArgs //if false there are a on duplicate key information. + // or there are already set to true by this check. + && i > this.onDuplicateKeyUpdateIndex ) { + this.isOnDuplicateKeyUpdateWithArgs = true; + } } if (!inQuotes && (i < stopLookingForLimitClause)) { @@ -1127,7 +1135,7 @@ this.canRewrite = StringUtils.startsWithIgnoreCaseAndWs( this.originalSql, "INSERT", this.statementAfterCommentsPos) && StringUtils.indexOfIgnoreCaseRespectMarker(this.statementAfterCommentsPos, this.originalSql, "SELECT", "\"'`", "\"'`", false) == -1 - && !containsOnDuplicateKeyUpdateInSQL(); + && ( !containsOnDuplicateKeyUpdateInSQL() || !containsOnDuplicateKeyUpdateInSQLWithArgs()); this.hasCheckedForRewrite = true; } @@ -2081,7 +2089,15 @@ } protected boolean containsOnDuplicateKeyUpdateInSQL() { - return this.parseInfo.isOnDuplicateKeyUpdate; + return this.parseInfo.onDuplicateKeyUpdateIndex != -1; + } + + protected int indexOfOnDuplicateKeyUpdateInSQL() { + return this.parseInfo.onDuplicateKeyUpdateIndex; + } + + protected boolean containsOnDuplicateKeyUpdateInSQLWithArgs() { + return this.parseInfo.isOnDuplicateKeyUpdateWithArgs; } private String extractValuesClause() throws SQLException { @@ -2112,7 +2128,9 @@ return null; } - int indexOfLastParen = this.originalSql.lastIndexOf(')'); + int indexOfLastParen = (containsOnDuplicateKeyUpdateInSQL() && !containsOnDuplicateKeyUpdateInSQLWithArgs()) ? + this.originalSql.lastIndexOf(')', (indexOfOnDuplicateKeyUpdateInSQL())) + : this.originalSql.lastIndexOf(')'); if (indexOfLastParen == -1) { return null; @@ -2238,12 +2256,19 @@ + (numBatches * (valuesClause.length() + 1))); newStatementSql.append(this.originalSql); + if ((containsOnDuplicateKeyUpdateInSQL() && !containsOnDuplicateKeyUpdateInSQLWithArgs())) { + newStatementSql.setLength(indexOfOnDuplicateKeyUpdateInSQL() + 1); + } for (int i = 0; i < numBatches - 1; i++) { newStatementSql.append(','); newStatementSql.append(valuesClause); } + if ((containsOnDuplicateKeyUpdateInSQL() && !containsOnDuplicateKeyUpdateInSQLWithArgs())) { + newStatementSql.append(this.originalSql.substring(indexOfOnDuplicateKeyUpdateInSQL())); + } + return newStatementSql.toString(); } @@ -5189,8 +5214,8 @@ return count; } - protected boolean containsOnDuplicateKeyInString(String sql) { + protected int containsOnDuplicateKeyInString(String sql) { return StringUtils.indexOfIgnoreCaseRespectMarker(0, - sql, " ON DUPLICATE KEY UPDATE ", "\"'`", "\"'`", !this.connection.isNoBackslashEscapesSet()) != -1; + sql, " ON DUPLICATE KEY UPDATE ", "\"'`", "\"'`", !this.connection.isNoBackslashEscapesSet()); } } --- src/com/mysql/jdbc/ServerPreparedStatement.java +++ src/com/mysql/jdbc/ServerPreparedStatement.java @@ -266,7 +266,7 @@ */ private static final byte MAX_TIME_REP_LENGTH = 13; - private boolean hasOnDuplicateKeyUpdate = false; + private int hasOnDuplicateKeyUpdate = -1; private void storeTime(Buffer intoBuf, Time tm) throws SQLException { @@ -2897,6 +2897,14 @@ } protected boolean containsOnDuplicateKeyUpdateInSQL() { + return this.hasOnDuplicateKeyUpdate != -1; + } + + protected int indexOfOnDuplicateKeyUpdateInSQL() { return this.hasOnDuplicateKeyUpdate; } + + protected boolean containsOnDuplicateKeyUpdateInSQLWithArgs() { + return true; //Return true to not parse the query + } } --- src/com/mysql/jdbc/StringUtils.java +++ src/com/mysql/jdbc/StringUtils.java @@ -1020,8 +1021,8 @@ contextMarker = c; } else if (c == target.charAt(0) && !escaped && contextMarker == Character.MIN_VALUE) { - if (indexOfIgnoreCase(i, src, target) != -1) + if (startsWithIgnoreCase(src, i, target)) } }