简体   繁体   English

在 Rust Diesel 中进行原始 sql 查询

[英]Making a raw sql-query in Rust Diesel

I need to query a function in Postgresql (14) using diesel.我需要使用柴油查询 Postgresql (14) 中的 function。 I already have queries that works on tables and views.我已经有适用于表和视图的查询。 This works, a view in this case.这有效,在这种情况下是一个视图。

schema.rs:

table! {
    latest_readings {
        measurement_time_default -> Timestamptz,
        id -> Integer,
        data -> Jsonb,
    }
}

models.rs:

#[derive(Serialize, Queryable)]
pub struct LatestReading {
    #[diesel(deserialize_as = "MyDateTimeWrapper")]
    pub measurement_time_default: DateTime<Local>,
    pub id: i32,
    pub data: serde_json::Value,
}

controller.rs:

pub async fn get_readings(db: web::Data<Pool>) -> Result<HttpResponse, Error> {
    Ok(web::block(move || db_get_readings(db))
        .await
        .map(|reading| HttpResponse::Ok().json(reading))
        .map_err(|_| HttpResponse::InternalServerError())?)
}

fn db_get_readings(pool: web::Data<Pool>) -> Result<Vec<LatestReading>, diesel::result::Error> {
    let conn = pool.get().unwrap();
    latest_readings.load::<LatestReading>(&conn)
}

This won't compile.这不会编译。 The part that call the postgresql-function.调用 postgresql 函数的部分。

schema.rs:

table! {
    measurements_single_location_function {
        id -> Integer,
        name -> Text,
        latitude -> Numeric,
        longitude -> Numeric,
        measurement_time_default -> Timestamptz,
        measurements -> Jsonb,
    }
}

models.rs:

#[derive(Serialize, Queryable, QueryableByName)]
#[table_name = "measurements_single_location_function"]
pub struct MeasurementsSingleLocation {
    pub id: i32,
    pub name: String,
    pub latitude: BigDecimal,
    pub longitude: BigDecimal,
    #[diesel(deserialize_as = "MyDateTimeWrapper")]
    pub measurement_time_default: DateTime<Local>,
    pub measurements: serde_json::Value,
}

DB-query in controllers.rs:

fn db_get_measurements_single_location(
    pool: web::Data<Pool>,
    location_id: i32,
    rows: i32,
) -> QueryResult<Vec<MeasurementsSingleLocation>> {
    let conn = pool.get().unwrap(); // Error on next line
    let result: QueryResult<Vec<MeasurementsSingleLocation>> =
        sql_query("select * from measurements_single_location_function(1,10)")
            .load::<MeasurementsSingleLocation>(&conn);
    return result;
}

The compile-error:编译错误:

   Compiling weather_rest v0.1.0 (/Users/claus/devel/rust/vegvesen/weather_rest)
error[E0277]: the trait bound `SqlQuery: LoadQuery<_, MeasurementsSingleLocation>` is not satisfied
    --> src/controller.rs:141:14
     |
141  |             .load::<MeasurementsSingleLocation>(&conn);
     |              ^^^^ the trait `LoadQuery<_, MeasurementsSingleLocation>` is not implemented for `SqlQuery`
     |
     = help: the following implementations were found:
               <SqlQuery as LoadQuery<Conn, T>>
note: required by a bound in `load`
    --> /Users/claus/.cargo/registry/src/github.com-1ecc6299db9ec823/diesel-1.4.6/src/query_dsl/mod.rs:1238:15
     |
1238 |         Self: LoadQuery<Conn, U>,
     |               ^^^^^^^^^^^^^^^^^^ required by this bound in `load`

I am not able to see what I am missing here.我看不到我在这里缺少的东西。

Cargo.toml:

diesel = { version = "1.4.6", features = ["postgres", "uuidv07", "r2d2", "chrono", "numeric", "serde_json"] }

I recently wrote a backend-service for another project using this excellent example as a template.我最近使用这个优秀示例作为模板为另一个项目编写了后端服务。 I applied the same structure to this and it now compiles.我对此应用了相同的结构,现在可以编译了。

schema.rs:

table! {
    measurements_single_location_function {
        id -> Integer,
        name -> Text,
        latitude -> Text,
        longitude -> Text,
        measurement_time_default -> Timestamptz,
        measurements -> Jsonb,
    }
}
routes.rs:

#[get("/measurements_single_location/{id}/{rows}")]
async fn measurements_single_location(path: web::Path<(i32, i32)>) -> Result<HttpResponse, CustomError> {
    let (id, rows) = path.into_inner();
    let m = MeasurementsSingleLocation::measurements_single_location(id, rows)?;
    Ok(HttpResponse::Ok().json(m))
}

pub fn init_routes(config: &mut web::ServiceConfig) {
    config.service(measurements_single_location);
}

models.rs:

#[derive(Serialize, QueryableByName)]
#[table_name = "measurements_single_location_function"]
pub struct MeasurementsSingleLocation {
    pub id: i32,
    pub name: String,
    pub latitude: String,
    pub longitude: String,
    pub measurement_time_default: NaiveDateTime,
    pub measurements: serde_json::Value,
}

impl MeasurementsSingleLocation {
    pub fn measurements_single_location(id: i32, rows: i32) -> Result<Vec<MeasurementsSingleLocation>, CustomError> {
        let q = "select * from measurements_single_location_function($1,$2)";
        let mut conn = db::connection()?;
        let m= diesel::sql_query(q)
            .bind::<Integer, _>(id)
            .bind::<Integer, _>(rows)
            .get_results(&mut conn)?;
        Ok(m)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM