Done first draft of strongly typed migrations
This commit is contained in:
parent
4a00f0b062
commit
c84201fc9f
18 changed files with 396 additions and 448 deletions
39
crates/sqlez/src/domain.rs
Normal file
39
crates/sqlez/src/domain.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use crate::connection::Connection;
|
||||
|
||||
pub trait Domain: Send + Sync + Clone {
|
||||
fn migrate(conn: &Connection) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
impl<D1: Domain, D2: Domain> Domain for (D1, D2) {
|
||||
fn migrate(conn: &Connection) -> anyhow::Result<()> {
|
||||
D1::migrate(conn)?;
|
||||
D2::migrate(conn)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D1: Domain, D2: Domain, D3: Domain> Domain for (D1, D2, D3) {
|
||||
fn migrate(conn: &Connection) -> anyhow::Result<()> {
|
||||
D1::migrate(conn)?;
|
||||
D2::migrate(conn)?;
|
||||
D3::migrate(conn)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D1: Domain, D2: Domain, D3: Domain, D4: Domain> Domain for (D1, D2, D3, D4) {
|
||||
fn migrate(conn: &Connection) -> anyhow::Result<()> {
|
||||
D1::migrate(conn)?;
|
||||
D2::migrate(conn)?;
|
||||
D3::migrate(conn)?;
|
||||
D4::migrate(conn)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D1: Domain, D2: Domain, D3: Domain, D4: Domain, D5: Domain> Domain for (D1, D2, D3, D4, D5) {
|
||||
fn migrate(conn: &Connection) -> anyhow::Result<()> {
|
||||
D1::migrate(conn)?;
|
||||
D2::migrate(conn)?;
|
||||
D3::migrate(conn)?;
|
||||
D4::migrate(conn)?;
|
||||
D5::migrate(conn)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
pub mod bindable;
|
||||
pub mod connection;
|
||||
pub mod domain;
|
||||
pub mod migrations;
|
||||
pub mod savepoint;
|
||||
pub mod statement;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use indoc::{formatdoc, indoc};
|
||||
use indoc::formatdoc;
|
||||
|
||||
use crate::connection::Connection;
|
||||
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
use std::{marker::PhantomData, ops::Deref, sync::Arc};
|
||||
|
||||
use connection::Connection;
|
||||
use thread_local::ThreadLocal;
|
||||
|
||||
use crate::{connection, migrations::Migration};
|
||||
use crate::{connection, domain::Domain};
|
||||
|
||||
pub struct ThreadSafeConnection {
|
||||
pub struct ThreadSafeConnection<D: Domain> {
|
||||
uri: Arc<str>,
|
||||
persistent: bool,
|
||||
initialize_query: Option<&'static str>,
|
||||
migrations: Option<&'static [Migration]>,
|
||||
connection: Arc<ThreadLocal<Connection>>,
|
||||
_pd: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl ThreadSafeConnection {
|
||||
impl<D: Domain> ThreadSafeConnection<D> {
|
||||
pub fn new(uri: &str, persistent: bool) -> Self {
|
||||
Self {
|
||||
uri: Arc::from(uri),
|
||||
persistent,
|
||||
initialize_query: None,
|
||||
migrations: None,
|
||||
connection: Default::default(),
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,13 +31,6 @@ impl ThreadSafeConnection {
|
|||
self
|
||||
}
|
||||
|
||||
/// Migrations have to be run per connection because we fallback to memory
|
||||
/// so this needs
|
||||
pub fn with_migrations(mut self, migrations: &'static [Migration]) -> Self {
|
||||
self.migrations = Some(migrations);
|
||||
self
|
||||
}
|
||||
|
||||
/// Opens a new db connection with the initialized file path. This is internal and only
|
||||
/// called from the deref function.
|
||||
/// If opening fails, the connection falls back to a shared memory connection
|
||||
|
@ -50,21 +43,33 @@ impl ThreadSafeConnection {
|
|||
fn open_shared_memory(&self) -> Connection {
|
||||
Connection::open_memory(self.uri.as_ref())
|
||||
}
|
||||
|
||||
// Open a new connection for the given domain, leaving this
|
||||
// connection intact.
|
||||
pub fn for_domain<D2: Domain>(&self) -> ThreadSafeConnection<D2> {
|
||||
ThreadSafeConnection {
|
||||
uri: self.uri.clone(),
|
||||
persistent: self.persistent,
|
||||
initialize_query: self.initialize_query,
|
||||
connection: Default::default(),
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ThreadSafeConnection {
|
||||
impl<D: Domain> Clone for ThreadSafeConnection<D> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
uri: self.uri.clone(),
|
||||
persistent: self.persistent,
|
||||
initialize_query: self.initialize_query.clone(),
|
||||
migrations: self.migrations.clone(),
|
||||
connection: self.connection.clone(),
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ThreadSafeConnection {
|
||||
impl<D: Domain> Deref for ThreadSafeConnection<D> {
|
||||
type Target = Connection;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
@ -83,13 +88,7 @@ impl Deref for ThreadSafeConnection {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
if let Some(migrations) = self.migrations {
|
||||
for migration in migrations {
|
||||
migration
|
||||
.run(&connection)
|
||||
.expect(&format!("Migrations failed to execute: {:?}", migration));
|
||||
}
|
||||
}
|
||||
D::migrate(&connection).expect("Migrations failed");
|
||||
|
||||
connection
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue