1#![doc = include_str!("../README.md")]
2#![deny(
3 missing_copy_implementations,
4 missing_debug_implementations,
5 missing_docs,
6 trivial_casts,
7 trivial_numeric_casts,
8 unsafe_code,
9 unused_import_braces,
10 unused_qualifications,
11 unused_extern_crates,
12 unused_results,
13 variant_size_differences
14)]
15#![cfg_attr(docsrs, feature(doc_cfg), allow(unused_attributes))]
16
17#[cfg(not(any(feature = "sqlite", feature = "postgres", feature = "mysql"),))]
18compile_error!(
19 "At least one of the following features must be enabled: sqlite, postgres or mysql."
20);
21#[cfg(not(any(feature = "sqlx", feature = "diesel"),))]
22compile_error!("At least one of the following features must be enabled: sqlx or diesel.");
23
24#[cfg(feature = "sqlite")]
25#[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
26mod sqlite;
27
28#[cfg(feature = "mysql")]
29#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))]
30mod mysql;
31
32#[cfg(feature = "postgres")]
33#[cfg_attr(docsrs, doc(cfg(feature = "mysql")))]
34mod postgres;
35
36#[cfg(all(
37 feature = "macros",
38 not(any(feature = "runtime-async-std", feature = "runtime-tokio"))
39))]
40compile_error!(
41 "At least one of the following features must be enabled: runtime-async-std or runtime-tokio."
42);
43
44#[cfg(all(
45 feature = "macros",
46 any(feature = "runtime-async-std", feature = "runtime-tokio")
47))]
48pub mod macros;
49
50pub(crate) mod process;
51
52pub mod error;
53pub use error::Error;
54
55#[cfg(all(
61 any(feature = "sqlite", feature = "postgres", feature = "mysql"),
62 any(feature = "sqlx", feature = "diesel")
63))]
64#[derive(Debug, Default)]
65pub struct DatabaseSchema(DatabaseSchemaInner);
66
67#[derive(Debug, Clone)]
68struct ConnectionUrl(String);
69
70impl Default for ConnectionUrl {
71 fn default() -> Self {
72 #[cfg(feature = "sqlite")]
73 let conn = ConnectionUrl(String::from(sqlite::DEFAULT_CONNECTION_URL));
74 #[cfg(feature = "mysql")]
75 let conn = ConnectionUrl(String::from(mysql::DEFAULT_CONNECTION_URL));
76 #[cfg(feature = "postgres")]
77 let conn = ConnectionUrl(String::from(postgres::DEFAULT_CONNECTION_URL));
78
79 conn
80 }
81}
82
83#[derive(Debug, Default, Clone)]
84struct DatabaseSchemaInner {
85 connection_url: ConnectionUrl,
86 migrations_path: std::path::PathBuf,
87 destination_path: std::path::PathBuf,
88}
89
90#[cfg(all(
92 any(feature = "sqlite", feature = "postgres", feature = "mysql"),
93 any(feature = "sqlx", feature = "diesel")
94))]
95#[derive(Debug, Default)]
96pub struct DatabaseSchemaBuilder(DatabaseSchemaInner);
97
98#[cfg(all(
99 any(feature = "sqlite", feature = "postgres", feature = "mysql"),
100 any(feature = "sqlx", feature = "diesel")
101))]
102#[allow(dead_code)]
103impl DatabaseSchemaBuilder {
104 pub fn new() -> Self {
106 Self::default()
107 }
108
109 pub fn connection_url<S: Into<String>>(&mut self, connection_url: S) -> &mut Self {
121 self.0.connection_url = ConnectionUrl(connection_url.into());
122 self
123 }
124
125 pub fn migrations_dir<P: AsRef<std::path::Path>>(
133 &mut self,
134 migrations_dir: P,
135 ) -> Result<&mut Self, Error> {
136 self.0.migrations_path = migrations_dir.as_ref().to_path_buf().canonicalize()?;
137 Ok(self)
138 }
139
140 pub fn destination_path<P: AsRef<std::path::Path>>(
144 &mut self,
145 destination_path: P,
146 ) -> &mut Self {
147 self.0.destination_path = destination_path.as_ref().to_path_buf();
148 self
149 }
150
151 pub fn build(&self) -> DatabaseSchema {
153 DatabaseSchema(self.0.clone())
154 }
155}
156
157impl DatabaseSchema {
158 pub async fn dump(&self) -> Result<(), Error> {
160 #[cfg(all(feature = "mysql", any(feature = "sqlx", feature = "diesel")))]
161 use crate::mysql::write_structure_sql;
162 #[cfg(all(feature = "postgres", any(feature = "sqlx", feature = "diesel")))]
163 use crate::postgres::write_structure_sql;
164 #[cfg(all(feature = "sqlite", any(feature = "sqlx", feature = "diesel")))]
165 use crate::sqlite::write_structure_sql;
166
167 write_structure_sql(
168 &self.0.connection_url.0,
169 self.0.migrations_path.clone(),
170 self.0.destination_path.clone(),
171 )
172 .await?;
173 Ok(())
174 }
175}
176
177#[cfg(all(
197 any(feature = "sqlite", feature = "postgres", feature = "mysql"),
198 any(feature = "sqlx", feature = "diesel")
199))]
200pub async fn generate<P: AsRef<std::path::Path>, Q: AsRef<std::path::Path>>(
201 connection_url: Option<&str>,
202 migrations_path: P,
203 destination_path: Q,
204) -> Result<(), Error> {
205 let mut builder = DatabaseSchemaBuilder::new();
206 if let Some(connection_url) = connection_url {
207 let _ = builder.connection_url(connection_url);
208 }
209 builder
210 .migrations_dir(migrations_path)?
211 .destination_path(destination_path)
212 .build()
213 .dump()
214 .await
215}