Skip to content

Commit 725fa74

Browse files
timsaucerclaude
andcommitted
Test planner rebinding and codec precedence in with_extensions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent fe05351 commit 725fa74

1 file changed

Lines changed: 39 additions & 0 deletions

File tree

examples/datafusion-ffi-query-planner-example/python/tests/_test_three_library_query_planner.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,45 @@ def __datafusion_session_extension__(
286286
assert batches[0].column(0).to_pylist() == [0, 1, 2, 3, 4, 5]
287287

288288

289+
def test_with_extensions_rebinds_existing_planner():
290+
"""Codec-only bundles installed on a context that already has an FFI
291+
planner rebind that planner to the new codec chains."""
292+
config = SessionConfig().with_extension(PlannerConfig(max_rows=2))
293+
planner = MyQueryPlanner()
294+
ctx = SessionContext(config).with_query_planner(planner)
295+
provider_ext = ProviderCodecsExtension()
296+
ctx = ctx.with_extensions(provider_ext)
297+
ctx.register_table("numbers", MyTableProvider(1, 6, 1))
298+
299+
batches = ctx.sql('SELECT "A" FROM numbers ORDER BY "A"').collect()
300+
assert batches[0].column(0).to_pylist() == [0, 1]
301+
assert planner.last_max_rows() == 2
302+
# The planner only sees these codecs if it was rebound to the chains
303+
# built during with_extensions.
304+
assert provider_ext.logical_codec.table_provider_decode_calls() > 0
305+
assert provider_ext.physical_codec.execution_plan_decode_calls() > 0
306+
307+
308+
def test_with_extensions_codec_precedence():
309+
"""Extensions are processed left to right and prepend to the codec
310+
chain, so codecs from later extensions are consulted first. Both
311+
bundles' codecs can handle the payload (they share the provider
312+
library's token registry); only the one consulted first is used."""
313+
config = SessionConfig().with_extension(PlannerConfig(max_rows=2))
314+
ext_a = ProviderCodecsExtension()
315+
ext_b = ProviderCodecsExtension()
316+
ctx = SessionContext(config).with_extensions(ext_a, ext_b, MyPlannerExtension())
317+
ctx.register_table("numbers", MyTableProvider(1, 6, 1))
318+
319+
batches = ctx.sql('SELECT "A" FROM numbers ORDER BY "A"').collect()
320+
assert batches[0].column(0).to_pylist() == [0, 1]
321+
322+
assert ext_b.logical_codec.table_provider_encode_calls() > 0
323+
assert ext_b.logical_codec.table_provider_decode_calls() > 0
324+
assert ext_a.logical_codec.table_provider_encode_calls() == 0
325+
assert ext_a.logical_codec.table_provider_decode_calls() == 0
326+
327+
289328
def test_dataframe_outliving_context_fails_cleanly():
290329
"""A DataFrame does not keep its SessionContext alive. FFI components
291330
resolve the task context through a weak reference, so using the

0 commit comments

Comments
 (0)