Skip to content

Commit

Permalink
Merge branch 'main' into integration/fix-15655
Browse files Browse the repository at this point in the history
  • Loading branch information
jkomyno committed Oct 11, 2022
2 parents faca4b0 + 578406b commit fc567f6
Show file tree
Hide file tree
Showing 25 changed files with 326 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ impl Connection {
.describe_impl()
.await
.map_err(|err| match err.into_kind() {
DescriberErrorKind::QuaintError(err) => panic!("{}", err),
DescriberErrorKind::QuaintError(err) => {
ConnectorError::from_source(err, "Error describing the database.")
}
DescriberErrorKind::CrossSchemaReference { .. } => {
unreachable!("No schemas on SQLite")
}
Expand Down
5 changes: 5 additions & 0 deletions psl/diagnostics/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ impl DatamodelError {
Self::new(msg, span)
}

pub fn new_duplicate_enum_database_name_error(span: Span) -> DatamodelError {
let msg = "An enum with the same database name is already defined.";
Self::new(msg, span)
}

pub fn new_duplicate_model_database_name_error(
model_database_name: &str,
existing_model_name: &str,
Expand Down
7 changes: 6 additions & 1 deletion psl/parser-database/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,12 @@ impl ParserDatabase {
&self.ast
}

/// The total number of models. This is O(1).
/// The total number of enums in the schema. This is O(1).
pub fn enums_count(&self) -> usize {
self.types.enum_attributes.len()
}

/// The total number of models in the schema. This is O(1).
pub fn models_count(&self) -> usize {
self.types.model_attributes.len()
}
Expand Down
17 changes: 10 additions & 7 deletions psl/parser-database/src/walkers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,18 @@ use crate::{ast, ParserDatabase};
/// A generic walker. Only walkers intantiated with a concrete ID type (`I`) are useful.
#[derive(Clone, Copy)]
pub struct Walker<'db, I> {
db: &'db crate::ParserDatabase,
id: I,
/// The parser database being traversed.
pub db: &'db crate::ParserDatabase,
/// The identifier of the focused element.
pub id: I,
}

impl ParserDatabase {
/// Traverse a schema element by id.
pub fn walk<I>(&self, id: I) -> Walker<'_, I> {
Walker { db: self, id }
}

/// Walk all enums in the schema.
pub fn walk_enums(&self) -> impl Iterator<Item = EnumWalker<'_>> {
self.ast()
Expand All @@ -44,11 +51,7 @@ impl ParserDatabase {

/// Find a model by ID.
pub(crate) fn walk_model(&self, model_id: ast::ModelId) -> ModelWalker<'_> {
ModelWalker {
model_id,
db: self,
model_attributes: &self.types.model_attributes[&model_id],
}
self.walk(model_id)
}

/// Find an enum by ID.
Expand Down
10 changes: 2 additions & 8 deletions psl/parser-database/src/walkers/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ impl<'db> EnumWalker<'db> {

/// The values of the enum.
pub fn values(self) -> impl Iterator<Item = EnumValueWalker<'db>> {
(0..self.ast_enum().values.len()).map(move |idx| Walker {
db: self.db,
id: (self.id, idx),
})
(0..self.ast_enum().values.len()).map(move |idx| self.db.walk((self.id, idx)))
}

/// The name of the schema the enum belongs to.
Expand All @@ -62,10 +59,7 @@ impl<'db> EnumWalker<'db> {

impl<'db> EnumValueWalker<'db> {
fn r#enum(self) -> EnumWalker<'db> {
Walker {
db: self.db,
id: self.id.0,
}
self.db.walk(self.id.0)
}

/// The enum documentation
Expand Down
6 changes: 1 addition & 5 deletions psl/parser-database/src/walkers/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,7 @@ impl<'db> IndexWalker<'db> {

/// The model the index is defined on.
pub fn model(self) -> ModelWalker<'db> {
ModelWalker {
model_id: self.model_id,
db: self.db,
model_attributes: &self.db.types.model_attributes[&self.model_id],
}
self.db.walk(self.model_id)
}

/// The field the model was defined on, if any.
Expand Down
78 changes: 33 additions & 45 deletions psl/parser-database/src/walkers/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,18 @@ pub use primary_key::*;

pub(crate) use unique_criteria::*;

use schema_ast::ast::{IndentationType, NewlineType, WithSpan};

use super::{
CompleteInlineRelationWalker, IndexWalker, InlineRelationWalker, RelationFieldWalker, RelationWalker,
ScalarFieldWalker,
};
use crate::{
ast::{self, WithName},
types::ModelAttributes,
ParserDatabase,
};
use std::hash::{Hash, Hasher};
use schema_ast::ast::{IndentationType, NewlineType, WithSpan};

/// A `model` declaration in the Prisma schema.
#[derive(Copy, Clone, Debug)]
pub struct ModelWalker<'db> {
pub(super) model_id: ast::ModelId,
pub(super) db: &'db ParserDatabase,
pub(super) model_attributes: &'db ModelAttributes,
}

impl<'db> PartialEq for ModelWalker<'db> {
fn eq(&self, other: &Self) -> bool {
self.model_id == other.model_id
}
}

impl<'db> Eq for ModelWalker<'db> {}

impl<'db> Hash for ModelWalker<'db> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.model_id.hash(state);
}
}
pub type ModelWalker<'db> = super::Walker<'db, ast::ModelId>;

impl<'db> ModelWalker<'db> {
/// The name of the model.
Expand Down Expand Up @@ -76,17 +54,17 @@ impl<'db> ModelWalker<'db> {

/// The ID of the model in the db
pub fn model_id(self) -> ast::ModelId {
self.model_id
self.id
}

/// The AST node.
pub fn ast_model(self) -> &'db ast::Model {
&self.db.ast[self.model_id]
&self.db.ast[self.id]
}

/// The parsed attributes.
pub(crate) fn attributes(self) -> &'db ModelAttributes {
self.model_attributes
&self.db.types.model_attributes[&self.id]
}

/// Model has the @@ignore attribute.
Expand All @@ -97,18 +75,18 @@ impl<'db> ModelWalker<'db> {
/// The name of the database table the model points to.
#[allow(clippy::unnecessary_lazy_evaluations)] // respectfully disagree
pub fn database_name(self) -> &'db str {
self.model_attributes
self.attributes()
.mapped_name
.map(|id| &self.db[id])
.unwrap_or_else(|| self.db.ast[self.model_id].name())
.unwrap_or_else(|| self.db.ast[self.id].name())
}

/// Get the database name of the scalar field.
pub fn get_field_database_name(self, field_id: ast::FieldId) -> &'db str {
self.db.types.scalar_fields[&(self.model_id, field_id)]
self.db.types.scalar_fields[&(self.id, field_id)]
.mapped_name
.map(|id| &self.db[id])
.unwrap_or_else(|| self.db.ast[self.model_id][field_id].name())
.unwrap_or_else(|| self.db.ast[self.id][field_id].name())
}

/// Get the database names of the constrained scalar fields.
Expand All @@ -131,8 +109,8 @@ impl<'db> ModelWalker<'db> {

/// The primary key of the model, if defined.
pub fn primary_key(self) -> Option<PrimaryKeyWalker<'db>> {
self.model_attributes.primary_key.as_ref().map(|pk| PrimaryKeyWalker {
model_id: self.model_id,
self.attributes().primary_key.as_ref().map(|pk| PrimaryKeyWalker {
model_id: self.id,
attribute: pk,
db: self.db,
})
Expand All @@ -142,10 +120,10 @@ impl<'db> ModelWalker<'db> {
#[track_caller]
pub(crate) fn scalar_field(self, field_id: ast::FieldId) -> ScalarFieldWalker<'db> {
ScalarFieldWalker {
model_id: self.model_id,
model_id: self.id,
field_id,
db: self.db,
scalar_field: &self.db.types.scalar_fields[&(self.model_id, field_id)],
scalar_field: &self.db.types.scalar_fields[&(self.id, field_id)],
}
}

Expand All @@ -154,7 +132,7 @@ impl<'db> ModelWalker<'db> {
let db = self.db;
db.types
.scalar_fields
.range((self.model_id, ast::FieldId::MIN)..=(self.model_id, ast::FieldId::MAX))
.range((self.id, ast::FieldId::MIN)..=(self.id, ast::FieldId::MAX))
.map(move |((model_id, field_id), scalar_field)| ScalarFieldWalker {
model_id: *model_id,
field_id: *field_id,
Expand All @@ -166,11 +144,11 @@ impl<'db> ModelWalker<'db> {
/// All unique criterias of the model; consisting of the primary key and
/// unique indexes, if set.
pub fn unique_criterias(self) -> impl Iterator<Item = UniqueCriteriaWalker<'db>> {
let model_id = self.model_id;
let model_id = self.id;
let db = self.db;

let from_pk = self
.model_attributes
.attributes()
.primary_key
.iter()
.map(move |pk| UniqueCriteriaWalker {
Expand All @@ -194,10 +172,10 @@ impl<'db> ModelWalker<'db> {
/// Iterate all the indexes in the model in the order they were
/// defined.
pub fn indexes(self) -> impl Iterator<Item = IndexWalker<'db>> {
let model_id = self.model_id;
let model_id = self.id;
let db = self.db;

self.model_attributes
self.attributes()
.ast_indexes
.iter()
.map(move |(index, index_attribute)| IndexWalker {
Expand All @@ -210,7 +188,7 @@ impl<'db> ModelWalker<'db> {

/// All (concrete) relation fields of the model.
pub fn relation_fields(self) -> impl Iterator<Item = RelationFieldWalker<'db>> {
let model_id = self.model_id;
let model_id = self.id;
let db = self.db;

self.db
Expand All @@ -232,18 +210,18 @@ impl<'db> ModelWalker<'db> {
/// If the field does not exist.
pub fn relation_field(self, field_id: ast::FieldId) -> RelationFieldWalker<'db> {
RelationFieldWalker {
model_id: self.model_id,
model_id: self.id,
field_id,
db: self.db,
relation_field: &self.db.types.relation_fields[&(self.model_id, field_id)],
relation_field: &self.db.types.relation_fields[&(self.id, field_id)],
}
}

/// All relations that start from this model.
pub fn relations_from(self) -> impl Iterator<Item = RelationWalker<'db>> {
self.db
.relations
.from_model(self.model_id)
.from_model(self.id)
.map(move |relation_id| RelationWalker {
id: relation_id,
db: self.db,
Expand All @@ -254,7 +232,7 @@ impl<'db> ModelWalker<'db> {
pub fn relations_to(self) -> impl Iterator<Item = RelationWalker<'db>> {
self.db
.relations
.to_model(self.model_id)
.to_model(self.id)
.map(move |relation_id| RelationWalker {
id: relation_id,
db: self.db,
Expand Down Expand Up @@ -326,4 +304,14 @@ impl<'db> ModelWalker<'db> {
pub fn schema(self) -> Option<(&'db str, ast::Span)> {
self.attributes().schema.map(|(id, span)| (&self.db[id], span))
}

/// The name of the schema the model belongs to.
///
/// ```ignore
/// @@schema("public")
/// ^^^^^^^^
/// ```
pub fn schema_name(self) -> Option<&'db str> {
self.schema().map(|(name, _)| name)
}
}
6 changes: 1 addition & 5 deletions psl/parser-database/src/walkers/model/primary_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ impl<'db> PrimaryKeyWalker<'db> {

/// The model the id is deined on.
pub fn model(self) -> ModelWalker<'db> {
ModelWalker {
db: self.db,
model_attributes: &self.db.types.model_attributes[&self.model_id],
model_id: self.model_id,
}
self.db.walk(self.model_id)
}

/// The `name` argument of the id attribute. The client name.
Expand Down
4 changes: 2 additions & 2 deletions psl/parser-database/src/walkers/relation/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ impl<'db> InlineRelationWalker<'db> {
match (self.forward_relation_field(), self.back_relation_field()) {
(Some(field_a), Some(field_b)) => {
let walker = CompleteInlineRelationWalker {
side_a: (self.referencing_model().model_id, field_a.field_id),
side_b: (self.referenced_model().model_id, field_b.field_id),
side_a: (self.referencing_model().id, field_a.field_id),
side_b: (self.referenced_model().id, field_b.field_id),
db: self.0.db,
};

Expand Down
16 changes: 4 additions & 12 deletions psl/parser-database/src/walkers/relation/inline/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,12 @@ pub struct CompleteInlineRelationWalker<'db> {
impl<'db> CompleteInlineRelationWalker<'db> {
/// The model that defines the relation fields and actions.
pub fn referencing_model(self) -> ModelWalker<'db> {
ModelWalker {
model_id: self.side_a.0,
db: self.db,
model_attributes: &self.db.types.model_attributes[&self.side_a.0],
}
self.db.walk(self.side_a.0)
}

/// The implicit relation side.
pub fn referenced_model(self) -> ModelWalker<'db> {
ModelWalker {
model_id: self.side_b.0,
db: self.db,
model_attributes: &self.db.types.model_attributes[&self.side_b.0],
}
self.db.walk(self.side_b.0)
}

pub fn referencing_field(self) -> RelationFieldWalker<'db> {
Expand All @@ -55,7 +47,7 @@ impl<'db> CompleteInlineRelationWalker<'db> {
/// The scalar fields defining the relation on the referenced model.
pub fn referenced_fields(self) -> impl ExactSizeIterator<Item = ScalarFieldWalker<'db>> + 'db {
let f = move |field_id: &ast::FieldId| {
let model_id = self.referenced_model().model_id;
let model_id = self.referenced_model().id;

ScalarFieldWalker {
model_id,
Expand All @@ -74,7 +66,7 @@ impl<'db> CompleteInlineRelationWalker<'db> {
/// The scalar fields on the defining the relation on the referencing model.
pub fn referencing_fields(self) -> impl ExactSizeIterator<Item = ScalarFieldWalker<'db>> + 'db {
let f = move |field_id: &ast::FieldId| {
let model_id = self.referencing_model().model_id;
let model_id = self.referencing_model().id;

ScalarFieldWalker {
model_id,
Expand Down

0 comments on commit fc567f6

Please sign in to comment.