Skip to content

Commit 244b3fb

Browse files
authored
fix(rust, python); fix projection pushdown in asof joins (#5542)
1 parent 9377116 commit 244b3fb

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

polars/polars-core/src/frame/asof_join/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
1111
use crate::prelude::*;
1212
use crate::utils::slice_slice;
1313

14-
#[derive(Clone, Debug, PartialEq, Eq)]
14+
#[derive(Clone, Debug, PartialEq, Eq, Default)]
1515
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1616
pub struct AsOfOptions {
1717
pub strategy: AsofStrategy,
@@ -51,6 +51,12 @@ pub enum AsofStrategy {
5151
Forward,
5252
}
5353

54+
impl Default for AsofStrategy {
55+
fn default() -> Self {
56+
AsofStrategy::Backward
57+
}
58+
}
59+
5460
impl<T> ChunkedArray<T>
5561
where
5662
T: PolarsNumericType,

polars/polars-lazy/polars-plan/src/logical_plan/optimizer/projection_pushdown.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,24 @@ impl ProjectionPushDown {
913913
for proj in acc_projections {
914914
let mut add_local = true;
915915

916+
// Asof joins don't replace
917+
// the right column name with the left one
918+
// so the two join columns remain
919+
#[cfg(feature = "asof_join")]
920+
if matches!(options.how, JoinType::AsOf(_)) {
921+
let names = aexpr_to_leaf_names(proj, expr_arena);
922+
if names.len() == 1
923+
// we only add to local projection
924+
// if the right join column differs from the left
925+
&& names_right.contains(&names[0])
926+
&& !names_left.contains(&names[0])
927+
&& !local_projection.contains(&proj)
928+
{
929+
local_projection.push(proj);
930+
continue;
931+
}
932+
}
933+
916934
// if it is an alias we want to project the root column name downwards
917935
// but we don't want to project it a this level, otherwise we project both
918936
// the root and the alias, hence add_local = false.

py-polars/tests/unit/test_joins.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,3 +670,28 @@ def test_streaming_joins() -> None:
670670
# we cast to integer because pandas joins creates floats
671671
a = pl.from_pandas(pd_result).with_column(pl.all().cast(int)).sort(["a", "b"])
672672
pl.testing.assert_frame_equal(a, pl_result, check_dtype=False)
673+
674+
675+
def test_join_asof_projection() -> None:
676+
df1 = pl.DataFrame(
677+
{
678+
"df1_date": [20221011, 20221012, 20221013, 20221014, 20221016],
679+
"df1_col1": ["foo", "bar", "foo", "bar", "foo"],
680+
}
681+
)
682+
683+
df2 = pl.DataFrame(
684+
{
685+
"df2_date": [20221012, 20221015, 20221018],
686+
"df2_col1": ["1", "2", "3"],
687+
}
688+
)
689+
690+
assert (
691+
(
692+
df1.lazy().join_asof(df2.lazy(), left_on="df1_date", right_on="df2_date")
693+
).select([pl.col("df2_date"), "df1_date"])
694+
).collect().to_dict(False) == {
695+
"df2_date": [None, 20221012, 20221012, 20221012, 20221015],
696+
"df1_date": [20221011, 20221012, 20221013, 20221014, 20221016],
697+
}

0 commit comments

Comments
 (0)