floe_core/checks/
not_null.rs1use polars::prelude::DataFrame;
2
3use super::RowError;
4use crate::{ConfigError, FloeResult};
5
6pub fn not_null_errors(df: &DataFrame, required_cols: &[String]) -> FloeResult<Vec<Vec<RowError>>> {
7 let mut errors_per_row = vec![Vec::new(); df.height()];
8 if required_cols.is_empty() {
9 return Ok(errors_per_row);
10 }
11
12 let mut null_masks = Vec::with_capacity(required_cols.len());
13 for name in required_cols {
14 let mask = df
15 .column(name)
16 .map_err(|err| {
17 Box::new(ConfigError(format!(
18 "required column {name} not found: {err}"
19 )))
20 })?
21 .is_null();
22 null_masks.push(mask);
23 }
24
25 for (row_idx, errors) in errors_per_row.iter_mut().enumerate() {
26 for (col, mask) in required_cols.iter().zip(null_masks.iter()) {
27 if mask.get(row_idx).unwrap_or(false) {
28 errors.push(RowError::new("not_null", col, "required value missing"));
29 }
30 }
31 }
32
33 Ok(errors_per_row)
34}