Backends
Pivotal supports four execution backends. The same DSL source runs unchanged on any of them.
Comparison
| pandas | Polars | DuckDB | SQL CTE | |
|---|---|---|---|---|
| Execution | Python in-process | Python in-process | In-process SQL engine | Generates SQL only |
| Speed | Fast for small–medium data | Fast — zero-copy columnar | Fast for large data | N/A — no execution |
| Memory | Loads everything | Columnar, efficient | Columnar, lazy | N/A |
| Python ops | Full support | Full support | Supported (via pandas fallback) | Skipped |
| Plots/tables | Full support | Full support | Full support | Skipped |
| Output | Python objects | Python objects | Python objects | .sql file |
| Best for | Interactive exploration | Performance-sensitive work | Large datasets, production | Sharing with SQL users |
Pandas (default)
The default backend. Uses pandas DataFrames throughout. Best for interactive analysis and datasets that fit comfortably in memory.
# Jupyter — set for the session
%pivotal_set backend=pandas
# Per-cell override
%%pivotal backend=pandas
Polars
Uses Polars DataFrames throughout. Polars is a fast, columnar DataFrame library with a Rust core. It is a good choice when you want pandas-style in-process execution but with better performance on larger datasets.
Requires pip install pivotal[polars].
Plots and Great Tables output work identically to the pandas backend — Polars DataFrames are converted to pandas automatically at the plot/table boundary so the Pivotal viewer works without changes.
Notes:
- Requires
polars >= 0.20. On older CPUs without AVX2, installpolars-lts-cpuinstead ofpolars. - The Polars backend uses strict typing —
fill_nullonly fills nulls whose column type matches the fill value.
DuckDB
Executes operations using DuckDB's in-process SQL engine. Significantly faster for large datasets (hundreds of millions of rows), uses columnar storage, and supports lazy evaluation.
Requires pip install pivotal[duckdb].
Limitations with DuckDB:
- Python-only operations (
apply, multi-linepython...endblocks, or user-defined Python functions that aren't DuckDB UDFs) fall back to pandas for that step - SQL dialect is DuckDB SQL — some edge cases may differ from pandas behaviour
SQL CTE
Generates a pure SQL WITH...AS chain. Does not execute the SQL — it writes it to a .sql file or returns it as a string.
Useful for: - Sharing queries with analysts using SQL tools (DBeaver, DataGrip, Tableau) - Producing dbt model files - Auditing what a notebook computes
Limitations with SQL CTE:
- Python operations (
apply,plot,table,show,python,python...end) are skipped and replaced with a-- [skipped: ...]comment fillnais not yet supported (skipped)- Output targets DuckDB SQL dialect; minor adjustments may be needed for other databases
Example output:
-- Generated by Pivotal from: analysis.ipynb
WITH
_cte_0_sales AS (
SELECT * FROM sales WHERE price > 100
),
_cte_1_sales AS (
SELECT region, SUM(revenue) AS total FROM _cte_0_sales GROUP BY region
)
SELECT * FROM _cte_1_sales
Setting the backend
JupyterLab
Persistent for the session:
Override for a single cell:
Python API
from pivotal import DSLParser
parser = DSLParser()
results = parser.parse(dsl)
# generate code
code = parser.generate_code(results, backend='duckdb')
# or execute directly
parser.execute(dsl, backend='duckdb')
CLI — notebook export
Or use the Export to Code File menu in JupyterLab and choose the format from the dropdown.