Skip to content

Commit fc8f8cf

Browse files
committed
feat[array]: validity in display array
Signed-off-by: Joe Isaacs <[email protected]>
1 parent dedab97 commit fc8f8cf

File tree

2 files changed

+98
-13
lines changed

2 files changed

+98
-13
lines changed

vortex-array/src/compute/zip.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ mod tests {
329329
let result = zip(&const1, &const2, &mask).unwrap();
330330

331331
insta::assert_snapshot!(result.display_tree(), @r"
332-
root: vortex.varbinview(utf8?, len=100) nbytes=1.66 kB (100.00%) all_valid
332+
root: vortex.varbinview(utf8?, len=100) nbytes=1.66 kB (100.00%) [all_valid]
333333
metadata: EmptyMetadata
334334
buffer (align=1): 29 B (1.75%)
335335
buffer (align=1): 28 B (1.69%)
@@ -348,7 +348,7 @@ mod tests {
348348
insta::assert_snapshot!(wrapped_result.display_tree(), @r"
349349
root: vortex.struct({nested=utf8?}, len=100) nbytes=1.66 kB (100.00%)
350350
metadata: EmptyMetadata
351-
nested: vortex.varbinview(utf8?, len=100) nbytes=1.66 kB (100.00%)
351+
nested: vortex.varbinview(utf8?, len=100) nbytes=1.66 kB (100.00%) [all_valid]
352352
metadata: EmptyMetadata
353353
buffer (align=1): 29 B (1.75%)
354354
buffer (align=1): 28 B (1.69%)

vortex-array/src/display/tree.rs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,110 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use std::fmt::Write;
45
use std::fmt::{self};
56

67
use humansize::DECIMAL;
78
use humansize::format_size;
89

10+
use crate::Array;
911
use crate::ArrayRef;
1012
use crate::ArrayVisitor;
1113
use crate::arrays::ChunkedVTable;
1214
use crate::display::DisplayOptions;
15+
use crate::expr::stats::Stat;
16+
use crate::expr::stats::StatsProvider;
17+
18+
/// Display wrapper for array statistics in compact format.
19+
struct StatsDisplay<'a>(&'a dyn Array);
20+
21+
impl fmt::Display for StatsDisplay<'_> {
22+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23+
let stats = self.0.statistics();
24+
let mut first = true;
25+
26+
// Helper to write separator
27+
let mut sep = |f: &mut fmt::Formatter<'_>| -> fmt::Result {
28+
if first {
29+
first = false;
30+
f.write_str(" [")
31+
} else {
32+
f.write_str(", ")
33+
}
34+
};
35+
36+
// Null count or validity fallback
37+
if let Some(nc) = stats.get(Stat::NullCount) {
38+
if let Ok(n) = usize::try_from(&nc.clone().into_inner()) {
39+
sep(f)?;
40+
write!(f, "nulls={}", n)?;
41+
} else {
42+
sep(f)?;
43+
write!(f, "nulls={}", nc)?;
44+
}
45+
} else if self.0.dtype().is_nullable() {
46+
if self.0.all_valid() {
47+
sep(f)?;
48+
f.write_str("all_valid")?;
49+
} else if self.0.all_invalid() {
50+
sep(f)?;
51+
f.write_str("all_invalid")?;
52+
}
53+
}
54+
55+
// NaN count (only if > 0)
56+
if let Some(nan) = stats.get(Stat::NaNCount) {
57+
if let Ok(n) = usize::try_from(&nan.clone().into_inner()) {
58+
if n > 0 {
59+
sep(f)?;
60+
write!(f, "nan={}", n)?;
61+
}
62+
}
63+
}
64+
65+
// Min/Max
66+
if let Some(min) = stats.get(Stat::Min) {
67+
sep(f)?;
68+
write!(f, "min={}", min)?;
69+
}
70+
if let Some(max) = stats.get(Stat::Max) {
71+
sep(f)?;
72+
write!(f, "max={}", max)?;
73+
}
74+
75+
// Sum
76+
if let Some(sum) = stats.get(Stat::Sum) {
77+
sep(f)?;
78+
write!(f, "sum={}", sum)?;
79+
}
80+
81+
// Boolean flags (compact)
82+
if let Some(c) = stats.get(Stat::IsConstant) {
83+
if bool::try_from(&c.into_inner()).unwrap_or(false) {
84+
sep(f)?;
85+
f.write_str("const")?;
86+
}
87+
}
88+
if let Some(s) = stats.get(Stat::IsStrictSorted) {
89+
if bool::try_from(&s.into_inner()).unwrap_or(false) {
90+
sep(f)?;
91+
f.write_str("strict")?;
92+
}
93+
} else if let Some(s) = stats.get(Stat::IsSorted) {
94+
if bool::try_from(&s.into_inner()).unwrap_or(false) {
95+
sep(f)?;
96+
f.write_str("sorted")?;
97+
}
98+
}
99+
100+
// Close bracket if we wrote anything
101+
if !first {
102+
f.write_char(']')?;
103+
}
104+
105+
Ok(())
106+
}
107+
}
13108

14109
pub(crate) struct TreeDisplayWrapper(pub(crate) ArrayRef);
15110

@@ -39,16 +134,6 @@ impl<'a, 'b: 'a> TreeFormatter<'a, 'b> {
39134
} else {
40135
100_f64 * nbytes as f64 / total_size as f64
41136
};
42-
// Compute validity status string
43-
let validity_str = if !array.dtype().is_nullable() {
44-
""
45-
} else if array.all_valid() {
46-
" all_valid"
47-
} else if array.all_invalid() {
48-
" all_invalid"
49-
} else {
50-
""
51-
};
52137

53138
writeln!(
54139
self,
@@ -57,7 +142,7 @@ impl<'a, 'b: 'a> TreeFormatter<'a, 'b> {
57142
array.display_as(DisplayOptions::MetadataOnly),
58143
format_size(nbytes, DECIMAL),
59144
percent,
60-
validity_str
145+
StatsDisplay(array.as_ref()),
61146
)?;
62147

63148
self.indent(|i| {

0 commit comments

Comments
 (0)