Rust diesel orm查询

标签 rust rust-cargo rust-diesel rust-crates

我是使用rust 和柴油机的新手。我正在尝试对我的查询执行以下操作:

  • 计数
  • 选择
  • 订购
  • 限制

但是我收到了错误。
我正在使用 postgres 数据库。

我在评论中的查询上方添加了确切的错误。
这是我的代码:

schema.rs

table! {
    employee (employee_id) {
        employee_id -> Int4,
        name -> Nullable<Text>,
        age -> Nullable<Int4>,
        address -> Nullable<Text>,
        email -> Nullable<Text>,
        dept_id -> Int4,
        salary -> Nullable<Numeric>,
        created_on -> Nullable<Timestamp>,
        created_by -> Nullable<Text>,
        modified_on -> Nullable<Timestamp>,
        modified_by -> Nullable<Text>,
        is_active -> Nullable<Bool>,
    }
}

模型.rs

#![allow(unused)]
#![allow(clippy::all)]
use super::schema::employee;

use bigdecimal::BigDecimal;
use chrono::NaiveDateTime;

#[derive(Queryable, Debug, Identifiable)]
#[table_name = "employee"]
#[primary_key(employee_id)]
pub struct Employee {
    pub employee_id: i32,
    pub name: Option<String>,
    pub age: Option<i32>,
    pub address: Option<String>,
    pub email: Option<String>,
    pub dept_id: i32,
    pub salary: Option<BigDecimal>,
    pub created_on: Option<NaiveDateTime>,
    pub created_by: Option<String>,
    pub modified_on: Option<NaiveDateTime>,
    pub modified_by: Option<String>,
    pub is_active: Option<bool>,
}

cargo.toml

[dependencies]
diesel = { version = "1.4.5", features = ["postgres","chrono","numeric"] }
dotenv = "0.15.0"
chrono = { version = "0.4.19" , features = ["serde"] }
bigdecimal = { version = "0.1.0" }

ma​​in.rs

#[macro_use]
extern crate diesel;
extern crate bigdecimal;
extern crate chrono;
extern crate dotenv;

use crate::models::Employee;
use crate::models::Players;
use crate::schema::employee::dsl::*;

use diesel::{pg::PgConnection, prelude::*};
use dotenv::dotenv;
use std::env;

mod models;
mod schema;

fn main() {
    dotenv().ok();
    let data_url: String = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let connection: PgConnection =
        PgConnection::establish(&data_url).expect(&format!("Error connect to {}", data_url));

    //get all employees name
    //This is working fine
    let _employee: Vec<Employee> = employee
        .load::<Employee>(&connection)
        .expect("Error loading department");

    for emp in _employee {
        println!("{}", emp.name.unwrap_or_default());
    }


    //----------------------------------------------
    //get employees count
    /*
    Error: error[E0282]: type annotations needed
           ^^^^^^^^^^^^^^^ consider giving `total_employees` a type
    */
    let total_employees = employee.count().get_result(&connection).expect("Error");
    println!("{}", total_employees);


    //-----------------------------------------------
     //get all names
    /*
        Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not satisfied
         ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let all_names = employee.select(name).load::<String>(&connection)?;
    println!("{}", all_names);


    //----------------------------------------------
    //order name
    /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not          satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let ordered_names = employee
        .select(name)
        .order(name.desc())
        .load::<String>(&connection)?;
    println!("{}", ordered_names);


   //------------------------------------------------
   /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not     satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
     */
    let limited = employee
        .select(name)
        .order(employee_id)
        .limit(1)
        .load::<String>(&connection)?;
    println!("{}", limited);
}

我错过了什么吗? 有人可以纠正我吗?
谢谢!

最佳答案

首先:您的代码缺少一个关键信息来实际重现那里描述的问题。在不知道您的底层数据库架构的情况下,只能猜测它的外观。对于我的回答,我将采用以下模式:

table! {
    employee(employee_id) {
        employee_id -> Integer,
        name -> Nullable<Text>,
        age -> Nullable<Integer>,
        address -> Nullable<Text>,
        email -> Nullable<Text>,
        dept_id -> Integer,
        salary -> Nullable<Numeric>,
        created_on -> Nullable<Timestamp>,
        created_by -> Nullable<Text>,
        modified_on -> Nullable<Timestamp>,
        modified_by -> Nullable<Text>,
        is_active -> Nullable<Bool>,
    }
}

现在作为一般规则:Diesel 使用此定义作为事实来源并且仅支持某些类型映射。如果您遇到编译错误,这可能意味着以下情况之一是错误的:

  • 您已尝试将查询结果映射到包含某些返回列的不兼容字段的结构
  • 您已尝试将查询结果映射到包含比查询返回的字段更多或更少的字段的结构

回答您的特定错误消息:

    //----------------------------------------------
    //get employees count
    /*
    Error: error[E0282]: type annotations needed
           ^^^^^^^^^^^^^^^ consider giving `total_employees` a type
    */
    let total_employees = employee.count().get_result(&connection).expect("Error");
    println!("{}", total_employees);

Rustc 需要知道 total_employees 的类型这里是get_result返回通用类型和 println另一方面使用通用类型。 Rustc 需要确切地知道应该在那里使用哪种类型。现在柴油文档在这里关于什么是正确的返回类型有点稀疏,但错误消息在 Daniel Porteous 中表示此查询返回 BigInt ,它与 i64 兼容如记录here .这意味着这个查询可以工作:

    let total_employees: i64 = employee.count().get_result(&connection).expect("Error");

您接下来的三个查询基本上无法编译并显示相同的错误消息:


    //-----------------------------------------------
     //get all names
    /*
        Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not satisfied
         ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let all_names = employee.select(name).load::<String>(&connection)?;
    println!("{}", all_names);


    //----------------------------------------------
    //order name
    /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not          satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
    */
    let ordered_names = employee
        .select(name)
        .order(name.desc())
        .load::<String>(&connection)?;
    println!("{}", ordered_names);


   //------------------------------------------------
   /*
    Error: error[E0277]: the trait bound `*const str: FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not     satisfied
    ^^^^ the trait `FromSql<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>` is not implemented for `*const str`
     */
    let limited = employee
        .select(name)
        .order(employee_id)
        .limit(1)
        .load::<String>(&connection)?;
    println!("{}", limited);

现在,此错误消息表明您尝试将查询返回的字段映射到 Rust 端的不兼容类型。在这种情况下映射 Text不是 NOT NULL 的字段到 String不支持,因为柴油如何表示 NULL在这种情况下的值(value)。 documentation states您需要将可空类型包装在 Option 中在使用rust 的一面。这意味着如果您将返回类型更改为 Option<String>在所有情况下,一切都会成功编译。

关于Rust diesel orm查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65158596/

相关文章:

rust - 我如何将 'pass down' 功能标志标记为 Cargo 中的子依赖项?

rust - 这是什么意思? "This is precisely because a library should not be deterministically recompiled for all users of the library."

generics - 使用 Diesel 的通用函数会导致溢出

rust - 在遍历元素时移除元素

rust - 为什么我在 Rust 2018 中使用模块时会得到 "can' t find crate?

rust - 在 Rust 中,clone() 和 to_owned() 有什么区别?

rust - 将 Option<T> 与 Diesel 的 Insertable 特性结合使用

ubuntu - 为什么我的程序比基准测试显示的慢?

rust - 如何使用工具链为 Linux 上的所有用户安装 rustup 和 cargo?

rust - diesel 应该使用同步 actor、actix_web::web::block 还是 futures-cpupool 来运行?