fix(deps): update rust crate sqlx to 0.9#270
Conversation
There was a problem hiding this comment.
Summary
This PR updates the sqlx dependency from version 0.8 to 0.9, a major version upgrade with several breaking changes. The changelog shows this release includes significant API changes, particularly around query building and migration handling.
Verdict: Needs changes - There are breaking API changes that will cause compilation failures in the current codebase.
Research notes
I reviewed the sqlx 0.9.0 changelog which documents the following key breaking changes:
-
#3723 - SqlStr introduction: All
query*()functions now takeimpl SqlSafeStrwhich is only implemented for&'static strandAssertSqlSafe. String literals work fine, but dynamically built queries usingformat!()must now be wrapped inAssertSqlSafe(). -
#3383 - Migrate trait changes: Significant changes to the
Migratetrait, though the codebase only usessqlx::migrate!()macro which should be unaffected. -
#3541 - Postgres nullability inference: May alter output of
query!()macros for certain queries - should verify type annotations still match. -
#3960 - Arguments trait lifetime removed: Could affect custom argument binding, though no custom implementations found in this codebase.
-
MSRV increased to Rust 1.94.0: The project must ensure it's running on Rust 1.94+.
-
Deleted deprecated runtime+TLS combination features: The PR correctly keeps
runtime-tokioandtls-rustlsas separate features.
Suggested next steps
- Blocking: Wrap the two
format!()query usages inAssertSqlSafe()(see inline comments) - Non-blocking: Run full test suite to catch any type inference changes from #3541
- Non-blocking: Verify Rust MSRV is 1.94.0 or higher
- Non-blocking: Run
cargo sqlx prepareafter upgrade to regenerate.sqlx/cache
General findings
The upgrade is straightforward for most usage patterns - string literal queries will continue to work without modification. However, the two dynamic query constructions using format!() will fail to compile without the AssertSqlSafe wrapper. This is an intentional design change in sqlx 0.9 to make SQL injection risks more visible at code review time.
No usage of the affected Migrator methods (set_ignore_missing, set_locking, resolve_blocking) was found, so those breaking changes don't impact this codebase.
The feature flags used (runtime-tokio, postgres, uuid, chrono, json, tls-rustls) are all still valid in 0.9.
General findings (auto-demoted from inline due to pre-validation)
- Blocking
src/manager/postgres.rs:3723— Thisformat!()call will fail to compile after upgrading to sqlx 0.9.- (demoted: path "src/manager/postgres.rs" is not in the PR diff)
- Blocking
src/manager/postgres.rs:3755— Thisformat!()call will fail to compile after upgrading to sqlx 0.9.- (demoted: path "src/manager/postgres.rs" is not in the PR diff)
| hostname = "0.4" | ||
| dashmap = { version = "6", features = ["serde"] } | ||
| sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "uuid", "chrono", "json", "tls-rustls"], optional = true } | ||
| sqlx = { version = "0.9", features = ["runtime-tokio", "postgres", "uuid", "chrono", "json", "tls-rustls"], optional = true } |
There was a problem hiding this comment.
Blocking: This sqlx 0.9 upgrade introduces a breaking change that will cause compilation failures in this file.
Why it matters: In sqlx 0.9, PR #3723 introduced the SqlSafeStr trait which all query*() functions now require. This trait is only implemented for &'static str and AssertSqlSafe<String>. The two uses of format!() to build dynamic SQL queries below (lines 3723 and 3755) will fail to compile because String no longer implements the required trait bound.
From the sqlx 0.9 changelog:
Breaking change: all
query*()functions now takeimpl SqlSafeStrwhich is only implemented for&'static strandAssertSqlSafe. For all others, wrap inAssertSqlSafe(<query>).
Suggested fix: Import sqlx::AssertSqlSafe and wrap the format!() calls:
use sqlx::AssertSqlSafe;
// Line ~3723
let plan_json: serde_json::Value = sqlx::query_scalar(AssertSqlSafe(&format!(
// ...
)))
// Line ~3755
let data: Vec<crate::request::RequestSummary> = sqlx::query_as(AssertSqlSafe(&format!(
// ...
)))Note: You may need to pass AssertSqlSafe(format!(...)) directly (without &) depending on the exact signature, as AssertSqlSafe wraps the String itself.
This PR contains the following updates:
0.8→0.9Release Notes
launchbadge/sqlx (sqlx)
v0.9.0Compare Source
Important Announcements
New Github Organization
Shortly after this release is published, the SQLx repository will be transferred to a new GitHub organization:
https://github.com/transact-rs/
This is because SQLx has not been owned or maintained by LaunchBadge, LLC. for a few years now, and has since been
informally transferred to the collective ownership of its principal authors. Moving the repository to a new
organization makes this change more clear, and also allows for potentially inviting outside collaborators.
Cargo.lockRemoved from TrackingThe
Cargo.lockhas been removed from tracking in Git. CI should now always test with the latest versions ofall dependencies by default, alongside our pass that checks with
cargo generate-lockfile -Z minimal-versions.This should eliminate the need for any PRs that update dependencies to also update
Cargo.lockorcontend with an endless stream of merge conflicts against it.
N.B.
cargo install --locked sqlx-cliwill no longer work. However,cargo install sqlx-clihas alwaysused the latest dependencies by default, ignoring the lockfile, so most users should not be affected. For users
requiring reproducible builds, consider maintaining your own lockfile instead; historically, we only ran
cargo updatesporadically, so relying on SQLx's lockfile offered few guarantees anyway.
See the manual page for
cargo installfor details.Breaking
As per our MSRV policy, the supported Rust version for this release cycle is
1.94.0.sqlx.tomlformat [[@abonander]]sqlx-clinow support per-crate configuration files (sqlx.toml)DATABASE_URLfor a crate (for multi-database workspaces)_sqlx_migrationstable (for multiple crates using the same database)sqlx-tomlto use.sqlx-clihas it enabled by default, butsqlxdoes not.so it's better to keep the default feature set as limited as possible.
This is something we learned the hard way.
sqlx::_configmodule in documentation.DATABASE_URLrenaming and global type overrides: [Link]_sqlx_migrationsrenaming and multiple schemas: [Link]chronowhentimeis enabled (e.g. when usingtower-sessions-sqlx-store): [Link]bigdecimalwhenrust_decimalis enabled is also shown, but problems withchrono/timeare more common.Migratetraitsqlx::migrate::resolve_blocking()is now#[doc(hidden)]and thus SemVer-exempt.tracinglogs from SQLx will need to update the spelling.PgAdvisoryLockGuard[[@bonsairobo]]Migrator::set_ignore_missingandset_lockingnow return&mut Selfinstead of&Selfwhich may break code in rare circumstances.
query!()macros for certain queries in Postgres.RawSqllifetime issues [[@abonander]]DBtype parameter to all methods ofRawSqlDecode,EncodeandTypeforBox,Arc,CowandRc[[@joeydewaal]]impl Decode for Cownow always decodesCow::Owned, lifetime is unlinkedquery*()functions now takeimpl SqlSafeStrwhich is only implemented for
&'static strandAssertSqlSafe.For all others, wrap in
AssertSqlSafe(<query>).Query<'static, DB>.SqlSafeStrtrait is deliberately similar tostd::panic::UnwindSafe,serving as a speedbump to warn users about naïvely building queries with
format!()while allowing a workaround for advanced usage that is easy to spot on code review.
PgConnectOptions::options()are now automatically escaped.Manual escaping of options is no longer necessary and may cause incorrect behavior.
runtime-tokio-native-tls)TransactionManagertrait insqlx.#[doc(hidden)],but it will break SeaORM if not proactively fixed.
str[[@abonander]]Vec<u8>will be inferred to beString(this should ultimately fix more code than it breaks).
SET NAMES utf8mb4 COLLATE utf8_general_ciis no longer sent by default; instead,SET NAMES utf8mb4is sent toallow the server to select the appropriate default collation (since this is version- and configuration-dependent).
MySqlConnectOptions::charset()and::collation()now imply::set_names(true)because they don't do anything otherwise.charsetdoesn't change what's sent in theProtocol::HandshakeResponse41packet as that normally onlymatters for error messages before
SET NAMESis sent.The default collation if
set_names = falseisutf8mb4_general_ci.RawSql::fetch_optional()now returnssqlx::Result<Option<DB::Row>>instead of
sqlx::Result<DB::Row>. Whoops.libsqlite3-sysversioning, feature flags, safety changes [[@abonander]]libsqlite3-sysversion is now specified using a range.The maximum of the range may now be increased in any backwards-compatible release.
The minimum of the range may only be increased in major releases.
If you have
libsqlite3-sysin your dependencies, Cargo should choose a compatible version automatically.If otherwise unconstrained, Cargo should choose the latest version supported.
sqlx-tomlfeature) is nowunsafe.sqlite-deserializeenablingSqliteConnection::serialize()andSqliteConnection::deserialize()sqlite-load-extensionenablingSqliteConnectOptions::extension()and::extension_with_entrypoint()sqlite-unlock-notifyenables internal use ofsqlite3_unlock_notify()SqliteValueandSqliteValueRefchanges:sqlite3_value*interface reserves the right to be stateful.Without protection, any call could theoretically invalidate values previously returned, leading to dangling pointers.
SqliteValueis now!SyncandSqliteValueRefis!Sendto prevent data races from concurrent accesses.SqliteValueinMutex, or convert theSqliteValueRefto an owned value.SqliteValueand any derivedSqliteValueRefs now internally track if that value has been used to decode aborrowed
&[u8]or&strand errors if it's used to decode any other type.per
SqliteValue/SqliteValueRef.SqliteValuefor details.PgLTree::fromtoFrom<Vec<PgLTreeLabel>>implementation [[@JerryQ17]]SqliteArguments[[@iamjpotts]].pgpassfile handling did not process backslash-escapes in the password part.Now it does, which may change what password is sent to the server.
#[derive(sqlx::Type)]automatically generateimpl PgHasArrayTypeby default for newtype structs [[@papaj-na-wrotkach]]Delete the manual impl or add
#[sqlx(no_pg_array)]where conflicts occur.offlineoptional to allow building withoutserde[[@CathalMullan]]mysql-rsafeatureor an error will be generated at runtime. RSA encryption is only used for plaintext (non-TLS) connections.
AnyTypeInfo[[@abonander]]Added
Arc<str>andArc<[u8]>(andRcequivalents) [[@joeydewaal]]runtime-smolandruntime-async-global-executorfeatures to replace usages of the deprecatedasync-stdcrate.no_txmigration support [[@AlexTMjugador]]Migrator::with_migrations()constructor [[@xb284524239]]sqlx.toml, update SQLite extension example [[@supleed2]]Json::into_inner()[[@chrxn1c]]SqlStr[[@joeydewaal]]PgNotificationstruct clone [[@michaelvanstraten]]Changed
OnceCell/Lazywith stdOnceLock/LazyLock[[@paolobarbolini]]Debugimplementations acrossPgRow,MySqlRowandSqliteRow[[@davidcornu]]QueryLoggerback [[@joeydewaal]].bind()inREADME.md[[@sobolevn]]randetceterato0.11.0libsqlite3-sysversion range to<0.38.0Fixed
futuresandfutures-util[[@paolobarbolini]]Pool.close: close all connections before returning [[@jpmelos]]ROLLBACKtransaction when dropped duringBEGIN. [[@kevincox]].envloading, caching, and invalidation [[@abonander]]which served as a useful comparison.
Command::cargo_bin()[[@abonander]]SASLprep[[@var4yn]]from_utf8_uncheckedwithfrom_utf8in SQLite column name handling [[@barry3406]]StdSocket::poll_ready()[[@abonander]]Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.