#![doc = include_str!("../README.md")]
#![deny(
missing_copy_implementations,
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unused_import_braces,
unused_qualifications,
unused_extern_crates,
unused_results,
variant_size_differences
)]
#![cfg_attr(docsrs, feature(doc_cfg), allow(unused_attributes))]
#[cfg(not(any(feature = "sqlite", feature = "postgres", feature = "mysql"),))]
compile_error!(
"At least one of the following features must be enabled: sqlite, postgres or mysql."
);
#[cfg(not(any(feature = "sqlx", feature = "diesel"),))]
compile_error!("At least one of the following features must be enabled: sqlx or diesel.");
#[cfg(feature = "sqlite")]
#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
mod sqlite;
#[cfg(feature = "mysql")]
#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))]
mod mysql;
#[cfg(feature = "postgres")]
#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))]
mod postgres;
#[cfg(all(
feature = "macros",
not(any(feature = "runtime-async-std", feature = "runtime-tokio"))
))]
compile_error!(
"At least one of the following features must be enabled: runtime-async-std or runtime-tokio."
);
#[cfg(all(
feature = "macros",
any(feature = "runtime-async-std", feature = "runtime-tokio")
))]
pub mod macros;
pub(crate) mod process;
pub mod error;
pub use error::Error;
#[cfg(all(
any(feature = "sqlite", feature = "postgres", feature = "mysql"),
any(feature = "sqlx", feature = "diesel")
))]
#[derive(Debug, Default)]
pub struct DatabaseSchema(DatabaseSchemaInner);
#[derive(Debug, Clone)]
struct ConnectionUrl(String);
impl Default for ConnectionUrl {
fn default() -> Self {
#[cfg(feature = "sqlite")]
let conn = ConnectionUrl(String::from(sqlite::DEFAULT_CONNECTION_URL));
#[cfg(feature = "mysql")]
let conn = ConnectionUrl(String::from(mysql::DEFAULT_CONNECTION_URL));
#[cfg(feature = "postgres")]
let conn = ConnectionUrl(String::from(postgres::DEFAULT_CONNECTION_URL));
conn
}
}
#[derive(Debug, Default, Clone)]
struct DatabaseSchemaInner {
connection_url: ConnectionUrl,
migrations_path: std::path::PathBuf,
destination_path: std::path::PathBuf,
}
#[cfg(all(
any(feature = "sqlite", feature = "postgres", feature = "mysql"),
any(feature = "sqlx", feature = "diesel")
))]
#[derive(Debug, Default)]
pub struct DatabaseSchemaBuilder(DatabaseSchemaInner);
#[cfg(all(
any(feature = "sqlite", feature = "postgres", feature = "mysql"),
any(feature = "sqlx", feature = "diesel")
))]
#[allow(dead_code)]
impl DatabaseSchemaBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn connection_url<S: Into<String>>(&mut self, connection_url: S) -> &mut Self {
self.0.connection_url = ConnectionUrl(connection_url.into());
self
}
pub fn migrations_dir<P: AsRef<std::path::Path>>(
&mut self,
migrations_dir: P,
) -> Result<&mut Self, Error> {
self.0.migrations_path = migrations_dir.as_ref().to_path_buf().canonicalize()?;
Ok(self)
}
pub fn destination_path<P: AsRef<std::path::Path>>(
&mut self,
destination_path: P,
) -> &mut Self {
self.0.destination_path = destination_path.as_ref().to_path_buf();
self
}
pub fn build(&self) -> DatabaseSchema {
DatabaseSchema(self.0.clone())
}
}
impl DatabaseSchema {
pub async fn dump(&self) -> Result<(), Error> {
#[cfg(all(feature = "mysql", any(feature = "sqlx", feature = "diesel")))]
use crate::mysql::write_structure_sql;
#[cfg(all(feature = "postgres", any(feature = "sqlx", feature = "diesel")))]
use crate::postgres::write_structure_sql;
#[cfg(all(feature = "sqlite", any(feature = "sqlx", feature = "diesel")))]
use crate::sqlite::write_structure_sql;
write_structure_sql(
&self.0.connection_url.0,
self.0.migrations_path.clone(),
self.0.destination_path.clone(),
)
.await?;
Ok(())
}
}
#[cfg(all(
any(feature = "sqlite", feature = "postgres", feature = "mysql"),
any(feature = "sqlx", feature = "diesel")
))]
pub async fn generate<P: AsRef<std::path::Path>, Q: AsRef<std::path::Path>>(
connection_url: Option<&str>,
migrations_path: P,
destination_path: Q,
) -> Result<(), Error> {
let mut builder = DatabaseSchemaBuilder::new();
if let Some(connection_url) = connection_url {
let _ = builder.connection_url(connection_url);
}
builder
.migrations_dir(migrations_path)?
.destination_path(destination_path)
.build()
.dump()
.await
}