| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-08-30 | 14.3 kB | |
| v0.20.0 source code.tar.gz | 2026-08-30 | 1.1 MB | |
| v0.20.0 source code.zip | 2026-08-30 | 1.5 MB | |
| Totals: 3 Items | 2.6 MB | 0 | |
GlueSQL v0.20.0 makes the Rust core synchronous, introduces StatementPlan and a typed query execution pipeline, and adds a clearer upgrade path for persistent storage. It also brings struct-based inserts, PostgreSQL-style regular-expression operators, and important correctness and performance improvements.
This release contains breaking API and storage-format changes. Read the upgrade notes before updating an existing application or database.
⚠️ Upgrade Notes
Upgrade persistent storage before opening it
The schemaless row representation now uses the same Vec<Value> model as schemaful tables. Schemaless rewrites happen during planning instead of execution, removing the former DataRow wrapper and unifying the storage interface (#1865).
Existing persistent data may require a one-time migration:
| Storage | Upgrade action |
|---|---|
| FileStorage | Upgrade format v1 to v2 with --upgrade or gluesql_file_storage::migrate_to_latest |
| RedbStorage | Upgrade format v1 or v2 to v3 with --upgrade or gluesql_redb_storage::migrate_to_latest |
| SledStorage | Upgrade format v1 to v2 with --upgrade or gluesql_sled_storage::migrate_to_latest |
| RedisStorage | Reset the GlueSQL namespace before reuse because the stored row payload changed |
| CSV, JSON, MongoDB, and Parquet | No persisted-data migration is required |
Back up persistent data before upgrading. The CLI can migrate supported storage types:
:::shell
gluesql --storage file --path ./data --upgrade
gluesql --storage redb --path ./data.redb --upgrade
gluesql --storage sled --path ./data --upgrade
RedbStorage now creates databases using redb file format v3 (#1901). The migration keeps GlueSQL's existing row serialization while upgrading the underlying redb file. Older GlueSQL releases cannot reopen the upgraded v3 file, so keep the backup if rollback may be necessary.
SledStorage is deprecated
SledStorage is deprecated in v0.20.0 and is planned for removal in v0.21.0 (#2013). Existing deployments can continue using it during the v0.20 release cycle, but new persistent deployments should use RedbStorage.
Before upgrading to v0.21.0, export an existing Sled database as SQL and recreate it with RedbStorage:
:::shell
gluesql --path ~/glue_data --dump ./dump.sql
gluesql --execute ./dump.sql --path ~/new_data --storage=redb
🌊 Breaking Changes
The Rust core and native storages are synchronous
GlueSQL's core execution model and native storage implementations no longer require async plumbing (#1928). Calls such as Glue::plan, Glue::execute, and Query Builder's execute now return their results directly:
:::rust
// v0.19
let payloads = glue.execute("SELECT * FROM User").await?;
// v0.20
let payloads = glue.execute("SELECT * FROM User")?;
Custom storage implementations need to update their Store, StoreMut, and Planner implementations:
- Remove
async_trait,async fn, and.awaitfrom the storage interface. - Return a standard
Iteratorfromscan_datainstead of a futuresStream. - Use
Vec<Value>for stored rows instead ofDataRow. - Accept and return
StatementPlanfrom custom planners.
JavaScript and Python packages moved to dedicated repositories
The language bindings now evolve outside the Rust workspace:
- JavaScript, WebStorage, and IdbStorage moved to gluesql/gluesql-js (#1926).
- Python moved to gluesql/gluesql-py (#1925).
This separation keeps browser-specific async requirements out of the synchronous Rust storage contract. JavaScript and Python users should follow releases from their respective repositories.
Before the JavaScript package moved, its npm release workflow adopted Trusted Publishing (#1870) and updated its Node.js and wasm-pack versions (#1872). Further JavaScript release changes now belong in gluesql-js.
StatementPlan and storage-specific planners
StatementPlan is the new public, execution-facing representation produced by Glue::plan and consumed by Glue::execute_stmt, custom planners, and Query Builder (#1900). The SQL AST remains a representation of parsed syntax and storage-facing definitions, while StatementPlan carries the concrete decisions needed by planning and execution.
This separation moves execution metadata out of the AST. Aggregate expressions, for example, now receive their execution slots during planning instead of being matched dynamically at runtime (#1895). SELECT and VALUES plans then form a typed execution pipeline whose stages can only accept valid preceding stages (#1937).
The existing Planner store trait now accepts and returns StatementPlan, giving each storage implementation a real execution-plan boundary to customize. The default planner validates the statement and applies schemaless, primary-key, hash-join, and aggregate planning. A storage can override Planner::plan to compose the available passes differently or add a storage-specific access strategy. SledStorage, for example, adds index planning so eligible queries carry TableAccessPlan::Index, while other storages keep a full scan or primary-key access plan.
The SELECT pipeline is represented explicitly as:
:::text
Source
-> Join
-> Filter
-> Aggregate
-> Project
-> Order By
-> Distinct
-> Offset
-> Limit
AST Builder is now Query Builder
The public ast_builder module has been renamed to query_builder (#1933). Imports and error names need to be updated, including AstBuilderError to QueryBuilderError.
Query Builder now produces StatementPlan values and mirrors the same typed execution relationships, so invalid stage combinations are rejected by the Rust type system. The join planner has also been named more precisely as the hash-join planner (#1988).
Other public API changes
EvaluateError::FormatParseErrornow stores an owned error string instead of exposingchrono::ParseErrorthrough GlueSQL's public error type (#1913).- The obsolete
gluesql-utilscrate has been removed after dropping its unused map exports (#1929) and customVectorwrapper (#1931).Triboolis now available fromgluesql_core::data::Tribool(#1932).
✨ Highlights
Insert Rust structs with ToGlueRow
The new ToGlueRow derive macro and Query Builder's values_from method convert named struct fields directly into INSERT columns and values (#1948, #1955). Option::None becomes SQL NULL, and #[glue(rename = "...")] maps a Rust field to a different column name.
:::rust
use gluesql::{
core::query_builder::{Execute, table},
ToGlueRow,
};
#[derive(ToGlueRow)]
struct Item {
id: i64,
#[glue(rename = "name")]
title: String,
rate: Option<f64>,
}
let items = vec![
Item {
id: 1,
title: "Fish".to_owned(),
rate: Some(0.2),
},
Item {
id: 2,
title: "Bread".to_owned(),
rate: None,
},
];
table("Item")
.insert()
.values_from(&items)?
.execute(&mut glue)?;
PostgreSQL-style regular-expression operators
GlueSQL now supports ~, ~*, !~, and !~* for regular-expression matching (#2001). Patterns use Rust regex syntax, support case-sensitive and case-insensitive matching, and preserve SQL NULL behavior.
:::sql
SELECT name
FROM Item
WHERE name ~* '^fish|bread$';
The same operations are available through Query Builder.
Query Builder improvements
Query Builder expressions can now specify ascending or descending order directly (#1882). The typed pipeline also exposes explicit source, join strategy, table access, distinct, ordering, offset, and limit stages.
🚀 Performance and Correctness
- ParquetStorage streams converted rows instead of loading an entire table into memory (#1968).
SUM,MIN,MAX,AVG,VARIANCE, andSTDEVnow ignoreNULLinputs according to SQL set-function semantics (#1990).- CompositeStorage rollback now delegates to rollback on each inner storage instead of accidentally committing the transaction (#1963).
- Primary-key lookup planning no longer applies an unsafe predicate to the wrong side of a join (#1943).
- Index planning preserves a primary-key access path instead of replacing it with a less appropriate index plan (#1919).
- Table-factor fields are checked before expressions are considered safe to evaluate during planning (#1961).
- ORDER BY expressions are included when scanning schema dependencies (#1982).
- Schemaless rewrites now apply to CREATE TABLE AS SELECT sources (#1987).
- One-shot Sled migration opens no longer run the background flusher (#1924).
- SledStorage waits for a previous database lock to be released before failing to open the same path (#1944).
🛡️ Clearer SQL Validation
Unsupported syntax is now rejected during translation instead of being silently ignored or failing later:
- Multi-column
INsubqueries (#1936) TEMPORARY,LIKE, andCLONEoptions on CREATE TABLE (#1972)- Arguments supplied to unsupported table functions (#1983)
- Unsupported transaction statement clauses (#1991)
- Unsupported CREATE INDEX options (#1998)
Translate errors now use typed enums for unsupported SQL options, making programmatic error handling more reliable (#1980).
🔧 Tooling and Maintenance
- Replaced Docusaurus with Zensical for the documentation site and updated its dependencies (#1916, #1874).
- Documented Redb transaction support, updated Rust examples for synchronous execution, and refreshed the Rust getting-started guide (#1832, #1934, #1940).
- Updated the project Rust toolchain to 1.94 (#1921).
- Replaced grcov with cargo-llvm-cov, improved trusted coverage publishing, and now runs coverage on pushes to
main(#1938, #1923, #1954). - Migrated the SQL test suite to readable file-based fixtures (#1941).
- Strengthened Sled migration tests with isolated paths and reliable temporary-directory setup (#1914, #1918).
- Simplified Rust CI package selection by using
cargo test -pdirectly (#1885). - Moved the
FromGlueRowderive implementation into its own module alongside the newToGlueRowimplementation (#1956). - Simplified the Rust crates.io publishing workflow (#1922).
- Removed deprecated Cargo
authorsfields from workspace packages (#2012).
👏 Contributors
Thanks to everyone who contributed to this release:
@miinhho, @panarch, @OmarAshour02, @devgony, @ssseft, @Bortlesboat, @red-sprout, @edomaur, @juhee200, @aswitocom, @ShreyasUday, @seosangwon, @dgg1dbg, @sweetpark, @MinhyukWoo, @kwondo1017, @jinwooky, @teddytennant, and @jun02160.
Full Changelog: v0.19.0...v0.20.0