SQLx Knowledge Patch
Covers SQLx 0.8.3–0.9.0-alpha.1 (2025-01-03 through 2025-10-14). Claude Opus 4.6 knows SQLx through 0.7.x. It is unaware of the 0.8+ features and 0.9 breaking changes below.
Index
| Topic | Reference | Key features |
|---|---|---|
| Transactions | references/transactions.md | begin_with, per-DB option types, is_in_transaction, type aliases |
| Type system & macros | references/type-system.md | SqlSafeStr, Arguments lifetime removal, smart pointer Encode/Decode, PgBindIter, PgHasArrayType auto-derive, json(nullable), transparent named structs |
| SQLite | references/sqlite.md | Commit/rollback/preupdate hooks, feature flags (sqlite-deserialize, sqlite-load-extension, sqlite-unlock-notify), sqlite-unbundled, no_tx migrations |
| Postgres & MySQL | references/postgres-and-mysql.md | Geometry types, ipnet support, PgConnectOptions auto-escaping, MySQL collation inference, PgListener improvements |
| Configuration & runtime | references/configuration.md | sqlx.toml, MSRV 1.86, runtime feature changes, Migrator::with_migrations, RawSql type parameter |
0.8 → 0.9 Migration — Breaking Changes
Note: 0.9.0-alpha.1 is the current alpha. Many breaking changes from 0.8.x.
| What changed | Before (0.8) | After (0.9) |
|---|---|---|
| Query string safety | query("...") accepts &str | Accepts impl SqlSafeStr — only &'static str or AssertSqlSafe |
| Arguments lifetime | Arguments<'q>, SqliteArguments<'q> | Arguments (no lifetime) — values are owned |
| Runtime features | runtime-tokio-native-tls combos | Separate runtime-tokio + native-tls; combos removed |
| MSRV | 1.75 | 1.86 |
| RawSql | No type parameter | RawSql methods require DB type parameter |
| RawSql::fetch_optional | Returns Result<DB::Row> | Returns Result<Option<DB::Row>> |
| Cow decoding | Could be Cow::Borrowed | Always Cow::Owned |
| SQLite extension loading | extension() safe method | unsafe; requires sqlite-load-extension feature |
| SqliteValue | Sync | !Sync; SqliteValueRef is !Send |
| MySQL text columns | Inferred as Vec<u8> | Inferred as String |
| PgConnectOptions::options() | Manual escaping needed | Auto-escaped — remove manual escaping |
| #[derive(sqlx::Type)] newtype | No auto PgHasArrayType | Auto-generates PgHasArrayType; add #[sqlx(no_pg_array)] if manual impl exists |
Also note: 0.8.4 was yanked — use 0.8.5+ instead. All 0.8.4 features are available in 0.8.5.
SqlSafeStr — Query String Safety (0.9)
The most impactful breaking change. All query*() functions now take impl SqlSafeStr instead of &str. Only &'static str and AssertSqlSafe implement it.
use sqlx::AssertSqlSafe;
// Static strings work as before
sqlx::query("SELECT * FROM users WHERE id = $1")
.bind(user_id)
.fetch_one(&pool).await?;
// Dynamic queries must be wrapped
let table = "users";
let q = format!("SELECT * FROM {table}");
sqlx::query(AssertSqlSafe(q)).fetch_all(&pool).await?;
This also enables returning owned queries as Query<'static, DB>.
begin_with — Transaction Options (0.8.4+)
Start transactions with database-specific options:
use sqlx::postgres::{PgIsolationLevel, PgTransactionOptions};
let tx = conn
.begin_with(
PgTransactionOptions::new()
.isolation_level(PgIsolationLevel::Serializable)
.read_only(true),
)
.await?;
Each database has its own options type: PgTransactionOptions, MySqlTransactionOptions, SqliteTransactionOptions.
See references/transactions.md for is_in_transaction and type aliases.
Arguments Lifetime Removal (0.9)
Arguments<'q> is now just Arguments (no lifetime). SqliteArguments and AnyArguments similarly lost their lifetime parameter. Bound values are now owned.
// Before (0.8)
fn build_query<'q>(args: &mut PgArguments<'q>) { ... }
// After (0.9)
fn build_query(args: &mut PgArguments) { ... }
Smart Pointer Encode/Decode/Type (0.9)
Box<T>, Arc<T>, Rc<T>, and Cow<'_, T> now implement Encode, Decode, and Type when T does. Breaking: Cow always decodes as Cow::Owned.
PgBindIter — Bind Iterators as Arrays (0.9)
Bind iterators directly as Postgres arrays without collecting to Vec:
use sqlx::postgres::PgBindIter;
let ids = [1i32, 2, 3];
sqlx::query("SELECT * FROM users WHERE id = ANY($1)")
.bind(PgBindIter(ids.iter()))
.fetch_all(&pool).await?;
#[derive(sqlx::Type)] Auto-Generates PgHasArrayType (0.9)
Newtype structs deriving sqlx::Type now automatically get a PgHasArrayType impl. Add #[sqlx(no_pg_array)] to opt out:
#[derive(sqlx::Type)]
#[sqlx(no_pg_array)] // needed if you had a manual PgHasArrayType impl
struct MyId(i32);
json(nullable) and Transparent Named Structs
Handle nullable JSON columns in FromRow derives (0.8.4+):
#[derive(sqlx::FromRow)]
struct MyRow {
#[sqlx(json(nullable))]
metadata: Option<MyJsonType>,
}
Single-field named structs can now use #[sqlx(transparent)] (0.9):
#[derive(sqlx::Type)]
#[sqlx(transparent)]
struct UserId {
id: i32, // single named field — now supported
}
Runtime Feature Migration (0.9)
Deprecated combination features removed. Use separate features:
# Before (0.8)
sqlx = { version = "0.8", features = ["runtime-tokio-native-tls"] }
# After (0.9)
sqlx = { version = "0.9", features = ["runtime-tokio", "native-tls"] }
New runtime options: runtime-smol and runtime-async-global-executor (replacing deprecated async-std).
sqlx.toml Configuration (0.9)
Per-crate configuration (requires sqlx-toml feature). Supports renaming DATABASE_URL, global type overrides for macros, renaming the _sqlx_migrations table, and SQLite extension loading in macros/CLI.
Guide: sqlx::_config module docs. See references/configuration.md for details.
SQLite Feature Flag Changes (0.9)
New non-default features for conditional SQLite APIs:
| Feature | Enables |
|---|---|
| sqlite-deserialize | SqliteConnection::serialize() / deserialize() |
| sqlite-load-extension | SqliteConnectOptions::extension() (now unsafe) |
| sqlite-unlock-notify | Internal sqlite3_unlock_notify() usage |
| sqlite-preupdate-hook | conn.on_preupdate() callback (added in 0.8.4) |
See references/sqlite.md for commit/rollback hooks and no_tx migrations.
New APIs Summary
| API | Version | Description |
|---|---|---|
| conn.on_commit() / on_rollback() | 0.8.3 | SQLite commit/rollback hook callbacks |
| PgListener: Acquire + next_buffered() | 0.8.3 | Use PgListener as connection; batch notifications |
| PgPoint, PgLine | 0.8.3 | Postgres geometry types |
| Transaction type aliases | 0.8.3 | PgTransaction<'c>, MySqlTransaction<'c>, SqliteTransaction<'c> |
| sqlite-unbundled feature | 0.8.3 | Dynamically link system libsqlite3.so |
| AnyQueryResult for SQLite/MySQL | 0.8.3 | Previously Postgres-only |
| begin_with + per-DB options | 0.8.4 | Custom transaction isolation, read-only, etc. |
| Connection::is_in_transaction | 0.8.4 | Check if inside a transaction |
| conn.on_preupdate() | 0.8.4 | SQLite preupdate hook (requires feature) |
| #[sqlx(json(nullable))] | 0.8.4 | Handle nullable JSON columns in FromRow |
| PgLineSegment, PgBox, PgPath, PgPolygon, PgCircle | 0.8.4 | Additional Postgres geometry types |
| ipnet::IpNet mapping | 0.8.4 | Maps to Postgres INET/CIDR (requires ipnet feature) |
| SqlSafeStr / AssertSqlSafe | 0.9 | Query string safety wrapper |
| PgBindIter | 0.9 | Bind iterators as Postgres arrays |
| Encode/Decode for Box<T>, Arc<T>, Rc<T>, Cow<T> | 0.9 | Smart pointer support |
| #[sqlx(no_pg_array)] | 0.9 | Opt out of auto PgHasArrayType |
| #[sqlx(transparent)] on named structs | 0.9 | Single-field named structs (not just tuple structs) |
| no_tx SQLite migrations | 0.9 | Opt out of transaction wrapping |
| Migrator::with_migrations() | 0.9 | Build Migrator from collection programmatically |
| sqlx.toml configuration | 0.9 | Per-crate config (requires sqlx-toml feature) |
Reference Files
| File | Contents |
|---|---|
| transactions.md | begin_with options, isolation levels, is_in_transaction, type aliases |
| type-system.md | SqlSafeStr, Arguments lifetime, smart pointers, PgBindIter, PgHasArrayType, json(nullable), transparent structs |
| sqlite.md | Commit/rollback/preupdate hooks, feature flags, sqlite-unbundled, no_tx migrations |
| postgres-and-mysql.md | Geometry types, ipnet, PgConnectOptions escaping, MySQL collation, PgListener |
| configuration.md | sqlx.toml, MSRV/runtime changes, Migrator::with_migrations, RawSql type parameter |