Skip to main content

datafusion-query-builder

A programmatic, injection-safe builder for DataFusion SQL — a typed Rust core with a pyo3-exposed Python API. It replaces hand-rolled f-string / template-literal SQL with a typed, composable surface, while still emitting SQL text (so the SQL stays visible in logs/traces, greppable, and cache-keyable).

Values are escaped by construction, so untrusted input (column values, user filters) is safe to embed. Strings, arrays, and numbers are quoted/encoded for you; an explicit raw(...) escape hatch is the only unescaped path.

Install

pip install datafusion-query-builder

Prebuilt abi3 wheels are published for CPython 3.9+ on macOS (Apple Silicon + Intel) and Linux (x86_64 + aarch64).

Quick start (Python)

from datafusion_query_builder import col, lit, param, raw, when, and_, table
from datafusion_query_builder import functions as f

q = (
    table("records")
    .filter((col("kind") == "span") & col("deployment_environment").is_in(["prod", "staging"]))
    .select(
        f.coalesce(col("service_name"), "(unknown)").alias("service"),
        f.approx_distinct(col("trace_id")).alias("request_count"),
        f.approx_percentile_cont(col("duration"), 0.95).alias("p95"),
    )
    .group_by(col("service_name"))
    .order_by(col("request_count").desc())
    .limit(200)
)
print(q.to_sql())

Bare Python scalars auto-promote to literals (so col("x") == "prod" works), and string/array literals are escaped — values are injection-safe by construction. Reach for raw(...) (a SQL fragment), f.call("name", ...) (any function), or param("name") (a ${name} placeholder) when you step outside the v1 grammar.

A raw(...) fragment must be one complete SQL expression. The builder parses it on its own, drops any comments, and adds brackets where its top-level operator binds looser than the surrounding one, as it does for native expressions. Pass a user-written predicate as raw(predicate), not raw(f"({predicate})"). Text wrapping breaks on a trailing -- comment, and a predicate such as 1=1) OR (1=1 can close the bracket.

The JSONB key-exists operators are first-class: col("attributes").has_key("gen_ai.input.messages") renders attributes ? 'gen_ai.input.messages' — a cheap presence check that never extracts the value (contrast raw("attributes ->> 'k'").is_not_null(), which reads the whole value out just to test it). has_any_key and has_all_keys render ?| / ?&.

CTEs default to leaving materialization up to the engine. Use table("chosen").with_cte("chosen", source, materialized=True) to emit AS MATERIALIZED, or materialized=False to emit AS NOT MATERIALIZED. Omitting the keyword (or passing None) preserves plain AS (...) SQL. These directives require engine support; rendering them does not guarantee that an engine honors them. Rust callers can use with_cte_materialization(name, source, Some(true)); the existing two-argument with_cte method is unchanged.

Architecture

façade types  ──lower.rs──▶  sqlparser::ast  ──Display──▶  SQL text
expr.rs / query.rs / functions.rs        (the only file that names sqlparser::ast)
  • expr.rs, query.rs, functions.rs — span-free, Default-friendly façade enums. Immutable / generative: every method returns a new value.
  • lower.rs — the single boundary to sqlparser::ast. A sqlparser version bump surfaces here and nowhere else.
  • render.rs — to_sql() plus validate() (renders then re-parses to prove well-formedness).
  • python.rs — Expr / Query wrappers, the f.* functions namespace, operator overloading with scalar→literal coercion. Gated behind the python feature.

sqlparser is pinned to the pydantic dollar-brace-0.62.0 fork via [patch.crates-io] — the same parser the DataFusion ecosystem uses, including the ${var} placeholder extension. The crate does not depend on DataFusion itself (only the test oracle does, optionally).

Develop & test

# Rust core (no Python toolchain needed):
cargo test --test core                       # rendering snapshots + regressions
cargo test --features datafusion-oracle --test properties   # property tests, see below
cargo clippy --all-targets --features datafusion-oracle -- -D warnings

# Coercion tests against a real embedded interpreter (needs PYO3_PYTHON -> a 3.9+ interpreter):
PYO3_PYTHON=$PWD/.venv/bin/python cargo test --lib --features test-embed

# Python extension:
uv venv && uvx maturin develop
python tests/test_python.py

How the tests are layered

The crate is correctness-critical (it generates SQL from user-controlled input), so the test surface is layered:

  • tests/properties.rs (proptest, behind datafusion-oracle) uses DataFusion itself as the oracle — it renders a query to SQL, then plans + executes it through real DataFusion and reads the value back. This upgrades "the SQL re-parses" to "the value survives a real engine round-trip", catching silent mis-encoding (escaping, float formatting, operator precedence). DataFusion is an optional, test-only dependency — never compiled into the lib or the wheel. tests/properties.proptest-regressions pins seeds that previously found bugs.
  • src/python.rs coercion_tests (behind test-embed) unit-test the Python-type → façade-literal boundary that can only be exercised with real Python objects (bool-before-int, big ints, non-finite floats, list/tuple). They compose with the property tests: coercion proves "Python value → correct value", the property tests prove "value → correct SQL → correct result".

When a property/coercion test finds a bug, fix it in the crate — that is the whole point of the library: one fix covers every caller.

Release

Wheels are built and published to PyPI by CI (.github/workflows/ci.yml) on a v* tag, using PyPI Trusted Publishing (OIDC) — no API tokens. To cut a release: bump version in Cargo.toml and pyproject.toml, tag vX.Y.Z, and push the tag.

License

MIT

Metadata

Release files for datafusion-query-builder 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for datafusion-query-builder 0.4.0
File Size Uploaded Provenance Actions
datafusion_query_builder-0.4.0.tar.gz 67.1 kB With provenance Details for datafusion_query_builder-0.4.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for datafusion-query-builder 0.4.0
File Interpreter ABI Platform Actions
datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details for datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details for datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
datafusion_query_builder-0.4.0-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for datafusion_query_builder-0.4.0-cp39-abi3-macosx_11_0_arm64.whl

Total release size: 8.8 MB

Release files / datafusion_query_builder-0.4.0.tar.gz

Download URL datafusion_query_builder-0.4.0.tar.gz
Size 67.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d4de06c4bc98be02d9d46fe2083dfa90440f599126bd06f75e1bb01b51336bb4
BLAKE2b-256 checksum
How to use checksums
862c571f41dd50c699179960fdc7887df51bb790c39cfb39b983f90651675535
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.1 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
7ddeee7e9ef3a6c2373e4bf058c695161cdcccc4b8b1755c388371f16dadd813
BLAKE2b-256 checksum
How to use checksums
8097e2b2d33731cec477ffc5e89b8c1d43fd9130d9021db8007ecbbc0dae03c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL datafusion_query_builder-0.4.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.0 MB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
5db22efc03ccd478bf2fd72b72bfe124a88bf6dc3f4e8c81d055560838739edf
BLAKE2b-256 checksum
How to use checksums
b385460d0625acb448e5015da1c585f098ffaa14d4d3ad96ba7832d5ee2378e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / datafusion_query_builder-0.4.0-cp39-abi3-macosx_11_0_arm64.whl

Download URL datafusion_query_builder-0.4.0-cp39-abi3-macosx_11_0_arm64.whl
Size 2.7 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ca30fcac5b17454f95a86b1b6921c26a0a5cdeda88c1648be250c18279eaccf6
BLAKE2b-256 checksum
How to use checksums
6442cc68d689473495ab8cfbef0f6e38c72475935fdf82fd59413195569cbdc1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Security for datafusion-query-builder 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for datafusion_query_builder-0.4.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page