如何使用 Diesel 生成和解析原始 SQL 查询?

cbl*_*bll 5 mysql rust rust-diesel

我正在使用 Rocket 框架测试 Rust。对于数据库,我使用 Diesel 与 MySQL 数据库交互。

通过几个例子,幕后发生了很多事情。我有一个 MySQL 数据库正在运行,其中有一个填充表,我想对其进行原始查询。

下面的代码有效:

use diesel::{prelude::*};

mod schema {
    table! {
        organization {
            id -> Nullable<Integer>,
            name -> Text,
            country -> Text,
        }
    }
}

use self::schema::organization;
use self::schema::organization::dsl::{organization as all_orgs};

#[table_name="organization"]
#[derive(Serialize, Deserialize, Queryable, Insertable, Debug, Clone)]
pub struct Organization {
    pub id: Option<i32>,
    pub name: String,
    pub country: String
}

impl Organization {
    pub fn all(conn: &MysqlConnection) -> Vec<Organization> {
        all_orgs.order(organization).load::<Organization>(conn).unwrap()
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我不需要按任何顺序订购。事实上,我只想进行一个原始查询,SELECT id, name, country FROM organization然后就到此为止了。

在查看了Diesel 文档并发现了名为sql_query.

我的代码现在看起来像:

use diesel::{prelude::*, sql_query};

mod schema {
    table! {
        organization {
            id -> Nullable<Integer>,
            name -> Text,
            country -> Text,
        }
    }
}

use self::schema::organization;

#[table_name="organization"]
#[derive(Serialize, Deserialize, Queryable, Insertable, Debug, Clone)]
pub struct Organization {
    pub id: Option<i32>,
    pub name: String,
    pub country: String
}

impl Organization {
    pub fn all(conn: &MysqlConnection) -> Vec<Organization> {
         sql_query("SELECT id, name, country FROM organization")
            .load(&conn).unwrap()
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,在进行cargo run此更改后,我面临着:

use diesel::{prelude::*};

mod schema {
    table! {
        organization {
            id -> Nullable<Integer>,
            name -> Text,
            country -> Text,
        }
    }
}

use self::schema::organization;
use self::schema::organization::dsl::{organization as all_orgs};

#[table_name="organization"]
#[derive(Serialize, Deserialize, Queryable, Insertable, Debug, Clone)]
pub struct Organization {
    pub id: Option<i32>,
    pub name: String,
    pub country: String
}

impl Organization {
    pub fn all(conn: &MysqlConnection) -> Vec<Organization> {
        all_orgs.order(organization).load::<Organization>(conn).unwrap()
    }
}
Run Code Online (Sandbox Code Playgroud)

在给定输入参数和所需输出的情况下,如何满足这些错误,同时允许执行原始 SQL 查询并从函数中正确解析它?

wei*_*ich 7

要解决您的问题,您可以删除.order(organization)以避免执行排序。

要回答明确提出的问题:错误消息提到两个问题:

error[E0277]: the trait bound `&diesel::MysqlConnection: diesel::Connection` is not satisfied
  --> src/org.rs:26:19
   |
26 |             .load(&conn).unwrap()
   |                   -^^^^
   |                   |
   |                   the trait `diesel::Connection` is not implemented for `&diesel::MysqlConnection`
   |                   help: consider removing the leading `&`-reference
   |
   = help: the following implementations were found:
             <diesel::MysqlConnection as diesel::Connection>
   = note: required because of the requirements on the impl of `LoadQuery<&diesel::MysqlConnection, _>` for `SqlQuery`
Run Code Online (Sandbox Code Playgroud)

这个问题很容易修复:按照编译器的建议进行操作,并删除&.load(&conn).

error[E0277]: the trait bound `Organization: QueryableByName<_>` is not satisfied
  --> src/org.rs:26:14
   |
26 |             .load(&conn).unwrap()
   |              ^^^^ the trait `QueryableByName<_>` is not implemented for `Organization`
   |
   = note: required because of the requirements on the impl of `LoadQuery<&diesel::MysqlConnection, Organization>` for `SqlQuery`
Run Code Online (Sandbox Code Playgroud)

这指出了不允许在Organization结构中加载结果的实际问题。需要告诉 Diesel 如何Organization根据查询响应构建结构。Diesel 为此提供了 2 个特征:

  • Queryable用于根据类型安全查询的结果构造一个结构体(==使用diesel提供的dsl构建查询,以便在编译时检查它)。`
  • QueryableByName从非类型安全查询的结果构造一个结构体(所以基本上是通过执行的查询diesel::sql_query

正如错误消息所提到的,您的结构没有实现QueryableByName,这是加载该结构中的结果所必需的diesel::sql_query。你需要实现这个特质。最简单的选择是使用deriveDiesel 提供的。

代码的固定版本将如下所示:

use diesel::{prelude::*, sql_query};

mod schema {
    table! {
        organization {
            id -> Nullable<Integer>,
            name -> Text,
            country -> Text,
        }
    }
}

use self::schema::organization;

#[table_name="organization"]
#[derive(Serialize, Deserialize, Queryable, QueryableByName, Insertable, Debug, Clone)]
pub struct Organization {
    pub id: Option<i32>,
    pub name: String,
    pub country: String
}

impl Organization {
    pub fn all(conn: &MysqlConnection) -> Vec<Organization> {
         sql_query("SELECT id, name, country FROM organization")
            .load(&conn).unwrap()
    }
}
Run Code Online (Sandbox Code Playgroud)