refac: add additional trait for migration names

This commit is contained in:
Dmitriy Pleshevskiy 2021-02-15 13:47:45 +03:00
parent 109c9ce52f
commit 33f392e18e
5 changed files with 44 additions and 34 deletions

View File

@ -1,6 +1,6 @@
use crate::config::Config; use crate::config::Config;
use crate::database::PostgresConnection; use crate::database::PostgresConnection;
use crate::migration::{DatabaseMigrationManager, MigrationManager}; use crate::migration::{DatabaseMigrationManager, MigrationManager, MigrationNames};
use crate::StdResult; use crate::StdResult;
use std::convert::TryFrom; use std::convert::TryFrom;

View File

@ -3,6 +3,7 @@ use crate::database::{DatabaseConnection, PostgresConnection};
use crate::error::{ErrorKind, StdResult}; use crate::error::{ErrorKind, StdResult};
use crate::migration::{ use crate::migration::{
filter_pending_migrations, DatabaseMigrationManager, Migration, MigrationManager, filter_pending_migrations, DatabaseMigrationManager, Migration, MigrationManager,
MigrationNames,
}; };
const EM_DASH: char = '—'; const EM_DASH: char = '—';

View File

@ -1,6 +1,8 @@
use crate::database::{DatabaseConnection, PostgresConnection}; use crate::database::PostgresConnection;
use crate::migration::Migration; use crate::migration::{
use crate::migration::{filter_pending_migrations, DatabaseMigrationManager, MigrationManager}; filter_pending_migrations, DatabaseMigrationManager, Migration, MigrationManager,
MigrationNames,
};
use crate::Config; use crate::Config;
use crate::StdResult; use crate::StdResult;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -25,13 +27,12 @@ fn is_up_to_date_migrations(migrations: &[Migration], applied_migration_names: &
migrations.is_empty() || migrations.last().map(|m| m.name()) == applied_migration_names.first() migrations.is_empty() || migrations.last().map(|m| m.name()) == applied_migration_names.first()
} }
fn upgrade_all_pending_migrations<Conn, ManagerT>( fn upgrade_all_pending_migrations<ManagerT>(
mut manager: ManagerT, mut manager: ManagerT,
pending_migrations: &[Migration], pending_migrations: &[Migration],
) -> StdResult<()> ) -> StdResult<()>
where where
Conn: DatabaseConnection, ManagerT: Sized + DatabaseMigrationManager,
ManagerT: Sized + DatabaseMigrationManager<Conn>,
{ {
for migration in pending_migrations.iter() { for migration in pending_migrations.iter() {
println!("upgrade {}...", migration.name()); println!("upgrade {}...", migration.name());

View File

@ -17,6 +17,13 @@ pub trait TryFromSql<QueryResultRow>: Sized {
fn try_from_sql(row: QueryResultRow) -> StdResult<Self>; fn try_from_sql(row: QueryResultRow) -> StdResult<Self>;
} }
impl TryFromSql<postgres::Row> for String {
fn try_from_sql(row: postgres::Row) -> StdResult<Self> {
let res: String = row.get(0);
Ok(res)
}
}
pub trait DatabaseConnection: Sized { pub trait DatabaseConnection: Sized {
type QueryResultRow; type QueryResultRow;
type QueryResult; type QueryResult;

View File

@ -1,4 +1,3 @@
use crate::database::TryFromSql;
use crate::database::{DatabaseConnection, PostgresConnection}; use crate::database::{DatabaseConnection, PostgresConnection};
use crate::path::PathBuilder; use crate::path::PathBuilder;
use crate::StdResult; use crate::StdResult;
@ -67,14 +66,7 @@ pub fn is_migrations_table_not_found<D: std::fmt::Display>(error: D) -> bool {
.contains(r#"relation "migrations" does not exist"#) .contains(r#"relation "migrations" does not exist"#)
} }
impl TryFromSql<postgres::Row> for String { pub trait DatabaseMigrationManager {
fn try_from_sql(row: postgres::Row) -> StdResult<Self> {
let res: String = row.get(0);
Ok(res)
}
}
pub trait DatabaseMigrationManager<Conn: DatabaseConnection> {
const CREATE_MIGRATIONS_STMT: &'static str = r#" const CREATE_MIGRATIONS_STMT: &'static str = r#"
CREATE TABLE IF NOT EXISTS migrations ( CREATE TABLE IF NOT EXISTS migrations (
id serial PRIMARY KEY, id serial PRIMARY KEY,
@ -88,8 +80,6 @@ pub trait DatabaseMigrationManager<Conn: DatabaseConnection> {
fn apply_sql(&mut self, sql_content: &str) -> StdResult<()>; fn apply_sql(&mut self, sql_content: &str) -> StdResult<()>;
fn applied_migration_names(&mut self) -> StdResult<Vec<String>>;
fn create_migrations_table(&mut self) -> StdResult<()>; fn create_migrations_table(&mut self) -> StdResult<()>;
fn insert_migration_info(&mut self, name: &str) -> StdResult<u64>; fn insert_migration_info(&mut self, name: &str) -> StdResult<u64>;
@ -116,26 +106,14 @@ pub trait DatabaseMigrationManager<Conn: DatabaseConnection> {
} }
} }
impl DatabaseMigrationManager<PostgresConnection> for MigrationManager<PostgresConnection> { impl<Conn> DatabaseMigrationManager for MigrationManager<Conn>
where
Conn: DatabaseConnection,
{
fn apply_sql(&mut self, sql_content: &str) -> StdResult<()> { fn apply_sql(&mut self, sql_content: &str) -> StdResult<()> {
self.conn.batch_execute(sql_content) self.conn.batch_execute(sql_content)
} }
fn applied_migration_names(&mut self) -> StdResult<Vec<String>> {
let res = self
.conn
.query("SELECT name FROM migrations ORDER BY id DESC", &[])
.or_else(|e| {
if is_migrations_table_not_found(&e) {
Ok(Vec::new())
} else {
Err(e)
}
})?;
Ok(res.into_iter().collect())
}
fn create_migrations_table(&mut self) -> StdResult<()> { fn create_migrations_table(&mut self) -> StdResult<()> {
self.conn.batch_execute(Self::CREATE_MIGRATIONS_STMT) self.conn.batch_execute(Self::CREATE_MIGRATIONS_STMT)
} }
@ -149,6 +127,29 @@ impl DatabaseMigrationManager<PostgresConnection> for MigrationManager<PostgresC
} }
} }
pub trait MigrationNames {
const APPLIED_MIGRATIONS_STMT: &'static str = "SELECT name FROM migrations ORDER BY id DESC";
fn applied_migration_names(&mut self) -> StdResult<Vec<String>>;
}
impl MigrationNames for MigrationManager<PostgresConnection> {
fn applied_migration_names(&mut self) -> StdResult<Vec<String>> {
let res = self
.conn
.query(Self::APPLIED_MIGRATIONS_STMT, &[])
.or_else(|e| {
if is_migrations_table_not_found(&e) {
Ok(Vec::new())
} else {
Err(e)
}
})?;
Ok(res.into_iter().collect())
}
}
pub fn filter_pending_migrations( pub fn filter_pending_migrations(
migrations: Vec<Migration>, migrations: Vec<Migration>,
applied_migration_names: &[String], applied_migration_names: &[String],