開発環境
- Macbook Pro M1 2020
- rustup 1.24.3 (ce5817a94 2021-05-31)
- mysql Ver 8.0.27 for macos12.0 on arm64 (Homebrew)
解決したいこと
今、RustでDieselを用いてMySQLにデータをCRUDする簡単なアプリケーションを作成しています。ここでプログラムにトランザクションを導入し、データベースを安全に利用したいと考えました。
トランザクション処理のクレートとしてtransaction-rsを選定しました。簡単なexampleも入っていたので手元の環境にコピーし、実行してみました。しかし、動きません。exampleはPostgresを使っていたので、自分のの環境用にデータベースの部分をMySQLへと書き換えました。
そしてわかる範囲でエラーをつぶしたのですが、まだ現状次のようなコンパイルエラーが残っています。
エラーメッセージ(抜粋)
error[E0277]: the trait bound `diesel::MysqlConnection: diesel::connection::Connection` is not satisfied --> src/main.rs:34:5 | 34 | transaction_diesel::run(&conn, tx).unwrap() | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::connection::Connection` is not implemented for `diesel::MysqlConnection` | note: required by a bound in `transaction_diesel::run` --> /path/to/user/.cargo/registry/src/github.com-1ecc6299db9ec823/transaction-diesel-0.2.2/src/lib.rs:11:9 | 11 | Cn: diesel::Connection, | ^^^^^^^^^^^^^^^^^^ required by this bound in `transaction_diesel::run` error[E0277]: the trait bound `diesel::result::Error: From<diesel::result::Error>` is not satisfied --> src/main.rs:34:36 | 34 | transaction_diesel::run(&conn, tx).unwrap() | ^^ | | | expected an implementor of trait `From<diesel::result::Error>` | help: consider borrowing here: `&tx` | note: required by a bound in `transaction_diesel::run` --> /path/to/user/.cargo/registry/src/github.com-1ecc6299db9ec823/transaction-diesel-0.2.2/src/lib.rs:12:8 | 12 | E: From<diesel::result::Error>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `transaction_diesel::run`
関係しそうなDieselのコード
DieselのGitHubのソースコードを確認するとMysqlConnectionはdiesel::Connectionを実装しているのに、mysql::connectionがプライベートになっていることに気づきました。
これのせいで該当のエラーが起きているように感じるが、ここを修正するのは正規の方法ではなさそうに感じています。
行き詰まってしまいました。
もし、このエラーの解決方法がわかる方がいらっしゃればご教示いただきたいです。
記述したコード
rust
// main.rs #[macro_use] extern crate diesel; extern crate dotenv; extern crate transaction; extern crate transaction_diesel; mod db; mod model; mod schema; use diesel::mysql::MysqlConnection; use diesel::result::Error; use transaction::prelude::*; pub fn establish_connection() -> MysqlConnection { use diesel::prelude::*; use dotenv::dotenv; use std::env; dotenv().ok(); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); MysqlConnection::establish(&database_url) .expect(&format!("Error connecting to {}", database_url)) } fn main() { let conn = establish_connection(); let tx = with_ctx(|ctx| -> Result<(), Error> { let size = db::create_user("keen").run(ctx)?; println!("created user count: {:?}", size); Ok(()) }); transaction_diesel::run(&conn, tx).unwrap() }
rust
// db.rs use diesel::mysql::MysqlConnection; use diesel::prelude::*; use diesel::result::Error; use transaction::prelude::*; use transaction_diesel::with_conn; use transaction_diesel::DieselContext; use crate::model::*; use crate::schema::users::dsl; type Ctx<'a> = DieselContext<'a, MysqlConnection>; type BoxTx<'a, T> = Box<dyn Transaction<Ctx = Ctx<'a>, Item = T, Err = Error> + 'a>; pub fn create_user<'a>(name: &'a str) -> BoxTx<'a, usize> { with_conn(move |cn| { let size = diesel::insert_into(dsl::users) .values(&NewUser { name: name.to_string(), }) .execute(cn); assert_eq!(Ok(1), size); size }) .boxed() }
rust
// model.rs use crate::schema::*; #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash, Queryable)] pub struct User { pub id: i32, pub name: String, } #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Default, Hash, Insertable)] #[table_name = "users"] pub struct NewUser { pub name: String, }
toml
# Cargo.toml [package] name = "keen_transaction_mini_try" version = "0.1.0" edition = "2021" [dependencies] dotenv = "0.15.0" transaction = "0.2.1" transaction-diesel = "0.2.2" [dependencies.diesel] features = ["mysql"] version = "1.4.8"
ご覧くださりありがとうございます。ご回答のほど何卒よろしくお願いします。
まだ回答がついていません
会員登録して回答してみよう