@@ -233,6 +233,29 @@ def test_simple_date_filter(self):
233233 # With maintain_order="left", row order should be preserved
234234 assert_frame_equal (result , expected )
235235
236+ def test_dt_date_filter_prunes_datetime_source (self ):
237+ """A ``.dt.date()`` window on a Datetime source prunes upstream (no full scan) and stays correct.
238+
239+ ``.dt.date()`` floors to day granularity (order-preserving, like ``cast(pl.Date)``), so the temporal range
240+ must still be extracted and pushed down rather than collapsing to the universe interval.
241+ """
242+ ts = [datetime (2024 , 1 , 1 ) + timedelta (days = i ) for i in range (90 )]
243+ df = pl .DataFrame ({"ts" : ts , "val" : list (range (90 ))})
244+ tracker = PredicateTracker (df )
245+
246+ lf = multi_source (
247+ sources = {"data" : (tracker .lazy_frame , {"ts" : FilterSpec ()})},
248+ combine = lambda s : s ["data" ],
249+ )
250+
251+ start , end = date (2024 , 1 , 1 ), date (2024 , 1 , 31 )
252+ result = lf .filter ((pl .col ("ts" ).dt .date () >= start ) & (pl .col ("ts" ).dt .date () <= end )).collect ()
253+
254+ # Range was extracted, so the source received a constraining predicate (not a silent full scan).
255+ assert tracker .last_predicate is not None
256+ assert result .height == 31
257+ assert result ["ts" ].max () == datetime (2024 , 1 , 31 )
258+
236259 def test_simple_equality_filter (self ):
237260 """Equality filter propagates correctly."""
238261 left = pl .LazyFrame ({"id" : ["A" , "B" , "C" ], "val" : [1 , 2 , 3 ]})
0 commit comments