From 89ea21db4928b15449cf609afbc4ce10a1a90c31 Mon Sep 17 00:00:00 2001 From: Michael-J-Ward Date: Fri, 9 Aug 2024 13:58:20 -0500 Subject: [PATCH] make Statistics::null_count return Option This removes ambiguity around whether the between all values are non-null or just that the null count stat is missing Ref: https://github.com/apache/arrow-rs/issues/6215 --- parquet/src/arrow/arrow_reader/statistics.rs | 2 +- parquet/src/arrow/arrow_writer/mod.rs | 2 +- parquet/src/column/page.rs | 10 +- parquet/src/column/writer/mod.rs | 22 +- parquet/src/file/metadata/mod.rs | 10 +- parquet/src/file/statistics.rs | 211 +++++++++++++------ parquet/src/file/writer.rs | 6 +- 7 files changed, 171 insertions(+), 92 deletions(-) diff --git a/parquet/src/arrow/arrow_reader/statistics.rs b/parquet/src/arrow/arrow_reader/statistics.rs index 98d327b50b11..dff861bac7d1 100644 --- a/parquet/src/arrow/arrow_reader/statistics.rs +++ b/parquet/src/arrow/arrow_reader/statistics.rs @@ -1387,7 +1387,7 @@ impl<'a> StatisticsConverter<'a> { let null_counts = metadatas .into_iter() .map(|x| x.column(parquet_index).statistics()) - .map(|s| s.map(|s| s.null_count())); + .map(|s| s.and_then(|s| s.null_count())); Ok(UInt64Array::from_iter(null_counts)) } diff --git a/parquet/src/arrow/arrow_writer/mod.rs b/parquet/src/arrow/arrow_writer/mod.rs index c8331aabb693..a52809daf3ed 100644 --- a/parquet/src/arrow/arrow_writer/mod.rs +++ b/parquet/src/arrow/arrow_writer/mod.rs @@ -2620,7 +2620,7 @@ mod tests { assert_eq!(row_group.num_columns(), 1); let column = row_group.column(0); let stats = column.statistics().unwrap(); - assert_eq!(stats.null_count(), 2); + assert_eq!(stats.null_count(), Some(2)); } } diff --git a/parquet/src/column/page.rs b/parquet/src/column/page.rs index 585d1951c14a..e3931dfe9e2b 100644 --- a/parquet/src/column/page.rs +++ b/parquet/src/column/page.rs @@ -370,7 +370,7 @@ mod tests { encoding: Encoding::PLAIN, def_level_encoding: Encoding::RLE, rep_level_encoding: Encoding::RLE, - statistics: Some(Statistics::int32(Some(1), Some(2), None, 1, true)), + statistics: Some(Statistics::int32(Some(1), Some(2), None, Some(1), true)), }; assert_eq!(data_page.page_type(), PageType::DATA_PAGE); assert_eq!(data_page.buffer(), vec![0, 1, 2].as_slice()); @@ -378,7 +378,7 @@ mod tests { assert_eq!(data_page.encoding(), Encoding::PLAIN); assert_eq!( data_page.statistics(), - Some(&Statistics::int32(Some(1), Some(2), None, 1, true)) + Some(&Statistics::int32(Some(1), Some(2), None, Some(1), true)) ); let data_page_v2 = Page::DataPageV2 { @@ -390,7 +390,7 @@ mod tests { def_levels_byte_len: 30, rep_levels_byte_len: 40, is_compressed: false, - statistics: Some(Statistics::int32(Some(1), Some(2), None, 1, true)), + statistics: Some(Statistics::int32(Some(1), Some(2), None, Some(1), true)), }; assert_eq!(data_page_v2.page_type(), PageType::DATA_PAGE_V2); assert_eq!(data_page_v2.buffer(), vec![0, 1, 2].as_slice()); @@ -398,7 +398,7 @@ mod tests { assert_eq!(data_page_v2.encoding(), Encoding::PLAIN); assert_eq!( data_page_v2.statistics(), - Some(&Statistics::int32(Some(1), Some(2), None, 1, true)) + Some(&Statistics::int32(Some(1), Some(2), None, Some(1), true)) ); let dict_page = Page::DictionaryPage { @@ -422,7 +422,7 @@ mod tests { encoding: Encoding::PLAIN, def_level_encoding: Encoding::RLE, rep_level_encoding: Encoding::RLE, - statistics: Some(Statistics::int32(Some(1), Some(2), None, 1, true)), + statistics: Some(Statistics::int32(Some(1), Some(2), None, Some(1), true)), }; let cpage = CompressedPage::new(data_page, 5); diff --git a/parquet/src/column/writer/mod.rs b/parquet/src/column/writer/mod.rs index cf2ddb4a70ff..81922ad20a96 100644 --- a/parquet/src/column/writer/mod.rs +++ b/parquet/src/column/writer/mod.rs @@ -897,7 +897,7 @@ impl<'a, E: ColumnValueEncoder> GenericColumnWriter<'a, E> { Some(min), Some(max), None, - self.page_metrics.num_page_nulls, + Some(self.page_metrics.num_page_nulls), false, ), ) @@ -1066,7 +1066,7 @@ impl<'a, E: ColumnValueEncoder> GenericColumnWriter<'a, E> { self.column_metrics.min_column_value.clone(), self.column_metrics.max_column_value.clone(), self.column_metrics.column_distinct_count, - self.column_metrics.num_column_nulls, + Some(self.column_metrics.num_column_nulls), false, ) .with_backwards_compatible_min_max(backwards_compatible_min_max) @@ -1842,7 +1842,7 @@ mod tests { assert_eq!(metadata.dictionary_page_offset(), Some(0)); if let Some(stats) = metadata.statistics() { assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); // TODO: None or 0? assert_eq!(stats.distinct_count(), None); if let Statistics::Int32(stats) = stats { assert_eq!(stats.min().unwrap(), &1); @@ -1971,7 +1971,7 @@ mod tests { assert_eq!(metadata.dictionary_page_offset(), Some(0)); if let Some(stats) = metadata.statistics() { assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); // TODO: None or 0? assert_eq!(stats.distinct_count().unwrap_or(0), 55); if let Statistics::Int32(stats) = stats { assert_eq!(stats.min().unwrap(), &-17); @@ -2002,7 +2002,7 @@ mod tests { let stats = r.metadata.statistics().unwrap(); assert_eq!(stats.min_bytes(), 1_i32.to_le_bytes()); assert_eq!(stats.max_bytes(), 7_i32.to_le_bytes()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); // TODO: None or 0? assert!(stats.distinct_count().is_none()); drop(write); @@ -2028,7 +2028,7 @@ mod tests { let page_statistics = pages[1].statistics().unwrap(); assert_eq!(page_statistics.min_bytes(), 1_i32.to_le_bytes()); assert_eq!(page_statistics.max_bytes(), 7_i32.to_le_bytes()); - assert_eq!(page_statistics.null_count(), 0); + assert_eq!(page_statistics.null_count(), Some(0)); // TODO: None or 0? assert!(page_statistics.distinct_count().is_none()); } @@ -2706,7 +2706,7 @@ mod tests { if let Some(stats) = r.metadata.statistics() { assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); assert_eq!(stats.distinct_count(), None); if let Statistics::Int32(stats) = stats { // first page is [1,2,3,4] @@ -2761,7 +2761,7 @@ mod tests { if let Some(stats) = r.metadata.statistics() { assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); assert_eq!(stats.distinct_count(), None); if let Statistics::FixedLenByteArray(stats) = stats { let column_index_min_value = &column_index.min_values[0]; @@ -2828,7 +2828,7 @@ mod tests { if let Some(stats) = r.metadata.statistics() { assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); assert_eq!(stats.distinct_count(), None); if let Statistics::FixedLenByteArray(_stats) = stats { let column_index_min_value = &column_index.min_values[0]; @@ -2952,7 +2952,7 @@ mod tests { let stats = r.metadata.statistics().expect("statistics"); assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); assert_eq!(stats.distinct_count(), None); if let Statistics::ByteArray(_stats) = stats { let min_value = _stats.min().unwrap(); @@ -3005,7 +3005,7 @@ mod tests { let stats = r.metadata.statistics().expect("statistics"); assert!(stats.has_min_max_set()); - assert_eq!(stats.null_count(), 0); + assert_eq!(stats.null_count(), Some(0)); assert_eq!(stats.distinct_count(), None); if let Statistics::FixedLenByteArray(_stats) = stats { let min_value = _stats.min().unwrap(); diff --git a/parquet/src/file/metadata/mod.rs b/parquet/src/file/metadata/mod.rs index 45ef0c546ffe..1fe5f50a42e0 100644 --- a/parquet/src/file/metadata/mod.rs +++ b/parquet/src/file/metadata/mod.rs @@ -1613,7 +1613,7 @@ mod tests { .iter() .map(|column_descr| { ColumnChunkMetaData::builder(column_descr.clone()) - .set_statistics(Statistics::new::(None, None, None, 0, false)) + .set_statistics(Statistics::new::(None, None, None, None, false)) .build() }) .collect::>>() @@ -1651,7 +1651,13 @@ mod tests { .iter() .map(|column_descr| { ColumnChunkMetaData::builder(column_descr.clone()) - .set_statistics(Statistics::new::(Some(0), Some(100), None, 0, false)) + .set_statistics(Statistics::new::( + Some(0), + Some(100), + None, + None, + false, + )) .build() }) .collect::>>() diff --git a/parquet/src/file/statistics.rs b/parquet/src/file/statistics.rs index 448b1efe922d..271acf4fd033 100644 --- a/parquet/src/file/statistics.rs +++ b/parquet/src/file/statistics.rs @@ -24,8 +24,8 @@ //! ```rust //! use parquet::file::statistics::Statistics; //! -//! let stats = Statistics::int32(Some(1), Some(10), None, 3, true); -//! assert_eq!(stats.null_count(), 3); +//! let stats = Statistics::int32(Some(1), Some(10), None, Some(3), true); +//! assert_eq!(stats.null_count(), Some(3)); //! assert!(stats.is_min_max_deprecated()); //! assert!(stats.min_is_exact()); //! assert!(stats.max_is_exact()); @@ -88,7 +88,7 @@ macro_rules! statistics_new_func { min: $vtype, max: $vtype, distinct: Option, - nulls: u64, + nulls: Option, is_deprecated: bool, ) -> Self { Statistics::$stat(ValueStatistics::new( @@ -136,7 +136,7 @@ pub fn from_thrift( } // Generic null count. - let null_count = null_count as u64; + let null_count = Some(null_count as u64); // Generic distinct count (count of distinct values occurring) let distinct_count = stats.distinct_count.map(|value| value as u64); // Whether or not statistics use deprecated min/max fields. @@ -245,11 +245,7 @@ pub fn to_thrift(stats: Option<&Statistics>) -> Option { let mut thrift_stats = TStatistics { max: None, min: None, - null_count: if stats.has_nulls() { - Some(stats.null_count() as i64) - } else { - None - }, + null_count: stats.null_count().map(|value| value as i64), distinct_count: stats.distinct_count().map(|value| value as i64), max_value: None, min_value: None, @@ -320,7 +316,7 @@ impl Statistics { min: Option, max: Option, distinct_count: Option, - null_count: u64, + null_count: Option, is_deprecated: bool, ) -> Self { Self::from(ValueStatistics::new( @@ -384,15 +380,10 @@ impl Statistics { /// Returns number of null values for the column. /// Note that this includes all nulls when column is part of the complex type. - pub fn null_count(&self) -> u64 { + pub fn null_count(&self) -> Option { statistics_enum_func![self, null_count] } - /// Returns `true` if statistics collected any null values, `false` otherwise. - pub fn has_nulls(&self) -> bool { - self.null_count() > 0 - } - /// Returns `true` if min value and max value are set. /// Normally both min/max values will be set to `Some(value)` or `None`. pub(crate) fn has_min_max_set(&self) -> bool { @@ -463,7 +454,7 @@ pub struct ValueStatistics { max: Option, // Distinct count could be omitted in some cases distinct_count: Option, - null_count: u64, + null_count: Option, // Whether or not the min or max values are exact, or truncated. is_max_value_exact: bool, @@ -484,7 +475,7 @@ impl ValueStatistics { min: Option, max: Option, distinct_count: Option, - null_count: u64, + null_count: Option, is_min_max_deprecated: bool, ) -> Self { Self { @@ -597,7 +588,7 @@ impl ValueStatistics { } /// Returns null count. - pub fn null_count(&self) -> u64 { + pub fn null_count(&self) -> Option { self.null_count } @@ -639,7 +630,11 @@ impl fmt::Display for ValueStatistics { Some(value) => write!(f, "{value}")?, None => write!(f, "N/A")?, } - write!(f, ", null_count: {}", self.null_count)?; + write!(f, ", null_count: ")?; + match self.null_count { + Some(value) => write!(f, "{value}")?, + None => write!(f, "N/A")?, + } write!(f, ", min_max_deprecated: {}", self.is_min_max_deprecated)?; write!(f, ", max_value_exact: {}", self.is_max_value_exact)?; write!(f, ", min_value_exact: {}", self.is_min_value_exact)?; @@ -651,7 +646,7 @@ impl fmt::Debug for ValueStatistics { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "{{min: {:?}, max: {:?}, distinct_count: {:?}, null_count: {}, \ + "{{min: {:?}, max: {:?}, distinct_count: {:?}, null_count: {:?}, \ min_max_deprecated: {}, min_max_backwards_compatible: {}, max_value_exact: {}, min_value_exact: {}}}", self.min, self.max, @@ -671,7 +666,7 @@ mod tests { #[test] fn test_statistics_min_max_bytes() { - let stats = Statistics::int32(Some(-123), Some(234), None, 1, false); + let stats = Statistics::int32(Some(-123), Some(234), None, Some(1), false); assert!(stats.has_min_max_set()); assert_eq!(stats.min_bytes(), (-123).as_bytes()); assert_eq!(stats.max_bytes(), 234.as_bytes()); @@ -680,7 +675,7 @@ mod tests { Some(ByteArray::from(vec![1, 2, 3])), Some(ByteArray::from(vec![3, 4, 5])), None, - 1, + Some(1), true, ); assert!(stats.has_min_max_set()); @@ -713,30 +708,30 @@ mod tests { #[test] fn test_statistics_debug() { - let stats = Statistics::int32(Some(1), Some(12), None, 12, true); + let stats = Statistics::int32(Some(1), Some(12), None, Some(12), true); assert_eq!( format!("{stats:?}"), - "Int32({min: Some(1), max: Some(12), distinct_count: None, null_count: 12, \ + "Int32({min: Some(1), max: Some(12), distinct_count: None, null_count: Some(12), \ min_max_deprecated: true, min_max_backwards_compatible: true, max_value_exact: true, min_value_exact: true})" ); - let stats = Statistics::int32(None, None, None, 7, false); + let stats = Statistics::int32(None, None, None, Some(7), false); assert_eq!( format!("{stats:?}"), - "Int32({min: None, max: None, distinct_count: None, null_count: 7, \ + "Int32({min: None, max: None, distinct_count: None, null_count: Some(7), \ min_max_deprecated: false, min_max_backwards_compatible: false, max_value_exact: false, min_value_exact: false})" ) } #[test] fn test_statistics_display() { - let stats = Statistics::int32(Some(1), Some(12), None, 12, true); + let stats = Statistics::int32(Some(1), Some(12), None, Some(12), true); assert_eq!( format!("{stats}"), "{min: 1, max: 12, distinct_count: N/A, null_count: 12, min_max_deprecated: true, max_value_exact: true, min_value_exact: true}" ); - let stats = Statistics::int64(None, None, None, 7, false); + let stats = Statistics::int64(None, None, None, Some(7), false); assert_eq!( format!("{stats}"), "{min: N/A, max: N/A, distinct_count: N/A, null_count: 7, min_max_deprecated: \ @@ -747,7 +742,7 @@ mod tests { Some(Int96::from(vec![1, 0, 0])), Some(Int96::from(vec![2, 3, 4])), None, - 3, + Some(3), true, ); assert_eq!( @@ -761,7 +756,7 @@ mod tests { Some(ByteArray::from(vec![1u8])), Some(ByteArray::from(vec![2u8])), Some(5), - 7, + Some(7), false, ) .with_max_is_exact(false) @@ -775,22 +770,22 @@ mod tests { #[test] fn test_statistics_partial_eq() { - let expected = Statistics::int32(Some(12), Some(45), None, 11, true); + let expected = Statistics::int32(Some(12), Some(45), None, Some(11), true); - assert!(Statistics::int32(Some(12), Some(45), None, 11, true) == expected); - assert!(Statistics::int32(Some(11), Some(45), None, 11, true) != expected); - assert!(Statistics::int32(Some(12), Some(44), None, 11, true) != expected); - assert!(Statistics::int32(Some(12), Some(45), None, 23, true) != expected); - assert!(Statistics::int32(Some(12), Some(45), None, 11, false) != expected); + assert!(Statistics::int32(Some(12), Some(45), None, Some(11), true) == expected); + assert!(Statistics::int32(Some(11), Some(45), None, Some(11), true) != expected); + assert!(Statistics::int32(Some(12), Some(44), None, Some(11), true) != expected); + assert!(Statistics::int32(Some(12), Some(45), None, Some(23), true) != expected); + assert!(Statistics::int32(Some(12), Some(45), None, Some(11), false) != expected); assert!( - Statistics::int32(Some(12), Some(45), None, 11, false) - != Statistics::int64(Some(12), Some(45), None, 11, false) + Statistics::int32(Some(12), Some(45), None, Some(11), false) + != Statistics::int64(Some(12), Some(45), None, Some(11), false) ); assert!( - Statistics::boolean(Some(false), Some(true), None, 0, true) - != Statistics::double(Some(1.2), Some(4.5), None, 0, true) + Statistics::boolean(Some(false), Some(true), None, None, true) + != Statistics::double(Some(1.2), Some(4.5), None, None, true) ); assert!( @@ -798,13 +793,13 @@ mod tests { Some(ByteArray::from(vec![1, 2, 3])), Some(ByteArray::from(vec![1, 2, 3])), None, - 0, + None, true ) != Statistics::fixed_len_byte_array( Some(ByteArray::from(vec![1, 2, 3]).into()), Some(ByteArray::from(vec![1, 2, 3]).into()), None, - 0, + None, true, ) ); @@ -814,14 +809,14 @@ mod tests { Some(ByteArray::from(vec![1, 2, 3])), Some(ByteArray::from(vec![1, 2, 3])), None, - 0, + None, true, ) != Statistics::ByteArray( ValueStatistics::new( Some(ByteArray::from(vec![1, 2, 3])), Some(ByteArray::from(vec![1, 2, 3])), None, - 0, + None, true, ) .with_max_is_exact(false) @@ -833,14 +828,14 @@ mod tests { Some(FixedLenByteArray::from(vec![1, 2, 3])), Some(FixedLenByteArray::from(vec![1, 2, 3])), None, - 0, + None, true, ) != Statistics::FixedLenByteArray( ValueStatistics::new( Some(FixedLenByteArray::from(vec![1, 2, 3])), Some(FixedLenByteArray::from(vec![1, 2, 3])), None, - 0, + None, true, ) .with_min_is_exact(false) @@ -857,45 +852,123 @@ mod tests { assert_eq!(from_thrift(tpe, thrift_stats).unwrap(), Some(stats)); } - check_stats(Statistics::boolean(Some(false), Some(true), None, 7, true)); - check_stats(Statistics::boolean(Some(false), Some(true), None, 7, true)); - check_stats(Statistics::boolean(Some(false), Some(true), None, 0, false)); - check_stats(Statistics::boolean(Some(true), Some(true), None, 7, true)); - check_stats(Statistics::boolean(Some(false), Some(false), None, 7, true)); - check_stats(Statistics::boolean(None, None, None, 7, true)); + check_stats(Statistics::boolean( + Some(false), + Some(true), + None, + Some(7), + true, + )); + check_stats(Statistics::boolean( + Some(false), + Some(true), + None, + Some(7), + true, + )); + check_stats(Statistics::boolean( + Some(false), + Some(true), + None, + Some(0), + false, + )); + check_stats(Statistics::boolean( + Some(true), + Some(true), + None, + Some(7), + true, + )); + check_stats(Statistics::boolean( + Some(false), + Some(false), + None, + Some(7), + true, + )); + check_stats(Statistics::boolean(None, None, None, Some(7), true)); - check_stats(Statistics::int32(Some(-100), Some(500), None, 7, true)); - check_stats(Statistics::int32(Some(-100), Some(500), None, 0, false)); - check_stats(Statistics::int32(None, None, None, 7, true)); + check_stats(Statistics::int32( + Some(-100), + Some(500), + None, + Some(7), + true, + )); + check_stats(Statistics::int32( + Some(-100), + Some(500), + None, + Some(0), + false, + )); + check_stats(Statistics::int32(None, None, None, Some(7), true)); - check_stats(Statistics::int64(Some(-100), Some(200), None, 7, true)); - check_stats(Statistics::int64(Some(-100), Some(200), None, 0, false)); - check_stats(Statistics::int64(None, None, None, 7, true)); + check_stats(Statistics::int64( + Some(-100), + Some(200), + None, + Some(7), + true, + )); + check_stats(Statistics::int64( + Some(-100), + Some(200), + None, + Some(0), + false, + )); + check_stats(Statistics::int64(None, None, None, Some(7), true)); - check_stats(Statistics::float(Some(1.2), Some(3.4), None, 7, true)); - check_stats(Statistics::float(Some(1.2), Some(3.4), None, 0, false)); - check_stats(Statistics::float(None, None, None, 7, true)); + check_stats(Statistics::float(Some(1.2), Some(3.4), None, Some(7), true)); + check_stats(Statistics::float( + Some(1.2), + Some(3.4), + None, + Some(0), + false, + )); + check_stats(Statistics::float(None, None, None, Some(7), true)); - check_stats(Statistics::double(Some(1.2), Some(3.4), None, 7, true)); - check_stats(Statistics::double(Some(1.2), Some(3.4), None, 0, false)); - check_stats(Statistics::double(None, None, None, 7, true)); + check_stats(Statistics::double( + Some(1.2), + Some(3.4), + None, + Some(7), + true, + )); + check_stats(Statistics::double( + Some(1.2), + Some(3.4), + None, + Some(0), + false, + )); + check_stats(Statistics::double(None, None, None, Some(7), true)); check_stats(Statistics::byte_array( Some(ByteArray::from(vec![1, 2, 3])), Some(ByteArray::from(vec![3, 4, 5])), None, - 7, + Some(7), true, )); - check_stats(Statistics::byte_array(None, None, None, 7, true)); + check_stats(Statistics::byte_array(None, None, None, Some(7), true)); check_stats(Statistics::fixed_len_byte_array( Some(ByteArray::from(vec![1, 2, 3]).into()), Some(ByteArray::from(vec![3, 4, 5]).into()), None, - 7, + Some(7), + true, + )); + check_stats(Statistics::fixed_len_byte_array( + None, + None, + None, + Some(7), true, )); - check_stats(Statistics::fixed_len_byte_array(None, None, None, 7, true)); } } diff --git a/parquet/src/file/writer.rs b/parquet/src/file/writer.rs index c84d06a2ce70..37681838e7c4 100644 --- a/parquet/src/file/writer.rs +++ b/parquet/src/file/writer.rs @@ -1397,7 +1397,7 @@ mod tests { encoding: Encoding::DELTA_BINARY_PACKED, def_level_encoding: Encoding::RLE, rep_level_encoding: Encoding::RLE, - statistics: Some(Statistics::int32(Some(1), Some(3), None, 7, true)), + statistics: Some(Statistics::int32(Some(1), Some(3), None, Some(7), true)), }, Page::DataPageV2 { buf: Bytes::from(vec![4; 128]), @@ -1408,7 +1408,7 @@ mod tests { def_levels_byte_len: 24, rep_levels_byte_len: 32, is_compressed: false, - statistics: Some(Statistics::int32(Some(1), Some(3), None, 7, true)), + statistics: Some(Statistics::int32(Some(1), Some(3), None, Some(7), true)), }, ]; @@ -1431,7 +1431,7 @@ mod tests { encoding: Encoding::DELTA_BINARY_PACKED, def_level_encoding: Encoding::RLE, rep_level_encoding: Encoding::RLE, - statistics: Some(Statistics::int32(Some(1), Some(3), None, 7, true)), + statistics: Some(Statistics::int32(Some(1), Some(3), None, Some(7), true)), }, Page::DataPageV2 { buf: Bytes::from(vec![4; 128]),