in src/main/java/com/aliyun/odps/jdbc/utils/SettingParser.java [51:161]
public ParseResult extractSetStatements(String s) {
Map<String, String> settings = new LinkedHashMap<>();
List<String> errors = new ArrayList<>();
List<int[]> excludeRanges = new ArrayList<>();
State currentState = State.DEFAULT;
// use for ignore the case of 'set'
String lowerS = s.toLowerCase();
int i = 0;
int currentStartIndex = -1;
while (i < s.length()) {
switch (currentState) {
case DEFAULT:
if (i <= s.length() - 2 && s.startsWith("--", i)) {
currentState = State.SINGLE_LINE_COMMENT;
i += 2;
} else if (i <= s.length() - 2 && s.startsWith("/*", i)) {
currentState = State.MULTI_LINE_COMMENT;
i += 2;
} else if (i <= s.length() - 3 && lowerS.startsWith("set", i)) {
if (i + 3 < s.length() && Character.isWhitespace(s.charAt(i + 3))) {
currentState = State.IN_SET;
currentStartIndex = i;
i += 4; // Skip 'set' and the following whitespace
} else {
i++;
}
} else {
if (!Character.isWhitespace(s.charAt(i))) {
currentState = State.STOP;
}
i++;
}
break;
case SINGLE_LINE_COMMENT:
while (i < s.length() && s.charAt(i) != '\n') {
i++;
}
if (i < s.length()) {
i++;
}
currentState = State.DEFAULT;
break;
case MULTI_LINE_COMMENT:
while (i < s.length()) {
if (i + 1 < s.length() && s.startsWith("*/", i)) {
i += 2;
currentState = State.DEFAULT;
break;
} else {
i++;
}
}
break;
case IN_SET:
while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
i++;
}
if (i < s.length()) {
currentState = State.IN_KEY_VALUE;
} else {
errors.add("Invalid SET statement: missing key-value after 'set'");
currentStartIndex = -1;
currentState = State.DEFAULT;
}
break;
case IN_KEY_VALUE:
int keyValueStart = i;
boolean foundSemicolon = false;
while (i < s.length()) {
// Allows escape of semicolons to place semicolons in settings
if (s.charAt(i) == ';' && s.charAt(i - 1) != '\\') {
foundSemicolon = true;
i++;
break;
}
i++;
}
if (foundSemicolon) {
String kv = s.substring(keyValueStart, i - 1).trim();
if (parseKeyValue(kv, settings, errors)) {
excludeRanges.add(new int[]{currentStartIndex, i});
}
} else {
errors.add("Invalid SET statement: missing semicolon");
}
currentState = State.DEFAULT;
currentStartIndex = -1;
break;
case STOP:
i = s.length();
break;
default:
}
}
// Build remaining query
StringBuilder remainingQuery = new StringBuilder();
int currentPos = 0;
for (int[] range : excludeRanges) {
if (currentPos < range[0]) {
remainingQuery.append(s, currentPos, range[0]);
}
currentPos = range[1];
}
if (currentPos < s.length()) {
remainingQuery.append(s, currentPos, s.length());
}
return new ParseResult(settings, remainingQuery.toString(), errors);
}