Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-plan/src/plans/aexpr/function_expr/struct_.rs
8391 views
1
use polars_utils::format_pl_smallstr;
2
3
use super::*;
4
5
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
6
#[cfg_attr(feature = "ir_serde", derive(serde::Serialize, serde::Deserialize))]
7
pub enum IRStructFunction {
8
FieldByName(PlSmallStr),
9
RenameFields(Arc<[PlSmallStr]>),
10
PrefixFields(PlSmallStr),
11
SuffixFields(PlSmallStr),
12
#[cfg(feature = "json")]
13
JsonEncode,
14
MapFieldNames(PlanCallback<PlSmallStr, PlSmallStr>),
15
}
16
17
impl IRStructFunction {
18
pub(super) fn get_field(&self, mapper: FieldsMapper) -> PolarsResult<Field> {
19
use IRStructFunction::*;
20
21
match self {
22
FieldByName(name) => mapper.try_map_field(|field| {
23
if let DataType::Struct(ref fields) = field.dtype {
24
let fld = fields
25
.iter()
26
.find(|fld| fld.name() == name)
27
.ok_or_else(|| polars_err!(StructFieldNotFound: "{}", name))?;
28
Ok(fld.clone())
29
} else {
30
polars_bail!(StructFieldNotFound: "{}", name);
31
}
32
}),
33
RenameFields(names) => mapper.map_dtype(|dt| match dt {
34
DataType::Struct(fields) => {
35
let fields = fields
36
.iter()
37
.zip(names.as_ref())
38
.map(|(fld, name)| Field::new(name.clone(), fld.dtype().clone()))
39
.collect();
40
DataType::Struct(fields)
41
},
42
// The types will be incorrect, but its better than nothing
43
// we can get an incorrect type with python lambdas, because we only know return type when running
44
// the query
45
dt => DataType::Struct(
46
names
47
.iter()
48
.map(|name| Field::new(name.clone(), dt.clone()))
49
.collect(),
50
),
51
}),
52
PrefixFields(prefix) => mapper.try_map_dtype(|dt| match dt {
53
DataType::Struct(fields) => {
54
let fields = fields
55
.iter()
56
.map(|fld| {
57
let name = fld.name();
58
Field::new(format_pl_smallstr!("{prefix}{name}"), fld.dtype().clone())
59
})
60
.collect();
61
Ok(DataType::Struct(fields))
62
},
63
_ => polars_bail!(op = "prefix_fields", got = dt, expected = "Struct"),
64
}),
65
SuffixFields(suffix) => mapper.try_map_dtype(|dt| match dt {
66
DataType::Struct(fields) => {
67
let fields = fields
68
.iter()
69
.map(|fld| {
70
let name = fld.name();
71
Field::new(format_pl_smallstr!("{name}{suffix}"), fld.dtype().clone())
72
})
73
.collect();
74
Ok(DataType::Struct(fields))
75
},
76
_ => polars_bail!(op = "suffix_fields", got = dt, expected = "Struct"),
77
}),
78
#[cfg(feature = "json")]
79
JsonEncode => mapper.with_dtype(DataType::String),
80
MapFieldNames(function) => mapper.try_map_dtype(|dt| match dt {
81
DataType::Struct(fields) => {
82
let fields = fields
83
.iter()
84
.map(|fld| {
85
let name = fld.name();
86
let new_name = function.call(name.clone()).map_err(|e| polars_err!(ComputeError: "'name.map_fields' produced an error: {e}."))?;
87
Ok(Field::new(new_name, fld.dtype().clone()))
88
})
89
.collect::<PolarsResult<_>>()?;
90
Ok(DataType::Struct(fields))
91
},
92
_ => polars_bail!(op = "prefix_fields", got = dt, expected = "Struct"),
93
}),
94
}
95
}
96
97
pub fn function_options(&self) -> FunctionOptions {
98
use IRStructFunction as S;
99
match self {
100
S::FieldByName(_) => {
101
FunctionOptions::elementwise().with_flags(|f| f | FunctionFlags::ALLOW_RENAME)
102
},
103
S::RenameFields(_) | S::PrefixFields(_) | S::SuffixFields(_) => {
104
FunctionOptions::elementwise()
105
},
106
#[cfg(feature = "json")]
107
S::JsonEncode => FunctionOptions::elementwise(),
108
S::MapFieldNames(_) => FunctionOptions::elementwise(),
109
}
110
}
111
}
112
113
impl Display for IRStructFunction {
114
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
115
use IRStructFunction::*;
116
match self {
117
FieldByName(name) => write!(f, "struct.field_by_name({name})"),
118
RenameFields(names) => write!(f, "struct.rename_fields({names:?})"),
119
PrefixFields(_) => write!(f, "name.prefix_fields"),
120
SuffixFields(_) => write!(f, "name.suffixFields"),
121
#[cfg(feature = "json")]
122
JsonEncode => write!(f, "struct.to_json"),
123
MapFieldNames(_) => write!(f, "map_field_names"),
124
}
125
}
126
}
127
128