はじめに
最近、RustのDieselを使い始めました。
DieselはPostgres/MySQL/SQLiteに接続することができます。
今回、PostgresのMACADDR型を使う際に躓いたので、解決策を備忘録的に残しておきます。
困ったこと
以下のようにMACADDRを使うスキーマとモデルを定義しました。
CREATE TABLE machines (
id SERIAL PRIMARY KEY,
name VARCHAR(20) NOT NULL,
mac_address MACADDR NOT NULL,
status_id INTEGER NOT NULL,
create_at timestamptz NOT NULL DEFAULT current_timestamp,
update_at timestamptz NOT NULL DEFAULT current_timestamp
);
#[derive(Debug, Queryable)]
pub struct Machine {
pub id: i32,
pub name: String,
pub mac_address: [u8; 6],
pub status_id: i32,
pub create_at: chrono::NaiveDateTime,
pub update_at: chrono::NaiveDateTime,
}
全件SELECTする処理を書いて実行すると...
let machines = machines_schema::dsl::machines
.load::<Machine>(&connection)
.expect("Error loading machines");
for machine in &machines {
println!("{:?}", machine);
}
$ cargo run
・
・
error[E0277]: the trait bound `[u8; 6]: Queryable<MacAddr, Pg>` is not satisfied
--> src/main.rs:66:10
|
66 | .load::<Machine>(&connection)
| ^^^^ the trait `Queryable<MacAddr, Pg>` is not implemented for `[u8; 6]`
モデルにパースする際、MACADDRを[u8; 6]に変換する実装がない、というエラーです。
Referenceを見ると[u8; 6]への変換で正しそうです。
解決策
RustのDieselはfeaturesを指定することで使えるようになる機能があります。
例えば、timestamp等の時間に関わるものであれば「chrono」を追加する必要があります。
・
・
[dependencies]
diesel = { version = "1.4.6", features = ["postgres", "chrono"], default-features = false }
ネットワーク系も同様にfeatures「network-address」を追加する必要がありました。
(DieselのGitHubのCargo.tomlに一覧があるのでここから探しました...)
・
・
[dependencies]
diesel = { version = "1.4.6", features = ["postgres", "chrono", "network-address"], default-features = false }
これでもう1度動作させると、無事SELECTできました。
Machine { id: 1, name: "machineC", mac_address: [82, 66, 0, 26, 169, 68], status_id: 1, create_at: 2021-03-18T14:01:48.632112, update_at: 2021-03-18T14:01:48.632112 }
Machine { id: 3, name: "machineA", mac_address: [82, 66, 0, 26, 169, 68], status_id: 1, create_at: 2021-03-18T14:53:06.281686, update_at: 2021-03-18T14:53:06.281686 }
Machine { id: 4, name: "machineB", mac_address: [82, 66, 0, 26, 169, 69], status_id: 1, create_at: 2021-03-18T14:53:06.281686, update_at: 2021-03-18T14:53:06.281686 }
まとめ
Dieselで「~ is not implemented for ~」というエラーが出た際はfeaturesを確認してみると良いよというお話でした。
機能を選択させることでCrateを軽くする設計でしょうね(必要なものだけ選択する)。
PS)
この記事を書く際にReferenceを見ていたら、先頭に「The MACADDR SQL type. This type can only be used with feature = "network-address"」と記載がありました...
Referenceはちゃんと読まないとだめですね。