Skip to content

Commit 7ba0a9b

Browse files
committed
test: cover unsorted contiguous groups in one partition
1 parent 714956b commit 7ba0a9b

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

  • datafusion/physical-plan/src/aggregates

‎datafusion/physical-plan/src/aggregates/mod.rs‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5438,6 +5438,83 @@ mod tests {
54385438
Ok(())
54395439
}
54405440

5441+
#[tokio::test]
5442+
async fn unsorted_contiguous_groups_use_final_emission() -> Result<()> {
5443+
let schema = Arc::new(Schema::new(vec![
5444+
Field::new("key", DataType::Int32, false),
5445+
Field::new("time_bin", DataType::Int64, false),
5446+
Field::new("value", DataType::Int64, false),
5447+
]));
5448+
// Two sorted logical runs are emitted as batches in one DataFusion
5449+
// partition. Every distinct grouping tuple occupies one contiguous range,
5450+
// but tuple order resets at the batch boundary, so (key, time_bin) is not
5451+
// globally sorted.
5452+
let input_batches = vec![
5453+
RecordBatch::try_new(
5454+
Arc::clone(&schema),
5455+
vec![
5456+
Arc::new(Int32Array::from(vec![1, 1, 2, 2])),
5457+
Arc::new(Int64Array::from(vec![20, 20, 20, 20])),
5458+
Arc::new(Int64Array::from(vec![10, 20, 30, 40])),
5459+
],
5460+
)?,
5461+
RecordBatch::try_new(
5462+
Arc::clone(&schema),
5463+
vec![
5464+
Arc::new(Int32Array::from(vec![1, 1, 2, 2])),
5465+
Arc::new(Int64Array::from(vec![0, 0, 0, 0])),
5466+
Arc::new(Int64Array::from(vec![50, 60, 70, 80])),
5467+
],
5468+
)?,
5469+
];
5470+
let group_by = PhysicalGroupBy::new_single(vec![
5471+
(col("key", &schema)?, "key".to_string()),
5472+
(col("time_bin", &schema)?, "time_bin".to_string()),
5473+
]);
5474+
let aggr_expr = Arc::new(
5475+
AggregateExprBuilder::new(sum_udaf(), vec![col("value", &schema)?])
5476+
.schema(Arc::clone(&schema))
5477+
.alias("SUM(value)")
5478+
.build()?,
5479+
);
5480+
let input: Arc<dyn ExecutionPlan> =
5481+
TestMemoryExec::try_new_exec(&[input_batches], Arc::clone(&schema), None)?;
5482+
assert_eq!(input.output_partitioning().partition_count(), 1);
5483+
5484+
let aggregate = AggregateExec::try_new(
5485+
AggregateMode::Single,
5486+
group_by,
5487+
vec![aggr_expr],
5488+
vec![None],
5489+
input,
5490+
schema,
5491+
)?;
5492+
5493+
assert_eq!(aggregate.input_order_mode(), &InputOrderMode::Linear);
5494+
// This captures the behavior before #24438. When the source can declare
5495+
// `(key, time_bin)` group-contiguous, the corresponding case can use
5496+
// `EmissionType::Incremental`.
5497+
assert_eq!(aggregate.cache().emission_type, EmissionType::Final);
5498+
5499+
let task_ctx = new_migrated_hash_ctx(1024);
5500+
let stream = aggregate.execute_typed(0, &task_ctx)?;
5501+
assert!(matches!(stream, StreamType::SingleHash(_)));
5502+
let stream: SendableRecordBatchStream = stream.into();
5503+
let output = collect(stream).await?;
5504+
assert_snapshot!(batches_to_sort_string(&output), @r"
5505+
+-----+----------+------------+
5506+
| key | time_bin | SUM(value) |
5507+
+-----+----------+------------+
5508+
| 1 | 0 | 110 |
5509+
| 1 | 20 | 30 |
5510+
| 2 | 0 | 150 |
5511+
| 2 | 20 | 70 |
5512+
+-----+----------+------------+
5513+
");
5514+
5515+
Ok(())
5516+
}
5517+
54415518
/// Ensures for ordered input, `OrderedPartialAggregateStream` is used.
54425519
#[tokio::test]
54435520
async fn ordered_partial_aggregate_planning() -> Result<()> {

0 commit comments

Comments
 (0)