如何在 graphQL 突变中使用柴油和杜松修复 mysql 的 sql 类型错误?

Posted

技术标签:

【中文标题】如何在 graphQL 突变中使用柴油和杜松修复 mysql 的 sql 类型错误?【英文标题】:how can I fix sql type error with diesel and juniper for mysql in graphQL mutation? 【发布时间】:2021-01-20 04:22:23 【问题描述】:

当我尝试通过柴油使用 graphGL 和 mysql 创建突变时,我遇到了以下错误日志。

目前枚举的类型只是柴油的类型,但我想用 graphQl 的类型来实现。 我为graphQL实现了客户结构,如下所示。 还不够吗?你有什么想法来解决这个问题吗? 谢谢

错误日志

error[E0277]: the trait bound `graphql::Customer: diesel::Queryable<(diesel::sql_types::Unsigned<diesel::sql_types::BigInt>, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), _>` is not satisfied
  --> src/graphql.rs:60:14
   |
60 |             .first::<crate::graphql::Customer>(&executor.context().db_con)
   |              ^^^^^ the trait `diesel::Queryable<(diesel::sql_types::Unsigned<diesel::sql_types::BigInt>, diesel::sql_types::Text, diesel::sql_types::Text, diesel::sql_types::Timestamp, diesel::sql_types::Timestamp), _>` is not implemented for `graphql::Customer`
   |
   = note: required because of the requirements on the impl of `diesel::query_dsl::LoadQuery<_, graphql::Customer>` for `diesel::query_builder::SelectStatement<schema::customers::table, diesel::query_builder::select_clause::DefaultSelectClause, diesel::query_builder::distinct_clause::NoDistinctClause, diesel::query_builder::where_clause::NoWhereClause, diesel::query_builder::order_clause::NoOrderClause, diesel::query_builder::limit_clause::LimitClause<diesel::expression::bound::Bound<diesel::sql_types::BigInt, i64>>>`

src/graphql.rs

use std::convert::From;
use std::sync::Arc;
use chrono::NaiveDateTime; 
use actix_web::web, Error, HttpResponse;
use futures01::future::Future;

use juniper::http::playground::playground_source;
use juniper::http::GraphQLRequest, Executor, FieldResult, FieldError,ID;
use juniper_from_schema::graphql_schema_from_file;

use diesel::prelude::*;

use itertools::Itertools;
use crate::schema::customers;

use crate::DbCon, DbPool;

graphql_schema_from_file!("src/schema.graphql");

pub struct Context 
    db_con: DbCon,

impl juniper::Context for Context 

pub struct Query;
pub struct Mutation;

impl QueryFields for Query 
    fn field_customers(
        &self,
        executor: &Executor<'_, Context>,
        _trail: &QueryTrail<'_, Customer, Walked>,
    ) -> FieldResult<Vec<Customer>> 
        //type FieldResult<T> = Result<T, String>;

        customers::table
            .load::<crate::models::Customer>(&executor.context().db_con)
            .and_then(|customers| Ok(customers.into_iter().map_into().collect()))
            .map_err(Into::into)
    


impl MutationFields for Mutation 
    fn field_create_customer(
        &self,
        executor: &Executor<'_, Context>,
        _trail: &QueryTrail<'_, Customer, Walked>,
        name: String,
        email: String,
    ) -> FieldResult<Customer> 
        //type FieldResult<T> = Result<T, String>;

        let new_customer = crate::models::NewCustomer  name: name, email: email;

        diesel::insert_into(customers::table)
            .values(&new_customer)
            .execute(&executor.context().db_con);
            
        customers::table
            .first::<crate::graphql::Customer>(&executor.context().db_con)
            .map_err(Into::into)
    


pub struct Customer 
    id: u64,
    name: String,
    email: String,
    created_at: NaiveDateTime,
    updated_at: NaiveDateTime,


impl CustomerFields for Customer 
    fn field_id(&self, _: &Executor<'_, Context>) -> FieldResult<juniper::ID> 
        Ok(juniper::ID::new(self.id.to_string()))
    

    fn field_name(&self, _: &Executor<'_, Context>) -> FieldResult<&String> 
        Ok(&self.name)
    
    fn field_email(&self, _: &Executor<'_, Context>) -> FieldResult<&String> 
        Ok(&self.email)
    


impl From<crate::models::Customer> for Customer 
    fn from(customer: crate::models::Customer) -> Self 
        Self 
            id: customer.id,
            name: customer.name,
            email: customer.email,
            created_at: customer.created_at,
            updated_at: customer.updated_at,
        
    


fn playground() -> HttpResponse 
    let html = playground_source("");
    HttpResponse::Ok()
        .content_type("text/html; charset=utf-8")
        .body(html)


fn graphql(
    schema: web::Data<Arc<Schema>>,
    data: web::Json<GraphQLRequest>,
    db_pool: web::Data<DbPool>,
) -> impl Future<Item = HttpResponse, Error = Error> 
    let ctx = Context 
        db_con: db_pool.get().unwrap(),
    ;

    web::block(move || 
        let res = data.execute(&schema, &ctx);
        Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?)
    )
    .map_err(Error::from)
    .and_then(|customer| 
        Ok(HttpResponse::Ok()
            .content_type("application/json")
            .body(customer))
    )


pub fn register(config: &mut web::ServiceConfig) 
    let schema = std::sync::Arc::new(Schema::new(Query, Mutation));

    config
        .data(schema)
        .route("/", web::post().to_async(graphql))
        .route("/", web::get().to(playground));


src/models.rs

#[derive(Queryable, Identifiable, AsChangeset, Clone, PartialEq, Debug)]
pub struct Customer 
    pub id: u64,
    pub name: String,
    pub email: String,
    pub created_at: NaiveDateTime,
    pub updated_at: NaiveDateTime,


use super::schema::customers;
#[derive(Queryable,Insertable, AsChangeset)]
#[table_name="customers"]
pub struct NewCustomer 
    pub name: String,
    pub email: String,

依赖关系

[dependencies]
diesel =  version = "1.4.5", features = ["mysql", "r2d2", "chrono"] 
dotenv = "~0.15"
serde = "~1.0"
serde_derive = "~1.0"
serde_json = "~1.0"
chrono = "~0.4"
rand = "0.7.3"
actix-web = "1.0.9"
actix-cors = "0.1.0"
juniper = "0.14.1"
juniper-from-schema = "0.5.1"
juniper-eager-loading = "0.5.0"
r2d2_mysql = "*"
r2d2-diesel = "0.16.0"
mysql = "*"
r2d2 = "*"
futures01 = "0.1.29"
itertools = "0.8.2"

src/schema.graphql

schema 
  query: Query
  mutation: Mutation


type Query 
  customers: [Customer!]! @juniper(ownership: "owned")


type Mutation 
  createCustomer(
    name: String!,
    email: String!,
  ): Customer! @juniper(ownership: "owned")


type Customer 
  id: ID! @juniper(ownership: "owned")
  name: String!
  email: String!

src/schema.rs

table! 
    customers (id) 
        id -> Unsigned<Bigint>,
        name -> Varchar,
        email -> Varchar,
        created_at -> Timestamp,
        updated_at -> Timestamp,
    

【问题讨论】:

【参考方案1】:

正如错误消息中提到的,您需要在src/graphql.rs 中为您的结构Customer 实现Queryable(该结构就在错误消息指向的下方)。最简单的方法是在这个结构中添加一个#[derive(Queryable)]

【讨论】:

以上是关于如何在 graphQL 突变中使用柴油和杜松修复 mysql 的 sql 类型错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 graphql 突变类型名错误

如何修复 TypeError:在使用 bcryptjs 对 GraphQL 突变进行哈希密码期间无法读取未定义的属性“哈希”?

如何使用 Mongoose Schema 修复 GraphQL Mutation 中的构造函数错误 [重复]

如何在 Graphql 突变中返回 PDF 文件?

如何使用动态别名在单个请求中多次调用 GraphQL 突变

如何使用突变在graphql中使用postgis的点类型坐标信息?