@VisibleForTesting
    static Estimate calculateDataSize(String column, Collection<PartitionStatistics> partitionStatistics, double totalRowCount)
    {
        List<PartitionStatistics> statisticsWithKnownRowCountAndDataSize = partitionStatistics.stream()
                .filter(statistics -> {
                    if (!statistics.getBasicStatistics().getRowCount().isPresent()) {
                        return false;
                    }
                    HiveColumnStatistics columnStatistics = statistics.getColumnStatistics().get(column);
                    if (columnStatistics == null) {
                        return false;
                    }
                    return columnStatistics.getTotalSizeInBytes().isPresent();
                })
                .collect(toImmutableList());

        if (statisticsWithKnownRowCountAndDataSize.isEmpty()) {
            return Estimate.unknown();
        }

        long knownRowCount = 0;
        long knownDataSize = 0;
        for (PartitionStatistics statistics : statisticsWithKnownRowCountAndDataSize) {
            long rowCount = statistics.getBasicStatistics().getRowCount().orElseThrow(() -> new VerifyException("rowCount is not present"));
            verify(rowCount >= 0, "rowCount must be greater than or equal to zero");
            HiveColumnStatistics columnStatistics = statistics.getColumnStatistics().get(column);
            verify(columnStatistics != null, "columnStatistics is null");
            long dataSize = columnStatistics.getTotalSizeInBytes().orElseThrow(() -> new VerifyException("totalSizeInBytes is not present"));
            verify(dataSize >= 0, "dataSize must be greater than or equal to zero");
            knownRowCount += rowCount;
            knownDataSize += dataSize;
        }

        if (totalRowCount == 0) {
            return Estimate.zero();
        }

        if (knownRowCount == 0) {
            return Estimate.unknown();
        }

        double averageValueDataSizeInBytes = ((double) knownDataSize) / knownRowCount;
        return Estimate.of(averageValueDataSizeInBytes * totalRowCount);
    }
@Test
    public void testCalculateDataSize()
    {
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(), 0), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(), 1000), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(PartitionStatistics.empty()), 1000), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(rowsCount(1000)), 1000), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(dataSize(1000)), 1000), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(dataSize(1000), rowsCount(1000)), 1000), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(rowsCountAndDataSize(500, 1000)), 2000), Estimate.of(4000));
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(rowsCountAndDataSize(0, 0)), 2000), Estimate.unknown());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(rowsCountAndDataSize(0, 0)), 0), Estimate.zero());
        assertEquals(calculateDataSize(COLUMN, ImmutableList.of(rowsCountAndDataSize(1000, 0)), 2000), Estimate.of(0));
        assertEquals(
                calculateDataSize(
                        COLUMN,
                        ImmutableList.of(
                                rowsCountAndDataSize(500, 1000),
                                rowsCountAndDataSize(1000, 5000)),
                        5000),
                Estimate.of(20000));
        assertEquals(
                calculateDataSize(
                        COLUMN,
                        ImmutableList.of(
                                dataSize(1000),
                                rowsCountAndDataSize(500, 1000),
                                rowsCount(3000),
                                rowsCountAndDataSize(1000, 5000)),
                        5000),
                Estimate.of(20000));
    }