use serde::{Deserialize, Serialize};
use crate::results::MinimalFallback;
use crate::results::{BooleanStats, DateStats, NumericStats};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ColumnStat {
pub i: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub t: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub pt: Option<String>,
#[serde(rename = "null_pct", default, skip_serializing_if = "Option::is_none")]
pub null_pct: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub uniq: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub num: Option<NumericStats>,
#[serde(rename = "bool", skip_serializing_if = "Option::is_none")]
pub bool_stats: Option<BooleanStats>,
#[serde(skip_serializing_if = "Option::is_none")]
pub date: Option<DateStats>,
}
#[derive(Debug, Clone)]
pub struct MergeColumnStatsInput {
pub column_count: usize,
pub column_names: Option<Vec<String>>,
pub column_types: Option<Vec<String>>,
pub null_percentages: Option<Vec<f64>>,
pub unique_counts: Option<Vec<usize>>,
pub numeric_stats: Option<Vec<Option<NumericStats>>>,
pub date_stats: Option<Vec<Option<DateStats>>>,
pub boolean_stats: Option<Vec<Option<BooleanStats>>>,
pub physical_types: Option<Vec<String>>,
}
#[must_use]
pub fn merge_column_stats(input: &MergeColumnStatsInput) -> Option<Vec<ColumnStat>> {
let column_count = input.column_count;
if column_count == 0 {
return None;
}
let mut out = Vec::with_capacity(column_count);
for j in 0..column_count {
let name = input.column_names.as_ref().and_then(|v| v.get(j).cloned());
let t = input
.column_types
.as_ref()
.and_then(|v| v.get(j))
.cloned()
.unwrap_or_else(|| "unknown".to_string());
let pt = input
.physical_types
.as_ref()
.and_then(|v| v.get(j).cloned());
let null_pct = input
.null_percentages
.as_ref()
.and_then(|v| v.get(j).copied());
let uniq = if t == "string" {
input.unique_counts.as_ref().and_then(|v| v.get(j).copied())
} else {
None
};
let num = input
.numeric_stats
.as_ref()
.and_then(|v| v.get(j))
.cloned()
.flatten();
let date = input
.date_stats
.as_ref()
.and_then(|v| v.get(j))
.cloned()
.flatten();
let bool_stats = input
.boolean_stats
.as_ref()
.and_then(|v| v.get(j))
.cloned()
.flatten();
out.push(ColumnStat {
i: j,
name,
t,
pt,
null_pct,
uniq,
num,
bool_stats,
date,
});
}
Some(out)
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct ColumnarCommonFields {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub row_count: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub column_count: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stats_rows_sampled: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub encoding: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub columns: Option<Vec<ColumnStat>>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct ParquetMetadata {
#[serde(flatten)]
pub common: ColumnarCommonFields,
#[serde(skip_serializing_if = "Option::is_none")]
pub num_row_groups: Option<usize>,
}
crate::impl_minimal_fallback!(ParquetMetadata, _);
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct ArrowIpcMetadata {
#[serde(flatten)]
pub common: ColumnarCommonFields,
#[serde(skip_serializing_if = "Option::is_none")]
pub container_kind: Option<String>,
}
crate::impl_minimal_fallback!(ArrowIpcMetadata, _);
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct AvroMetadata {
#[serde(flatten)]
pub common: ColumnarCommonFields,
#[serde(skip_serializing_if = "Option::is_none")]
pub schema_canonical: Option<String>,
}
crate::impl_minimal_fallback!(AvroMetadata, _);
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct OrcMetadata {
#[serde(flatten)]
pub common: ColumnarCommonFields,
#[serde(skip_serializing_if = "Option::is_none")]
pub num_stripes: Option<usize>,
}
crate::impl_minimal_fallback!(OrcMetadata, _);
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct CsvMetadata {
#[serde(flatten)]
pub common: ColumnarCommonFields,
#[serde(skip_serializing_if = "Option::is_none")]
pub delimiter: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quote_character: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub escape_character: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_header: Option<bool>,
}
crate::impl_minimal_fallback!(CsvMetadata, _);