Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(schema-engine): CHECK and EXCLUDE constraints stopgap for Postgres #3860

Merged
merged 28 commits into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4f9dc25
feat(schema-engine): add constraints_query.sql for postgres
jkomyno Apr 10, 2023
70b804a
feat(schema-engine): add check and exclusion constraints stopgap supp…
jkomyno Apr 10, 2023
10c2062
feat(schema-engine): add skeleton for stopgap warnings for check and …
jkomyno Apr 10, 2023
64ae322
feat(schema-engine): emit warnings when finding check and exclusion c…
jkomyno Apr 10, 2023
5e5fc2e
chore: remove comments
jkomyno Apr 10, 2023
993f731
chore: remove dbg
jkomyno Apr 10, 2023
302f30e
test(schema-engine): add missing defaults in describer tests
jkomyno Apr 10, 2023
4fb955b
chore: merge main, fix conflicts
jkomyno Apr 11, 2023
142f618
chore: update warning messages so that they make more sense
jkomyno Apr 11, 2023
b7b2aae
feat(schema-engine): updated check and exclusion constraints warning …
jkomyno Apr 12, 2023
4408b43
test(schema-engine): validate introspected schemas for check and excl…
jkomyno Apr 12, 2023
aeb68b8
feat(schema-engine): introspecting models with check or exclusion con…
jkomyno Apr 12, 2023
19d6541
feat(schema-engine): fix edge case of model having both check and exc…
jkomyno Apr 12, 2023
9c5d854
Merge branch 'main' into feat/postgres-check-constraints-stopgap
jkomyno Apr 12, 2023
b0d01da
feat(schema-engine): fix https://github.com/prisma/prisma/issues/17515
jkomyno Apr 12, 2023
24b02a9
Merge branch 'feat/postgres-check-constraints-stopgap' of github.com:…
jkomyno Apr 12, 2023
22b2c26
chore: merge main, fix conflicts
jkomyno Apr 16, 2023
df347af
chore: remove dead code
jkomyno Apr 16, 2023
e936a8b
chore: fix conflicts
jkomyno Apr 16, 2023
2c6e879
fix: avoid duplicated model commments upon reintrospection
jkomyno Apr 16, 2023
51f06d9
feat(schema-engine): use ModelAndConstraint rather than CheckConstrai…
jkomyno Apr 17, 2023
3c74298
feat(schema-engine): replace IndexMap with BTreeMap for leaner flag "…
jkomyno Apr 17, 2023
e5a6d89
chore: add TODO to answer Tom's review comment
jkomyno Apr 17, 2023
99045f1
Merge branch 'main' into feat/postgres-check-constraints-stopgap
jkomyno Apr 17, 2023
b9af982
Exclude constraints are PG only, lighten up the api (#3887)
Apr 17, 2023
e79ebe6
Merge branch 'main' into feat/postgres-check-constraints-stopgap
jkomyno Apr 18, 2023
4362401
feat(schema-engine): apply review comments
jkomyno Apr 18, 2023
ea9510a
Merge branch 'main' into feat/postgres-check-constraints-stopgap
jkomyno Apr 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ pub(crate) trait IntrospectionFlavour {
) -> bool {
false
}

fn uses_exclude_constraint(&self, _ctx: &DatamodelCalculatorContext<'_>, _table: TableWalker<'_>) -> bool {
false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ impl super::IntrospectionFlavour for PostgresIntrospectionFlavour {
}

fn generate_warnings(&self, ctx: &DatamodelCalculatorContext<'_>, warnings: &mut Warnings) {
let pg_ext: &PostgresSchemaExt = ctx.sql_schema.downcast_connector_data();

for table in ctx.sql_schema.table_walkers() {
for index in table.indexes() {
for column in index.columns().filter(|c| self.uses_non_default_null_position(ctx, *c)) {
Expand Down Expand Up @@ -46,6 +48,15 @@ impl super::IntrospectionFlavour for PostgresIntrospectionFlavour {
model: ctx.table_prisma_name(table.id).prisma_name().to_string(),
});
}

for constraint in pg_ext.exclude_constraints(table.id) {
let exclusion_constraint = ModelAndConstraint {
model: ctx.table_prisma_name(table.id).prisma_name().to_string(),
constraint: constraint.to_string(),
};

warnings.exclusion_constraints.push(exclusion_constraint);
}
}
}

Expand Down Expand Up @@ -80,4 +91,9 @@ impl super::IntrospectionFlavour for PostgresIntrospectionFlavour {

pg_ext.non_default_null_position(column)
}

fn uses_exclude_constraint(&self, ctx: &DatamodelCalculatorContext<'_>, table: TableWalker<'_>) -> bool {
let pg_ext: &PostgresSchemaExt = ctx.sql_schema.downcast_connector_data();
pg_ext.uses_exclude_constraint(table.id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,21 @@ impl<'a> ModelPair<'a> {
self.next.has_row_level_security()
}

/// Whether the model has check constraints.
pub(crate) fn adds_check_constraints(self) -> bool {
self.previous.is_none() && self.next.has_check_constraints()
}

/// The names of check constraints for this model.
pub(crate) fn check_constraints(self) -> impl Iterator<Item = &'a str> {
self.next.check_constraints()
}

/// Whether the model has exclusion constraints.
pub(crate) fn adds_exclusion_constraints(self) -> bool {
self.previous.is_none() && self.context.flavour.uses_exclude_constraint(self.context, self.next)
}

/// True, if we add a new model with row level security enabled.
pub(crate) fn adds_row_level_security(self) -> bool {
self.previous.is_none() && self.has_row_level_security()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ fn render_model(model: ModelPair<'_>, sql_family: SqlFamily) -> renderer::Model<
rendered.documentation(docs);
}

if model.adds_check_constraints() {
let docs = "This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/postgres-check-constraints for more info.";

rendered.documentation(docs);
}

if model.adds_exclusion_constraints() {
let docs = "This table contains exclusion constraints and requires additional setup for migrations. Visit https://pris.ly/d/postgres-exclusion-constraints for more info.";

rendered.documentation(docs);
}

if let Some(namespace) = model.namespace() {
rendered.schema(namespace);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ pub(crate) struct Warnings {
pub(crate) non_default_index_null_sort_order: Vec<IndexedColumn>,
/// Warn about using row level security, which is currently unsupported.
pub(crate) row_level_security_tables: Vec<Model>,
/// Warn about check constraints.
pub(crate) check_constraints: Vec<ModelAndConstraint>,
/// Warn about exclusion constraints.
pub(crate) exclusion_constraints: Vec<ModelAndConstraint>,
/// Warn about row level TTL
pub(crate) row_level_ttl: Vec<Model>,
/// Warn about non-default unique deferring setup
Expand Down Expand Up @@ -218,6 +222,14 @@ impl Warnings {
&mut self.warnings,
);

maybe_warn(&self.check_constraints, check_constraints_found, &mut self.warnings);

maybe_warn(
&self.exclusion_constraints,
exclusion_constraints_found,
&mut self.warnings,
);

maybe_warn(&self.row_level_ttl, row_level_ttl_in_tables, &mut self.warnings);
maybe_warn(&self.non_default_deferring, non_default_deferring, &mut self.warnings);
maybe_warn(&self.objects_with_comments, commented_objects, &mut self.warnings);
Expand Down Expand Up @@ -600,6 +612,26 @@ pub(crate) fn row_level_ttl_in_tables(affected: &[Model]) -> Warning {
}
}

pub(crate) fn check_constraints_found(affected: &[ModelAndConstraint]) -> Warning {
let message = "These constraints are not supported by the Prisma Client, because Prisma currently does not fully support check constraints. Read more: https://pris.ly/d/postgres-check-constraints";

Warning {
code: 33,
message: message.into(),
affected: serde_json::to_value(affected).unwrap(),
}
}

pub(crate) fn exclusion_constraints_found(affected: &[ModelAndConstraint]) -> Warning {
let message = "These constraints are not supported by the Prisma Client, because Prisma currently does not fully support exclusion constraints. Read more: https://pris.ly/d/postgres-exclusion-constraints";

Warning {
code: 34,
message: message.into(),
affected: serde_json::to_value(affected).unwrap(),
}
}

pub(crate) fn non_default_deferring(affected: &[ModelAndConstraint]) -> Warning {
let message = "These primary key, foreign key or unique constraints are using non-default deferring in the database, which is not yet fully supported. Read more: https://pris.ly/d/constraint-deferring";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ pub(super) fn generate_warnings(model: ModelPair<'_>, warnings: &mut Warnings) {
})
}

for constraint in model.check_constraints() {
warnings.check_constraints.push(generators::ModelAndConstraint {
model: model.name().to_string(),
constraint: constraint.to_string(),
})
}

for field in model.scalar_fields() {
if let Some(DefaultKind::Prisma1Uuid) = field.default().kind() {
let warn = generators::ModelAndField {
Expand Down
Loading