Skip to content

Commit dcb9b34

Browse files
committed
Account for constant equivalence properties in union, tests
1 parent b0ec2d6 commit dcb9b34

File tree

4 files changed

+440
-96
lines changed

4 files changed

+440
-96
lines changed

datafusion/physical-expr-common/src/sort_expr.rs

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,28 +96,48 @@ impl PhysicalSortExpr {
9696
}
9797

9898
/// Set the sort sort options to ASC
99-
pub fn asc(mut self) -> Self {
100-
self.options.descending = false;
101-
self
99+
pub fn asc(self) -> Self {
100+
self.with_descending(false)
102101
}
103102

104103
/// Set the sort sort options to DESC
105-
pub fn desc(mut self) -> Self {
106-
self.options.descending = true;
107-
self
104+
pub fn desc(self) -> Self {
105+
self.with_descending(true)
108106
}
109107

110-
/// Set the sort sort options to NULLS FIRST
111-
pub fn nulls_first(mut self) -> Self {
112-
self.options.nulls_first = true;
108+
/// set the sort options `descending` flag
109+
pub fn with_descending(mut self, descending: bool) -> Self {
110+
self.options.descending = descending;
113111
self
114112
}
115113

116-
/// Set the sort sort options to NULLS LAST
117-
pub fn nulls_last(mut self) -> Self {
118-
self.options.nulls_first = false;
114+
/// Set the sort options to NULLS FIRST
115+
pub fn nulls_first(self) -> Self {
116+
self.with_nulls_first(true)
117+
}
118+
119+
/// Set the sort options to NULLS LAST
120+
pub fn nulls_last(self) -> Self {
121+
self.with_nulls_first(false)
122+
}
123+
124+
/// set the sort options `nulls_first` flag
125+
pub fn with_nulls_first(mut self, nulls_first: bool) -> Self {
126+
self.options.nulls_first = nulls_first;
119127
self
120128
}
129+
130+
/// return the underlying PhysicalExpr
131+
pub fn expr(&self) -> &Arc<dyn PhysicalExpr> {
132+
&self.expr
133+
}
134+
}
135+
136+
/// Access the PhysicalSortExpr as a PhysicalExpr
137+
impl AsRef<dyn PhysicalExpr> for PhysicalSortExpr {
138+
fn as_ref(&self) -> &(dyn PhysicalExpr + 'static) {
139+
self.expr.as_ref()
140+
}
121141
}
122142

123143
impl PartialEq for PhysicalSortExpr {

datafusion/physical-expr/src/equivalence/class.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use datafusion_common::tree_node::{Transformed, TransformedResult, TreeNode};
3030
use datafusion_common::JoinType;
3131
use datafusion_physical_expr_common::physical_expr::format_physical_expr_list;
3232

33-
#[derive(Debug, Clone)]
3433
/// A structure representing a expression known to be constant in a physical execution plan.
3534
///
3635
/// The `ConstExpr` struct encapsulates an expression that is constant during the execution
@@ -41,9 +40,10 @@ use datafusion_physical_expr_common::physical_expr::format_physical_expr_list;
4140
///
4241
/// - `expr`: Constant expression for a node in the physical plan.
4342
///
44-
/// - `across_partitions`: A boolean flag indicating whether the constant expression is
45-
/// valid across partitions. If set to `true`, the constant expression has same value for all partitions.
46-
/// If set to `false`, the constant expression may have different values for different partitions.
43+
/// - `across_partitions`: A boolean flag indicating whether the constant
44+
/// expression is the same across partitions. If set to `true`, the constant
45+
/// expression has same value for all partitions. If set to `false`, the
46+
/// constant expression may have different values for different partitions.
4747
///
4848
/// # Example
4949
///
@@ -56,11 +56,22 @@ use datafusion_physical_expr_common::physical_expr::format_physical_expr_list;
5656
/// // create a constant expression from a physical expression
5757
/// let const_expr = ConstExpr::from(col);
5858
/// ```
59+
#[derive(Debug, Clone)]
5960
pub struct ConstExpr {
61+
/// The expression that is known to be constant (e.g. a `Column`)
6062
expr: Arc<dyn PhysicalExpr>,
63+
/// Does the constant have the same value across all partitions? See
64+
/// struct docs for more details
6165
across_partitions: bool,
6266
}
6367

68+
impl PartialEq for ConstExpr {
69+
fn eq(&self, other: &Self) -> bool {
70+
self.across_partitions == other.across_partitions
71+
&& self.expr.eq(other.expr.as_any())
72+
}
73+
}
74+
6475
impl ConstExpr {
6576
/// Create a new constant expression from a physical expression.
6677
///
@@ -74,11 +85,17 @@ impl ConstExpr {
7485
}
7586
}
7687

88+
/// Set the `across_partitions` flag
89+
///
90+
/// See struct docs for more details
7791
pub fn with_across_partitions(mut self, across_partitions: bool) -> Self {
7892
self.across_partitions = across_partitions;
7993
self
8094
}
8195

96+
/// Is the expression the same across all partitions?
97+
///
98+
/// See struct docs for more details
8299
pub fn across_partitions(&self) -> bool {
83100
self.across_partitions
84101
}
@@ -101,6 +118,31 @@ impl ConstExpr {
101118
across_partitions: self.across_partitions,
102119
})
103120
}
121+
122+
/// Returns true if this constant expression is equal to the given expression
123+
pub fn eq_expr(&self, other: impl AsRef<dyn PhysicalExpr>) -> bool {
124+
self.expr.eq(other.as_ref().as_any())
125+
}
126+
127+
/// Returns a [`Display`]able list of `ConstExpr`.
128+
pub fn format_list(input: &[ConstExpr]) -> impl Display + '_ {
129+
struct DisplayableList<'a>(&'a [ConstExpr]);
130+
impl<'a> Display for DisplayableList<'a> {
131+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
132+
let mut first = true;
133+
for const_expr in self.0 {
134+
if first {
135+
first = false;
136+
} else {
137+
write!(f, ",")?;
138+
}
139+
write!(f, "{}", const_expr)?;
140+
}
141+
Ok(())
142+
}
143+
}
144+
DisplayableList(input)
145+
}
104146
}
105147

106148
/// Display implementation for `ConstExpr`

0 commit comments

Comments
 (0)