diff --git a/refinery_core/src/drivers/config.rs b/refinery_core/src/drivers/config.rs index c7539028..9a9067ba 100644 --- a/refinery_core/src/drivers/config.rs +++ b/refinery_core/src/drivers/config.rs @@ -18,7 +18,10 @@ use std::convert::Infallible; impl Transaction for Config { type Error = Infallible; - fn execute(&mut self, _queries: &[&str]) -> Result { + fn execute<'a, T: Iterator>( + &mut self, + _queries: T, + ) -> Result { Ok(0) } } @@ -33,7 +36,10 @@ impl Query> for Config { impl AsyncTransaction for Config { type Error = Infallible; - async fn execute(&mut self, _queries: &[&str]) -> Result { + async fn execute<'a, T: Iterator + Send>( + &mut self, + _queries: T, + ) -> Result { Ok(0) } } diff --git a/refinery_core/src/drivers/mysql.rs b/refinery_core/src/drivers/mysql.rs index 33148d94..c2947152 100644 --- a/refinery_core/src/drivers/mysql.rs +++ b/refinery_core/src/drivers/mysql.rs @@ -43,10 +43,13 @@ fn query_applied_migrations( impl Transaction for Conn { type Error = MError; - fn execute(&mut self, queries: &[&str]) -> Result { + fn execute<'a, T: Iterator>( + &mut self, + queries: T, + ) -> Result { let mut transaction = self.start_transaction(get_tx_opts())?; let mut count = 0; - for query in queries.iter() { + for query in queries { transaction.query_iter(query)?; count += 1; } @@ -58,11 +61,14 @@ impl Transaction for Conn { impl Transaction for PooledConn { type Error = MError; - fn execute(&mut self, queries: &[&str]) -> Result { + fn execute<'a, T: Iterator>( + &mut self, + queries: T, + ) -> Result { let mut transaction = self.start_transaction(get_tx_opts())?; let mut count = 0; - for query in queries.iter() { + for query in queries { transaction.query_iter(query)?; count += 1; } diff --git a/refinery_core/src/drivers/mysql_async.rs b/refinery_core/src/drivers/mysql_async.rs index c92fcd86..675b96f9 100644 --- a/refinery_core/src/drivers/mysql_async.rs +++ b/refinery_core/src/drivers/mysql_async.rs @@ -40,7 +40,10 @@ async fn query_applied_migrations<'a>( impl AsyncTransaction for Pool { type Error = MError; - async fn execute(&mut self, queries: &[&str]) -> Result { + async fn execute<'a, T: Iterator + Send>( + &mut self, + queries: T, + ) -> Result { let mut conn = self.get_conn().await?; let mut options = TxOpts::new(); options.with_isolation_level(Some(IsolationLevel::ReadCommitted)); @@ -48,7 +51,7 @@ impl AsyncTransaction for Pool { let mut transaction = conn.start_transaction(options).await?; let mut count = 0; for query in queries { - transaction.query_drop(*query).await?; + transaction.query_drop(query).await?; count += 1; } transaction.commit().await?; diff --git a/refinery_core/src/drivers/postgres.rs b/refinery_core/src/drivers/postgres.rs index 3d177509..fa4d5b9e 100644 --- a/refinery_core/src/drivers/postgres.rs +++ b/refinery_core/src/drivers/postgres.rs @@ -33,10 +33,13 @@ fn query_applied_migrations( impl Transaction for PgClient { type Error = PgError; - fn execute(&mut self, queries: &[&str]) -> Result { + fn execute<'a, T: Iterator>( + &mut self, + queries: T, + ) -> Result { let mut transaction = PgClient::transaction(self)?; let mut count = 0; - for query in queries.iter() { + for query in queries { PgTransaction::batch_execute(&mut transaction, query)?; count += 1; } diff --git a/refinery_core/src/drivers/rusqlite.rs b/refinery_core/src/drivers/rusqlite.rs index 9547ba48..9ee4ced9 100644 --- a/refinery_core/src/drivers/rusqlite.rs +++ b/refinery_core/src/drivers/rusqlite.rs @@ -32,10 +32,13 @@ fn query_applied_migrations( impl Transaction for RqlConnection { type Error = RqlError; - fn execute(&mut self, queries: &[&str]) -> Result { + fn execute<'a, T: Iterator>( + &mut self, + queries: T, + ) -> Result { let transaction = self.transaction()?; let mut count = 0; - for query in queries.iter() { + for query in queries { transaction.execute_batch(query)?; count += 1; } diff --git a/refinery_core/src/drivers/tiberius.rs b/refinery_core/src/drivers/tiberius.rs index 4218ee7d..4095f1b7 100644 --- a/refinery_core/src/drivers/tiberius.rs +++ b/refinery_core/src/drivers/tiberius.rs @@ -47,13 +47,16 @@ where { type Error = Error; - async fn execute(&mut self, queries: &[&str]) -> Result { + async fn execute<'a, T: Iterator + Send>( + &mut self, + queries: T, + ) -> Result { // Tiberius doesn't support transactions, see https://github.com/prisma/tiberius/issues/28 self.simple_query("BEGIN TRAN T1;").await?; let mut count = 0; for query in queries { // Drop the returning `QueryStream<'a>` to avoid compiler complaning regarding lifetimes - if let Err(err) = self.simple_query(*query).await.map(drop) { + if let Err(err) = self.simple_query(query).await.map(drop) { if let Err(err) = self.simple_query("ROLLBACK TRAN T1").await { log::error!("could not ROLLBACK transaction, {}", err); } diff --git a/refinery_core/src/drivers/tokio_postgres.rs b/refinery_core/src/drivers/tokio_postgres.rs index ec8bb9c8..346cfd7c 100644 --- a/refinery_core/src/drivers/tokio_postgres.rs +++ b/refinery_core/src/drivers/tokio_postgres.rs @@ -35,7 +35,10 @@ async fn query_applied_migrations( impl AsyncTransaction for Client { type Error = PgError; - async fn execute(&mut self, queries: &[&str]) -> Result { + async fn execute<'a, T: Iterator + Send>( + &mut self, + queries: T, + ) -> Result { let transaction = self.transaction().await?; let mut count = 0; for query in queries { diff --git a/refinery_core/src/traits/async.rs b/refinery_core/src/traits/async.rs index 8e42337e..a0305d2e 100644 --- a/refinery_core/src/traits/async.rs +++ b/refinery_core/src/traits/async.rs @@ -12,7 +12,10 @@ use std::string::ToString; pub trait AsyncTransaction { type Error: std::error::Error + Send + Sync + 'static; - async fn execute(&mut self, query: &[&str]) -> Result; + async fn execute<'a, T: Iterator + Send>( + &mut self, + queries: T, + ) -> Result; } #[async_trait] @@ -43,10 +46,13 @@ async fn migrate( migration.set_applied(); let update_query = insert_migration_query(&migration, migration_table_name); transaction - .execute(&[ - migration.sql().as_ref().expect("sql must be Some!"), - &update_query, - ]) + .execute( + [ + migration.sql().as_ref().expect("sql must be Some!"), + update_query.as_str(), + ] + .into_iter(), + ) .await .migration_err( &format!("error applying migration {migration}"), @@ -109,10 +115,8 @@ async fn migrate_grouped( ); } - let refs: Vec<&str> = grouped_migrations.iter().map(AsRef::as_ref).collect(); - transaction - .execute(refs.as_ref()) + .execute(grouped_migrations.iter().map(AsRef::as_ref)) .await .migration_err("error applying migrations", None)?; @@ -142,7 +146,7 @@ where migration_table_name: &str, ) -> Result, Error> { let mut migrations = self - .query(Self::get_last_applied_migration_query(migration_table_name).as_str()) + .query(Self::get_last_applied_migration_query(migration_table_name).as_ref()) .await .migration_err("error getting last applied migration", None)?; @@ -154,7 +158,7 @@ where migration_table_name: &str, ) -> Result, Error> { let migrations = self - .query(Self::get_applied_migrations_query(migration_table_name).as_str()) + .query(Self::get_applied_migrations_query(migration_table_name).as_ref()) .await .migration_err("error getting applied migrations", None)?; @@ -170,9 +174,11 @@ where target: Target, migration_table_name: &str, ) -> Result { - self.execute(&[&Self::assert_migrations_table_query(migration_table_name)]) - .await - .migration_err("error asserting migrations table", None)?; + self.execute( + [Self::assert_migrations_table_query(migration_table_name).as_ref()].into_iter(), + ) + .await + .migration_err("error asserting migrations table", None)?; let applied_migrations = self .get_applied_migrations(migration_table_name) diff --git a/refinery_core/src/traits/sync.rs b/refinery_core/src/traits/sync.rs index 0225f879..f7ad2a65 100644 --- a/refinery_core/src/traits/sync.rs +++ b/refinery_core/src/traits/sync.rs @@ -8,7 +8,10 @@ use crate::{Error, Migration, Report, Target}; pub trait Transaction { type Error: std::error::Error + Send + Sync + 'static; - fn execute(&mut self, queries: &[&str]) -> Result; + fn execute<'a, T: Iterator>( + &mut self, + queries: T, + ) -> Result; } pub trait Query: Transaction { @@ -66,7 +69,7 @@ pub fn migrate( } }; - let refs: Vec<&str> = migration_batch.iter().map(AsRef::as_ref).collect(); + let refs = migration_batch.iter().map(AsRef::as_ref); if batched { let migrations_display = applied_migrations @@ -76,10 +79,10 @@ pub fn migrate( .join("\n"); log::info!("going to apply batch migrations in single transaction:\n{migrations_display}"); transaction - .execute(refs.as_ref()) + .execute(refs) .migration_err("error applying migrations", None)?; } else { - for (i, update) in refs.iter().enumerate() { + for (i, update) in refs.enumerate() { // first iteration is pair so we know the following even in the iteration index // marks the previous (pair) migration as completed. let applying_migration = i % 2 == 0; @@ -91,7 +94,7 @@ pub fn migrate( log::debug!("applied migration: {current_migration} writing state to db."); } transaction - .execute(&[update]) + .execute([update].into_iter()) .migration_err("error applying update", Some(&applied_migrations[0..i / 2]))?; } } @@ -119,8 +122,10 @@ where fn assert_migrations_table(&mut self, migration_table_name: &str) -> Result { // Needed cause some database vendors like Mssql have a non sql standard way of checking the migrations table, // though on this case it's just to be consistent with the async trait `AsyncMigrate` - self.execute(&[Self::assert_migrations_table_query(migration_table_name).as_str()]) - .migration_err("error asserting migrations table", None) + self.execute( + [Self::assert_migrations_table_query(migration_table_name).as_ref()].into_iter(), + ) + .migration_err("error asserting migrations table", None) } fn get_last_applied_migration(