代码之家  ›  专栏  ›  技术社区  ›  Ross Rogers

是否可以将装箱过滤器通用化以应用于单个表或预设该表的任何查询集?

  •  0
  • Ross Rogers  · 技术社区  · 3 年前

    如何将通用装箱过滤器应用于包含表的查询集以及该表所在的其他所有查询集?

    对于下面的玩具示例,有没有办法制作 get_filter 返回可以应用于具有 Foo 桌上有

    use diesel::*;
    use diesel::expression::*;
    use std::boxed::Box;
    
    type DB = diesel::pg::Pg;
    
    diesel::table! {
        Foo (id) {
            id -> Int4,
        }
    }
    
    diesel::table! {
        Bar (id) {
            id -> Int4,
            foo_id -> Int4,
        }
    }
    
    diesel::allow_tables_to_appear_in_same_query!(
        Foo,
        Bar,
    );
    
    pub fn get_queryset<'a>() -> Foo::BoxedQuery<'a, DB> {
        Foo::table.into_boxed()
    }
    
    use diesel::helper_types::*;
    type QuerySetJoinType<'a> = IntoBoxed<
        'a,
        Filter<                                     
            InnerJoinOn<Foo::table, Bar::table, Eq<Bar::foo_id, Foo::id>>,
            Eq<Bar::id, diesel::expression::SqlLiteral<diesel::sql_types::Integer>>
        >,
        DB
    >;
    
    pub fn get_queryset_with_join<'a>() -> QuerySetJoinType<'a> {
        Foo::table
            .inner_join(Bar::table.on(Bar::foo_id.eq(Foo::id)))
            .filter(Bar::id.eq(42))
            .into_boxed()
    }
    
    type FilterReturnType = Box<dyn BoxableExpression<Foo::table, DB, SqlType = diesel::sql_types::Bool>>;
    
    pub fn get_filter<'a>() -> FilterReturnType {
        let mut result : FilterReturnType = Box::new(Foo::id.eq(Foo::id));
        result = Box::new(result.and(Foo::id.gt(42)));
        result
    }
    
    
    fn main() {
        get_queryset().filter(get_filter());
        
        get_queryset_with_join().filter(get_filter());
    }
    

    这是抱怨

       |
    58 |     get_queryset_with_join().filter(get_filter());
       |                              ^^^^^^ the trait `AppearsOnTable<JoinOn<query_source::joins::Join<Foo::table, Bar::table, Inner>, diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<Bar::columns::foo_id, Foo::columns::id>>>>` is not implemented for `dyn diesel::BoxableExpression<Foo::table, Pg, SqlType = Bool>`
    
    

    我想我可以通过参数化查询集来实现这一点,比如:

    pub fn get_filter<'a, QS>() -> Box<dyn BoxableExpression<QS, DB, SqlType = diesel::sql_types::Bool>> {
        let mut result : Box<dyn BoxableExpression<QS, DB, SqlType = diesel::sql_types::Bool>> 
            = Box::new(Foo::id.eq(Foo::id));
        result = Box::new(result.and(Foo::id.gt(42)));
        result
    }
    

    但我被困在了需要设定的特质界限上 QS ?

    有什么想法吗?

    这个问题 类似 this other question ,除了我实际上想要函数的类型,而且我们现在使用的是柴油机的版本2

    0 回复  |  直到 3 年前
        1
  •  1
  •   Ross Rogers    3 年前

    @韦兹尼奇为 gitter.im/diesel-rs/diesel 使查询函数通用为:

    pub fn get_filter<'a, QS>() -> Box<dyn BoxableExpression<QS, DB, SqlType = diesel::sql_types::Bool>>
    where
        QS: 'static,
        dsl::Eq<Foo::id, Foo::id>: BoxableExpression<QS, DB>,
        dsl::Gt<Foo::id, i32>: BoxableExpression<QS, DB>,
        dsl::AssumeNotNull<dsl::Eq<Foo::label, String>>: BoxableExpression<QS, DB>,
    {
        let mut result : Box<dyn BoxableExpression<QS, DB, SqlType = diesel::sql_types::Bool>>
            = Box::new(Foo::id.eq(Foo::id));
        result = Box::new(result.and(Foo::id.gt(42)));
        let s = "asdf".to_string();
        result = Box::new(result.and(
            Foo::label.eq(s).assume_not_null()));
        result
    }
    
    推荐文章