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/builder.rs
6940 views
1
use polars_core::chunked_array::cast::CastOptions;
2
use polars_core::prelude::{DataType, SortMultipleOptions, SortOptions};
3
use polars_core::scalar::Scalar;
4
use polars_utils::IdxSize;
5
use polars_utils::arena::{Arena, Node};
6
use polars_utils::pl_str::PlSmallStr;
7
8
use super::{AExpr, IRAggExpr, IRBooleanFunction, IRFunctionExpr, RowEncodingVariant};
9
use crate::dsl::Operator;
10
use crate::plans::{ExprIR, LiteralValue, OutputName};
11
12
#[derive(Clone, Copy)]
13
pub struct AExprBuilder {
14
node: Node,
15
}
16
17
impl AExprBuilder {
18
pub fn new_from_node(node: Node) -> Self {
19
Self { node }
20
}
21
22
pub fn new_from_aexpr(expr: AExpr, arena: &mut Arena<AExpr>) -> Self {
23
Self::new_from_node(arena.add(expr))
24
}
25
26
pub fn lit(lit: LiteralValue, arena: &mut Arena<AExpr>) -> Self {
27
Self::new_from_aexpr(AExpr::Literal(lit), arena)
28
}
29
30
pub fn lit_scalar(scalar: Scalar, arena: &mut Arena<AExpr>) -> Self {
31
Self::lit(LiteralValue::Scalar(scalar), arena)
32
}
33
34
pub fn col(name: impl Into<PlSmallStr>, arena: &mut Arena<AExpr>) -> Self {
35
Self::new_from_aexpr(AExpr::Column(name.into()), arena)
36
}
37
38
pub fn dataframe_length(arena: &mut Arena<AExpr>) -> Self {
39
Self::new_from_aexpr(AExpr::Len, arena)
40
}
41
42
pub fn function(
43
input: Vec<ExprIR>,
44
function: IRFunctionExpr,
45
arena: &mut Arena<AExpr>,
46
) -> Self {
47
let options = function.function_options();
48
Self::new_from_aexpr(
49
AExpr::Function {
50
input,
51
function,
52
options,
53
},
54
arena,
55
)
56
}
57
58
pub fn row_encode_unary(
59
self,
60
variant: RowEncodingVariant,
61
dtype: DataType,
62
arena: &mut Arena<AExpr>,
63
) -> Self {
64
Self::function(
65
vec![ExprIR::from_node(self.node(), arena)],
66
IRFunctionExpr::RowEncode(vec![dtype], variant),
67
arena,
68
)
69
}
70
71
pub fn cast(self, dtype: DataType, arena: &mut Arena<AExpr>) -> Self {
72
Self {
73
node: arena.add(AExpr::Cast {
74
expr: self.node,
75
dtype,
76
options: CastOptions::Strict,
77
}),
78
}
79
}
80
81
pub fn binary_op(
82
self,
83
other: impl IntoAExprBuilder,
84
op: Operator,
85
arena: &mut Arena<AExpr>,
86
) -> Self {
87
Self {
88
node: arena.add(AExpr::BinaryExpr {
89
left: self.node,
90
op,
91
right: other.into_aexpr_builder().node,
92
}),
93
}
94
}
95
96
pub fn agg(agg: IRAggExpr, arena: &mut Arena<AExpr>) -> Self {
97
Self::new_from_aexpr(AExpr::Agg(agg), arena)
98
}
99
100
pub fn first(self, arena: &mut Arena<AExpr>) -> Self {
101
Self::agg(IRAggExpr::First(self.node()), arena)
102
}
103
104
pub fn last(self, arena: &mut Arena<AExpr>) -> Self {
105
Self::agg(IRAggExpr::Last(self.node()), arena)
106
}
107
108
pub fn min(self, arena: &mut Arena<AExpr>) -> Self {
109
Self::agg(
110
IRAggExpr::Min {
111
input: self.node(),
112
propagate_nans: false,
113
},
114
arena,
115
)
116
}
117
118
pub fn max(self, arena: &mut Arena<AExpr>) -> Self {
119
Self::agg(
120
IRAggExpr::Max {
121
input: self.node(),
122
propagate_nans: false,
123
},
124
arena,
125
)
126
}
127
128
pub fn nan_min(self, arena: &mut Arena<AExpr>) -> Self {
129
Self::agg(
130
IRAggExpr::Min {
131
input: self.node(),
132
propagate_nans: true,
133
},
134
arena,
135
)
136
}
137
138
pub fn nan_max(self, arena: &mut Arena<AExpr>) -> Self {
139
Self::agg(
140
IRAggExpr::Max {
141
input: self.node(),
142
propagate_nans: true,
143
},
144
arena,
145
)
146
}
147
148
pub fn sum(self, arena: &mut Arena<AExpr>) -> Self {
149
Self::agg(IRAggExpr::Sum(self.node()), arena)
150
}
151
152
pub fn len(self, arena: &mut Arena<AExpr>) -> Self {
153
Self::agg(
154
IRAggExpr::Count {
155
input: self.node(),
156
include_nulls: true,
157
},
158
arena,
159
)
160
}
161
162
pub fn count(self, arena: &mut Arena<AExpr>) -> Self {
163
Self::agg(
164
IRAggExpr::Count {
165
input: self.node(),
166
include_nulls: false,
167
},
168
arena,
169
)
170
}
171
172
pub fn count_opt_nulls(self, include_nulls: bool, arena: &mut Arena<AExpr>) -> Self {
173
Self::agg(
174
IRAggExpr::Count {
175
input: self.node(),
176
include_nulls,
177
},
178
arena,
179
)
180
}
181
182
pub fn explode_skip_empty(self, arena: &mut Arena<AExpr>) -> Self {
183
Self::new_from_aexpr(
184
AExpr::Explode {
185
expr: self.node(),
186
skip_empty: true,
187
},
188
arena,
189
)
190
}
191
192
pub fn explode_null_empty(self, arena: &mut Arena<AExpr>) -> Self {
193
Self::new_from_aexpr(
194
AExpr::Explode {
195
expr: self.node(),
196
skip_empty: false,
197
},
198
arena,
199
)
200
}
201
202
pub fn sort(self, options: SortOptions, arena: &mut Arena<AExpr>) -> Self {
203
Self::new_from_aexpr(
204
AExpr::Sort {
205
expr: self.node(),
206
options,
207
},
208
arena,
209
)
210
}
211
212
pub fn sort_by(
213
self,
214
by: Vec<Node>,
215
options: SortMultipleOptions,
216
arena: &mut Arena<AExpr>,
217
) -> Self {
218
Self::new_from_aexpr(
219
AExpr::SortBy {
220
expr: self.node(),
221
by,
222
sort_options: options,
223
},
224
arena,
225
)
226
}
227
228
pub fn filter(self, by: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
229
Self::new_from_aexpr(
230
AExpr::Filter {
231
input: self.node(),
232
by: by.into_aexpr_builder().node(),
233
},
234
arena,
235
)
236
}
237
238
pub fn when_then_otherwise(
239
when: impl IntoAExprBuilder,
240
then: impl IntoAExprBuilder,
241
otherwise: impl IntoAExprBuilder,
242
arena: &mut Arena<AExpr>,
243
) -> Self {
244
when.into_aexpr_builder().ternary(then, otherwise, arena)
245
}
246
247
pub fn ternary(
248
self,
249
truthy: impl IntoAExprBuilder,
250
falsy: impl IntoAExprBuilder,
251
arena: &mut Arena<AExpr>,
252
) -> Self {
253
Self::new_from_aexpr(
254
AExpr::Ternary {
255
predicate: self.into_aexpr_builder().node(),
256
truthy: truthy.into_aexpr_builder().node(),
257
falsy: falsy.into_aexpr_builder().node(),
258
},
259
arena,
260
)
261
}
262
263
pub fn shift(self, periods: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
264
Self::function(
265
vec![
266
self.expr_ir_unnamed(),
267
periods.into_aexpr_builder().expr_ir_unnamed(),
268
],
269
IRFunctionExpr::Shift,
270
arena,
271
)
272
}
273
274
pub fn slice(
275
self,
276
offset: impl IntoAExprBuilder,
277
length: impl IntoAExprBuilder,
278
arena: &mut Arena<AExpr>,
279
) -> Self {
280
Self::new_from_aexpr(
281
AExpr::Slice {
282
input: self.into_aexpr_builder().node(),
283
offset: offset.into_aexpr_builder().node(),
284
length: length.into_aexpr_builder().node(),
285
},
286
arena,
287
)
288
}
289
290
#[cfg(feature = "is_in")]
291
pub fn is_in(
292
self,
293
other: impl IntoAExprBuilder,
294
nulls_equal: bool,
295
arena: &mut Arena<AExpr>,
296
) -> Self {
297
Self::function(
298
vec![
299
self.expr_ir_unnamed(),
300
other.into_aexpr_builder().expr_ir_unnamed(),
301
],
302
IRFunctionExpr::Boolean(IRBooleanFunction::IsIn { nulls_equal }),
303
arena,
304
)
305
}
306
307
pub fn to_physical(self, arena: &mut Arena<AExpr>) -> Self {
308
Self::function(
309
vec![self.expr_ir_unnamed()],
310
IRFunctionExpr::ToPhysical,
311
arena,
312
)
313
}
314
315
#[cfg(feature = "abs")]
316
pub fn abs(self, arena: &mut Arena<AExpr>) -> Self {
317
Self::function(vec![self.expr_ir_unnamed()], IRFunctionExpr::Abs, arena)
318
}
319
320
pub fn negate(self, arena: &mut Arena<AExpr>) -> Self {
321
Self::function(vec![self.expr_ir_unnamed()], IRFunctionExpr::Negate, arena)
322
}
323
324
pub fn not(self, arena: &mut Arena<AExpr>) -> Self {
325
Self::function(
326
vec![self.expr_ir_unnamed()],
327
IRFunctionExpr::Boolean(IRBooleanFunction::Not),
328
arena,
329
)
330
}
331
332
pub fn null_count(self, arena: &mut Arena<AExpr>) -> Self {
333
Self::function(
334
vec![self.expr_ir_unnamed()],
335
IRFunctionExpr::NullCount,
336
arena,
337
)
338
}
339
340
pub fn is_null(self, arena: &mut Arena<AExpr>) -> Self {
341
Self::function(
342
vec![self.expr_ir_unnamed()],
343
IRFunctionExpr::Boolean(IRBooleanFunction::IsNull),
344
arena,
345
)
346
}
347
348
pub fn is_not_null(self, arena: &mut Arena<AExpr>) -> Self {
349
Self::function(
350
vec![self.expr_ir_unnamed()],
351
IRFunctionExpr::Boolean(IRBooleanFunction::IsNotNull),
352
arena,
353
)
354
}
355
356
pub fn is_nan(self, arena: &mut Arena<AExpr>) -> Self {
357
Self::function(
358
vec![self.expr_ir_unnamed()],
359
IRFunctionExpr::Boolean(IRBooleanFunction::IsNan),
360
arena,
361
)
362
}
363
364
pub fn is_not_nan(self, arena: &mut Arena<AExpr>) -> Self {
365
Self::function(
366
vec![self.expr_ir_unnamed()],
367
IRFunctionExpr::Boolean(IRBooleanFunction::IsNotNan),
368
arena,
369
)
370
}
371
372
pub fn has_no_nulls(self, arena: &mut Arena<AExpr>) -> Self {
373
let nc = self.null_count(arena);
374
let idx_zero = Self::lit_scalar(Scalar::from(0 as IdxSize), arena);
375
nc.eq(idx_zero, arena)
376
}
377
378
pub fn has_nulls(self, arena: &mut Arena<AExpr>) -> Self {
379
let nc = self.null_count(arena);
380
let idx_zero = Self::lit_scalar(Scalar::from(0 as IdxSize), arena);
381
nc.gt(idx_zero, arena)
382
}
383
384
pub fn drop_nulls(self, arena: &mut Arena<AExpr>) -> Self {
385
Self::function(
386
vec![self.expr_ir_retain_name(arena)],
387
IRFunctionExpr::DropNulls,
388
arena,
389
)
390
}
391
392
pub fn drop_nans(self, arena: &mut Arena<AExpr>) -> Self {
393
Self::function(
394
vec![self.expr_ir_retain_name(arena)],
395
IRFunctionExpr::DropNans,
396
arena,
397
)
398
}
399
400
pub fn eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
401
self.binary_op(other, Operator::Eq, arena)
402
}
403
404
pub fn eq_validity(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
405
self.binary_op(other, Operator::EqValidity, arena)
406
}
407
408
pub fn not_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
409
self.binary_op(other, Operator::NotEq, arena)
410
}
411
412
pub fn not_eq_validity(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
413
self.binary_op(other, Operator::NotEqValidity, arena)
414
}
415
416
pub fn lt(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
417
self.binary_op(other, Operator::Lt, arena)
418
}
419
420
pub fn lt_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
421
self.binary_op(other, Operator::LtEq, arena)
422
}
423
424
pub fn gt(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
425
self.binary_op(other, Operator::Gt, arena)
426
}
427
428
pub fn gt_eq(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
429
self.binary_op(other, Operator::GtEq, arena)
430
}
431
432
pub fn plus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
433
self.binary_op(other, Operator::Plus, arena)
434
}
435
436
pub fn minus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
437
self.binary_op(other, Operator::Minus, arena)
438
}
439
440
pub fn multiply(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
441
self.binary_op(other, Operator::Multiply, arena)
442
}
443
444
pub fn divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
445
self.binary_op(other, Operator::Divide, arena)
446
}
447
448
pub fn true_divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
449
self.binary_op(other, Operator::TrueDivide, arena)
450
}
451
452
pub fn floor_divide(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
453
self.binary_op(other, Operator::FloorDivide, arena)
454
}
455
456
pub fn modulus(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
457
self.binary_op(other, Operator::Modulus, arena)
458
}
459
460
pub fn and(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
461
self.binary_op(other, Operator::And, arena)
462
}
463
464
pub fn or(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
465
self.binary_op(other, Operator::Or, arena)
466
}
467
468
pub fn xor(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
469
self.binary_op(other, Operator::Xor, arena)
470
}
471
472
pub fn logical_and(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
473
self.binary_op(other, Operator::LogicalAnd, arena)
474
}
475
476
pub fn logical_or(self, other: impl IntoAExprBuilder, arena: &mut Arena<AExpr>) -> Self {
477
self.binary_op(other, Operator::LogicalOr, arena)
478
}
479
480
pub fn expr_ir(self, name: impl Into<PlSmallStr>) -> ExprIR {
481
ExprIR::new(self.node(), OutputName::Alias(name.into()))
482
}
483
484
pub fn expr_ir_retain_name(self, arena: &Arena<AExpr>) -> ExprIR {
485
ExprIR::from_node(self.node(), arena)
486
}
487
488
pub fn expr_ir_unnamed(self) -> ExprIR {
489
self.expr_ir(PlSmallStr::EMPTY)
490
}
491
492
pub fn node(self) -> Node {
493
self.node
494
}
495
}
496
497
pub trait IntoAExprBuilder {
498
fn into_aexpr_builder(self) -> AExprBuilder;
499
}
500
501
impl IntoAExprBuilder for Node {
502
fn into_aexpr_builder(self) -> AExprBuilder {
503
AExprBuilder { node: self }
504
}
505
}
506
507
impl IntoAExprBuilder for AExprBuilder {
508
fn into_aexpr_builder(self) -> AExprBuilder {
509
self
510
}
511
}
512
513