mod composites;
mod declarations;
mod defaults;
mod ir_builder;
mod models;
mod names;
mod relations;
use crate::ast::*;
use crate::error::{Result, SchemaError};
use crate::ir::*;
use crate::span::Span;
use std::collections::{HashMap, HashSet, VecDeque};
const KNOWN_DATASOURCE_FIELDS: &[&str] = &["provider", "url", "direct_url"];
const KNOWN_GENERATOR_FIELDS: &[&str] = &["provider", "output", "interface"];
const PYTHON_ONLY_GENERATOR_FIELDS: &[&str] = &["recursive_type_depth"];
pub fn validate_schema(schema: Schema) -> Result<SchemaIr> {
let validator = SchemaValidator::new(schema);
validator.validate()
}
pub(crate) fn validate_all(schema: Schema) -> (Option<SchemaIr>, Vec<SchemaError>) {
let validator = SchemaValidator::new(schema);
validator.validate_collect_all()
}
struct SchemaValidator {
schema: Schema,
errors: VecDeque<SchemaError>,
warnings: VecDeque<SchemaError>,
models: HashMap<String, Span>,
enums: HashMap<String, Span>,
composite_types: HashMap<String, Span>,
}
impl SchemaValidator {
fn new(schema: Schema) -> Self {
Self {
schema,
errors: VecDeque::new(),
warnings: VecDeque::new(),
models: HashMap::new(),
enums: HashMap::new(),
composite_types: HashMap::new(),
}
}
fn validate(mut self) -> Result<SchemaIr> {
self.collect_names();
if !self.errors.is_empty() {
return Err(self.errors.pop_front().unwrap());
}
self.validate_datasources();
self.validate_generators();
self.validate_composite_types();
self.validate_models();
self.validate_relations();
self.validate_back_relations();
self.validate_defaults();
self.validate_updated_at_fields();
self.validate_computed_fields();
self.validate_check_constraints();
self.check_physical_name_collisions();
if !self.errors.is_empty() {
return Err(self.errors.pop_front().unwrap());
}
self.build_ir()
}
fn validate_collect_all(mut self) -> (Option<SchemaIr>, Vec<SchemaError>) {
self.collect_names();
if !self.errors.is_empty() {
return (None, self.errors.into_iter().collect());
}
self.validate_datasources();
self.validate_generators();
self.validate_composite_types();
self.validate_models();
self.validate_relations();
self.validate_back_relations();
self.validate_defaults();
self.validate_updated_at_fields();
self.validate_computed_fields();
self.validate_check_constraints();
self.check_physical_name_collisions();
if !self.errors.is_empty() {
let mut all: Vec<SchemaError> = self.errors.into_iter().collect();
all.extend(self.warnings);
return (None, all);
}
let warnings: Vec<SchemaError> = self.warnings.drain(..).collect();
match self.build_ir() {
Ok(ir) => (Some(ir), warnings),
Err(e) => (None, vec![e]),
}
}
}