header source
my icon
esplo.net
ぷるぷるした直方体
Cover Image for Notes on diesel

Notes on diesel

だいたい6分で読めます

I'm using diesel for work, but it's often difficult to find things in the documentation or to immediately understand how to achieve certain things.
Therefore, this article is a personal note to jot down things I've noticed while using it. I plan to add to it as I feel inclined.

Executing raw SQL

Diesel doesn't support window functions or subqueries.
As a result, I implement pagination by directly manipulating SQL.

http://diesel.rs/guides/extending-diesel/

While it's good to create such descriptions for frequently used queries, it can be quite cumbersome when you just want to get something working. Therefore, it's useful to know how to handle raw SQL.

To execute raw SQL, you can use sql_query, which will perform by-name mapping during loading.
For the struct to map to, derive QueryableByName.

#[derive(QueryableByName, Serialize, Debug)]
pub struct LastUpdate {
    #[sql_type = "Datetime"]
    pub dt: chrono::NaiveDateTime,
}

use diesel::sql_query;
use diesel::sql_types::Integer;

sql_query(
r#"
  SELECT x.*, updated_at as dt
  FROM hoge
  LIMIT ?
"#
)
.bind::<Integer, _>(5)
.load::<(Hoge, Rank)>(&*conn)
.expect("cannot execute ....")

Association

When pulling related tables, you can add derive(Associations) and #[belongs_to(XXX)] to the struct and retrieve by specifying the ID with belonging_to.
This performs a WHERE IN filter.

https://docs.diesel.rs/diesel/associations/index.html

SELECT * FROM hoge
WHERE IN (1,2,3....)

Therefore, the ID needs to be determined at the time of executing the corresponding SQL, and cannot be executed in a subquery.
Since it executes the query twice, if you're concerned about performance, you should use raw SQL or other methods.

grouped_by

Unlike SQL's group_by, grouped_by is a function that groups already loaded data.
It connects with foreign keys.
By zipping afterwards, you can obtain a structure that pairs parent data with an array of child data.
For more details, see ↓.

https://docs.diesel.rs/diesel/associations/trait.GroupedBy.html

Retrieving a single record

You can simply use find.
Load with a struct that has derive(Identifiable) attached.

SELECT restrictions when using GROUP BY

QueryBuilder has a stronger constraint than MySQL 8.0's engine, where only columns that appear in GROUP BY can be specified in SELECT.
Therefore, descriptions like the following need to be written in raw SQL (A and B have a 1:many relationship).

SELECT A.*
FROM B
LEFT JOIN A on B.a_id = A.id
GROUP BY B.A_id

https://github.com/diesel-rs/diesel/issues/772

Useful URLs

Summary

Diesel is fun.
I'll add more as I notice things.

Share