Skip to content

Commit

Permalink
Merge pull request #2094 from prisma/datamodel/move-name-validation-i…
Browse files Browse the repository at this point in the history
…nto-db
  • Loading branch information
tomhoule committed Jul 19, 2021
2 parents 215319b + a842269 commit 354c407
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 118 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::SqlFamilyTrait;
use datamodel::{reserved_model_names, Datamodel, DefaultValue, Field, FieldType, Model, WithDatabaseName, WithName};
use datamodel::{
reserved_model_names::is_reserved_type_name, Datamodel, DefaultValue, Field, FieldType, Model, WithDatabaseName,
WithName,
};
use introspection_connector::IntrospectionContext;
use once_cell::sync::Lazy;
use prisma_value::PrismaValue;
Expand Down Expand Up @@ -210,9 +213,7 @@ fn rename_reserved(model: &mut Model) {

/// Reformats a reserved string as "Renamed{}"
fn reformat_reserved_string(s: &str) -> String {
let validator = reserved_model_names::TypeNameValidator::new();

if validator.is_reserved(s) {
if is_reserved_type_name(s) {
format!("Renamed{}", s)
} else {
s.to_owned()
Expand Down
2 changes: 1 addition & 1 deletion libs/datamodel/connectors/dml/src/field.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::*;
use crate::native_type_instance::NativeTypeInstance;
use crate::relation_info::RelationInfo;
use crate::scalars::ScalarType;
use crate::traits::{Ignorable, WithDatabaseName, WithName};
use crate::{
Expand Down
2 changes: 0 additions & 2 deletions libs/datamodel/connectors/dml/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,3 @@ pub mod native_type_instance;
pub mod relation_info;
pub mod scalars;
pub mod traits;

use crate::relation_info::RelationInfo;
4 changes: 0 additions & 4 deletions libs/datamodel/core/src/transform/ast_to_dml/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,4 @@ impl<'ast> ParserDatabase<'ast> {
.range((model_id, ast::FieldId::ZERO)..=(model_id, ast::FieldId::MAX))
.map(|((_, field_id), scalar_type)| (*field_id, scalar_type))
}

pub(super) fn get_enum(&self, name: &str) -> Option<&'ast ast::Enum> {
self.names.tops.get(name).and_then(|top_id| self.ast[*top_id].as_enum())
}
}
3 changes: 3 additions & 0 deletions libs/datamodel/core/src/transform/ast_to_dml/db/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::Context;
use crate::{
ast::{self, Argument, FieldId, TopId, WithAttributes, WithIdentifier},
diagnostics::DatamodelError,
reserved_model_names::{validate_enum_name, validate_model_name},
};
use dml::scalars::ScalarType;
use std::{
Expand Down Expand Up @@ -41,6 +42,7 @@ pub(super) fn resolve_names(ctx: &mut Context<'_>) {
(_, ast::Top::Enum(ast_enum)) => {
tmp_names.clear();
ast_enum.name.validate("Enum", &mut ctx.diagnostics);
validate_enum_name(ast_enum, &mut ctx.diagnostics);
ast_enum.validate_attributes(&mut ctx.diagnostics);

for value in &ast_enum.values {
Expand All @@ -60,6 +62,7 @@ pub(super) fn resolve_names(ctx: &mut Context<'_>) {
}
(ast::TopId::Model(model_id), ast::Top::Model(model)) => {
model.name.validate("Model", &mut ctx.diagnostics);
validate_model_name(model, &mut ctx.diagnostics);
model.validate_attributes(&mut ctx.diagnostics);

for (field_id, field) in model.iter_fields() {
Expand Down
145 changes: 80 additions & 65 deletions libs/datamodel/core/src/transform/ast_to_dml/reserved_model_names.rs
Original file line number Diff line number Diff line change
@@ -1,73 +1,88 @@
pub struct TypeNameValidator {
reserved_names: &'static [&'static str],
use crate::{
ast,
diagnostics::{DatamodelError, Diagnostics},
};

pub fn is_reserved_type_name(name: &str) -> bool {
RESERVED_NAMES.contains(&name)
}

impl TypeNameValidator {
// The source of the following list is from prisma-client-js. Any edit should be done in both places.
// https://github.com/prisma/prisma/blob/master/src/packages/client/src/generation/generateClient.ts#L443
pub fn new() -> Self {
Self {
reserved_names: &[
"PrismaClient",
// JavaScript keywords
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"function",
"if",
"implements",
"import",
"in",
"instanceof",
"interface",
"let",
"new",
"null",
"package",
"private",
"protected",
"public",
"return",
"super",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"var",
"void",
"while",
"with",
"yield",
],
}
pub(crate) fn validate_model_name(ast_model: &ast::Model, diagnostics: &mut Diagnostics) {
if !is_reserved_type_name(&ast_model.name.name) {
return;
}

pub fn is_reserved<T>(&self, name: T) -> bool
where
T: AsRef<str>,
{
self.reserved_names.contains(&name.as_ref())
}
diagnostics.push_error(DatamodelError::new_model_validation_error(
&format!(
"The model name `{}` is invalid. It is a reserved name. Please change it. Read more at https://pris.ly/d/naming-models",
&ast_model.name.name
),
&ast_model.name.name,
ast_model.span,
))
}

impl Default for TypeNameValidator {
fn default() -> Self {
Self::new()
pub(crate) fn validate_enum_name(ast_enum: &ast::Enum, diagnostics: &mut Diagnostics) {
if !is_reserved_type_name(&ast_enum.name.name) {
return;
}

diagnostics.push_error(DatamodelError::new_enum_validation_error(
&format!(
"The enum name `{}` is invalid. It is a reserved name. Please change it. Read more at https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model#naming-enums",
&ast_enum.name.name
), &ast_enum.name.name,
ast_enum.span,
));
}

// The source of the following list is from prisma-client-js. Any edit should be done in both places.
// https://github.com/prisma/prisma/blob/master/src/packages/client/src/generation/generateClient.ts#L443
const RESERVED_NAMES: &[&str] = &[
"PrismaClient",
// JavaScript keywords
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"function",
"if",
"implements",
"import",
"in",
"instanceof",
"interface",
"let",
"new",
"null",
"package",
"private",
"protected",
"public",
"return",
"super",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"var",
"void",
"while",
"with",
"yield",
];
42 changes: 0 additions & 42 deletions libs/datamodel/core/src/transform/ast_to_dml/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ impl<'a> Validator<'a> {
diagnostics.push_error(err);
}

if let Err(err) = self.validate_model_name(ast_model, model) {
diagnostics.push_error(err);
}

if let Err(err) = self.validate_relations_not_ambiguous(ast_schema, model) {
diagnostics.push_error(err);
}
Expand All @@ -79,12 +75,6 @@ impl<'a> Validator<'a> {
diagnostics.append(the_errors);
}
}

// Enum level validations.
for declared_enum in schema.enums() {
let ast_enum = db.get_enum(&declared_enum.name).expect(STATE_ERROR);
self.validate_enum_name(ast_enum, declared_enum, diagnostics);
}
}

pub fn post_standardisation_validate(
Expand Down Expand Up @@ -251,38 +241,6 @@ impl<'a> Validator<'a> {
Ok(())
}

fn validate_model_name(&self, ast_model: &ast::Model, model: &dml::Model) -> Result<(), DatamodelError> {
let validator = super::reserved_model_names::TypeNameValidator::new();

if validator.is_reserved(&model.name) {
Err(DatamodelError::new_model_validation_error(
&format!(
"The model name `{}` is invalid. It is a reserved name. Please change it. Read more at https://pris.ly/d/naming-models",
&model.name
),
&model.name,
ast_model.span,
))
} else {
Ok(())
}
}

fn validate_enum_name(&self, ast_enum: &ast::Enum, dml_enum: &dml::Enum, diagnostics: &mut Diagnostics) {
let validator = super::reserved_model_names::TypeNameValidator::new();

if validator.is_reserved(&dml_enum.name) {
diagnostics.push_error(DatamodelError::new_enum_validation_error(
&format!(
"The enum name `{}` is invalid. It is a reserved name. Please change it. Read more at https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model#naming-enums",
&dml_enum.name
),
&dml_enum.name,
ast_enum.span,
))
}
}

fn validate_field_connector_specific(&self, ast_model: &ast::Model, model: &dml::Model) -> Result<(), Diagnostics> {
let mut diagnostics = Diagnostics::new();

Expand Down

0 comments on commit 354c407

Please sign in to comment.