Optimizer rules and configuration#

Two hooks contribute things that are neither data nor functions: a rewrite pass over physical plans, and typed entries in the session config. Both take no argument and both are implemented in datafusion-ffi-example.

A physical optimizer rule#

__datafusion_physical_optimizer_rule__ contributes a rule that rewrites physical plans, installed with add_physical_optimizer_rule(). Reach for this rather than a query planner when you want to adjust the plan DataFusion produced rather than produce it yourself — it is much the smaller commitment, and rules accumulate where planners nest.

fn __datafusion_physical_optimizer_rule__<'py>(
    &self,
    py: Python<'py>,
) -> PyResult<Bound<'py, PyCapsule>> {
    let rule: Arc<dyn PhysicalOptimizerRule + Send + Sync> = Arc::new(self.clone());
    let runtime = get_tokio_runtime().handle().clone();
    let ffi = FFI_PhysicalOptimizerRule::new(rule, Some(runtime));

    PyCapsule::new_with_value(py, ffi, cr"datafusion_physical_optimizer_rule")
}

Typed configuration#

__datafusion_extension_options__ contributes typed configuration entries that your components can read back out of the session config, installed with SessionConfig.with_extension. FFI_ExtensionOptions carries no version field, so it is one of the three components that cannot be version-checked on import.

fn __datafusion_extension_options__<'py>(
    &self,
    py: Python<'py>,
) -> PyResult<Bound<'py, PyCapsule>> {
    let mut config = FFI_ExtensionOptions::default();
    config
        .add_config(self)
        .map_err(|e| PyRuntimeError::new_err(e.to_string()))?;

    PyCapsule::new_with_value(py, config, cr"datafusion_extension_options")
}