Diesel:table 及其连接上的 BoxableExpressions 泛型?
Diesel: BoxableExpressions generic over a table and its joins?
我正在尝试在 运行 时构建一些过滤器,这些过滤器可以应用于 table tunnel
或 tunnel LEFT OUTER JOIN connection ON (tunnel.id = connection.tunnel_id)
。
table的定义如下:
// Define the tunnel table and struct
table! {
#[allow(unused_imports)]
use diesel::sql_types::*;
tunnel (id) {
id -> BigInt,
name -> Text,
}
}
#[derive(Queryable, Identifiable, Clone, Debug, PartialEq, Eq)]
#[table_name = "tunnel"]
pub struct Tunnel {
pub id: i64,
pub name: String,
}
// Define the connection table and struct
table! {
#[allow(unused_imports)]
use diesel::sql_types::*;
connection(id) {
id -> BigInt,
tunnel_id -> BigInt,
}
}
#[derive(Debug, Associations, Identifiable, Queryable)]
#[table_name = "connection"]
#[primary_key(id)]
#[belongs_to(Tunnel)]
pub struct Connection {
pub id: i64,
pub tunnel_id: i64,
}
joinable!(connection -> tunnel(tunnel_id));
allow_tables_to_appear_in_same_query!(connection, tunnel);
我可以编写一个函数,为单个 table:
构造动态
fn filters_t(
name: &'static str,
) -> Vec<Box<dyn BoxableExpression<tunnel::table, Pg, SqlType = Bool>>> {
let mut wheres: Vec<Box<dyn BoxableExpression<tunnel::table, Pg, SqlType = Bool>>> = Vec::new();
wheres.push(Box::new(tunnel::name.eq(name)));
wheres
}
或加入:
pub type TunnelJoinConnection = JoinOn<
Join<tunnel::table, connection::table, LeftOuter>,
Eq<Nullable<connection::columns::tunnel_id>, Nullable<tunnel::columns::id>>,
>;
fn filters_j(
name: &'static str,
) -> Vec<Box<dyn BoxableExpression<TunnelJoinConnection, Pg, SqlType = Bool>>> {
let mut wheres: Vec<Box<dyn BoxableExpression<TunnelJoinConnection, Pg, SqlType = Bool>>> =
Vec::new();
wheres.push(Box::new(tunnel::name.eq(name)));
wheres
}
请注意,这两个过滤器函数具有完全相同的函数体,因此我应该能够制作一个实现这两个函数的通用函数。但是当我尝试使其通用时出现错误。
fn filters<T>(name: &'static str) -> Vec<Box<dyn BoxableExpression<T, Pg, SqlType = Bool>>>
where
T: AppearsInFromClause<tunnel::table, Count = Once>,
{
vec![Box::new(tunnel::name.eq(name))]
}
错误是
|
85 | vec![Box::new(tunnel::name.eq(name))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::SelectableExpression<T>` is not implemented for `tunnel::columns::name`
|
= note: required because of the requirements on the impl of `diesel::SelectableExpression<T>` for `diesel::expression::operators::Eq<tunnel::columns::name, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>>`
= note: required because of the requirements on the impl of `diesel::BoxableExpression<T, diesel::pg::Pg>` for `diesel::expression::operators::Eq<tunnel::columns::name, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>>`
= note: required for the cast to the object type `dyn diesel::BoxableExpression<T, diesel::pg::Pg, SqlType = diesel::sql_types::Bool>`
最小示例 here,您可以克隆该最小示例并 运行 cargo check
自己查看错误。
这可以通过一个小改动来解决:
fn filters<T>(name: &'static str) -> Vec<Box<dyn BoxableExpression<T, Pg, SqlType = Bool>>>
where
diesel::dsl::Eq<tunnel::name, &'static str>: BoxableExpression<T, Pg, SqlType = Bool>,
{
vec![Box::new(tunnel::name.eq(name))]
}
基本上您需要在编译时断言您的盒装表达式确实为所有可能的 T
实现了 BoxableExpression<T, Pg, SqlType = Bool>
。如果只有一个特定的 T
被 rustc 检查,对于一般情况,这需要明确地写出来。 diesel::dsl::Eq
帮助器类型是 tunnel::name.eq(name)
返回类型的类型级构造函数。这意味着您需要为添加到列表中的每个表达式添加一个类似的子句。
另一个不相关的注释:
pub type TunnelJoinConnection = JoinOn<
Join<tunnel::table, connection::table, LeftOuter>,
Eq<Nullable<connection::columns::tunnel_id>, Nullable<tunnel::columns::id>>,
>;
使用不属于 public API 柴油的类型。这意味着这样的表达式可以随着任何更新而中断。使用 public API 编写此类型的正确方法是
pub type TunnelJoinConnection = diesel::dsl::LeftJoin<tunnel::table, connection::table>;`
我正在尝试在 运行 时构建一些过滤器,这些过滤器可以应用于 table tunnel
或 tunnel LEFT OUTER JOIN connection ON (tunnel.id = connection.tunnel_id)
。
table的定义如下:
// Define the tunnel table and struct
table! {
#[allow(unused_imports)]
use diesel::sql_types::*;
tunnel (id) {
id -> BigInt,
name -> Text,
}
}
#[derive(Queryable, Identifiable, Clone, Debug, PartialEq, Eq)]
#[table_name = "tunnel"]
pub struct Tunnel {
pub id: i64,
pub name: String,
}
// Define the connection table and struct
table! {
#[allow(unused_imports)]
use diesel::sql_types::*;
connection(id) {
id -> BigInt,
tunnel_id -> BigInt,
}
}
#[derive(Debug, Associations, Identifiable, Queryable)]
#[table_name = "connection"]
#[primary_key(id)]
#[belongs_to(Tunnel)]
pub struct Connection {
pub id: i64,
pub tunnel_id: i64,
}
joinable!(connection -> tunnel(tunnel_id));
allow_tables_to_appear_in_same_query!(connection, tunnel);
我可以编写一个函数,为单个 table:
构造动态fn filters_t(
name: &'static str,
) -> Vec<Box<dyn BoxableExpression<tunnel::table, Pg, SqlType = Bool>>> {
let mut wheres: Vec<Box<dyn BoxableExpression<tunnel::table, Pg, SqlType = Bool>>> = Vec::new();
wheres.push(Box::new(tunnel::name.eq(name)));
wheres
}
或加入:
pub type TunnelJoinConnection = JoinOn<
Join<tunnel::table, connection::table, LeftOuter>,
Eq<Nullable<connection::columns::tunnel_id>, Nullable<tunnel::columns::id>>,
>;
fn filters_j(
name: &'static str,
) -> Vec<Box<dyn BoxableExpression<TunnelJoinConnection, Pg, SqlType = Bool>>> {
let mut wheres: Vec<Box<dyn BoxableExpression<TunnelJoinConnection, Pg, SqlType = Bool>>> =
Vec::new();
wheres.push(Box::new(tunnel::name.eq(name)));
wheres
}
请注意,这两个过滤器函数具有完全相同的函数体,因此我应该能够制作一个实现这两个函数的通用函数。但是当我尝试使其通用时出现错误。
fn filters<T>(name: &'static str) -> Vec<Box<dyn BoxableExpression<T, Pg, SqlType = Bool>>>
where
T: AppearsInFromClause<tunnel::table, Count = Once>,
{
vec![Box::new(tunnel::name.eq(name))]
}
错误是
|
85 | vec![Box::new(tunnel::name.eq(name))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::SelectableExpression<T>` is not implemented for `tunnel::columns::name`
|
= note: required because of the requirements on the impl of `diesel::SelectableExpression<T>` for `diesel::expression::operators::Eq<tunnel::columns::name, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>>`
= note: required because of the requirements on the impl of `diesel::BoxableExpression<T, diesel::pg::Pg>` for `diesel::expression::operators::Eq<tunnel::columns::name, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>>`
= note: required for the cast to the object type `dyn diesel::BoxableExpression<T, diesel::pg::Pg, SqlType = diesel::sql_types::Bool>`
最小示例 here,您可以克隆该最小示例并 运行 cargo check
自己查看错误。
这可以通过一个小改动来解决:
fn filters<T>(name: &'static str) -> Vec<Box<dyn BoxableExpression<T, Pg, SqlType = Bool>>>
where
diesel::dsl::Eq<tunnel::name, &'static str>: BoxableExpression<T, Pg, SqlType = Bool>,
{
vec![Box::new(tunnel::name.eq(name))]
}
基本上您需要在编译时断言您的盒装表达式确实为所有可能的 T
实现了 BoxableExpression<T, Pg, SqlType = Bool>
。如果只有一个特定的 T
被 rustc 检查,对于一般情况,这需要明确地写出来。 diesel::dsl::Eq
帮助器类型是 tunnel::name.eq(name)
返回类型的类型级构造函数。这意味着您需要为添加到列表中的每个表达式添加一个类似的子句。
另一个不相关的注释:
pub type TunnelJoinConnection = JoinOn<
Join<tunnel::table, connection::table, LeftOuter>,
Eq<Nullable<connection::columns::tunnel_id>, Nullable<tunnel::columns::id>>,
>;
使用不属于 public API 柴油的类型。这意味着这样的表达式可以随着任何更新而中断。使用 public API 编写此类型的正确方法是
pub type TunnelJoinConnection = diesel::dsl::LeftJoin<tunnel::table, connection::table>;`