1use std::fmt::Display;
2use std::ops::BitAnd;
3
4use super::*;
5use crate::plans::conversion::is_regex_projection;
6use crate::plans::ir::tree_format::TreeFmtVisitor;
7use crate::plans::visitor::{AexprNode, TreeWalker};
8use crate::prelude::tree_format::TreeFmtVisitorDisplay;
9
10pub struct MetaNameSpace(pub(crate) Expr);
12
13impl MetaNameSpace {
14 pub fn pop(self) -> PolarsResult<Vec<Expr>> {
16 let mut arena = Arena::with_capacity(8);
17 let node = to_aexpr(self.0, &mut arena)?;
18 let ae = arena.get(node);
19 let mut inputs = Vec::with_capacity(2);
20 ae.inputs_rev(&mut inputs);
21 Ok(inputs
22 .iter()
23 .map(|node| node_to_expr(*node, &arena))
24 .collect())
25 }
26
27 pub fn root_names(&self) -> Vec<PlSmallStr> {
29 expr_to_leaf_column_names(&self.0)
30 }
31
32 pub fn is_simple_projection(&self) -> bool {
34 let mut arena = Arena::with_capacity(8);
35 to_aexpr(self.0.clone(), &mut arena)
36 .map(|node| aexpr_is_simple_projection(node, &arena))
37 .unwrap_or(false)
38 }
39
40 pub fn output_name(&self) -> PolarsResult<PlSmallStr> {
42 expr_output_name(&self.0)
43 }
44
45 pub fn undo_aliases(self) -> Expr {
47 self.0.map_expr(|e| match e {
48 Expr::Alias(input, _)
49 | Expr::KeepName(input)
50 | Expr::RenameAlias { expr: input, .. } => Arc::unwrap_or_clone(input),
51 e => e,
52 })
53 }
54
55 pub fn has_multiple_outputs(&self) -> bool {
57 self.0.into_iter().any(|e| match e {
58 Expr::Selector(_) | Expr::Wildcard | Expr::Columns(_) | Expr::DtypeColumn(_) => true,
59 Expr::IndexColumn(idxs) => idxs.len() > 1,
60 Expr::Column(name) => is_regex_projection(name),
61 _ => false,
62 })
63 }
64
65 pub fn is_column(&self) -> bool {
67 match &self.0 {
68 Expr::Column(name) => !is_regex_projection(name),
69 _ => false,
70 }
71 }
72
73 pub fn is_column_selection(&self, allow_aliasing: bool) -> bool {
77 self.0.into_iter().all(|e| match e {
78 Expr::Column(_)
79 | Expr::Columns(_)
80 | Expr::DtypeColumn(_)
81 | Expr::Exclude(_, _)
82 | Expr::Nth(_)
83 | Expr::IndexColumn(_)
84 | Expr::Selector(_)
85 | Expr::Wildcard => true,
86 Expr::Alias(_, _) | Expr::KeepName(_) | Expr::RenameAlias { .. } => allow_aliasing,
87 _ => false,
88 })
89 }
90
91 pub fn is_literal(&self, allow_aliasing: bool) -> bool {
93 self.0.into_iter().all(|e| match e {
94 Expr::Literal(_) => true,
95 Expr::Alias(_, _) => allow_aliasing,
96 Expr::Cast {
97 expr,
98 dtype: DataType::Datetime(_, _),
99 options: CastOptions::Strict,
100 } if matches!(&**expr, Expr::Literal(LiteralValue::DateTime(_, _, _))) => true,
101 _ => false,
102 })
103 }
104
105 pub fn is_regex_projection(&self) -> bool {
107 self.0.into_iter().any(|e| match e {
108 Expr::Column(name) => is_regex_projection(name),
109 _ => false,
110 })
111 }
112
113 pub fn _selector_add(self, other: Expr) -> PolarsResult<Expr> {
114 if let Expr::Selector(mut s) = self.0 {
115 if let Expr::Selector(s_other) = other {
116 s = s + s_other;
117 } else {
118 s = s + Selector::Root(Box::new(other))
119 }
120 Ok(Expr::Selector(s))
121 } else {
122 polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
123 }
124 }
125
126 pub fn _selector_and(self, other: Expr) -> PolarsResult<Expr> {
127 if let Expr::Selector(mut s) = self.0 {
128 if let Expr::Selector(s_other) = other {
129 s = s.bitand(s_other);
130 } else {
131 s = s.bitand(Selector::Root(Box::new(other)))
132 }
133 Ok(Expr::Selector(s))
134 } else {
135 polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
136 }
137 }
138
139 pub fn _selector_sub(self, other: Expr) -> PolarsResult<Expr> {
140 if let Expr::Selector(mut s) = self.0 {
141 if let Expr::Selector(s_other) = other {
142 s = s - s_other;
143 } else {
144 s = s - Selector::Root(Box::new(other))
145 }
146 Ok(Expr::Selector(s))
147 } else {
148 polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
149 }
150 }
151
152 pub fn _selector_xor(self, other: Expr) -> PolarsResult<Expr> {
153 if let Expr::Selector(mut s) = self.0 {
154 if let Expr::Selector(s_other) = other {
155 s = s ^ s_other;
156 } else {
157 s = s ^ Selector::Root(Box::new(other))
158 }
159 Ok(Expr::Selector(s))
160 } else {
161 polars_bail!(ComputeError: "expected selector, got {:?}", self.0)
162 }
163 }
164
165 pub fn _into_selector(self) -> Expr {
166 if let Expr::Selector(_) = self.0 {
167 self.0
168 } else {
169 Expr::Selector(Selector::new(self.0))
170 }
171 }
172
173 pub fn into_tree_formatter(self, display_as_dot: bool) -> PolarsResult<impl Display> {
176 let mut arena = Default::default();
177 let node = to_aexpr(self.0, &mut arena)?;
178 let mut visitor = TreeFmtVisitor::default();
179 if display_as_dot {
180 visitor.display = TreeFmtVisitorDisplay::DisplayDot;
181 }
182
183 AexprNode::new(node).visit(&mut visitor, &arena)?;
184
185 Ok(visitor)
186 }
187}