public static ClickHouseResponse of(ClickHouseResponse response, ClickHouseRecordTransformer func) {
        if (response == null) {
            return EMPTY;
        } else if (response instanceof ClickHouseSimpleResponse) {
            return response;
        }

        List<ClickHouseColumn> columns = response.getColumns();
        Map<String, Integer> columnIndex = IntStream.range(0, columns.size()).boxed().
                collect(Collectors.toMap(i->columns.get(i).getColumnName() , i -> i));

        int size = columns.size();
        List<ClickHouseRecord> records = new LinkedList<>();
        int rowIndex = 0;
        for (ClickHouseRecord r : response.records()) {
            ClickHouseValue[] values = new ClickHouseValue[size];
            for (int i = 0; i < size; i++) {
                values[i] = r.getValue(i).copy();
            }

            ClickHouseRecord rec = ClickHouseSimpleRecord.of(columnIndex, values);
            if (func != null) {
                func.update(rowIndex, rec);
            }
            records.add(rec);
        }

        return new ClickHouseSimpleResponse(response.getColumns(), records, response.getSummary(), response.getTimeZone());
    }
Creates a response object by copying columns and values from the given one.
You should never use this method against a large response, because it will
load everything into memory. Worse than that, when {@code func} is not null,
it will be applied to every single row, which is going to be slow when
original response contains many records.

@param response response to copy
@param func     optinal function to update value by column index
@return new response object
clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseSimpleResponse.java