public static void apply(StringBuilder builder, String sql, Map<String, String> params) {
        int len = sql == null ? 0 : sql.length();
        if (len < 2 || params == null || params.isEmpty()) {
            builder.append(sql);
            return;
        }

        for (int i = 0; i < len; i++) {
            char ch = sql.charAt(i);
            if (ClickHouseUtils.isQuote(ch)) {
                int endIndex = ClickHouseUtils.skipQuotedString(sql, i, len, ch);
                builder.append(sql.substring(i, endIndex));
                i = endIndex - 1;
            } else if (i + 1 < len) {
                int endIndex = i + 1;
                char nextCh = sql.charAt(endIndex);
                if (ch == '-' && nextCh == ch) {
                    endIndex = ClickHouseUtils.skipSingleLineComment(sql, i + 2, len);
                    builder.append(sql.substring(i, endIndex));
                    i = endIndex - 1;
                } else if (ch == '/' && nextCh == '*') {
                    endIndex = ClickHouseUtils.skipMultiLineComment(sql, i + 2, len);
                    builder.append(sql.substring(i, endIndex));
                    i = endIndex - 1;
                } else if (ch == ':') {
                    if (nextCh == ch) { // skip PostgreSQL-like type conversion
                        builder.append(ch).append(ch);
                        i = i + 1;
                    } else if (Character.isJavaIdentifierStart(nextCh)) {
                        StringBuilder sb = new StringBuilder().append(nextCh);
                        for (i = i + 2; i < len; i++) {
                            char c = sql.charAt(i);
                            if (c == '(') {
                                i = ClickHouseUtils.skipBrackets(sql, i, len, c) - 1;
                                break;
                            } else if (Character.isJavaIdentifierPart(c)) {
                                sb.append(c);
                            } else {
                                i--;
                                break;
                            }
                        }

                        builder.append(params.getOrDefault(sb.toString(), ClickHouseValues.NULL_EXPR));
                    } else {
                        builder.append(ch);
                    }
                } else {
                    builder.append(ch);
                }
            } else {
                builder.append(ch);
            }
        }
    }
Substitute named parameters in given SQL.

@param builder non-null string builder
@param sql     SQL containing named parameters
@param params  mapping between parameter name and correspoding SQL
               expression(NOT raw value)
clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseParameterizedQuery.java