static CompletableFuture<List<ClickHouseResponseSummary>> send(ClickHouseNode server, String sql,
            List<ClickHouseColumn> columns, Object[]... params) {
        int len = columns == null ? 0 : columns.size();
        if (len == 0) {
            throw new IllegalArgumentException("Non-empty column list is required");
        }

        // FIXME better get the configuration from request/client
        ClickHouseConfig config = new ClickHouseConfig();
        ClickHouseValue[] templates = new ClickHouseValue[len];
        int index = 0;
        for (ClickHouseColumn column : columns) {
            templates[index++] = ClickHouseChecker.nonNull(column, ClickHouseColumn.TYPE_NAME).newValue(config);
        }

        return send(server, sql, templates, params);
    }
Sends SQL query along with raw parameters(e.g. byte value for Int8) to
specified server. Parameters will be stringified based on given column types.

@param server  non-null server to connect to
@param sql     non-null SQL query
@param columns non-empty column list
@param params  non-empty raw parameters
@return list of {@link ClickHouseResponseSummary} one for each execution
@throws IllegalArgumentException if columns is null, empty or contains null
                                 column
@throws CompletionException      when error occurred during execution
clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseClient.java