#[cfg(feature = "check")]
mod lint;
mod registry;
#[cfg(test)]
mod tests;
pub use registry::{
ColumnMeta, SchemaIssue, SchemaIssueKind, SchemaIssueLevel, SchemaRegistry, TableMeta,
TableSchema,
};
#[cfg(feature = "check")]
pub use lint::*;
#[cfg(feature = "check")]
pub use crate::checked_client::CheckedClient;
#[macro_export]
macro_rules! check_models {
($registry:expr, $($model:ty),+ $(,)?) => {{
let mut results: Vec<(&'static str, std::collections::HashMap<&'static str, Vec<$crate::check::SchemaIssue>>)> = Vec::new();
$(
results.push((stringify!($model), <$model>::check_schema(&$registry)));
)+
results
}};
}
#[macro_export]
macro_rules! assert_models_valid {
($registry:expr, $($model:ty),+ $(,)?) => {{
let mut all_issues: Vec<(&'static str, Vec<String>)> = Vec::new();
$(
let issues = <$model>::check_schema(&$registry);
if !issues.is_empty() {
let messages: Vec<String> = issues
.iter()
.flat_map(|(sql_name, issue_list)| {
issue_list.iter().map(move |i| format!("{}: {}", sql_name, i.message))
})
.collect();
all_issues.push((stringify!($model), messages));
}
)+
if !all_issues.is_empty() {
let mut msg = String::from("Schema validation failed:\n");
for (model, issues) in &all_issues {
msg.push_str(&format!("\n{}:\n", model));
for issue in issues {
msg.push_str(&format!(" - {}\n", issue));
}
}
panic!("{}", msg);
}
}};
}
#[macro_export]
macro_rules! print_model_check {
($registry:expr, $($model:ty),+ $(,)?) => {{
println!("Model Schema Validation:");
let mut all_valid = true;
$(
let issues = <$model>::check_schema(&$registry);
if issues.is_empty() {
println!(" ✓ {}", stringify!($model));
} else {
all_valid = false;
let total: usize = issues.values().map(|v| v.len()).sum();
println!(" ✗ {} ({} issues)", stringify!($model), total);
for (sql_name, issue_list) in &issues {
for issue in issue_list {
println!(" {}: {:?} - {}", sql_name, issue.kind, issue.message);
}
}
}
)+
all_valid
}};
}
#[macro_export]
macro_rules! check_models_db {
($client:expr, $($model:ty),+ $(,)?) => {{
async {
let db_schema = $client.load_db_schema().await?;
let mut results: Vec<$crate::ModelCheckResult> = Vec::new();
$(
results.push($crate::ModelCheckResult::check::<$model>(&db_schema));
)+
Ok::<_, $crate::OrmError>(results)
}
}};
}
#[macro_export]
macro_rules! print_models_db_check {
($client:expr, $($model:ty),+ $(,)?) => {{
async {
let db_schema = $client.load_db_schema().await?;
println!("Model Database Validation:");
let mut all_valid = true;
$(
let result = $crate::ModelCheckResult::check::<$model>(&db_schema);
if !result.is_valid() {
all_valid = false;
}
result.print();
)+
Ok::<_, $crate::OrmError>(all_valid)
}
}};
}
#[macro_export]
macro_rules! assert_models_db_valid {
($client:expr, $($model:ty),+ $(,)?) => {{
async {
let db_schema = $client.load_db_schema().await?;
let mut errors: Vec<String> = Vec::new();
$(
let result = $crate::ModelCheckResult::check::<$model>(&db_schema);
if !result.table_found {
errors.push(format!("{}: table '{}' not found", result.model, result.table));
} else if !result.missing_in_db.is_empty() {
errors.push(format!("{}: missing columns {:?}", result.model, result.missing_in_db));
}
)+
if !errors.is_empty() {
panic!("Schema validation failed:\n {}", errors.join("\n "));
}
Ok::<_, $crate::OrmError>(())
}
}};
}