public ParseResult extractSetStatements()

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);
  }