Description:
CallableStatement.extractProcedureName() don't work correct when procedure name with dash "-"
How to repeat:
import com.mysql.jdbc.StringUtils;
import com.mysql.jdbc.util.BaseBugReport;
public class MyBugReport extends BaseBugReport{
@Override
public void setUp() throws Exception {}
@Override
public void tearDown() throws Exception {}
@Override
public void runTest() throws Exception {
String originalSql= "CALL a-bug.proc_stock(?,?)";
//mysql-connector-java 5.1.40
//com.mysql.jdbc.CallableStatement.extractProcedureName()
String sanitizedSql = StringUtils.stripComments(originalSql, "`\"'", "`\"'", true, false, true, true);
assertTrue("\""+sanitizedSql+"\" should be equal to \""+originalSql+"\"", originalSql.equals(sanitizedSql));
}
public static void main(String[] args) throws Exception {
new MyBugReport().run();
}
}
Suggested fix:
package com.mysql.jdbc;
public class StringUtils {
public static String stripComments(String src, String stringOpens, String stringCloses, boolean slashStarComments, boolean slashSlashComments,
boolean hashComments, boolean dashDashComments) {
if (src == null) {
return null;
}
StringBuilder strBuilder = new StringBuilder(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 (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 != '-') {
strBuilder.append('-');
if (currentChar != -1) {
strBuilder.append((char) currentChar);
}
continue;
}
// Slurp up everything until the newline
while ((currentChar = sourceReader.read()) != '\n' && currentChar != '\r' && currentChar >= 0) {
}
}
if (currentChar != -1) {
strBuilder.append((char) currentChar);
}
}
} catch (IOException ioEx) {
// we'll never see this from a StringReader
}
return strBuilder.toString();
}
}