Archived
1
0
Fork 0

refac: move postgres initialization to separate dir

This commit is contained in:
Dmitriy Pleshevskiy 2021-02-16 18:11:39 +03:00
parent 9679519380
commit d4106c50e6
9 changed files with 106 additions and 97 deletions

View file

@ -1,5 +1,5 @@
use crate::config::Config; use crate::config::Config;
use crate::database::PostgresConnection; use crate::databases::*;
use crate::migration::{DatabaseMigrationManager, MigrationManager}; use crate::migration::{DatabaseMigrationManager, MigrationManager};
use crate::opts::ApplyCommandOpt; use crate::opts::ApplyCommandOpt;
use crate::path::PathBuilder; use crate::path::PathBuilder;

View file

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

View file

@ -1,5 +1,6 @@
use crate::config::Config; use crate::config::Config;
use crate::database::{DatabaseConnection, PostgresConnection}; use crate::database::DatabaseConnection;
use crate::databases::*;
use crate::error::{ErrorKind, StdResult}; use crate::error::{ErrorKind, StdResult};
use crate::migration::{filter_pending_migrations, Migration, MigrationManager, MigrationNames}; use crate::migration::{filter_pending_migrations, Migration, MigrationManager, MigrationNames};

View file

@ -1,4 +1,4 @@
use crate::database::PostgresConnection; use crate::databases::*;
use crate::migration::{ use crate::migration::{
filter_pending_migrations, DatabaseMigrationManager, Migration, MigrationManager, filter_pending_migrations, DatabaseMigrationManager, Migration, MigrationManager,
MigrationNames, MigrationNames,

View file

@ -1,7 +1,4 @@
use crate::config::Config;
use crate::StdResult; use crate::StdResult;
use postgres::{Client, NoTls};
use std::convert::TryFrom;
pub trait ToSql { pub trait ToSql {
fn to_sql(&self) -> String; fn to_sql(&self) -> String;
@ -17,13 +14,6 @@ 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;
@ -42,67 +32,3 @@ pub trait DatabaseConnection: Sized {
where where
OutputItem: ?Sized + TryFromSql<Self::QueryResultRow>; OutputItem: ?Sized + TryFromSql<Self::QueryResultRow>;
} }
pub struct PostgresConnection {
client: Client,
}
impl TryFrom<&Config> for PostgresConnection {
type Error = Box<dyn std::error::Error>;
fn try_from(config: &Config) -> Result<Self, Self::Error> {
PostgresConnection::open(&config.database_connection_string()?)
}
}
impl DatabaseConnection for PostgresConnection {
type QueryResultRow = postgres::Row;
type QueryResult = Vec<Self::QueryResultRow>;
fn open(connection_string: &str) -> StdResult<Self> {
let client = Client::connect(connection_string, NoTls)?;
Ok(PostgresConnection { client })
}
fn batch_execute(&mut self, query: &str) -> StdResult<()> {
self.client.batch_execute(query)?;
Ok(())
}
fn execute<'b>(&mut self, query: &str, params: &'b [&'b dyn ToSql]) -> StdResult<u64> {
let stmt = params
.iter()
.enumerate()
.fold(query.to_string(), |acc, (i, p)| {
str::replace(&acc, &format!("${}", i), &p.to_sql())
});
let res = self.client.execute(stmt.as_str(), &[])?;
Ok(res)
}
fn query<'b, OutputItem>(
&mut self,
query: &str,
params: &'b [&'b dyn ToSql],
) -> StdResult<Vec<OutputItem>>
where
OutputItem: ?Sized + TryFromSql<Self::QueryResultRow>,
{
let stmt = params
.iter()
.enumerate()
.fold(query.to_string(), |acc, (i, p)| {
str::replace(&acc, &format!("${}", i), &p.to_sql())
});
let res: Self::QueryResult = self.client.query(stmt.as_str(), &[])?;
let res = res
.into_iter()
.map(OutputItem::try_from_sql)
.collect::<Result<Vec<OutputItem>, _>>()?;
Ok(res)
}
}

View file

@ -0,0 +1,3 @@
mod postgres;
pub use self::postgres::*;

View file

@ -0,0 +1,95 @@
use crate::migration::{MigrationNames, MigrationManager, is_migrations_table_not_found};
use postgres::{Client, NoTls};
use crate::config::Config;
use std::convert::TryFrom;
use crate::error::StdResult;
use crate::database::{TryFromSql, ToSql, DatabaseConnection};
pub struct PostgresConnection {
client: Client,
}
impl TryFrom<&Config> for PostgresConnection {
type Error = Box<dyn std::error::Error>;
fn try_from(config: &Config) -> Result<Self, Self::Error> {
PostgresConnection::open(&config.database_connection_string()?)
}
}
impl DatabaseConnection for PostgresConnection {
type QueryResultRow = postgres::Row;
type QueryResult = Vec<Self::QueryResultRow>;
fn open(connection_string: &str) -> StdResult<Self> {
let client = Client::connect(connection_string, NoTls)?;
Ok(PostgresConnection { client })
}
fn batch_execute(&mut self, query: &str) -> StdResult<()> {
self.client.batch_execute(query)?;
Ok(())
}
fn execute<'b>(&mut self, query: &str, params: &'b [&'b dyn ToSql]) -> StdResult<u64> {
let stmt = params
.iter()
.enumerate()
.fold(query.to_string(), |acc, (i, p)| {
str::replace(&acc, &format!("${}", i), &p.to_sql())
});
let res = self.client.execute(stmt.as_str(), &[])?;
Ok(res)
}
fn query<'b, OutputItem>(
&mut self,
query: &str,
params: &'b [&'b dyn ToSql],
) -> StdResult<Vec<OutputItem>>
where
OutputItem: ?Sized + TryFromSql<Self::QueryResultRow>,
{
let stmt = params
.iter()
.enumerate()
.fold(query.to_string(), |acc, (i, p)| {
str::replace(&acc, &format!("${}", i), &p.to_sql())
});
let res: Self::QueryResult = self.client.query(stmt.as_str(), &[])?;
let res = res
.into_iter()
.map(OutputItem::try_from_sql)
.collect::<Result<Vec<OutputItem>, _>>()?;
Ok(res)
}
}
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())
}
}
impl TryFromSql<postgres::Row> for String {
fn try_from_sql(row: postgres::Row) -> StdResult<Self> {
let res: String = row.get(0);
Ok(res)
}
}

View file

@ -3,6 +3,7 @@
mod commands; mod commands;
mod config; mod config;
mod database; mod database;
mod databases;
mod error; mod error;
mod migration; mod migration;
mod opts; mod opts;

View file

@ -1,4 +1,4 @@
use crate::database::{DatabaseConnection, PostgresConnection}; use crate::database::DatabaseConnection;
use crate::path::PathBuilder; use crate::path::PathBuilder;
use crate::StdResult; use crate::StdResult;
use std::fs; use std::fs;
@ -51,7 +51,7 @@ impl Migration {
} }
pub struct MigrationManager<Conn: DatabaseConnection> { pub struct MigrationManager<Conn: DatabaseConnection> {
conn: Conn, pub(crate) conn: Conn,
} }
impl<Conn: DatabaseConnection> MigrationManager<Conn> { impl<Conn: DatabaseConnection> MigrationManager<Conn> {
@ -129,23 +129,6 @@ pub trait MigrationNames {
fn applied_migration_names(&mut self) -> StdResult<Vec<String>>; 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],