You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: let extension bundles declare tables and table functions
`SessionExtensionComponents` gains `udtfs` and `table_providers`, both as
`(name, value)` pairs. Neither carries a name of its own the way a scalar
function's capsule does, and both getters take the session — which is what
makes them different from everything the stack has added so far.
Because they take the session, the host resolves them against the handle
carrying the completed codec chains rather than against the context the
components hook received. A bundle wrapping one itself would bind it to a chain
missing every library in the call, including its own, and the failure would not
surface until a decode somewhere else. So a bundle hands over the unwrapped
value and lets the host wrap it. `RecordingTableFunction` in the example crate
records the codec ids it was handed, which turns that claim into an assertion
rather than a paragraph.
Tables do not shadow. DataFusion refuses a duplicate table registration rather
than replacing it, so a declared name already on the session is an error too,
not just one two bundles both claim. Both are caught while resolving, alongside
resolving the destination schema, so a bad name costs nothing.
`_resolve_extension_tables` and `_install_extension_tables` keep the same split
as the rules, with one honest exception: the insert goes through a
`SchemaProvider`, and a foreign one can still refuse what it reported as free.
Tables are therefore committed first, so nothing else has been written when
that happens. The guide says so rather than claiming a guarantee that does not
hold.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/source/extension-guide/functions.md
+13-1Lines changed: 13 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,7 @@ the same registration methods.
31
31
|`__datafusion_scalar_udf__`| scalar function | {py:func}`datafusion.udf`| {py:meth}`~datafusion.SessionContext.register_udf`|`udfs`|
32
32
|`__datafusion_aggregate_udf__`| aggregate function | {py:func}`datafusion.udaf`| {py:meth}`~datafusion.SessionContext.register_udaf`|`udafs`|
33
33
|`__datafusion_window_udf__`| window function | {py:func}`datafusion.udwf`| {py:meth}`~datafusion.SessionContext.register_udwf`|`udwfs`|
34
-
|`__datafusion_table_function__`| function returning a table | {py:func}`datafusion.udtf`| {py:meth}`~datafusion.SessionContext.register_udtf`|—|
34
+
|`__datafusion_table_function__`| function returning a table | {py:func}`datafusion.udtf`| {py:meth}`~datafusion.SessionContext.register_udtf`|`udtfs`, as `(name, func)`|
35
35
36
36
All four are implemented in [`datafusion-ffi-example`], one per file. The last
37
37
column is the {py:class}`~datafusion.SessionExtensionComponents` field a
@@ -128,6 +128,18 @@ Only literal expressions are supported as arguments. The Python side is
0 commit comments