Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-plan/src/dsl/meta.rs
6939 views
1
use std::fmt::Display;
2
3
use super::*;
4
use crate::plans::conversion::is_regex_projection;
5
use crate::plans::tree_format::TreeFmtVisitor;
6
use crate::plans::visitor::{AexprNode, TreeWalker};
7
use crate::prelude::tree_format::TreeFmtVisitorDisplay;
8
9
/// Specialized expressions for Categorical dtypes.
10
pub struct MetaNameSpace(pub(crate) Expr);
11
12
impl MetaNameSpace {
13
/// Pop latest expression and return the input(s) of the popped expression.
14
pub fn pop(self, _schema: Option<&Schema>) -> PolarsResult<Vec<Expr>> {
15
let mut out = Vec::new();
16
self.0.nodes_owned(&mut out);
17
Ok(out)
18
}
19
20
/// Get the root column names.
21
pub fn root_names(&self) -> Vec<PlSmallStr> {
22
expr_to_leaf_column_names(&self.0)
23
}
24
25
/// A projection that only takes a column or a column + alias.
26
pub fn is_simple_projection(&self, schema: Option<&Schema>) -> bool {
27
let schema = match schema {
28
None => &Default::default(),
29
Some(s) => s,
30
};
31
let mut arena = Arena::with_capacity(8);
32
let mut ctx = ExprToIRContext::new_no_verification(&mut arena, schema);
33
to_expr_ir(self.0.clone(), &mut ctx)
34
.map(|expr| aexpr_is_simple_projection(expr.node(), &arena))
35
.unwrap_or(false)
36
}
37
38
/// Get the output name of this expression.
39
pub fn output_name(&self) -> PolarsResult<PlSmallStr> {
40
expr_output_name(&self.0)
41
}
42
43
/// Undo any renaming operation like `alias`, `keep_name`.
44
pub fn undo_aliases(self) -> Expr {
45
self.0.map_expr(|e| match e {
46
Expr::Alias(input, _)
47
| Expr::KeepName(input)
48
| Expr::RenameAlias { expr: input, .. } => Arc::unwrap_or_clone(input),
49
e => e,
50
})
51
}
52
53
/// Indicate if this expression expands to multiple expressions.
54
pub fn has_multiple_outputs(&self) -> bool {
55
self.0.into_iter().any(|e| {
56
matches!(
57
e,
58
Expr::Selector(_)
59
| Expr::Function {
60
function: FunctionExpr::StructExpr(StructFunction::SelectFields(_)),
61
..
62
}
63
)
64
})
65
}
66
67
/// Indicate if this expression is a basic (non-regex) column.
68
pub fn is_column(&self) -> bool {
69
match &self.0 {
70
Expr::Column(name) => !is_regex_projection(name),
71
_ => false,
72
}
73
}
74
75
/// Indicate if this expression only selects columns; the presence of any
76
/// transform operations will cause the check to return `false`, though
77
/// aliasing of the selected columns is optionally allowed.
78
pub fn is_column_selection(&self, allow_aliasing: bool) -> bool {
79
self.0.into_iter().all(|e| match e {
80
Expr::Column(_) | Expr::Selector(_) => true,
81
Expr::Alias(_, _) | Expr::KeepName(_) | Expr::RenameAlias { .. } => allow_aliasing,
82
_ => false,
83
})
84
}
85
86
/// Indicate if this expression represents a literal value (optionally aliased).
87
pub fn is_literal(&self, allow_aliasing: bool) -> bool {
88
self.0.into_iter().all(|e| match e {
89
Expr::Literal(_) => true,
90
Expr::Alias(_, _) => allow_aliasing,
91
Expr::Cast {
92
expr,
93
dtype,
94
options: CastOptions::Strict,
95
} if matches!(dtype.as_literal(), Some(DataType::Datetime(_, _))) && matches!(&**expr, Expr::Literal(LiteralValue::Scalar(sc)) if matches!(sc.as_any_value(), AnyValue::Datetime(..))) => true,
96
_ => false,
97
})
98
}
99
100
/// Indicate if this expression expands to multiple expressions with regex expansion.
101
pub fn is_regex_projection(&self) -> bool {
102
self.0
103
.into_iter()
104
.any(|e| matches!(e, Expr::Selector(Selector::Matches(_))))
105
}
106
107
/// Get a hold to an implementor of the `Display` trait that will format as
108
/// the expression as a tree
109
pub fn into_tree_formatter(
110
self,
111
display_as_dot: bool,
112
schema: Option<&Schema>,
113
) -> PolarsResult<impl Display> {
114
let schema = match schema {
115
None => &Default::default(),
116
Some(s) => s,
117
};
118
let mut arena = Default::default();
119
let mut ctx = ExprToIRContext::new_no_verification(&mut arena, schema);
120
let node = to_expr_ir(self.0, &mut ctx)?.node();
121
let mut visitor = TreeFmtVisitor::default();
122
if display_as_dot {
123
visitor.display = TreeFmtVisitorDisplay::DisplayDot;
124
}
125
AexprNode::new(node).visit(&mut visitor, &arena)?;
126
Ok(visitor)
127
}
128
}
129
130