code: @NotNull
      protected static String parse(@NotNull String sql, @NotNull Map<String, List<Integer>> paramMap) {
          int length = sql.length();
          StringBuilder parsedQuery = new StringBuilder(length);
          boolean inSingleQuote = false;
          boolean inDoubleQuote = false;
          int index = 1;
  
          for (int i = 0; i < length; i++) {
              char c = sql.charAt(i);
              if (inSingleQuote) {
                  if (c == '\'') {
                      inSingleQuote = false;
                  }
              } else if (inDoubleQuote) {
                  if (c == '"') {
                      inDoubleQuote = false;
                  }
              } else {
                  if (c == '\'') {
                      inSingleQuote = true;
                  } else {
                      if (c == '"') {
                          inDoubleQuote = true;
                      } else {
                          if (c == ':' && i + 1 < length && Character.isJavaIdentifierStart(sql.charAt(i + 1))) {
                              int j = i + 2;
                              while (j < length && Character.isJavaIdentifierPart(sql.charAt(j))) {
                                  j++;
                              }
                              String name = sql.substring(i + 1, j);
                              c = '?'; // replace the parameter with a question mark
                              i += name.length(); // skip past the end if the parameter
  
                              List<Integer> indexList = paramMap.computeIfAbsent(name, k -> new ArrayList<>());
                              indexList.add(index);
  
                              index++;
                          }
                      }
                  }
              }
              parsedQuery.append(c);
          }
          return parsedQuery.toString();
      }
docs: TODO: add mappings cache for parsed maps -> reuse DbConnection -> Db::cache!