Skip to content

Commit 2642d4d

Browse files
Support co-partitioned range inner equi joins
1 parent 6a0e76e commit 2642d4d

16 files changed

Lines changed: 1018 additions & 380 deletions

File tree

datafusion/core/tests/physical_optimizer/sanity_checker.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use insta::assert_snapshot;
1919
use std::sync::Arc;
2020

2121
use crate::physical_optimizer::test_utils::{
22-
bounded_window_exec, global_limit_exec, local_limit_exec, memory_exec,
23-
projection_exec, repartition_exec, sort_exec, sort_expr, sort_expr_options,
24-
sort_merge_join_exec, sort_preserving_merge_exec, union_exec,
22+
bounded_window_exec, global_limit_exec, hash_join_exec, local_limit_exec,
23+
memory_exec, projection_exec, repartition_exec, sort_exec, sort_expr,
24+
sort_expr_options, sort_merge_join_exec, sort_preserving_merge_exec, union_exec,
2525
};
2626

2727
use arrow::compute::SortOptions;
@@ -30,8 +30,8 @@ use datafusion::datasource::stream::{FileStreamProvider, StreamConfig, StreamTab
3030
use datafusion::prelude::{CsvReadOptions, SessionContext};
3131
use datafusion_common::config::ConfigOptions;
3232
use datafusion_common::{JoinType, Result, ScalarValue};
33-
use datafusion_physical_expr::Partitioning;
3433
use datafusion_physical_expr::expressions::{Literal, col};
34+
use datafusion_physical_expr::{Partitioning, RangePartitioning, SplitPoint};
3535
use datafusion_physical_expr_common::sort_expr::LexOrdering;
3636
use datafusion_physical_optimizer::PhysicalOptimizerRule;
3737
use datafusion_physical_optimizer::sanity_checker::SanityCheckPlan;
@@ -400,6 +400,50 @@ fn assert_sanity_check(plan: &Arc<dyn ExecutionPlan>, is_sane: bool) {
400400
);
401401
}
402402

403+
fn range_partitioned_exec(
404+
schema: &SchemaRef,
405+
key: &str,
406+
split_points: impl IntoIterator<Item = i32>,
407+
) -> Result<Arc<dyn ExecutionPlan>> {
408+
let split_points = split_points
409+
.into_iter()
410+
.map(|value| SplitPoint::new(vec![ScalarValue::Int32(Some(value))]))
411+
.collect();
412+
let partitioning = Partitioning::Range(RangePartitioning::try_new(
413+
[sort_expr(key, schema)].into(),
414+
split_points,
415+
)?);
416+
RepartitionExec::try_new(memory_exec(schema), partitioning)
417+
.map(|exec| Arc::new(exec) as Arc<dyn ExecutionPlan>)
418+
}
419+
420+
#[test]
421+
fn test_partitioned_hash_join_requires_co_partitioned_children() -> Result<()> {
422+
let schema = create_test_schema2();
423+
let join_on = vec![(col("a", &schema)?, col("b", &schema)?)];
424+
let right = range_partitioned_exec(&schema, "b", [10])?;
425+
426+
let valid_join = hash_join_exec(
427+
range_partitioned_exec(&schema, "a", [10])?,
428+
Arc::clone(&right),
429+
join_on.clone(),
430+
None,
431+
&JoinType::Inner,
432+
)?;
433+
assert_sanity_check(&valid_join, true);
434+
435+
let invalid_join = hash_join_exec(
436+
range_partitioned_exec(&schema, "a", [20])?,
437+
right,
438+
join_on,
439+
None,
440+
&JoinType::Inner,
441+
)?;
442+
assert_sanity_check(&invalid_join, false);
443+
444+
Ok(())
445+
}
446+
403447
#[tokio::test]
404448
/// Tests that plan is valid when the sort requirements are satisfied.
405449
async fn test_bounded_window_agg_sort_requirement() -> Result<()> {

0 commit comments

Comments
 (0)