Repository: diesel-rs/diesel
File: diesel_derives/src/selectable.rs (Rust)

Code before:

    let (impl_generics, _, where_clause) = generics.split_for_impl();

    let struct_name = &item.ident;

    let field_columns_ty = model
        .fields()
        .iter()
        .map(|f| field_column_ty(f, &model))
        .collect::<Vec<_>>();
    let field_columns_inst = model.fields().iter().map(|f| field_column_inst(f, &model));

    let field_check_bound = model
        .fields()
        .iter()
        .zip(&field_columns_ty)
        .filter(|(f, _)| !f.embed())
        .flat_map(|(f, ty)| {
            let field_ty = to_field_ty_bound(&f.ty);
            let span = field_ty.span();
            let mut out = Vec::new();
            if let Some(field_ty) = field_ty {

                if cfg!(feature = "postgres") {
                    out.push(quote::quote_spanned! {span=>
                                                     #field_ty: diesel::prelude::Queryable<diesel::dsl::SqlTypeOf<#ty>, diesel::pg::Pg>
                    });
                }
                if cfg!(feature = "sqlite") {
                    out.push(quote::quote_spanned! {span=>
                                                     #field_ty: diesel::prelude::Queryable<diesel::dsl::SqlTypeOf<#ty>, diesel::sqlite::Sqlite>
                    });
                }
                if cfg!(feature = "mysql") {
                    out.push(quote::quote_spanned! {span=>
                                                     #field_ty: diesel::prelude::Queryable<diesel::dsl::SqlTypeOf<#ty>, diesel::mysql::Mysql>
                    });
                }
            }
            out
        });

    wrap_in_dummy_mod(quote! {
        use diesel::expression::Selectable;

        impl #impl_generics Selectable<__DB>
            for #struct_name #ty_generics
        #where_clause
        {
            type SelectExpression = (#(#field_columns_ty,)*);


Review comment (refactor):
Isn't the `Queryable` requirement a bit harsh? (since it's essentially a helper to implement `FromSqlRow` shouldn't we require that instead?)

Code after:

    let (impl_generics, _, where_clause) = generics.split_for_impl();

    let struct_name = &item.ident;

    let field_columns_ty = model
        .fields()
        .iter()
        .map(|f| field_column_ty(f, &model))
        .collect::<Vec<_>>();
    let field_columns_inst = model.fields().iter().map(|f| field_column_inst(f, &model));

    let check_function = if let Some(ref backends) = model.check_for_backend {
        let field_check_bound = model
            .fields()
            .iter()
            .zip(&field_columns_ty)
            .filter(|(f, _)| !f.embed())
            .flat_map(|(f, ty)| {
                backends.iter().map(move |b| {
                    let field_ty = to_field_ty_bound(&f.ty);
                    let span = field_ty.span();
                    quote::quote_spanned! {span =>
                        #field_ty: diesel::deserialize::FromSqlRow<diesel::dsl::SqlTypeOf<#ty>, #b>
                    }
                })
            });
        Some(quote::quote! {
            fn _check_field_compatibility()
            where
                #(#field_check_bound,)*
            {

            }
        })
    } else {
        None
    };

    wrap_in_dummy_mod(quote! {
        use diesel::expression::Selectable;

        impl #impl_generics Selectable<__DB>
            for #struct_name #ty_generics
        #where_clause
        {
            type SelectExpression = (#(#field_columns_ty,)*);

            fn construct_selection() -> Self::SelectExpression {
                (#(#field_columns_inst,)*)
            }