Skip to content

Commit 18f33da

Browse files
committed
Add cardinality_effect regression tests for union and window execs
1 parent 7f63d43 commit 18f33da

3 files changed

Lines changed: 86 additions & 0 deletions

File tree

datafusion/physical-plan/src/union.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ impl ExecutionPlan for UnionExec {
344344
}
345345

346346
fn cardinality_effect(&self) -> CardinalityEffect {
347+
// Union combines rows from multiple inputs, so output rows are not tied
348+
// to any single input and can only be constrained as greater-or-equal.
347349
CardinalityEffect::GreaterEqual
348350
}
349351

@@ -1182,4 +1184,25 @@ mod tests {
11821184
)
11831185
);
11841186
}
1187+
1188+
#[test]
1189+
fn test_union_cardinality_effect() -> Result<()> {
1190+
let schema = create_test_schema()?;
1191+
let input1: Arc<dyn ExecutionPlan> =
1192+
Arc::new(TestMemoryExec::try_new(&[], Arc::clone(&schema), None)?);
1193+
let input2: Arc<dyn ExecutionPlan> =
1194+
Arc::new(TestMemoryExec::try_new(&[], Arc::clone(&schema), None)?);
1195+
1196+
let union = UnionExec::try_new(vec![input1, input2])?;
1197+
let union = union
1198+
.as_any()
1199+
.downcast_ref::<UnionExec>()
1200+
.expect("expected UnionExec for multiple inputs");
1201+
1202+
assert!(matches!(
1203+
union.cardinality_effect(),
1204+
CardinalityEffect::GreaterEqual
1205+
));
1206+
Ok(())
1207+
}
11851208
}

datafusion/physical-plan/src/windows/bounded_window_agg_exec.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,7 @@ mod tests {
12491249
use std::time::Duration;
12501250

12511251
use crate::common::collect;
1252+
use crate::execution_plan::CardinalityEffect;
12521253
use crate::expressions::PhysicalSortExpr;
12531254
use crate::projection::{ProjectionExec, ProjectionExpr};
12541255
use crate::streaming::{PartitionStream, StreamingTableExec};
@@ -1833,4 +1834,22 @@ mod tests {
18331834

18341835
Ok(())
18351836
}
1837+
1838+
#[test]
1839+
fn test_bounded_window_agg_cardinality_effect() -> Result<()> {
1840+
let schema = test_schema();
1841+
let input: Arc<dyn ExecutionPlan> =
1842+
Arc::new(TestMemoryExec::try_new(&[], Arc::clone(&schema), None)?);
1843+
let plan = bounded_window_exec_pb_latent_range(input, 1, "hash", "sn")?;
1844+
let plan = plan
1845+
.as_any()
1846+
.downcast_ref::<BoundedWindowAggExec>()
1847+
.expect("expected BoundedWindowAggExec");
1848+
1849+
assert!(matches!(
1850+
plan.cardinality_effect(),
1851+
CardinalityEffect::Equal
1852+
));
1853+
Ok(())
1854+
}
18361855
}

datafusion/physical-plan/src/windows/window_agg_exec.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,3 +446,47 @@ impl RecordBatchStream for WindowAggStream {
446446
Arc::clone(&self.schema)
447447
}
448448
}
449+
450+
#[cfg(test)]
451+
mod tests {
452+
use super::*;
453+
use crate::test::TestMemoryExec;
454+
use crate::windows::create_window_expr;
455+
use arrow::datatypes::{DataType, Field, Schema};
456+
use datafusion_common::ScalarValue;
457+
use datafusion_expr::{
458+
WindowFrame, WindowFrameBound, WindowFrameUnits, WindowFunctionDefinition,
459+
};
460+
use datafusion_functions_aggregate::count::count_udaf;
461+
462+
#[test]
463+
fn test_window_agg_cardinality_effect() -> Result<()> {
464+
let schema = Arc::new(Schema::new(vec![Field::new("a", DataType::Int64, true)]));
465+
let input: Arc<dyn ExecutionPlan> =
466+
Arc::new(TestMemoryExec::try_new(&[], Arc::clone(&schema), None)?);
467+
let args = vec![crate::expressions::col("a", &schema)?];
468+
let window_expr = create_window_expr(
469+
&WindowFunctionDefinition::AggregateUDF(count_udaf()),
470+
"count(a)".to_string(),
471+
&args,
472+
&[],
473+
&[],
474+
Arc::new(WindowFrame::new_bounds(
475+
WindowFrameUnits::Rows,
476+
WindowFrameBound::Preceding(ScalarValue::UInt64(None)),
477+
WindowFrameBound::CurrentRow,
478+
)),
479+
Arc::clone(&schema),
480+
false,
481+
false,
482+
None,
483+
)?;
484+
485+
let window = WindowAggExec::try_new(vec![window_expr], input, true)?;
486+
assert!(matches!(
487+
window.cardinality_effect(),
488+
CardinalityEffect::Equal
489+
));
490+
Ok(())
491+
}
492+
}

0 commit comments

Comments
 (0)