Coding的痕迹

一位互联网奔跑者的网上日记

0%

Diesel 中 count 行数

最近在用 Diesel 查询符合条件的行数时遇到了个问题。按照官方例子

1
2
let count = users.count().get_result(&connection);
assert_eq!(Ok(2), count);

get_result 返回一个 Result,在例子中是 Ok(2)。于是我写了这样一段代码:

1
2
3
4
5
6
7
8
let connection = establish_connection();
let uid_bindings_count = verifications.filter(uid.eq(self.uid))
.count()
.get_result(&connection)?;

if uid_bindings_count < 2 {
return Err(OpError(NoMoreVerification));
}

但是编译的时候报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
error[E0277]: can't compare `()` with `i32`
--> src\user\manager.rs:74:31
|
74 | if uid_bindings_count < 2 {
| ^ no implementation for `() < i32` and `() > i32`
|
= help: the trait `std::cmp::PartialOrd<i32>` is not implemented for `()`

error[E0277]: the trait bound `(): diesel::Queryable<diesel::sql_types::BigInt, diesel::pg::Pg>` is not satisfied
--> src\user\manager.rs:73:14
|
73 | .get_result(&connection)?;
| ^^^^^^^^^^ the trait `diesel::Queryable<diesel::sql_types::BigInt, diesel::pg::Pg>` is not implemented for `()`
|
= note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<diesel::PgConnection, ()>` for `diesel::query_builder::SelectStatement<schema::verifications::table, diesel::query_builder::select_clause::SelectClause<diesel::dsl::CountStar>, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::WhereClause<diesel::expression::operators::Eq<schema::verifications::columns::uid, diesel::expression::bound::Bound<diesel::sql_types::Integer, i32>>>>`

注意到上面出现了两个错误,第一个错误中编译器认为 uid_bindings_count 的类型是空类型(),感觉是 get_result 的问题。再看第二个错误,get_result 似乎无法执行查询,还是类型问题。实在解决不了,在社区群里问了下,有人说可能是例子过时了。

后来余光一瞟,看到 example 中有这样的写法:

1
2
3
4
5
// This will return `NotFound`, as there is no user with ID 4
let update_result = update(users.find(4))
.set(name.eq("Jim"))
.get_result::<(i32, String)>(&connection);
assert_eq!(Err(diesel::NotFound), update_result);

于是将我的代码改成

1
2
3
let uid_bindings_count = verifications.filter(uid.eq(self.uid))
.count()
.get_result::<(i32)>(&connection)?;

还是不行。求助于网友 i@c0de.me,后来解决了这个问题,在此表示感谢!因为结果是一个整数,并且 PostgreSQL 用 i64 表示行号,所以改成

1
2
3
let uid_bindings_count = verifications.filter(uid.eq(self.uid))
.count()
.get_result::<i64>(&connection)?;

就好了。

回过头来看 get_result 的声明:

1
2
fn get_result<U>(self, conn: &Conn) -> QueryResult<U> where
Self: LoadQuery<Conn, U>,

get_result 需要指定具体类型 U 。之前文档上的例子可能确实过时了吧。在此记录一下,并为后来人提供参考。 diesel 的内容,可能很多的依赖于文档,而文档和代码紧密结合,并没有特别丰富的 guide。很多时候就需要自己花时间去探索和踩坑了。

以上。

希望收获一份惊喜