Rust 理解柴油机的特征界误差

Rust 理解柴油机的特征界误差,rust,rust-diesel,Rust,Rust Diesel,我想写一个函数,在数据库连接参数为泛型的数据库中插入一个类型,这样它就可以在多个后端上工作 我使用以下函数使用通用连接插入对象: pub fn create_label<C>(connection: &C, label: &model::Label) where C: Connection, C::Backend: diesel::backend::Backend, C::Backend: diesel::backend::SupportsDe

我想写一个函数,在数据库连接参数为泛型的数据库中插入一个类型,这样它就可以在多个后端上工作

我使用以下函数使用通用连接插入对象:

pub fn create_label<C>(connection: &C, label: &model::Label)
where
    C: Connection,
    C::Backend: diesel::backend::Backend,
    C::Backend: diesel::backend::SupportsDefaultKeyword,
{
    diesel::insert(&label)
        .into(schema::label::table)
        .execute(connection);
}
为什么泛型函数需要
SupportsDefaultKeyword
约束,而使用
SqliteConnection
的函数则不需要

下面是一个例子来说明这个问题。根据注释,
main.rs
的第60行不会编译上面的错误,而第61行编译:

#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;

mod schema {
    table! {
        labels {
            id -> Integer,
            name -> VarChar,
        }
    }
}

mod model {
    use schema::labels;

    #[derive(Debug, Identifiable, Insertable)]
    #[table_name = "labels"]
    pub struct Label {
        pub id: i32,
        pub name: String,
    }
}

use diesel::ExecuteDsl;
use diesel::Connection;
use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;

pub fn create_label<C>(connection: &C, label: &model::Label)
where
    C: Connection,
    C::Backend: diesel::backend::Backend,
    C::Backend: diesel::backend::SupportsDefaultKeyword,
{
    diesel::insert(label)
        .into(schema::labels::table)
        .execute(connection)
        .expect("nope");
}

pub fn create_label_sqlite(connection: &SqliteConnection, label: &model::Label) {
    diesel::insert(label)
        .into(schema::labels::table)
        .execute(connection)
        .expect("nope");
}

pub fn establish_connection() -> SqliteConnection {
    let url = "test.db";
    SqliteConnection::establish(&url).expect(&format!("Error connecting to {}", url))
}

fn main() {
    let label = model::Label {
        id: 1,
        name: String::from("test"),
    };
    let conn = establish_connection();

    create_label(&conn, &label); /* Does not compile */
    create_label_sqlite(&conn, &label); /*Compiles */
}
Diesel函数有多个具体实现。此处相关的两个方面是:

impl<'a, T, U, Op, Ret, Conn, DB> ExecuteDsl<Conn, DB> for BatchInsertStatement<T, &'a [U], Op, Ret> 
where
    Conn: Connection<Backend = DB>,
    DB: Backend + SupportsDefaultKeyword,
    InsertStatement<T, &'a [U], Op, Ret>: ExecuteDsl<Conn>, 
impl
哪里
康涅狄格州:连接,
DB:Backend+SupportsDefaultKeyword,
BatchInsertStatement的InsertStatement ExecuteSL:ExecuteSL,
T:收到,
作品:复制,,
雷特:收到,
从这两个方面可以看出,SQLite的实现是特殊情况的。我对Diesel的细节了解不够,不知道为什么,但我猜SQLite缺少默认关键字

相反,您可以重新制定使用该特定语句的任何连接的要求:

use diesel::query_builder::insert_statement::InsertStatement;

pub fn create_label<C>(connection: &C, label: &model::Label)
where
    C: Connection,
    for<'a> InsertStatement<schema::labels::table, &'a model::Label>: ExecuteDsl<C>,
{
    diesel::insert(label)
        .into(schema::labels::table)
        .execute(connection)
        .expect("nope");
}
use diesel::query\u builder::insert\u语句::InsertStatement;
发布fn创建标签(连接:&C,标签:&model::标签)
哪里
C:连接,
for:executesl,
{
柴油机:插入(标签)
.into(架构::标签::表)
.执行(连接)
.预期(“不”);
}
impl<'a, T, U, Op, Ret, Conn, DB> ExecuteDsl<Conn, DB> for BatchInsertStatement<T, &'a [U], Op, Ret> 
where
    Conn: Connection<Backend = DB>,
    DB: Backend + SupportsDefaultKeyword,
    InsertStatement<T, &'a [U], Op, Ret>: ExecuteDsl<Conn>, 
impl<'a, T, U, Op, Ret> ExecuteDsl<SqliteConnection> for BatchInsertStatement<T, &'a [U], Op, Ret> 
where
    InsertStatement<T, &'a U, Op, Ret>: ExecuteDsl<SqliteConnection>,
    T: Copy,
    Op: Copy,
    Ret: Copy, 
use diesel::query_builder::insert_statement::InsertStatement;

pub fn create_label<C>(connection: &C, label: &model::Label)
where
    C: Connection,
    for<'a> InsertStatement<schema::labels::table, &'a model::Label>: ExecuteDsl<C>,
{
    diesel::insert(label)
        .into(schema::labels::table)
        .execute(connection)
        .expect("nope");
}