1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! Shape thresholds for lowering native IR expressions into cuDF expressions.
//!
//! The engine's prepared-expression lowering and its filter operator read one
//! policy here so the two agree on which `IN (...)` lists become a row
//! predicate tree and which become a membership kernel; each list takes one
//! of the two paths, never both.
/// Internal policy for lowering native IR expressions into cudf expressions.
///
/// These gates avoid creating execution expressions whose shape is worse for
/// cudf than the original IR operator. Keep them internal until lower-level
/// cudf diagnostics can report authoritative expression strategy choices.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[doc(hidden)]
pub struct ExpressionLoweringPolicy {
/// Largest `IN` list expanded into an `OR` chain of equality nodes. Each
/// list element becomes one AST node, so the limit bounds the expression
/// tree depth cuDF has to compile.
row_predicate_in_list_expansion_limit: usize,
}
impl ExpressionLoweringPolicy {
pub const DEFAULT_ROW_PREDICATE_IN_LIST_EXPANSION_LIMIT: usize = 128;
/// Whether a filter `IN` list of `list_len` values is lowered as an
/// equality chain inside the row predicate tree.
pub fn filter_in_list_should_use_row_predicate_tree(self, list_len: usize) -> bool {
list_len <= self.row_predicate_in_list_expansion_limit
}
/// The complement of
/// [`Self::filter_in_list_should_use_row_predicate_tree`]: the list is
/// evaluated by a membership kernel over the column instead.
pub fn filter_in_list_should_use_specialized_series(self, list_len: usize) -> bool {
!self.filter_in_list_should_use_row_predicate_tree(list_len)
}
}
impl Default for ExpressionLoweringPolicy {
fn default() -> Self {
Self { row_predicate_in_list_expansion_limit: Self::DEFAULT_ROW_PREDICATE_IN_LIST_EXPANSION_LIMIT }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn in_list_row_predicate_expansion_allows_limit_but_rejects_above_it() {
let policy = ExpressionLoweringPolicy::default();
assert!(policy.filter_in_list_should_use_row_predicate_tree(
ExpressionLoweringPolicy::DEFAULT_ROW_PREDICATE_IN_LIST_EXPANSION_LIMIT
));
assert!(!policy.filter_in_list_should_use_row_predicate_tree(
ExpressionLoweringPolicy::DEFAULT_ROW_PREDICATE_IN_LIST_EXPANSION_LIMIT + 1
));
}
#[test]
fn specialized_in_list_series_starts_above_row_predicate_limit() {
let policy = ExpressionLoweringPolicy::default();
assert!(!policy.filter_in_list_should_use_specialized_series(
ExpressionLoweringPolicy::DEFAULT_ROW_PREDICATE_IN_LIST_EXPANSION_LIMIT
));
assert!(policy.filter_in_list_should_use_specialized_series(
ExpressionLoweringPolicy::DEFAULT_ROW_PREDICATE_IN_LIST_EXPANSION_LIMIT + 1
));
}
}