jetbrick-orm/src/main/java/jetbrick/dao/orm/utils/NamedParameterStatement.java
private static String parseNamedSql(String sql, Map<String, List<Integer>> nameIndexMap) {
        // I was originally using regular expressions, but they didn't work well for ignoring
        // parameter-like strings inside quotes.
        int length = sql.length();
        StringBuffer parsedSql = new StringBuffer(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 = nameIndexMap.get(name);
                    if (indexList == null) {
                        indexList = new LinkedList<Integer>();
                        nameIndexMap.put(name, indexList);
                    }
                    indexList.add(index);
                    index++;
                }
            }
            parsedSql.append(c);
        }

        return parsedSql.toString();
    }
private static String parseNamedSql(String sql, Map<String, List<Integer>> nameIndexMap) {
        // I was originally using regular expressions, but they didn't work well for ignoring
        // parameter-like strings inside quotes.
        int length = sql.length();
        StringBuffer parsedSql = new StringBuffer(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 = nameIndexMap.get(name);
                    if (indexList == null) {
                        indexList = new LinkedList<Integer>();
                        nameIndexMap.put(name, indexList);
                    }
                    indexList.add(index);
                    index++;
                }
            }
            parsedSql.append(c);
        }

        return parsedSql.toString();
    }
Parses a sql with named parameters. The parameter-index mappings
are put into the map, and the parsed sql is returned.
@param sql    sql with named parameters
@return the parsed sql