A version requirement that the resolver happily satisfies with the wrong crate is not a convenience — it is a latent build break waiting for a stale Cargo.lock. OxiSQL 0.4.0 ships exactly zero lines of new engine code and closes that gap for the entire 17-crate family, permanently.
Today — July 18, 2026 — we released OxiSQL 0.4.0, the sovereign Pure-Rust SQL layer for the COOLJAPAN ecosystem. It is a packaging and release-hygiene minor bump with no source-code changes since 0.3.3: the engine, the wire protocols, and the public oxisql API are byte-for-byte identical. What changed is the dependency metadata. Every inter-crate dependency floor across all 17 crates is now pinned to the exact full-triple 0.4.0 — resolving to >= 0.4.0, < 0.5.0 — instead of the loose minor-only caret "0.4", giving the whole family one clean, reproducible baseline.
No C. No Fortran. No libpq, no libmysqlclient, no libsqlite3, no zstd-sys — OxiSQL’s dependency graph is exactly as C-free in 0.4.0 as it was in 0.3.3, because at the source level it is 0.3.3: the same C-free oxisqlite engine, the same Pure-Rust tokio-postgres and mysql_async wire clients, the same OxiTLS-routed TLS, the same open_from_bytes, the same PostgreSQL logical replication. 0.4.0 does not touch a line of it. It moves version numbers — and it moves them for a specific, load-bearing reason.
Why a packaging release earns a minor bump
A version that “resolves” is not the same as a version that builds. Until this line was drawn, the OxiSQL family carried a quiet trap in its own dependency metadata:
- Every internal floor was declared with a minor-only caret —
"0.4", and on the previous line"0.3"— which tells Cargo “any compatible release at or above the floor will do.” That floor is only as strong as its lower bound. - On the
0.3.xline, a"0.3"requirement (lower bound0.3.0) was still satisfied by a0.3.2engine already frozen in a downstreamCargo.lock. Butoxisql-sqlite-compat/oxisqlite0.3.3callopen_from_bytes, an API that only exists inoxisqlite/oxisqlite-core0.3.3. The requirement was “met”; the symbol was not there. - That is the worst kind of failure: a resolve that succeeds and a compile that fails, with
open_from_bytes not foundat the bottom of a wall of green checkmarks. - The same looseness ran the entire chain —
oxisqlite→oxisqlite-core, andoxisqlite-core→oxisqlite-sqlite3-parser/oxisqlite-time/oxisqlite-uuid— so a single stale lock could strand any layer. 0.3.4shipped an emergency fix that pinned every floor to the exact patch"0.3.4", but that was a tightening bolted onto the tail of the0.3.xseries.
OxiSQL 0.4.0 makes that fix the permanent shape of the family:
- Every internal floor now names the exact full triple
0.4.0. The whole 17-crate family is released together at0.4.0, and each inter-crate requirement reads"0.4.0"(>= 0.4.0, < 0.5.0) — the baseline for the entire0.4.xline names its own version, not a bare minor. - The
0.3.4stale-lock fix is carried forward as the0.4.xbaseline, rather than a patch retrofitted onto a shipped line. Exact-patch pinning is now the convention the family is built on, not an afterthought. - The resolver can no longer pair a newer caller with an older family member. As the
0.4.xline grows, each crate names the exact patch it shipped with, so a staleCargo.lockholding an older sibling is rejected outright — the whole set always moves together. - The minor bump gives 0.3.3’s two internal breaking changes a proper semantic-version home. They should never have ridden a patch release;
0.4.0is where they belong. - Upgrading is a no-risk version bump. Because the API is identical to 0.3.3, there is nothing to migrate — no renamed types, no changed signatures, no feature-flag churn.
Technical Deep Dive: where the version numbers actually moved
- The workspace manifest. The root
Cargo.tomlbumped[workspace.package].versionto0.4.0and rewrote every[workspace.dependencies]inter-crate entry —oxisql-core,oxisql-parse,oxisql-embedded,oxisql-postgres,oxisql-mysql,oxisql-datafusion,oxisql-pool,oxisql-migrate,oxisql-sqlite-compat, and theoxisqlite/limbo_ext/limbo_macrosengine paths — to carry the exactversion = "0.4.0"alongside theirpath =. - The engine’s internal chain. The floors that the
0.3.3incident exposed one level at a time are now all exact:oxisql-sqlite-compat→oxisqlite,oxisqlite→oxisqlite-core, andoxisqlite-core→oxisqlite-sqlite3-parser/oxisqlite-time/oxisqlite-uuid. No link in that chain can resolve to a pre-0.4.0sibling. - The semver home for two internal breaking changes.
0.3.3changed the shape of two low-level engine types:oxisqlite’sParams::Namedmoved its key type fromStringtoCow<'static, str>(so binding a'staticplaceholder name borrows instead of allocating), andoxisqlite-sqlite3-parser’s lexerTokendropped its lifetime parameter (Token<'i>(usize, &'i [u8], usize)→Token(usize, Cow<'static, str>, usize)). Both are internal to the engine and parser beneathoxisql-sqlite-compat— the facade-levelConnection::query_named/execute_namedAPI is untouched — but a breaking change belongs behind a minor bump, and0.4.0provides one. - What did not change: everything else.
crates/*/srcis byte-for-byte identical between the0.3.3and0.4.0tags. Engine behavior, wire protocols, and the publicoxisqlsurface are the same code you were already running — this is a packaging-metadata release, and nothing more.
Getting Started
cargo add oxisql --features sqlite,pool-sqlite-compat
Or pin the exact baseline in Cargo.toml:
[dependencies]
oxisql = { version = "0.4.0", features = ["embedded", "postgres", "pool-embedded", "migrate"] }
The C-free SQLite path — the same oxisqlite engine, unchanged — supports real transactional ROLLBACK:
use oxisql::SqliteConnection;
use oxisql::prelude::*;
#[tokio::main]
async fn main() -> Result<(), oxisql::OxiSqlError> {
let conn = SqliteConnection::open_memory().await?;
conn.execute("CREATE TABLE t (id INTEGER, name TEXT)", &[]).await?;
// BEGIN ... ROLLBACK discards the INSERT.
conn.execute("BEGIN", &[]).await?;
conn.execute("INSERT INTO t VALUES (1, 'Alice')", &[]).await?;
conn.execute("ROLLBACK", &[]).await?;
let rows = conn.query("SELECT COUNT(*) FROM t", &[]).await?;
println!("rows after ROLLBACK: {:?}", rows); // → one row holding COUNT(*) = 0
Ok(())
}
Everything 0.3.3 added is exactly where you left it — including open_from_bytes, which opens a database straight from an in-memory image with no temporary file:
use oxisql::SqliteConnection;
#[tokio::main]
async fn main() -> Result<(), oxisql::OxiSqlError> {
let image: &[u8] = include_bytes!("bundled.sqlite");
let conn = SqliteConnection::open_from_bytes(image).await?;
let rows = conn.query("SELECT count(*) FROM sqlite_master", &[]).await?;
println!("{:?}", rows);
Ok(())
}
Reach the same engine through the facade with oxisql::connect("sqlite::memory:") or oxisql::connect("sqlite://path/to/file.db").
What’s New in 0.4.0
- Exact full-triple inter-crate floors (all 17 crates). Every internal dependency requirement moved from the minor-only caret
"0.4"to the exact"0.4.0"(>= 0.4.0, < 0.5.0), so the whole family names a single, consistent baseline. - Stale-lock breakage closed for good. With each internal floor naming its exact patch, the resolver can never satisfy a newer caller with an older family member held back in a stale
Cargo.lock— theopen_from_bytes“resolves yet fails to compile” failure mode from the0.3.xline cannot recur across0.4.x. - The
0.3.4emergency fix, made permanent.0.4.0carries the exact-patch pinning forward as the shape of the0.4.xline rather than a patch tacked onto the previous series. - A proper semver home for two internal breaking changes.
oxisqlite::Params::Named’s key type (String→Cow<'static, str>) andoxisqlite-sqlite3-parser’s lexerToken(lifetime parameter dropped), both introduced in0.3.3, now sit behind the minor bump where breaking changes belong. - No source changes since 0.3.3. Packaging metadata only. Engine behavior, wire protocols, and the public
oxisqlAPI are byte-for-byte identical — 2,157 tests passing with default features, 2,651 with--all-features, 0 failing, 0 clippy warnings, exactly as in 0.3.3.
Tips
- Upgrading is a version bump, not a migration. Bump the pin to
oxisql = "0.4.0", or runcargo update -p oxisql. Because the API is identical to 0.3.3, no source or feature-flag change is required — this is the safest upgrade OxiSQL will ever ship. "0.4.0"is still a caret requirement, not a freeze. The exact triple resolves to>= 0.4.0, < 0.5.0, so you keep receiving every compatible0.4.xupdate automatically — the floor only guarantees nothing older than0.4.0can sneak in. Full-triple pinning tightens the lower bound; it does not pin you to exactly0.4.0.- Why the exact patch matters as the line grows. A bare
"0.4"stops carrying weight the moment0.4.1ships: it would still accept a stale-locked0.4.0engine underneath a0.4.1caller that needs a0.4.1symbol — the same shape as theopen_from_bytesbreak. Pinning every floor to the exact patch it shipped with means the resolver rejects any older sibling a staleCargo.locktries to keep, so the whole family always resolves consistently. - If you hit the “resolves but won’t compile” error on 0.3.x, this is the clean fix. Move the whole family to
0.4.0(or run a freshcargo update) and the exact floors guarantee a coherent set — no moreopen_from_bytes not foundfrom a mismatched engine. - SQLite users: reach for
oxisql-sqlite-compat. The C-free SQLite path is the sanctioned replacement forrusqliteunder the COOLJAPAN Pure Rust Policy — enable thesqliteandpool-sqlite-compatfeatures, and you getlibsqlite3-free transactional SQL,ROLLBACK, UPSERT, andopen_from_bytes, all Pure Rust. - For reproducible builds, pin
oxisqland let the floors do the rest. Depend onoxisql = "0.4.0"and the exact-triple metadata beneath it ensures every family member — facade, drivers, and the seven-crate engine — resolves at a consistent0.4.x, with no hand-maintained pins on the internal crates.
This is the foundation
OxiSQL’s facade/driver layer is 10 crates sitting on the 7-crate, C-free oxisqlite-* engine, alongside a perf benchmark crate and two vendored [patch.crates-io] shim crates (whoami-patched and zstd-shim) that keep the --all-features build genuinely C-free; the TLS crypto provider now arrives CVE-clean directly from OxiTLS, so no rustls patch is needed here anymore. As of 0.4.0 — source-identical to 0.3.3 — that is 2,157 tests passing with default features, 2,651 with --all-features, 0 failing, 0 clippy warnings, across roughly 178,591 lines of Rust in 484 source files.
OxiSQL itself sits on OxiTLS (transport/TLS), oxicode (row serde), OxiCrypto (encryption-at-rest), and OxiStore (lower storage layer). It is depended on by oxirouter, oxirs, oxify, oxigdal-db-connectors, oximedia, oxigaf, and oxirag — the database tier each of those reaches for when it needs SQL. A family that whole depends on resolving as one; 0.4.0 is the release that guarantees it always does.
Repository: https://github.com/cool-japan/oxisql
Star the repo if you want a SQL layer where “the versions resolved” and “the code compiled” are the same promise, and a stale lockfile can never quietly pair a new caller with an old engine again.
The era of a green resolve hiding a red build is over. Pure Rust SQL — sovereign, safe, and now pinned to one clean, reproducible baseline — is here.
— KitaSan at COOLJAPAN OÜ July 18, 2026