数据库后端【免费下载链接】sqlx The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.项目地址https://gitcode.com/gh_mirrors/sql/sqlx点击查看免费下载SQLx 是一个面向 Rust 的异步 SQL 工具包主打无需 DSL 的编译期查询校验同时支持 PostgreSQL、MySQL/MariaDB 与 SQLite。本文以官方 README 为主线结合仓库源码系统讲解依赖与 feature 配置、连接池、查询 API、query!宏的编译期校验原理以及配套的 sqlx-cli 离线构建工作流帮助你从零搭建一个类型安全、可并发的数据库应用。项目概览SQLx 到底是什么SQLx 的核心定位是async、pure Rust 的 SQL 库它不提供 ORM 式的对象映射 API而是直接以 SQL 字符串为输入通过宏在编译期让数据库本身帮你验证查询。README 中概括了它的几大设计取向真正异步从底层起基于async/await构建最大化并发能力。编译期检查查询可选即query!系列宏见下文SQLx 不是 ORM一节。数据库无关支持 [PostgreSQL]、[MySQL]、[MariaDB]、[SQLite]MSSQL 在 0.7 版本之前曾被支持之后被移除等待官方驱动重写。纯 RustPostgres 与 MySQL/MariaDB 驱动用纯 Rust 编写且使用零unsafe代码SQLite 例外见安全承诺一节。运行时无关兼容 [async-std]、[tokio]、[actix] 等运行时以及 [native-tls]、[rustls] 两种 TLS 后端。此外还有一批面向工程化的能力均有对应源码实现内建连接池sqlx::Pool实现位于 sqlx-core/src/pool/mod.rs。行流式读取数据从数据库异步读出按需解码。自动语句准备与缓存使用高层查询 APIsqlx::query时语句按连接准备并缓存。简单非 prepared查询执行同样支持批量执行并返回所有语句的结果。TLS 支持MySQL/MariaDB 与 PostgreSQL 均支持需开启对应 TLS feature。异步通知PostgreSQL 的LISTEN/NOTIFY。嵌套事务支持保存点savepoint。Any驱动可在运行时按 URL scheme 切换底层数据库驱动。快速上手安装与 Cargo Feature 组合SQLx 兼容 [async-std]、[tokio]、[actix] 运行时以及 [native-tls]、[rustls] TLS 后端。添加依赖时必须选择一个runtime tls的组合README 给出了完整的示例清单# Cargo.toml [dependencies] # PICK ONE OF THE FOLLOWING: # tokio (no TLS) sqlx { version 0.9, features [ runtime-tokio ] } # tokio native-tls sqlx { version 0.9, features [ runtime-tokio, tls-native-tls ] } # tokio rustls with ring and WebPKI CA certificates sqlx { version 0.9, features [ runtime-tokio, tls-rustls-ring-webpki ] } # tokio rustls with ring and platforms native CA certificates sqlx { version 0.9, features [ runtime-tokio, tls-rustls-ring-native-roots ] } # tokio rustls with aws-lc-rs sqlx { version 0.9, features [ runtime-tokio, tls-rustls-aws-lc-rs ] } # async-std (no TLS) sqlx { version 0.9, features [ runtime-async-std ] } # async-std native-tls sqlx { version 0.9, features [ runtime-async-std, tls-native-tls ] } # async-std rustls with ring and WebPKI CA certificates sqlx { version 0.9, features [ runtime-async-std, tls-rustls-ring-webpki ] ] # async-std rustls with ring and platforms native CA certificates sqlx { version 0.9, features [ runtime-async-std, tls-rustls-ring-native-roots ] } # async-std rustls with aws-lc-rs sqlx { version 0.9, features [ runtime-async-std, tls-rustls-aws-lc-rs ] }运行时与 TLS feature 的取舍为保持向后兼容runtime 与 TLS feature 既可以合并成一个 feature 使用也可以分开声明。面向未来兼容应使用分开的 runtime 与 TLS feature因为合并型组合 feature 未来可能被移除。从仓库 Cargo.toml 的 feature 定义可以看到runtime-tokio、runtime-async-std等独立 feature 与tls-native-tls、tls-rustls-*系列是平级拆分的。运行时选择的具体规则见 src/lib.md若同时启用多个运行时 feature当前线程存在 Tokio 上下文即tokio::runtime::Handle::try_current()返回Ok时使用 Tokio否则使用 async-std。SQLx 不再对零个或多个运行时 feature产生编译错误方便库作者二次封装但几乎任何异步 API 在未启用至少一个运行时 feature 时调用都会 panic。唯一的例外是 SQLite 驱动本身与运行时无关不过SqlitePool的 timeout 与内部管理任务仍需要运行时支持。TLS 方面tls-native-tls使用操作系统原生 TLSmacOS 用 SecureTransport、Windows 用 SChannel、其他平台用 OpenSSLtls-rustls是跨平台实现仅支持 TLS 1.2 与 1.3。若使用 rustls 遇到HandshakeFailure通常意味着数据库服务器不支持这些新版本可尝试启用或切换tls-native-tls。同时启用多个 TLS feature 时tls-native-tls优先。若连接配置需要 TLS 升级但未启用 TLS feature连接会直接返回错误。Cargo Feature 全表README 完整列出了各 feature 的语义整理如下Feature说明runtime-async-std使用async-std运行时不启用 TLS 后端runtime-tokio使用tokio运行时不启用 TLS 后端Actix-web 与 Tokio 完全兼容无需单独的 runtime featuretls-native-tls使用native-tls后端*nix 用 OpenSSL、Windows 用 SChannel、macOS 用 Secure Transporttls-rustls使用rustls后端跨平台仅支持 TLS 1.2 与 1.3tls-rustls-aws-lc-rs使用rustlsaws-lc-rs加密提供者postgres支持 Postgres 数据库mysql支持 MySQL/MariaDB非 TLS 场景的 RSA 认证需要额外开启mysql-rsamysql-rsa在 TLS 关闭时为caching_sha2_password/sha256_password启用 RSA 密码加密仅在必须无 TLS 连接且服务器要求 RSA 认证时开启优先建议使用 TLSmssql支持 MSSQL 数据库sqlite支持内嵌 SQLite捆绑并静态链接 SQLitesqlite-unbundled同上但链接系统 SQLite 而非捆绑版本可独立升级或使用 fork 版本系统需安装 SQLite 或在构建时提供库路径SQLite 过旧低于 3.20.0可能链接失败因使用 bindgen 可能增加构建时间sqlite-preupdate-hook启用 SQLite 的 preupdate hook API默认不开启与sqlite-unbundled联用可能因系统 SQLite 版本不支持而链接失败any支持可在运行时代理到具体驱动的Any驱动derive启用 derive 宏家族FromRow、Type、Encode、Decodemacros启用query*!宏实现编译期检查查询migrate启用迁移管理与migrate!宏支持编译期内嵌迁移uuid支持 UUID 类型chrono支持chronocrate 的日期时间类型time支持timecrate 的日期时间类型与chrono二选一若两者都启用query!宏默认偏好timebstr支持bstr::BStringbigdecimal使用bigdecimalcrate 支持NUMERICrust_decimal使用rust_decimalcrate 支持NUMERICipnet支持 Postgres 的INET/CIDR基于ipnetipnetwork同上基于ipnetworkjson使用serde_json支持JSON/JSONBPostgres注意 README 中特别说明离线模式offline mode现已默认启用详见 sqlx-cli/README.md 的离线构建章节。另外从仓库根 Cargo.toml 可以看到sqlx的默认 features 为[any, macros, migrate, json]即默认就带上Any驱动、查询宏、迁移能力与 JSON 支持。编译期校验的设计哲学SQLx 不是 ORMREADME 用一个独立章节强调了这一设计立场SQLx 支持编译期检查查询但不是通过提供 Rust API 或 DSL 来构建查询而是提供以普通 SQL 为输入的宏并确保这些 SQL 对你的数据库是有效的。其工作方式是在编译时连接你的开发数据库让数据库自身去校验并返回相关信息SQL 查询。这会带来两个值得注意的推论由于 SQLx 从不自行解析 SQL 字符串任何开发数据库能接受的语法都能使用包括数据库扩展新增的语法。不同数据库允许查询方获取的信息量不同因此查询宏能做的校验程度取决于数据库。这一机制对应宏实现位于 sqlx-macros-core/src/query含输入解析、数据库连接、元数据缓存与输出生成等模块。如果你需要的是异步ORMREADME 建议查阅官方 Ecosystem wiki 页如ormx、SeaORM等。基础用法连接、连接池与查询仓库在 examples 目录提供了多数据库、多场景的完整示例Postgres/MySQL/SQLite 的 todos、事务、监听、多数据库、多租户等下面结合 README 的 Quickstart 与示例源码展开。QuickstartREADME 给出了一个最小可运行的程序use sqlx::postgres::PgPoolOptions; // use sqlx::mysql::MySqlPoolOptions; // etc. #[async_std::main] // Requires the attributes feature of async-std // or #[tokio::main] // or #[actix_web::main] async fn main() - Result(), sqlx::Error { // Create a connection pool // for MySQL/MariaDB, use MySqlPoolOptions::new() // for SQLite, use SqlitePoolOptions::new() // etc. let pool PgPoolOptions::new() .max_connections(5) .connect(postgres://postgres:passwordlocalhost/test).await?; // Make a simple query to return the given parameter (use a question mark ? instead of $1 for MySQL/MariaDB) let row: (i64,) sqlx::query_as(SELECT $1) .bind(150_i64) .fetch_one(pool).await?; assert_eq!(row.0, 150); Ok(()) }注意占位符的差异Postgres 使用$1MySQL/MariaDB 使用?。建立连接单个连接可通过任意数据库连接类型调用connect()建立src/lib.rs 统一导出了各数据库的连接与池类型use sqlx::Connection; let conn SqliteConnection::connect(sqlite::memory:).await?;但实际项目中通常建议改用连接池sqlx::Pool以调控应用占用服务端连接的数量let pool MySqlPool::connect(mysql://user:passhost/database).await?;连接池为什么应该用 Pool连接池模块的源码文档sqlx-core/src/pool/mod.rs详细解释了为什么要用池开连接的代价高对 SQLite 意味着大量文件系统请求与内存分配对服务端数据库则涉及 DNS 解析、新 TCP 连接、缓冲区分配以及复杂的握手认证、连接参数协商、加密隧道升级。服务端往往还要为每个连接派生线程/进程。连接上限MySQL/Postgres 等服务器通常对并发连接数设硬上限如 Postgres 默认约 100保留 3 个给超级用户。用池可以让客户端在连接耗尽时进入公平等待队列而不是直接报错或产生 500。资源复用prepared statement 与查询计划缓存通常按连接隔离池促成了连接的复用从而摊销准备语句的开销。Pool本身是Send Sync Clone的引用计数句柄内部为ArcPoolInnerDB建议在应用/服务启动时创建一次然后共享给所有任务。Pool可以直接传给任何需要Executor的地方自动为你借出连接sqlx::query(DELETE FROM table).execute(pool).await?;池的默认参数定义在 sqlx-core/src/pool/options.rs 的PoolOptions::new()中常用默认值如下配置项默认值语义max_connections10池可维护的最大连接数生产应用通常需要调高min_connections0池预建并尽力维持的最小连接数test_before_acquiretrue借出连接前调用Connection::ping校验健康度acquire_timeout30 秒acquire()等待连接的总时长上限超时返回PoolTimedOutacquire_slow_threshold2 秒超过该阈值视为慢获取并记日志acquire_slow_levelWarn慢获取的日志级别acquire_time_levelOff普通获取的日志级别默认关闭idle_timeout10 分钟空闲连接在池中停留的上限超时关闭按用量计费的服务可省钱max_lifetime30 分钟连接最大生命周期到期后回收避免服务端内存/资源泄漏fairtrueacquire()是否公平先到先得此外PoolOptions还支持三个回调after_connect连接建立后执行如设置application_name、search_path等连接参数、before_acquire借出前对空闲连接执行检查返回Ok(true)才借出、after_release归还时处理。由于 Rust 无法直接表达带高阶生命周期的闭包返回类型这些回调统一要求返回Box::pin的 future。关于优雅关闭Pool::close().await会唤醒所有等待者、拒绝后续acquire并等待所有连接归还后向服务器发送关闭消息由于没有 async drop仅靠 drop 最后一个Pool句柄可能不会立刻通知服务端服务端要等 TCP keepalive 超时频繁创建销毁池还可能触发连接上限错误因此文档明确建议在关闭阶段调用.close().await。查询prepared 与 unpreparedSQL 中的查询可分为prepared参数化与unprepared简单两类Prepared查询计划会被缓存使用二进制通信带宽更低、解码更快通过参数绑定避免 SQL 注入。Unprepared简单直接仅用于 prepared 无法工作的场景如PRAGMA、SET、BEGIN等数据库命令。SQLx 对两者都支持。在 SQLx 中str被视为 unprepared 查询Query/QueryAs结构体被视为 prepared 查询// low-level, Executor trait conn.execute(BEGIN).await?; // unprepared, simple query conn.execute(sqlx::query(DELETE FROM table)).await?; // prepared, cached query应优先使用高层query接口类型上有 finalizer终结器省去手动包 executor 的麻烦sqlx::query(DELETE FROM table).execute(mut conn).await?; sqlx::query(DELETE FROM table).execute(pool).await?;execute返回受影响行数并丢弃所有结果另有fetch、fetch_one、fetch_optional、fetch_all用于取回结果。sqlx::query返回的Query会产生Rowconn列值可用row.get()按序号或列名访问由于Row持有连接的不可变借用同一时刻只能存在一个Row。fetch返回类流类型可逐行迭代// provides try_next use futures_util::TryStreamExt; // provides try_get use sqlx::Row; let mut rows sqlx::query(SELECT * FROM users WHERE email ?) .bind(userexample.com) .fetch(mut conn); while let Some(row) rows.try_next().await? { // map the row into a user-defined domain type let email: str row.try_get(email)?; }把行映射为领域类型有两种惯用写法let mut stream sqlx::query(SELECT * FROM users) .map(|row: PgRow| { // map the row into a user-defined domain type }) .fetch(mut conn);#[derive(sqlx::FromRow)] struct User { name: String, id: i64 } let mut stream sqlx::query_as::_, User(SELECT * FROM users WHERE email ? OR name ?) .bind(userexample.com) .bind(example_username) .fetch(mut conn);若只需要单个结果用fetch_one必需结果或fetch_optional可选结果。事务事务通过Connection::begin/Pool::begin开启结束时应调用commit或rollback若两者都未调用就离开作用域drop时会自动回滚见 sqlx-core/src/transaction.rs。事务本身也实现了Executor可以直接在其上执行查询let mut tx conn.begin().await?; let result sqlx::query(DELETE FROM \testcases\ WHERE id $1) .bind(id) .execute(mut *tx) .await? .rows_affected(); tx.commit().await嵌套事务通过保存点savepoint实现TransactionManager的get_transaction_depth定义了深度语义——0 级无事务、1 级有活动事务、2 级及以上表示事务内建立了保存点。README 强调的嵌套事务 保存点能力即来自这一机制。编译期校验的查询宏query! 与 query_as!这是 SQLx 最具特色的能力。使用sqlx::query!宏可以在编译期获得 SQL 的语法与语义双重校验输出为匿名记录类型每个 SQL 列对应一个 Rust 字段必要时使用 raw identifierlet countries sqlx::query!( SELECT country, COUNT(*) as count FROM users GROUP BY country WHERE organization ? , organization ) .fetch_all(pool) // - Vec{ country: String, count: i64 } .await?; // countries[0].country // countries[0].count与query()的差异绑定参数必须一次性全部给出且编译期会校验参数的数量与类型是否正确。输出类型是匿名记录上例中类型形如{ country: String, count: i64 }。构建时必须设置DATABASE_URL环境变量指向一个可供准备语句的数据库该库不必有数据但必须与运行时连接的库同类型MySQL、Postgres 等且同 schema。为了方便可以用 [.env文件]基于dotenvycrate格式与dotenv相同持久化DATABASE_URLDATABASE_URLmysql://localhost/my_databasequery!()最大的缺点是输出类型无法命名Rust 尚未官方支持匿名记录因此提供了query_as!()宏除可命名输出类型外其余行为基本一致// no traits are needed struct Country { country: String, count: i64 } let countries sqlx::query_as!(Country, SELECT country, COUNT(*) as count FROM users GROUP BY country WHERE organization ? , organization ) .fetch_all(pool) // - VecCountry .await?; // countries[0].country // countries[0].count各数据库下的占位符与类型差异从仓库示例可看到不同数据库的细节差异Postgres使用$1占位符且可用RETURNING id直接拿回插入的 id见 examples/postgres/todos/src/main.rs。MySQL/MariaDB使用?占位符插入后通过.last_insert_id()获取自增 id且 MySQL 的布尔值实际存储为TINYINT(1)/i80 为 false、非 0 为 true因此读取done字段时要与! 0比较见 examples/mysql/todos/src/main.rs。以 Postgres todos 为例一个完整的 CRUD 流程长这样async fn add_todo(pool: PgPool, description: String) - anyhow::Resulti64 { let rec sqlx::query!( r# INSERT INTO todos ( description ) VALUES ( $1 ) RETURNING id #, description ) .fetch_one(pool) .await?; Ok(rec.id) } async fn complete_todo(pool: PgPool, id: i64) - anyhow::Resultbool { let rows_affected sqlx::query!( r# UPDATE todos SET done TRUE WHERE id $1 #, id ) .execute(pool) .await? .rows_affected(); Ok(rows_affected 0) }加速增量编译编译期校验在编译期做了不少工作。README 建议在Cargo.toml中加入以下配置让cargo check、cargo build的增量构建显著变快[profile.dev.package.sqlx-macros] opt-level 3离线模式offline mode如果项目代码数据库访问部分没有改动却仍需要开发数据库才能编译可以启用离线模式用 sqlx 命令行工具把 SQL 查询分析结果缓存下来。详细步骤见 sqlx-cli/README.md保存查询元数据cargo sqlx prepare必须通过cargo sqlx调用。它会将查询元数据写入当前目录的.sqlx若工作区有多个 crate 使用查询宏加--workspace会在工作区根生成统一的.sqlx目录。把该目录提交进版本控制后构建项目不再需要活动的数据库连接。构建之后正常cargo build即可。CI 场景可用cargo sqlx prepare --check或--check --workspace若.sqlx中的数据与当前数据库 schema 或项目中的查询不一致会以非零退出码结束。另外DATABASE_URL环境变量的优先级高于.sqlx目录——只要它存在SQLx 默认仍会尝试连数据库构建。若想强制离线可设置SQLX_OFFLINEtrue也可写入.env文件作为默认cargo sqlx prepare本身不受影响、仍会正常连库。对于 feature flag 或测试中的查询可通过给 cargo 传参来让 prepare 覆盖到例如cargo sqlx prepare -- --all-targets --all-features。进阶能力Listen/Notify、Any 驱动与迁移PostgreSQL 异步通知通过LISTEN/NOTIFY实现仓库示例见 examples/postgres/listen。Any 驱动AnyPool依据 URL scheme 在运行时选择底层驱动相关实现位于 src/any 与各驱动的any.rs。迁移migrationsqlx-cli 提供sqlx migrate add生成migrations/timestamp-name.sql、sqlx migrate run对比数据库迁移历史并执行待应用脚本、--source指定迁移目录、-r生成可逆迁移.up.sql/.down.sql之后所有迁移都会是可逆的以及sqlx migrate revert。数据库的创建/删除可用sqlx database create/sqlx database drop所有命令都通过--database-url或DATABASE_URL环境变量或.env文件提供连接信息。仓库各示例目录下都有真实的迁移文件可参考如 examples/postgres/todos/migrations/20200718111257_todos.sql。安全承诺与许可README 与 src/lib.rs 都确认SQLx 使用#![forbid(unsafe_code)]保证核心代码 100% Safe Rust。启用sqlitefeature 后会降级为#![deny(unsafe_code)]并仅对sqlx::sqlite模块放行unsafe——因为 SQLite 是嵌入式数据库纯 Rust 只能靠移植整个 SQLite 实现SQLx 的实际做法是通过libsqlite3-sys直接调用 SQLite3 C API。SQLx 官方欢迎社区对 unsafe 用法进行审计相关调用点集中在 sqlx-sqlite 的语句句柄与连接实现中。SQLx 采用Apache-2.0 或 MIT双许可以你选择的方式授权许可文本见 LICENSE-APACHE 与 LICENSE-MIT。除非明确另行声明按 Apache-2.0 定义提交的贡献均按上述双许可授权。总结SQLx 的竞争力来自三件事的叠加纯 Rust 异步驱动连接、流式读取、池、事务全套齐备、以数据库为裁判的编译期查询校验query!/query_as! 离线缓存以及跨数据库、跨运行时、跨 TLS 后端的可组合 feature 体系。上手路径很清晰先按 README 的组合表配好依赖用PgPoolOptions之类建池再用query!享受编译期保障遇到无库可连的 CI 场景就把cargo sqlx prepare与SQLX_OFFLINE纳入构建流程。赞分享数据库后端【免费下载链接】sqlx The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.项目地址https://gitcode.com/gh_mirrors/sql/sqlx点击查看免费下载相关推荐使用 SQLx 管理 Tabby 数据库从编译期查询校验到迁移工作流使用 SQLx 管理 Tabby 数据库从编译期查询校验到迁移工作流 TabbySelf hosted AI coding assistant使用 SQL人工智能大模型本地部署模型推理服务后端RAG交互助手Ajv 异步验证完全指南用 $async 与异步关键词构建数据库查询校验Ajv 异步验证完全指南用 $async 与异步关键词构建数据库查询校验 导读 Ajv 不仅是一个同步的 JSON Schema 验证器还内置了一整套异步验后端API设计如何用GitHub Insights追踪Rainmeter社区贡献统计完整指南如何用GitHub Insights追踪Rainmeter社区贡献统计完整指南 Rainmeter是一款强大的Windows桌面自定义工具它让用户能够创建个桌面应用上一篇PptxGenJS 安装配置教程5 分钟上手这款 JavaScript PPT生成库下一篇connectedhomeip 的 CHIPTool Android 演示应用jniLibs 原生库目录结构与 ABI 组织指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考