diff --git a/Cargo.lock b/Cargo.lock index 6fb116734862..6b5ff500ec5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5056,6 +5056,7 @@ dependencies = [ "url", "user-facing-errors", "uuid", + "versions", ] [[package]] @@ -6026,6 +6027,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "versions" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37ff4899935ba747849dd9eeb27c0bdd0da0210236704b7e4681a6c7bd6f9c6" +dependencies = [ + "itertools 0.12.0", + "nom", +] + [[package]] name = "void" version = "1.0.2" diff --git a/schema-engine/connectors/sql-schema-connector/Cargo.toml b/schema-engine/connectors/sql-schema-connector/Cargo.toml index b118b18cbc5c..767014b22bf8 100644 --- a/schema-engine/connectors/sql-schema-connector/Cargo.toml +++ b/schema-engine/connectors/sql-schema-connector/Cargo.toml @@ -33,3 +33,4 @@ url = "2.1.1" either = "1.6" sqlformat = "0.2.1" sqlparser = "0.32.0" +versions = "6.1.0" diff --git a/schema-engine/connectors/sql-schema-connector/src/flavour/mysql.rs b/schema-engine/connectors/sql-schema-connector/src/flavour/mysql.rs index 1efb4611bb50..da934258b042 100644 --- a/schema-engine/connectors/sql-schema-connector/src/flavour/mysql.rs +++ b/schema-engine/connectors/sql-schema-connector/src/flavour/mysql.rs @@ -15,6 +15,7 @@ use schema_connector::{ use sql_schema_describer::SqlSchema; use std::future; use url::Url; +use versions::Versioning; const ADVISORY_LOCK_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); static QUALIFIED_NAME_RE: Lazy = Lazy::new(|| Regex::new(r"`[^ ]+`\.`[^ ]+`").unwrap()); @@ -430,6 +431,7 @@ pub(crate) enum Circumstances { IsMysql57, IsMariadb, IsVitess, + CheckConstraints, } fn check_datamodel_for_mysql_5_6(datamodel: &ValidatedSchema, errors: &mut Vec) { @@ -533,6 +535,9 @@ where let mut circumstances = BitFlags::::default(); if let Some((version, global_version)) = versions { + let semver = Versioning::new(&global_version).unwrap_or_default(); + let min_check_constraints_semver = Versioning::new("8.0.16").unwrap(); + if version.contains("vitess") || version.contains("Vitess") { circumstances |= Circumstances::IsVitess; } @@ -548,6 +553,10 @@ where if global_version.contains("MariaDB") { circumstances |= Circumstances::IsMariadb; } + + if semver >= min_check_constraints_semver { + circumstances |= Circumstances::CheckConstraints; + } } let result_set = connection diff --git a/schema-engine/connectors/sql-schema-connector/src/flavour/mysql/connection.rs b/schema-engine/connectors/sql-schema-connector/src/flavour/mysql/connection.rs index c0d216ef4a4d..34fe9ef42fdd 100644 --- a/schema-engine/connectors/sql-schema-connector/src/flavour/mysql/connection.rs +++ b/schema-engine/connectors/sql-schema-connector/src/flavour/mysql/connection.rs @@ -52,6 +52,21 @@ impl Connection { describer_circumstances |= describer::Circumstances::MySql57; } + if circumstances.contains(super::Circumstances::CheckConstraints) + && !describer_circumstances.intersects( + describer::Circumstances::MySql56 + | describer::Circumstances::MySql57 + | describer::Circumstances::MariaDb, + ) + { + // MySQL 8.0.16 and above supports check constraints. + // MySQL 5.6 and 5.7 do not have a CHECK_CONSTRAINTS table we can query. + // MariaDB, although it supports check constraints, adds them unexpectedly. + // E.g., MariaDB 10 adds the `json_valid(\`Priv\`)` check constraint on every JSON column; + // this creates a noisy, unexpected diff when comparing the introspected schema with the prisma schema. + describer_circumstances |= describer::Circumstances::CheckConstraints; + } + let mut schema = sql_schema_describer::mysql::SqlSchemaDescriber::new(&self.0, describer_circumstances) .describe(&[params.url.dbname()]) .await diff --git a/schema-engine/sql-schema-describer/src/mysql.rs b/schema-engine/sql-schema-describer/src/mysql.rs index 0d5fd98140dd..b1c50f460eaa 100644 --- a/schema-engine/sql-schema-describer/src/mysql.rs +++ b/schema-engine/sql-schema-describer/src/mysql.rs @@ -47,6 +47,7 @@ pub enum Circumstances { MariaDb, MySql56, MySql57, + CheckConstraints, } pub struct SqlSchemaDescriber<'a> { @@ -737,7 +738,7 @@ impl<'a> SqlSchemaDescriber<'a> { table_names: &IndexMap, sql_schema: &mut SqlSchema, ) -> DescriberResult<()> { - // Only MySQL 8 and above supports check constraints and has the CHECK_CONSTRAINTS table we can query. + // Only MySQL 8.0.16 and above supports check constraints and has the CHECK_CONSTRAINTS table we can query. if !self.supports_check_constraints() { return Ok(()); } @@ -806,14 +807,7 @@ impl<'a> SqlSchemaDescriber<'a> { /// Tests whether the current database supports check constraints fn supports_check_constraints(&self) -> bool { - // MySQL 8 and above supports check constraints. - // MySQL 5.6 and 5.7 do not have a CHECK_CONSTRAINTS table we can query. - // MariaDB, although it supports check constraints, adds them unexpectedly. - // E.g., MariaDB 10 adds the `json_valid(\`Priv\`)` check constraint on every JSON column; - // this creates a noisy, unexpected diff when comparing the introspected schema with the prisma schema. - !self - .circumstances - .intersects(Circumstances::MySql56 | Circumstances::MySql57 | Circumstances::MariaDb) + self.circumstances.contains(Circumstances::CheckConstraints) } }