简体   繁体   中英

How can I use the sql function CAST in rust, diesel?

I'm developing a new endpoint using Rocket and am trying to return a Vec<> made of various structs.

The raw query I want to replicate in diesel is:

select location.id, location.name, w.datetime, t.temp, w.compass, w.speed, r.probability, s.height
from location
inner join rainfall r on location.id = r.location
inner join temperature t on location.id = t.location
inner join wind w on location.id = w.location
inner join swell s on location.id = s.location
where t.datetime = w.datetime
  and s.datetime = t.datetime
  and CAST(t.datetime as date) = CAST(r.datetime as date)
  and t.datetime > now() and t.datetime < NOW() + INTERVAL 1 HOUR;

and I recognize, that in order to use the CAST function I need to use the sql_function! macro:

sql_function! {
#[sql_name="CAST"]
    fn cast(x: sql_types::Nullable<sql_types::Datetime>) -> sql_types::Date;
}

which allows me to create the following query:

let summaries: Vec<(Location, Swell, Wind, Temperature, Rainfall)> = location::table
        .inner_join(swell::table)
        .inner_join(wind::table)
        .inner_join(temperature::table)
        .inner_join(rainfall::table)
        .filter(temperature::datetime.eq(wind::datetime))
        .filter(temperature::datetime.eq(swell::datetime))
        .filter(temperature::datetime.gt(utilities::today()))
        .filter(temperature::datetime.lt(utilities::future_hour(1)))
        .filter(cast(temperature::datetime).eq(cast(rainfall::datetime)))
        .load(&conn.0)?;

However, when I run this query I get a SQL Query error:

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \\') = CAST('rainfall'.'datetime')\\' at line 1"

As illustrated in the raw SQL statement it should read CAST('rainfall'.'datetime' as date) .

My question is, how can I add the 'as date' component to my diesel query? Is something missing in the sql_function definition?

Thanks for your help.

I found the answer after digging a little deeper into similar questions.

Turns out you can enter a raw sql string into the .filter method after adding: use diesel::expression::sql_literal::sql; .

So the final snippet becomes:

let summaries: Vec<(Location, Swell, Wind, Temperature, Rainfall)> = location::table
        .inner_join(swell::table)
        .inner_join(wind::table)
        .inner_join(temperature::table)
        .inner_join(rainfall::table)
        .filter(temperature::datetime.eq(wind::datetime))
        .filter(temperature::datetime.eq(swell::datetime))
        .filter(temperature::datetime.gt(utilities::today()))
        .filter(temperature::datetime.lt(utilities::future_hour(1)))
        .filter(sql("CAST(`temperature`.`datetime` as date) = CAST(`rainfall`.`datetime` as date)"))
        .load(&conn.0)?;

I hope this helps someone else!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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