diff --git a/Cargo.lock b/Cargo.lock index 258972d..b3f272a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1173,6 +1173,12 @@ version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -1557,18 +1563,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "postgres" -version = "0.1.0" -dependencies = [ - "anyhow", - "lombok", - "once_cell", - "postgres 0.19.7", - "r2d2", - "r2d2_postgres", -] - [[package]] name = "postgres" version = "0.19.7" @@ -1612,6 +1606,23 @@ dependencies = [ "postgres-protocol", ] +[[package]] +name = "postgresql" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "lombok", + "once_cell", + "postgres", + "proc-macro2", + "r2d2", + "r2d2_postgres", + "tokio", + "tokio-postgres", + "yaml-rust", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1678,7 +1689,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7029c56be658cb54f321e0bee597810ee16796b735fa2559d7056bf06b12230b" dependencies = [ - "postgres 0.19.7", + "postgres", "r2d2", ] @@ -2616,6 +2627,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/practice_collection/postgres/src/pool_2.rs b/practice_collection/postgres/src/pool_2.rs deleted file mode 100644 index 8ec3d16..0000000 --- a/practice_collection/postgres/src/pool_2.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::sync::Mutex; -use std::time::Duration; -use r2d2_postgres::{postgres::NoTls, PostgresConnectionManager}; -use r2d2_postgres::r2d2::Pool; -use once_cell::sync::Lazy; - -#[allow(dead_code)] -// connection str -static CONNECTION_STR: &str = "host=localhost port=5432 dbname=rust_sample user=postgres password=admin"; - -#[allow(dead_code)] -// create connection pool -pub static SAMPLE_POOL_2: Lazy>>> = - Lazy::new(|| { - let config = CONNECTION_STR.parse().unwrap(); - let manager = PostgresConnectionManager::new(config, NoTls); - let pool = r2d2::Pool::builder() - .max_size(30) - .min_idle(Some(1)) - .connection_timeout(Duration::from_secs_f32(60.0)) - .build(manager) - .unwrap(); - Mutex::new(pool) - }); \ No newline at end of file diff --git a/practice_collection/postgres/Cargo.toml b/practice_collection/postgresql/Cargo.toml similarity index 57% rename from practice_collection/postgres/Cargo.toml rename to practice_collection/postgresql/Cargo.toml index 24088d9..34f7012 100644 --- a/practice_collection/postgres/Cargo.toml +++ b/practice_collection/postgresql/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "postgres" +name = "postgresql" version = "0.1.0" edition = "2021" @@ -13,4 +13,10 @@ once_cell = "1.18.0" postgres = "0.19.7" r2d2 = "0.8.10" -r2d2_postgres = "0.18.1" \ No newline at end of file +r2d2_postgres = "0.18.1" + +tokio ={ version = "1.24.1", features = ["full"] } +tokio-postgres = "0.7.1" +proc-macro2 = "1.0.49" +async-trait = "0.1.61" +yaml-rust = "0.4.5" diff --git a/practice_collection/postgres/README.md b/practice_collection/postgresql/README.md similarity index 66% rename from practice_collection/postgres/README.md rename to practice_collection/postgresql/README.md index 4446c8d..2ec1246 100644 --- a/practice_collection/postgres/README.md +++ b/practice_collection/postgresql/README.md @@ -53,4 +53,16 @@ class Product { } ProductRepository ..> Repository~T,PK,UPD~ ProductRepository ..> Product +``` + +## QA + +[[cargo clippy warning]arning: this `MutexGuard` is held across an `await` point](https://users.rust-lang.org/t/cargo-clippy-warning-arning-this-mutexguard-is-held-across-an-await-point/99225) + +```rust +let config; +{ + let params = CONNECT_PARAMS.lock().unwrap(); // params lock here. + config = params.connect_string().clone(); +} // params drop here. ``` \ No newline at end of file diff --git a/practice_collection/postgresql/resources/sql.yaml b/practice_collection/postgresql/resources/sql.yaml new file mode 100644 index 0000000..c8ed30c --- /dev/null +++ b/practice_collection/postgresql/resources/sql.yaml @@ -0,0 +1,11 @@ +product: + select_all: SELECT id, name, price, category_id FROM product + select_by_id: SELECT id, name, price, category_id FROM product WHERE id = $1 + insert: INSERT INTO product VALUES(nextval('product_seq'), $1, $2, $3) + update_by_id: UPDATE product SET name=$1, price=#2, category_id=$3 WHERE id = $4 + delete_by_id: DELETE FROM product WHERE id = $1 +product_category: + select_all: SELECT id, name FROM product_category + select_by_id: SELECT id, name FROM FROM product_category + insert: INSERT INTO product_category VALUES(nextval('product_category_seq')), $1) + delete_by_id: DELETE FROM product_category WHERE id = $1 diff --git a/practice_collection/postgres/sql/create_table.sql b/practice_collection/postgresql/sql/create_table.sql similarity index 74% rename from practice_collection/postgres/sql/create_table.sql rename to practice_collection/postgresql/sql/create_table.sql index bd2b054..dafe8d6 100644 --- a/practice_collection/postgres/sql/create_table.sql +++ b/practice_collection/postgresql/sql/create_table.sql @@ -16,4 +16,11 @@ CREATE SEQUENCE product_seq INCREMENT 1 MINVALUE 10 MAXVALUE 100000 - CYCLE; \ No newline at end of file + CYCLE; + +CREATE SEQUENCE product_category_seq + START 10 + INCREMENT 1 + MINVALUE 10 + MAXVALUE 100000 + CYCLE; diff --git a/practice_collection/postgres/src/connect.rs b/practice_collection/postgresql/src/connect.rs similarity index 95% rename from practice_collection/postgres/src/connect.rs rename to practice_collection/postgresql/src/connect.rs index f114742..6ba112f 100644 --- a/practice_collection/postgres/src/connect.rs +++ b/practice_collection/postgresql/src/connect.rs @@ -1,5 +1,5 @@ -use postgres::{Client, NoTls, Config}; use crate::params::ConnectParams; +use postgres::{Client, Config, NoTls}; /// データベース接続機能の実装 #[allow(dead_code)] @@ -36,7 +36,7 @@ mod tests { 5432, "rust_sample".to_owned(), "postgres".to_owned(), - "admin".to_owned() + "admin".to_owned(), ); match super::PostgresSampleClient::simple_connect(params.clone()) { Ok(client) => { @@ -53,4 +53,4 @@ mod tests { Err(err) => println!("{}", err), } } -} \ No newline at end of file +} diff --git a/practice_collection/postgres/src/entities.rs b/practice_collection/postgresql/src/entities.rs similarity index 99% rename from practice_collection/postgres/src/entities.rs rename to practice_collection/postgresql/src/entities.rs index c8e81b1..0267483 100644 --- a/practice_collection/postgres/src/entities.rs +++ b/practice_collection/postgresql/src/entities.rs @@ -14,4 +14,4 @@ pub struct Product { price: i32, category_id: i32, product_category: Option>, -} \ No newline at end of file +} diff --git a/practice_collection/postgres/src/lib.rs b/practice_collection/postgresql/src/lib.rs similarity index 56% rename from practice_collection/postgres/src/lib.rs rename to practice_collection/postgresql/src/lib.rs index 6e7f3f1..14f9ecb 100644 --- a/practice_collection/postgres/src/lib.rs +++ b/practice_collection/postgresql/src/lib.rs @@ -1,10 +1,15 @@ -mod params; mod connect; -mod transaction; mod entities; -mod repository; -mod product_repository; -mod product_category_repository; +mod manager; +mod params; mod pool_1; mod pool_2; -mod manager; \ No newline at end of file +mod product_category_repository; +mod product_repository; +mod repository; +mod tokio_connect; +mod tokio_product_repository; +mod tokio_repository; +mod tokio_transaction; +mod transaction; +pub mod sql; \ No newline at end of file diff --git a/practice_collection/postgres/src/main.rs b/practice_collection/postgresql/src/main.rs similarity index 100% rename from practice_collection/postgres/src/main.rs rename to practice_collection/postgresql/src/main.rs diff --git a/practice_collection/postgres/src/manager.rs b/practice_collection/postgresql/src/manager.rs similarity index 99% rename from practice_collection/postgres/src/manager.rs rename to practice_collection/postgresql/src/manager.rs index b076604..b800185 100644 --- a/practice_collection/postgres/src/manager.rs +++ b/practice_collection/postgresql/src/manager.rs @@ -1,7 +1,7 @@ -use r2d2_postgres::{postgres::NoTls, PostgresConnectionManager}; -use r2d2::PooledConnection; -use anyhow::Result; use crate::pool_1::SAMPLE_POOL_1; +use anyhow::Result; +use r2d2::PooledConnection; +use r2d2_postgres::{postgres::NoTls, PostgresConnectionManager}; /// ConnectionManager pub struct SamplePoolManager; impl SamplePoolManager { @@ -19,10 +19,10 @@ impl SamplePoolManager { #[cfg(test)] mod tests { use super::*; - use std::thread; + use crate::product_repository::ProductRepository; use crate::repository::Repository; use crate::transaction::TransactionUtil; - use crate::product_repository::ProductRepository; + use std::thread; #[ignore = "Not connection database"] #[test] @@ -38,4 +38,4 @@ mod tests { assert_eq!(product.get_name(), "はしちゃん"); Ok(()) } -} \ No newline at end of file +} diff --git a/practice_collection/postgres/src/params.rs b/practice_collection/postgresql/src/params.rs similarity index 78% rename from practice_collection/postgres/src/params.rs rename to practice_collection/postgresql/src/params.rs index b860a84..45fa690 100644 --- a/practice_collection/postgres/src/params.rs +++ b/practice_collection/postgresql/src/params.rs @@ -10,7 +10,9 @@ pub struct ConnectParams { } impl ConnectParams { pub fn connect_string(&self) -> String { - format!("host={} port={} dbname={} user={} password={}", - self.host, self.port, self.dbname, self.user, self.password) + format!( + "host={} port={} dbname={} user={} password={}", + self.host, self.port, self.dbname, self.user, self.password + ) } -} \ No newline at end of file +} diff --git a/practice_collection/postgres/src/pool_1.rs b/practice_collection/postgresql/src/pool_1.rs similarity index 78% rename from practice_collection/postgres/src/pool_1.rs rename to practice_collection/postgresql/src/pool_1.rs index b7755e9..a01a4df 100644 --- a/practice_collection/postgres/src/pool_1.rs +++ b/practice_collection/postgresql/src/pool_1.rs @@ -1,19 +1,19 @@ -use std::sync::Mutex; -use r2d2_postgres::{postgres::NoTls, PostgresConnectionManager}; -use r2d2_postgres::r2d2::Pool; use once_cell::sync::Lazy; +use r2d2_postgres::r2d2::Pool; +use r2d2_postgres::{postgres::NoTls, PostgresConnectionManager}; +use std::sync::Mutex; #[allow(dead_code)] // Connecttion String -static CONNECTION_STR: &str = "host=localhost port=5432 dbname=rust_sample user=postgres password=admin"; +static CONNECTION_STR: &str = + "host=localhost port=5432 dbname=rust_sample user=postgres password=admin"; #[allow(dead_code)] // Create Connection Pool -pub static SAMPLE_POOL_1: Lazy>>> = -Lazy::new(|| { +pub static SAMPLE_POOL_1: Lazy>>> = Lazy::new(|| { let config = CONNECTION_STR.parse().unwrap(); // create connection manager let manager = PostgresConnectionManager::new(config, NoTls); // create pool let pool = r2d2::Pool::new(manager).unwrap(); Mutex::new(pool) -}); \ No newline at end of file +}); diff --git a/practice_collection/postgresql/src/pool_2.rs b/practice_collection/postgresql/src/pool_2.rs new file mode 100644 index 0000000..99e6811 --- /dev/null +++ b/practice_collection/postgresql/src/pool_2.rs @@ -0,0 +1,24 @@ +use once_cell::sync::Lazy; +use r2d2_postgres::r2d2::Pool; +use r2d2_postgres::{postgres::NoTls, PostgresConnectionManager}; +use std::sync::Mutex; +use std::time::Duration; + +#[allow(dead_code)] +// connection str +static CONNECTION_STR: &str = + "host=localhost port=5432 dbname=rust_sample user=postgres password=admin"; + +#[allow(dead_code)] +// create connection pool +pub static SAMPLE_POOL_2: Lazy>>> = Lazy::new(|| { + let config = CONNECTION_STR.parse().unwrap(); + let manager = PostgresConnectionManager::new(config, NoTls); + let pool = r2d2::Pool::builder() + .max_size(30) + .min_idle(Some(1)) + .connection_timeout(Duration::from_secs_f32(60.0)) + .build(manager) + .unwrap(); + Mutex::new(pool) +}); diff --git a/practice_collection/postgres/src/product_category_repository.rs b/practice_collection/postgresql/src/product_category_repository.rs similarity index 80% rename from practice_collection/postgres/src/product_category_repository.rs rename to practice_collection/postgresql/src/product_category_repository.rs index 5039795..b2fee72 100644 --- a/practice_collection/postgres/src/product_category_repository.rs +++ b/practice_collection/postgresql/src/product_category_repository.rs @@ -1,11 +1,11 @@ -use postgres::Transaction; -use postgres::types::Type; -use anyhow::{Result, Error}; use crate::entities::{Product, ProductCategory}; +use anyhow::{Error, Result}; +use postgres::types::Type; +use postgres::Transaction; #[allow(dead_code)] pub struct ProductCategoryRepository<'a, 'b>(pub &'a mut Transaction<'b>); -impl ProductCategoryRepository<'_,'_> { +impl ProductCategoryRepository<'_, '_> { #[allow(dead_code)] pub fn select_by_id_join_product(&mut self, id: i32) -> Result { let sql = r#" @@ -26,9 +26,15 @@ impl ProductCategoryRepository<'_,'_> { product_category.set_id(row.get("idc_id")); product_category.set_name(row.get("c_name")); } - products.push(Product::new(row.get("id"), row.get("name"), row.get("price"), row.get("category_id"), None)); + products.push(Product::new( + row.get("id"), + row.get("name"), + row.get("price"), + row.get("category_id"), + None, + )); } product_category.set_products(Some(products)); Ok(product_category) } -} \ No newline at end of file +} diff --git a/practice_collection/postgres/src/product_repository.rs b/practice_collection/postgresql/src/product_repository.rs similarity index 82% rename from practice_collection/postgres/src/product_repository.rs rename to practice_collection/postgresql/src/product_repository.rs index 1bd6dc0..f55c0ec 100644 --- a/practice_collection/postgres/src/product_repository.rs +++ b/practice_collection/postgresql/src/product_repository.rs @@ -1,14 +1,12 @@ -use postgres::Transaction; -use postgres::types::Type; -use anyhow::{Result, Error}; -use crate::repository::Repository; use crate::entities::Product; - +use crate::repository::Repository; +use anyhow::{Error, Result}; +use postgres::types::Type; +use postgres::Transaction; /// productテーブルにアクセスするRepository pub struct ProductRepository<'a, 'b>(pub &'a mut Transaction<'b>); impl Repository for ProductRepository<'_, '_> { - fn select_all(&mut self) -> Result> { let sql = r#" SELECT id, name, price, category_id FROM product @@ -17,15 +15,13 @@ impl Repository for ProductRepository<'_, '_> { let rows = self.0.query(sql, &[])?; let mut products = Vec::::new(); for row in rows { - products.push( - Product::new( - row.get("id"), - row.get("name"), - row.get("price"), - row.get("category_id"), - None, - ) - ); + products.push(Product::new( + row.get("id"), + row.get("name"), + row.get("price"), + row.get("category_id"), + None, + )); } Ok(products) } @@ -37,32 +33,29 @@ impl Repository for ProductRepository<'_, '_> { let stmt = self.0.prepare_typed(sql, &[Type::INT4])?; // 4byte let result = self.0.query_opt(&stmt, &[&id])?; match result { - Some(row) => { - Ok(Product::new( - row.get("id"), - row.get("name"), - row.get("price"), - row.get("category_id"), - None - )) - }, - None => Err(Error::msg( - format!("Not found id:{}", id) + Some(row) => Ok(Product::new( + row.get("id"), + row.get("name"), + row.get("price"), + row.get("category_id"), + None, )), + None => Err(Error::msg(format!("Not found id:{}", id))), } } fn update_by_id(&mut self, _id: i32) -> Result { todo!() } fn insert(&mut self, row: Product) -> Result { - let stmt = self.0.prepare_typed( "INSERT INTO product VALUES(nextval('product_seq'), $1, $2, $3)", - &[Type::VARCHAR, Type::INT4, Type::INT4] + &[Type::VARCHAR, Type::INT4, Type::INT4], + )?; + let count = self.0.execute( + &stmt, + &[row.get_name(), row.get_price(), row.get_category_id()], )?; - let count = self.0.execute(&stmt, &[row.get_name(), row.get_price(), row.get_category_id()])?; Ok(count) - } } @@ -73,7 +66,7 @@ impl ProductRepository<'_, '_> { SELECT CAST(AVG(price) AS FLOAT) as price_avg FROM product "#; let row = self.0.query_one(stmt, &[])?; - let avg: f64= row.get(0); + let avg: f64 = row.get(0); Ok(avg) } } @@ -81,8 +74,8 @@ impl ProductRepository<'_, '_> { #[cfg(test)] mod tests { - use crate::{params::ConnectParams, transaction::TransactionUtil}; use crate::connect::PostgresSampleClient; + use crate::{params::ConnectParams, transaction::TransactionUtil}; use super::*; @@ -92,13 +85,12 @@ mod tests { 5432, "rust_sample".to_owned(), "postgres".to_owned(), - "admin".to_owned() + "admin".to_owned(), ) } #[ignore = "Unable to establish a connection with PostgreSQL"] #[test] fn test_select_all() -> anyhow::Result<()> { - let mut client = PostgresSampleClient::config_connect(connection_params())?; let mut transaction = TransactionUtil::start(&mut client, true)?; let mut repository = ProductRepository(&mut transaction); @@ -109,7 +101,6 @@ mod tests { #[ignore = "Unable to establish a connection with PostgreSQL"] #[test] fn test_avg_by_price() -> anyhow::Result<()> { - let mut client = PostgresSampleClient::config_connect(connection_params())?; let mut transaction = TransactionUtil::start(&mut client, true)?; let mut repository = ProductRepository(&mut transaction); @@ -118,7 +109,6 @@ mod tests { Ok(()) } - #[ignore = "Unable to establish a connection with PostgreSQL"] #[test] fn test_select_by_id() -> anyhow::Result<()> { @@ -152,8 +142,8 @@ mod tests { TransactionUtil::commit(transaction)?; assert_eq!(count, 1); } - Err(e) => println!("{:?}", e) + Err(e) => println!("{:?}", e), } Ok(()) } -} \ No newline at end of file +} diff --git a/practice_collection/postgres/src/repository.rs b/practice_collection/postgresql/src/repository.rs similarity index 91% rename from practice_collection/postgres/src/repository.rs rename to practice_collection/postgresql/src/repository.rs index 2cad0e3..8c1ba83 100644 --- a/practice_collection/postgres/src/repository.rs +++ b/practice_collection/postgresql/src/repository.rs @@ -1,6 +1,6 @@ use anyhow::Result; -pub trait Repository { +pub trait Repository { fn select_all(&mut self) -> Result> { todo!() } @@ -16,4 +16,4 @@ pub trait Repository { fn delete(&mut self, _id: PK) -> Result { todo!() } -} \ No newline at end of file +} diff --git a/practice_collection/postgresql/src/sql.rs b/practice_collection/postgresql/src/sql.rs new file mode 100644 index 0000000..7caf672 --- /dev/null +++ b/practice_collection/postgresql/src/sql.rs @@ -0,0 +1,34 @@ +use once_cell::sync::Lazy; +use yaml_rust::{Yaml, YamlLoader}; +use std::sync::Mutex; +use anyhow::{Result,Error}; +use std::env; + +static SQLS: Lazy> = Lazy::new(||{ + init_sqls().unwrap_or_else(|err| panic!("{:?}", err)) +}); + +fn init_sqls() -> Result> { + let current = concat!(env!("CARGO_MANIFEST_DIR"), "/resources/sql.yaml"); + dbg!(¤t); + let str_yaml = std::fs::read_to_string(current)?; + let values: Vec = YamlLoader::load_from_str(str_yaml.as_str())?; + dbg!(&values); + let result = Mutex::new(values[0].clone()); + Ok(result) +} + +/// return sql +pub async fn get_sql(table_name: &str, method_name: &str) -> Result { + dbg!("------"); + let yaml = SQLS.lock().unwrap(); + let sqls = match yaml[table_name].as_hash() { + Some(sqls) => sqls, + None => return Err(Error::msg("Not found table")), + }; + let sql = match sqls.get(&Yaml::String(method_name.to_owned())) { + Some(sql) => sql.as_str().unwrap(), + None => return Err(Error::msg("Not found method")), + }; + Ok(sql.to_owned()) +} \ No newline at end of file diff --git a/practice_collection/postgresql/src/tokio_connect.rs b/practice_collection/postgresql/src/tokio_connect.rs new file mode 100644 index 0000000..307621e --- /dev/null +++ b/practice_collection/postgresql/src/tokio_connect.rs @@ -0,0 +1,51 @@ +use anyhow::Result; +use tokio_postgres::{Client, NoTls}; +use once_cell::sync::Lazy; +use std::sync::Mutex; +use crate::params::ConnectParams; + +#[allow(dead_code)] +pub static CONNECT_PARAMS: Lazy> = + Lazy::new(||{ + let params = ConnectParams::new( + "localhost".to_owned(), 5432, "rust_sample".to_owned(), + "postgres".to_owned(), "admin".to_owned() + ); + Mutex::new(params) + }); + +/// 非同期実行データベース接続機能 +#[allow(dead_code)] +pub struct AsyncSimpleClient; +impl AsyncSimpleClient { + #[allow(dead_code)] + pub async fn connect() -> Result { + //let config = CONNECT_PARAMS.lock().unwrap().connect_string().clone(); + let config; + { + let params = CONNECT_PARAMS.lock().unwrap(); // params lock here. + config = params.connect_string().clone(); + } // params drop here. + + let (client, connection) = tokio_postgres::connect(config.as_str(), NoTls).await?; + tokio::spawn(async move { + if let Err(e) = connection.await { + eprintln!("Connection error: {}", e); + } + }); + //handle.await.expect("Async task panicked"); + Ok(client) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[ignore = "Need database access."] + #[tokio::test] + async fn test_connection() -> Result<()> { + let _connect = AsyncSimpleClient::connect().await?; + Ok(()) + + } +} \ No newline at end of file diff --git a/practice_collection/postgresql/src/tokio_product_repository.rs b/practice_collection/postgresql/src/tokio_product_repository.rs new file mode 100644 index 0000000..35c2615 --- /dev/null +++ b/practice_collection/postgresql/src/tokio_product_repository.rs @@ -0,0 +1,54 @@ +use crate::entities::Product; +use crate::tokio_repository::AsyncRepository; +use anyhow::Result; +use async_trait::async_trait; +use tokio_postgres::Transaction; + +pub struct ProductRepository<'a, 'b> { + transaction: &'a mut Transaction<'b>, +} +impl<'a, 'b> ProductRepository<'a, 'b> { + #[allow(dead_code)] + pub fn new(tran: &'a mut Transaction<'b>) -> Self { + Self { transaction: tran } + } +} +#[async_trait] +impl AsyncRepository for ProductRepository<'_, '_> { + async fn select_all(&mut self) -> Result> { + use crate::sql::get_sql; + let sql = get_sql("product", "select_all").await?; + //let sql = "SELECT id, name, price, category_id FROM product"; + let rows = self.transaction.query(sql.as_str(), &[]).await?; + let mut products = Vec::::new(); + for row in rows { + products.push(Product::new( + row.get(0), + row.get(1), + row.get(2), + row.get(3), + None, + )); + } + Ok(products) + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::tokio_connect::AsyncSimpleClient; + use crate::tokio_transaction::AsyncTransactionUtil; + use anyhow::Result; + + #[ignore = "Need database access"] + #[tokio::test] + async fn test_select_all() -> Result<()> { + let mut client = AsyncSimpleClient::connect().await?; + let mut transaction = AsyncTransactionUtil::start(&mut client, true).await?; + let mut repository = ProductRepository::new(&mut transaction); + let products = repository.select_all().await?; + dbg!(&products); + Ok(()) + } +} diff --git a/practice_collection/postgresql/src/tokio_repository.rs b/practice_collection/postgresql/src/tokio_repository.rs new file mode 100644 index 0000000..079ec2a --- /dev/null +++ b/practice_collection/postgresql/src/tokio_repository.rs @@ -0,0 +1,11 @@ +use anyhow::Result; +use async_trait::async_trait; + +#[async_trait] +pub trait AsyncRepository { + async fn select_all(&mut self) -> Result>; + //async fn select_by_id(&mut self, id: PK) -> Result; + //async fn insert(&mut self, row: T) -> Result<()>; + //async fn update_by_id(&mut self, id: PK) -> Result; + //async fn delete_by_id(&mut self, id: PK) -> Result; +} diff --git a/practice_collection/postgresql/src/tokio_transaction.rs b/practice_collection/postgresql/src/tokio_transaction.rs new file mode 100644 index 0000000..290f189 --- /dev/null +++ b/practice_collection/postgresql/src/tokio_transaction.rs @@ -0,0 +1,17 @@ +use anyhow::Result; +use tokio_postgres::{Client, Transaction}; + +#[allow(dead_code)] +/// 非同期実行 トランザクション制御機能の実装 +pub struct AsyncTransactionUtil; +impl AsyncTransactionUtil { + #[allow(dead_code)] + pub async fn start(client: &mut Client, read_only: bool) -> Result { + let transaction = client + .build_transaction() + .read_only(read_only) + .start() + .await?; + Ok(transaction) + } +} diff --git a/practice_collection/postgres/src/transaction.rs b/practice_collection/postgresql/src/transaction.rs similarity index 99% rename from practice_collection/postgres/src/transaction.rs rename to practice_collection/postgresql/src/transaction.rs index ca7fb42..3c08185 100644 --- a/practice_collection/postgres/src/transaction.rs +++ b/practice_collection/postgresql/src/transaction.rs @@ -1,5 +1,5 @@ -use postgres::{Client, Transaction}; use anyhow::Result; +use postgres::{Client, Transaction}; /// トランザクション制御 pub struct TransactionUtil; @@ -22,4 +22,4 @@ impl TransactionUtil { transaction.rollback()?; Ok(()) } -} \ No newline at end of file +} diff --git a/practice_collection/thread_and_async/src/task/writer.rs b/practice_collection/thread_and_async/src/task/writer.rs index e9eaa7b..21d906e 100644 --- a/practice_collection/thread_and_async/src/task/writer.rs +++ b/practice_collection/thread_and_async/src/task/writer.rs @@ -7,7 +7,6 @@ use std::io::BufWriter; use std::marker::PhantomData; /// Serialize CSV - pub struct SampleWriter { phantom: PhantomData, }