ぷるぷるした直方体

エンジニアの雑記です。My opinions are my ownというやつです

dieselのメモ

所用でdieselを使っているのですが、ドキュメントから探すのが難しかったり、実現できなかったりすることがパッと分からなかったりします。 ということで、本記事は触ってみて気づいたことを書き溜めておくチラ裏です。気が向いたときに追記してゆく予定です。

生SQLの実行

dieselではwindow関数やsubqueryをサポートしていません。 そのため、paginationはsqlを直にいじることで実現しています。

diesel.rs

頻繁に使う記述はこのように作ると良いのですが、とりあえず動かしたい場合にはなかなか手間です。ということで、生SQLを扱う方法を覚えておくと便利です。

生SQLの実行にはsql_queryを使うと、load時にby-nameでマッピングを行ってくれます。 マッピングする先のstructでは、QueryableByNameをderiveしておきます。

#[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

関連するテーブルを引っ張ってくる場合は、structにderive(Associations)#[belongs_to(XXX)]を付けてbelonging_toでIDを指定して取得できます。 これはWHERE INによる絞り込みが行われます。

docs.diesel.rs

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

そのため、IDが該当SQLの実行時に決まっている必要があり、subqueryでは実行できません。 2度クエリを実行するため、パフォーマンスが気になる場合は生SQLなどで頑張りましょう。

grouped_by

SQLのgroup_byとは異なり、既にloadしたデータをグルーピングする関数がgrouped_byです。 外部キーでくっつきます。 この後にzipすることで、親データと小データの配列をセットにした構造が得られます。 詳しくは↓で。

docs.diesel.rs

1件取得

普通にfindが使えます。 derive(Identifiable)を付けたstructでloadすること。

GROUP BYした際のselect制限

QueryBuilderにはGROUP BYに現れたカラムのみSELECTで指定できるという、MySQL 8.0のエンジンより強い制約があります。 そのため、下記のような記述は生SQLで書く必要があります(AとBは1:多対応)。

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

github.com

便利なURLたち

まとめ

diesel楽しい。 気づいたことがあれば追記してゆきます。