本来标题是“惨痛的经历”,想想去掉了。 ——题记
(2021.2.16 更新:建议使用 sqlx
库,而不要直接使用 tokio-postgres
或 postgres
)
在项目中打算使用 PostgresSQL 做主力数据库,发现 Rust 下有个叫 postgres 的库,正好直接拿来用。 Rust 版本为 1.41,postgres 库版本 0.17。库官方给了 example,照着改了下,写了一小段业务代码做测试,然后一晚上就没了:
1 | use postgres::{Client, NoTls}; |
在 Cargo.toml
中加入:
1 | [dependencies] |
兴冲冲地去编译,得到了以下错误:
1 | error[E0277]: the trait bound `chrono::datetime::DateTime<chrono::offset::local::Local>: postgres_typ |
我的数据库中create_time
字段是 timestamptz
类型的。按照错误提示,DateTime<Local>
没有实现ToSql
trait。于是接着翻文档,开始没有太注意,后来在社区QQ群友的提示下,说我可能少加了feature
。再一次看了一遍,发现文档中提到了:
In addition, some implementations are provided for types in third party crates. These are disabled by default; to opt into one of these implementations, activate the Cargo feature corresponding to the crate’s name prefixed by
with-
. For example, thewith-serde_json-1
feature enables the implementation for theserde_json::Value
type.
后面跟着一张表,有这样的数据:
Rust type | Postgres type(s) |
---|---|
serde_json::Value |
JSON, JSONB |
chrono::DateTime |
TIMESTAMP WITH TIME ZONE |
但是实现(impl)chrono
对应的with-
是啥也没说。没说就自己编呗,试了几个,发现不行。在postgres
的源码里搜feature
也没有找到特别有用的信息,后来看到了这篇《【RUST】Restful API Server(8)–postgres里的时间格式》,开拓了思路,在postgres
目录下的Cargo.toml
中找到了支持的 features:
1 | [features] |
行,叫with-chrono-0_4
。于是改了下项目的Cargo.toml
:
1 | postgres = { version = "0.17.1", features = ["with-chrono-0_4"] } |
再次编译运行,仍然找不到 ToSql
trait。后来在 Stack Overflow 上找到了上个月的一个提问, 类似问题。我完全使用上面的代码,依然编译不过。
打算改用 diesel 库,但又有些不甘心。装好之后重启过一次电脑,发现cargo build
又能跑通了。运行发现:
1 | thread 'main' panicked at 'INSERT INTO 错误: Error { kind: ToSql(3), cause: Some(WrongType { postgres |
又回去看了下简书上的那篇博文,发现作者用的是 0.16
版本的 postgres 库(Stack overflow下的回答用的是 0.15
版本,但接口不太样,遂放弃)。于是降版本,编译通过。猜测是升到0.17
版本时库内部的代码或实现有些不稳定。
更加坚定了我用 diesel 的决心。以上。