polite
The core rusqlite × Polars bridge.
polite makes it easy to move data between SQLite databases and Polars DataFrames.
Features
- Open SQLite databases (file-based only).
- Execute arbitrary SQL statements.
- Bulk-load query results into Polars
DataFrames (to_dataframe) via ConnectorX. - Write Polars
DataFrames into SQLite tables (from_dataframe).
Requirements
When using polite, please be aware of the current upstream version restrictions:
- Built against Polars 0.45 (the latest release supported by ConnectorX).
- Pins
chrono <= 0.4.39due to an upstream Arrow/Polars issue (this will be removed once the conflict is resolved there).- (Recommended) pin the chrono crate to
=0.4.39in your dependencies.
- (Recommended) pin the chrono crate to
Limitations (MVP)
- Supported SQLite column types:
INTEGER→ PolarsInt64REAL→ PolarsFloat64TEXT→ PolarsString - Other SQLite types are stored as
String. - Output uses Polars’ standard debug
DataFrameformat. - No advanced type inference or schema evolution yet.
⚠️ Notes on SQLite backends
politeuses ConnectorX for bulk reads into Polars.- File-backed databases (
.sqlite,.db) are required. - In-memory databases (
:memory:) are not supported — use atempfileif you don’t want persistence.
Core functions
💡 All of these functions are also available via
use polite::prelude::*;
The two basic functions provided by the library are:
to_dataframe(db_path, sql)– run a query and return aDataFrame.from_dataframe(&conn, table, &df)– write aDataFrameinto a table. Takes an openrusqlite::Connection, the table name to write to, and your DataFrame.
polite also provides a couple of convenience wrappers
(with simplified string errors and without connection handling):
-
save_dataframe(db_path, table, &df)
Opens a connection and writes the DataFrame in one step.
Creates and closes its own connection; use this for one-off saves. -
load_dataframe(db_path, sql)
Wrapsto_dataframebut adds context to errors (e.g."Failed to load DataFrame from demo.db: no such table: users").
This makes it clearer where the failure came from, especially if you’re working with multiple databases.
Why use these helpers?
These helpers don’t add new capabilities beyond the core API, but they provide more ergonomic errors.
The raw API (to_dataframe, from_dataframe) exposes detailed error variants (Query, Arrow, Polars, rusqlite, etc.), which is useful if you want to distinguish exactly what failed.
The convenience wrappers (load_dataframe, save_dataframe) normalize those into a single error variant per operation:
load_dataframealways yieldsPoliteError::Loadsave_dataframealways yieldsPoliteError::Save
- ✅ You don’t have to juggle
Query,Arrow,ArrowToPolarsvariants ofPoliteError,rusqlite::Erroretc. - ✅ They’re the "safe default" for people who just want “load/save a DataFrame” and don’t care which stage failed.
- ✅ Advanced users can drop down to
to_dataframe/from_dataframefor finer control and granular error inspection.
In practice, wrappers are the recommended default for most use cases. Drop down to the raw API when you want maximum control.
🎤 Demo time
use *;
use *;
🤓 I am making friends in SQLite! I don't have any there yet...
shape: (0, 2)
┌─────┬──────┐
│ id ┆ name │
│ --- ┆ --- │
│ str ┆ str │
╞═════╪══════╡
└─────┴──────┘
🪄 I have lovingly restored my friends into a Polars DataFrame:
shape: (3, 2)
┌─────┬─────────┐
│ id ┆ name │
│ --- ┆ --- │
│ i64 ┆ str │
╞═════╪═════════╡
│ 1 ┆ Alice │
│ 2 ┆ Bob │
│ 3 ┆ Charlie │
└─────┴─────────┘
🆒 My friends from Polars are now my friends in SQLite:
shape: (2, 2)
┌─────┬──────┐
│ id ┆ name │
│ --- ┆ --- │
│ i64 ┆ str │
╞═════╪══════╡
│ 4 ┆ Dora │
│ 5 ┆ Eve │
└─────┴──────┘
🎉 All my friends are politely gathered in a DataFrame:
shape: (5, 2)
┌─────┬─────────┐
│ id ┆ name │
│ --- ┆ --- │
│ i64 ┆ str │
╞═════╪═════════╡
│ 1 ┆ Alice │
│ 2 ┆ Bob │
│ 3 ┆ Charlie │
│ 4 ┆ Dora │
│ 5 ┆ Eve │
└─────┴─────────┘
- Note: the minor bug here is in the
idcolumn'sstrdtype when the DataFrame is empty: this is a known issue that will be solved by the next release of connectorx (0.4.4)
Type system
Note that the type system used by rusqlite via ConnectorX is as shown
here
Integration
- Use this library in Rust projects that need to bridge SQLite and Polars.
- For a quick playground, see the CLI.
Documentation
- Crate docs: docs.rs/polite
- Workspace guide: DEVELOPMENT.md
License
Licensed under the MIT License. See LICENSE for details.