Skip to content

Commit a3cac01

Browse files
authored
Merge branch 'main' into fix/exact-hash-table-accounting-primitive
2 parents 3a4d084 + 1fa378d commit a3cac01

9 files changed

Lines changed: 700 additions & 121 deletions

File tree

‎datafusion/core/tests/sql/joins.rs‎

Lines changed: 1 addition & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -521,33 +521,6 @@ async fn asof_join_all_match_directions_across_batches() -> Result<()> {
521521
Ok(())
522522
}
523523

524-
#[tokio::test]
525-
async fn asof_join_coerces_equality_and_match_types() -> Result<()> {
526-
let ctx = SessionContext::new();
527-
let batches = ctx
528-
.sql(
529-
"SELECT t.id, p.price \
530-
FROM (VALUES (CAST(1 AS INT), CAST(4 AS INT), 7)) t(k, ts, id) \
531-
ASOF JOIN \
532-
(VALUES (CAST(1 AS BIGINT), CAST(2 AS BIGINT), 20)) p(k, ts, price) \
533-
MATCH_CONDITION (t.ts >= p.ts) ON t.k = p.k",
534-
)
535-
.await?
536-
.collect()
537-
.await?;
538-
assert_batches_eq!(
539-
[
540-
"+----+-------+",
541-
"| id | price |",
542-
"+----+-------+",
543-
"| 7 | 20 |",
544-
"+----+-------+",
545-
],
546-
&batches
547-
);
548-
Ok(())
549-
}
550-
551524
#[tokio::test]
552525
async fn asof_join_broadcasts_multi_partition_right_input() -> Result<()> {
553526
let config = SessionConfig::new().with_target_partitions(4);
@@ -639,28 +612,6 @@ async fn asof_join_projection_drops_output_ordering() -> Result<()> {
639612
Ok(())
640613
}
641614

642-
#[tokio::test]
643-
async fn asof_join_explain_names_equality_and_match_conditions() -> Result<()> {
644-
let ctx = SessionContext::new();
645-
register_asof_test_tables(&ctx)?;
646-
let batches = ctx
647-
.sql(
648-
"EXPLAIN SELECT t.trade_id, p.price FROM trades t \
649-
ASOF JOIN prices p MATCH_CONDITION (t.ts >= p.ts) \
650-
ON t.symbol = p.symbol",
651-
)
652-
.await?
653-
.collect()
654-
.await?;
655-
let explain = arrow::util::pretty::pretty_format_batches(&batches)?.to_string();
656-
assert_contains!(explain.as_str(), "AsOf Join: match=[t.ts >= p.ts]");
657-
assert_contains!(explain.as_str(), "on=[t.symbol = p.symbol]");
658-
assert_contains!(explain.as_str(), "AsOfJoinExec:");
659-
assert_contains!(explain.as_str(), "on=[(symbol = symbol)]");
660-
assert_contains!(explain.as_str(), "match=[ts >= ts]");
661-
Ok(())
662-
}
663-
664615
#[tokio::test]
665616
async fn asof_join_rejects_unbounded_inputs_during_physical_planning() -> Result<()> {
666617
let ctx = SessionContext::new();
@@ -698,7 +649,7 @@ async fn asof_join_rejects_unbounded_inputs_during_physical_planning() -> Result
698649
}
699650

700651
#[tokio::test]
701-
async fn asof_join_using_preserves_key_access_and_unparser_round_trips() -> Result<()> {
652+
async fn asof_join_using_unparser_round_trips() -> Result<()> {
702653
let ctx = SessionContext::new();
703654
register_asof_test_tables(&ctx)?;
704655
let df = ctx
@@ -707,45 +658,11 @@ async fn asof_join_using_preserves_key_access_and_unparser_round_trips() -> Resu
707658
MATCH_CONDITION (t.ts >= p.ts) USING (symbol)",
708659
)
709660
.await?;
710-
assert_eq!(
711-
df.schema()
712-
.fields()
713-
.iter()
714-
.map(|field| field.name())
715-
.collect::<Vec<_>>(),
716-
vec!["ts", "trade_id", "symbol", "ts", "price"]
717-
);
718661
let sql = plan_to_sql(df.logical_plan())?.to_string();
719662
assert!(sql.contains("ASOF JOIN"));
720663
assert!(sql.contains("MATCH_CONDITION"));
721664
assert!(sql.contains("USING(symbol)"), "unexpected SQL: {sql}");
722665
ctx.sql(&sql).await?;
723-
724-
let batches = ctx
725-
.sql(
726-
"SELECT t.trade_id, t.symbol AS left_symbol, p.symbol AS right_symbol \
727-
FROM trades t ASOF JOIN prices p \
728-
MATCH_CONDITION (t.ts >= p.ts) USING (symbol) \
729-
ORDER BY t.trade_id",
730-
)
731-
.await?
732-
.collect()
733-
.await?;
734-
assert_batches_eq!(
735-
[
736-
"+----------+-------------+--------------+",
737-
"| trade_id | left_symbol | right_symbol |",
738-
"+----------+-------------+--------------+",
739-
"| 1 | A | |",
740-
"| 2 | A | A |",
741-
"| 3 | A | A |",
742-
"| 4 | B | B |",
743-
"| 5 | B | B |",
744-
"| 6 | | |",
745-
"+----------+-------------+--------------+",
746-
],
747-
&batches
748-
);
749666
Ok(())
750667
}
751668

@@ -784,20 +701,3 @@ async fn asof_join_unparser_preserves_right_preselection() -> Result<()> {
784701
}
785702
Ok(())
786703
}
787-
788-
#[tokio::test]
789-
async fn asof_join_rejects_invalid_contracts() -> Result<()> {
790-
let ctx = SessionContext::new();
791-
register_asof_test_tables(&ctx)?;
792-
for sql in [
793-
"SELECT * FROM trades t ASOF JOIN prices p MATCH_CONDITION (t.ts = p.ts) ON t.symbol = p.symbol",
794-
"SELECT * FROM trades t ASOF JOIN prices p MATCH_CONDITION (p.ts >= t.ts) ON t.symbol = p.symbol",
795-
"SELECT * FROM trades t ASOF JOIN prices p MATCH_CONDITION (t.ts >= p.ts) ON t.symbol > p.symbol",
796-
"SELECT * FROM trades t ASOF JOIN prices p MATCH_CONDITION (1 >= p.ts) ON t.symbol = p.symbol",
797-
"SELECT * FROM trades t ASOF JOIN prices p MATCH_CONDITION (t.ts >= p.ts) ON 1 = 1",
798-
"SELECT * FROM trades t ASOF JOIN prices p MATCH_CONDITION (t.ts >= p.ts AND t.ts > p.ts) ON t.symbol = p.symbol",
799-
] {
800-
assert!(ctx.sql(sql).await.is_err(), "query should fail: {sql}");
801-
}
802-
Ok(())
803-
}

‎datafusion/physical-expr/src/aggregate.rs‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use datafusion_functions_aggregate_common::accumulator::{
6161
};
6262
use datafusion_functions_aggregate_common::order::AggregateOrderSensitivity;
6363
use datafusion_physical_expr_common::physical_expr::PhysicalExpr;
64-
use datafusion_physical_expr_common::sort_expr::PhysicalSortExpr;
64+
use datafusion_physical_expr_common::sort_expr::{LexOrdering, PhysicalSortExpr};
6565

6666
#[derive(Debug, Clone)]
6767
struct AggregateHumanDisplay {
@@ -265,12 +265,18 @@ impl AggregateExprBuilder {
265265
assert_or_internal_err!(!args.is_empty(), "args should not be empty");
266266

267267
// An order-insensitive aggregate ignores its ORDER BY, so drop it here.
268-
// Everything derived from `order_bys` below, such as the ordering fields
269-
// in the aggregate's state, then agrees that there is no ordering.
268+
// Otherwise drop sort keys that repeat an earlier one: a repeated key can
269+
// never break a tie the earlier one left (`ORDER BY b ASC, b DESC` orders
270+
// like `ORDER BY b ASC`), and accumulators build their ordering with
271+
// `LexOrdering`, which drops such repeats. Everything derived from
272+
// `order_bys` below, such as the ordering fields in the aggregate's
273+
// state, then matches the sort keys the accumulators compare.
270274
let order_bys = if fun.order_sensitivity().is_insensitive() {
271275
vec![]
272276
} else {
273-
order_bys
277+
LexOrdering::new(order_bys)
278+
.map(Vec::from)
279+
.unwrap_or_default()
274280
};
275281

276282
let ordering_types = order_bys

0 commit comments

Comments
 (0)