mod autoincrement;
mod composite_types;
mod constraint_namespace;
mod database_name;
mod datasource;
mod default_value;
mod enums;
mod fields;
mod indexes;
mod models;
mod names;
mod relation_fields;
mod relations;
mod views;
use super::context::Context;
use names::Names;
use parser_database::walkers::RefinedRelationWalker;
pub(super) fn validate(ctx: &mut Context<'_>) {
let names = Names::new(ctx);
composite_types::detect_composite_cycles(ctx);
for composite_type in ctx.db.walk_composite_types() {
composite_types::composite_types_support(composite_type, ctx);
if !ctx.diagnostics.has_errors() {
composite_types::more_than_one_field(composite_type, ctx);
for field in composite_type.fields() {
composite_types::validate_default_value(field, ctx);
fields::validate_native_type_arguments(field, ctx);
}
}
}
ctx.connector
.validate_scalar_field_unknown_default_functions(ctx.db, ctx.diagnostics);
if let Some(ds) = ctx.datasource {
datasource::schemas_property_without_preview_feature(ds, ctx);
datasource::schemas_property_with_no_connector_support(ds, ctx);
ctx.connector
.validate_datasource(ctx.preview_features, ds, ctx.diagnostics);
}
models::database_name_clashes(ctx);
for model in ctx.db.walk_models().chain(ctx.db.walk_views()) {
if model.ast_model().is_view() {
views::view_definition_without_preview_flag(model, ctx);
}
models::has_a_strict_unique_criteria(model, ctx);
models::has_a_unique_primary_key_name(model, &names, ctx);
models::has_a_unique_custom_primary_key_name_per_model(model, &names, ctx);
models::id_has_fields(model, ctx);
models::id_client_name_does_not_clash_with_field(model, ctx);
models::primary_key_connector_specific(model, ctx);
models::primary_key_length_prefix_supported(model, ctx);
models::primary_key_sort_order_supported(model, ctx);
models::only_one_fulltext_attribute_allowed(model, ctx);
models::multischema_feature_flag_needed(model, ctx);
models::schema_is_defined_in_the_datasource(model, ctx);
models::schema_attribute_supported_in_connector(model, ctx);
models::schema_attribute_missing(model, ctx);
models::connector_specific(model, ctx);
autoincrement::validate_auto_increment(model, ctx);
if let Some(pk) = model.primary_key() {
for field_attribute in pk.scalar_field_attributes() {
let span = pk.ast_attribute().span;
let attribute = (pk.attribute_name(), span);
fields::validate_length_used_with_correct_types(field_attribute, attribute, ctx);
}
fields::id_supports_clustering_setting(pk, ctx);
fields::clustering_can_be_defined_only_once(pk, ctx);
}
for field in model.scalar_fields() {
fields::validate_scalar_field_connector_specific(field, ctx);
fields::validate_client_name(field.into(), &names, ctx);
fields::has_a_unique_default_constraint_name(field, &names, ctx);
fields::validate_native_type_arguments(field, ctx);
fields::validate_default_value(field, ctx);
fields::validate_unsupported_field_type(field, ctx)
}
for field in model.relation_fields() {
if let Err(error) = relation_fields::ambiguity(field, &names) {
ctx.push_error(error);
return;
}
fields::validate_client_name(field.into(), &names, ctx);
relation_fields::ignored_related_model(field, ctx);
relation_fields::referential_actions(field, ctx);
relation_fields::map(field, ctx);
relation_fields::validate_missing_relation_indexes(field, ctx);
relation_fields::connector_specific(field, ctx);
}
for index in model.indexes() {
indexes::has_fields(index, ctx);
indexes::has_a_unique_constraint_name(index, &names, ctx);
indexes::unique_client_name_does_not_clash_with_field(index, ctx);
indexes::unique_index_has_a_unique_custom_name_per_model(index, &names, ctx);
indexes::field_length_prefix_supported(index, ctx);
indexes::index_algorithm_is_supported(index, ctx);
indexes::hash_index_must_not_use_sort_param(index, ctx);
indexes::fulltext_index_preview_feature_enabled(index, ctx);
indexes::fulltext_index_supported(index, ctx);
indexes::fulltext_columns_should_not_define_length(index, ctx);
indexes::fulltext_column_sort_is_supported(index, ctx);
indexes::fulltext_text_columns_should_be_bundled_together(index, ctx);
indexes::has_valid_mapped_name(index, ctx);
indexes::supports_clustering_setting(index, ctx);
indexes::clustering_can_be_defined_only_once(index, ctx);
indexes::opclasses_are_not_allowed_with_other_than_normal_indices(index, ctx);
indexes::composite_type_in_compound_unique_index(index, ctx);
for field_attribute in index.scalar_field_attributes() {
let span = index.ast_attribute().span;
let attribute = (index.attribute_name(), span);
fields::validate_length_used_with_correct_types(field_attribute, attribute, ctx);
}
}
}
if ctx.connector.supports_enums() {
enums::database_name_clashes(ctx);
}
for r#enum in ctx.db.walk_enums() {
enums::connector_supports_enums(r#enum, ctx);
enums::multischema_feature_flag_needed(r#enum, ctx);
enums::schema_is_defined_in_the_datasource(r#enum, ctx);
enums::schema_attribute_supported_in_connector(r#enum, ctx);
enums::schema_attribute_missing(r#enum, ctx);
ctx.connector.validate_enum(r#enum, ctx.diagnostics);
}
for relation in ctx.db.walk_relations() {
match relation.refine() {
RefinedRelationWalker::Inline(relation) => {
if let Some(relation) = relation.as_complete() {
relations::cycles(relation, ctx);
relations::multiple_cascading_paths(relation, ctx);
}
relations::references_unique_fields(relation, ctx);
relations::same_length_in_referencing_and_referenced(relation, ctx);
relations::field_arity(relation, ctx);
relations::referencing_scalar_field_types(relation, ctx);
relations::has_a_unique_constraint_name(&names, relation, ctx);
relations::required_relation_cannot_use_set_null(relation, ctx);
if relation.is_one_to_one() {
relations::one_to_one::both_sides_are_defined(relation, ctx);
relations::one_to_one::fields_and_references_are_defined(relation, ctx);
relations::one_to_one::fields_and_references_defined_on_one_side_only(relation, ctx);
relations::one_to_one::referential_actions(relation, ctx);
relations::one_to_one::fields_must_be_a_unique_constraint(relation, ctx);
relations::one_to_one::fields_references_mixups(relation, ctx);
relations::one_to_one::back_relation_arity_is_optional(relation, ctx);
relations::one_to_one::fields_and_references_on_wrong_side(relation, ctx);
} else {
relations::one_to_many::both_sides_are_defined(relation, ctx);
relations::one_to_many::fields_and_references_are_defined(relation, ctx);
relations::one_to_many::referential_actions(relation, ctx);
}
}
RefinedRelationWalker::ImplicitManyToMany(relation) => {
use relations::many_to_many::implicit;
implicit::supports_implicit_relations(relation, ctx);
implicit::validate_singular_id(relation, ctx);
implicit::validate_no_referential_actions(relation, ctx);
implicit::cannot_define_references_argument(relation, ctx);
}
RefinedRelationWalker::TwoWayEmbeddedManyToMany(relation) => {
use relations::many_to_many::embedded;
embedded::supports_embedded_relations(relation, ctx);
embedded::defines_references_on_both_sides(relation, ctx);
embedded::defines_fields_on_both_sides(relation, ctx);
embedded::references_id_from_both_sides(relation, ctx);
embedded::referencing_with_an_array_field_of_correct_type(relation, ctx);
embedded::validate_no_referential_actions(relation, ctx);
}
}
}
}