Skip to content

Commit 36969e7

Browse files
committed
test: cover unsorted contiguous groups in one partition
1 parent ebdb657 commit 36969e7

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
@@ -5530,6 +5530,83 @@ mod tests {
55305530
Ok(())
55315531
}
55325532

5533+
#[tokio::test]
5534+
async fn unsorted_contiguous_groups_use_final_emission() -> Result<()> {
5535+
let schema = Arc::new(Schema::new(vec![
5536+
Field::new("key", DataType::Int32, false),
5537+
Field::new("time_bin", DataType::Int64, false),
5538+
Field::new("value", DataType::Int64, false),
5539+
]));
5540+
// Two sorted logical runs are emitted as batches in one DataFusion
5541+
// partition. Every distinct grouping tuple occupies one contiguous range,
5542+
// but tuple order resets at the batch boundary, so (key, time_bin) is not
5543+
// globally sorted.
5544+
let input_batches = vec![
5545+
RecordBatch::try_new(
5546+
Arc::clone(&schema),
5547+
vec![
5548+
Arc::new(Int32Array::from(vec![1, 1, 2, 2])),
5549+
Arc::new(Int64Array::from(vec![20, 20, 20, 20])),
5550+
Arc::new(Int64Array::from(vec![10, 20, 30, 40])),
5551+
],
5552+
)?,
5553+
RecordBatch::try_new(
5554+
Arc::clone(&schema),
5555+
vec![
5556+
Arc::new(Int32Array::from(vec![1, 1, 2, 2])),
5557+
Arc::new(Int64Array::from(vec![0, 0, 0, 0])),
5558+
Arc::new(Int64Array::from(vec![50, 60, 70, 80])),
5559+
],
5560+
)?,
5561+
];
5562+
let group_by = PhysicalGroupBy::new_single(vec![
5563+
(col("key", &schema)?, "key".to_string()),
5564+
(col("time_bin", &schema)?, "time_bin".to_string()),
5565+
]);
5566+
let aggr_expr = Arc::new(
5567+
AggregateExprBuilder::new(sum_udaf(), vec![col("value", &schema)?])
5568+
.schema(Arc::clone(&schema))
5569+
.alias("SUM(value)")
5570+
.build()?,
5571+
);
5572+
let input: Arc<dyn ExecutionPlan> =
5573+
TestMemoryExec::try_new_exec(&[input_batches], Arc::clone(&schema), None)?;
5574+
assert_eq!(input.output_partitioning().partition_count(), 1);
5575+
5576+
let aggregate = AggregateExec::try_new(
5577+
AggregateMode::Single,
5578+
group_by,
5579+
vec![aggr_expr],
5580+
vec![None],
5581+
input,
5582+
schema,
5583+
)?;
5584+
5585+
assert_eq!(aggregate.input_order_mode(), &InputOrderMode::Linear);
5586+
// This captures the behavior before #24438. When the source can declare
5587+
// `(key, time_bin)` group-contiguous, the corresponding case can use
5588+
// `EmissionType::Incremental`.
5589+
assert_eq!(aggregate.cache().emission_type, EmissionType::Final);
5590+
5591+
let task_ctx = new_migrated_hash_ctx(1024);
5592+
let stream = aggregate.execute_typed(0, &task_ctx)?;
5593+
assert!(matches!(stream, StreamType::SingleHash(_)));
5594+
let stream: SendableRecordBatchStream = stream.into();
5595+
let output = collect(stream).await?;
5596+
assert_snapshot!(batches_to_sort_string(&output), @r"
5597+
+-----+----------+------------+
5598+
| key | time_bin | SUM(value) |
5599+
+-----+----------+------------+
5600+
| 1 | 0 | 110 |
5601+
| 1 | 20 | 30 |
5602+
| 2 | 0 | 150 |
5603+
| 2 | 20 | 70 |
5604+
+-----+----------+------------+
5605+
");
5606+
5607+
Ok(())
5608+
}
5609+
55335610
/// Ensures for ordered input, `OrderedPartialAggregateStream` is used.
55345611
#[tokio::test]
55355612
async fn ordered_partial_aggregate_planning() -> Result<()> {

0 commit comments

Comments
 (0)