From 013aa27fcca5eb529c614267f24aa737e4f959d0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Apr 2020 15:57:53 +0200 Subject: [PATCH 01/20] pass up full data type information from sql describer --- .../identify_version/mod.rs | 67 +++++++++++++++++++ .../tests/db_specific_introspection/mod.rs | 1 + libs/sql-schema-describer/src/lib.rs | 9 ++- libs/sql-schema-describer/src/mysql.rs | 3 +- libs/sql-schema-describer/src/postgres.rs | 3 +- libs/sql-schema-describer/src/sqlite.rs | 7 +- 6 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs new file mode 100644 index 000000000000..def6c5cced99 --- /dev/null +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -0,0 +1,67 @@ +use crate::*; +use barrel::types; +use test_harness::*; + +// Enum (NON_PRISMA, PRISMA_1, PRISMA_1_1, PRISMA_2) + +//Testing +// SQLITE +// -> PRISMA_2: Migration Table, no-onDelete, no non-default types (D) +// -> NON_PRISMA: fallthrough + +// MYSQL +// -> PRISMA_2: Migration Table, no-onDelete, no non-default types (D) +// -> PRISMA_1: No Migration Table, no-onDelete, all relation tables with Id, createdAt/updatedAt always exist, no non-default types (D) +// -> PRISMA_1_1: No Migration Table, no-onDelete, all relation tables without Id, no non-default types (D) +// -> NON_PRISMA: fall through + +// POSTGRES +// -> PRISMA_2: Migration Table, no-onDelete, no non-default types (D) +// -> PRISMA_1: No Migration Table, no-onDelete, all relation tables with Id, createdAt/updatedAt always exist, no non-default types (D) +// -> PRISMA_1_1: No Migration Table, no-onDelete, all relation tables without Id, no non-default types (D) +// -> NON_PRISMA: fall through + +#[test_each_connector(tags("mysql"))] +async fn introspecting_a_table_enums_should_work(api: &TestApi) {} + +#[test_each_connector(tags("postgresql"))] +async fn introspecting_a_table_with_an_enum_default_value_that_is_an_empty_string_should_work(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("color ENUM ( 'black', '') Not Null default ''"); + }); + }) + .await; + + let dm = r#" + model Book { + color Book_color @default(EMPTY_ENUM_VALUE) + id Int @default(autoincrement()) @id + } + + enum Book_color{ + black + EMPTY_ENUM_VALUE @map("") + } + + "#; + + let result = dbg!(api.introspect().await); + custom_assert(&result, dm); +} + +#[test_each_connector(tags("sqlite"))] +async fn introspecting_a_table_enums_should_return_alphabetically_even_when_in_different_order(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + }); + }) + .await; + + let result = dbg!(api.introspect().await); + custom_assert(&result4, dm); +} diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/mod.rs index be12554a0962..aa38e1d1994e 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/mod.rs @@ -1,3 +1,4 @@ +pub mod identify_version; pub mod mysql; pub mod postgres; pub mod sqlite; diff --git a/libs/sql-schema-describer/src/lib.rs b/libs/sql-schema-describer/src/lib.rs index 4226a07264a2..e824f68ce617 100644 --- a/libs/sql-schema-describer/src/lib.rs +++ b/libs/sql-schema-describer/src/lib.rs @@ -232,8 +232,10 @@ impl Column { #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ColumnType { - /// The raw SQL type. - pub raw: String, + /// The SQL data type. + pub data_type: String, + /// The full SQL data type. + pub full_data_type: String, /// The family of the raw type. pub family: ColumnTypeFamily, /// The arity of the column. @@ -243,7 +245,8 @@ pub struct ColumnType { impl ColumnType { pub fn pure(family: ColumnTypeFamily, arity: ColumnArity) -> ColumnType { ColumnType { - raw: "".to_string(), + data_type: "".to_string(), + full_data_type: "".to_string(), family, arity, } diff --git a/libs/sql-schema-describer/src/mysql.rs b/libs/sql-schema-describer/src/mysql.rs index 7a76106aae35..208a4fe6e7ef 100644 --- a/libs/sql-schema-describer/src/mysql.rs +++ b/libs/sql-schema-describer/src/mysql.rs @@ -539,7 +539,8 @@ fn get_column_type_and_enum( }; let tpe = ColumnType { - raw: data_type.to_string(), + data_type: data_type.to_owned(), + full_data_type: full_data_type.to_owned(), family: family.clone(), arity, }; diff --git a/libs/sql-schema-describer/src/postgres.rs b/libs/sql-schema-describer/src/postgres.rs index 98b29bf91d14..8bd1d1afc1a5 100644 --- a/libs/sql-schema-describer/src/postgres.rs +++ b/libs/sql-schema-describer/src/postgres.rs @@ -651,7 +651,8 @@ fn get_column_type<'a>(data_type: &str, full_data_type: &'a str, arity: ColumnAr data_type => Unsupported(data_type.into()), }; ColumnType { - raw: full_data_type.to_owned(), + data_type: data_type.to_owned(), + full_data_type: full_data_type.to_owned(), family, arity, } diff --git a/libs/sql-schema-describer/src/sqlite.rs b/libs/sql-schema-describer/src/sqlite.rs index 53a7d63c4b86..86c853dd005e 100644 --- a/libs/sql-schema-describer/src/sqlite.rs +++ b/libs/sql-schema-describer/src/sqlite.rs @@ -236,7 +236,7 @@ impl SqlSchemaDescriber { if pk_cols.len() == 1 { let pk_col = &columns[0]; for col in cols.iter_mut() { - if &col.name == pk_col && &col.tpe.raw.to_lowercase() == "integer" { + if &col.name == pk_col && &col.tpe.data_type.to_lowercase() == "integer" { debug!( "Detected that the primary key column corresponds to rowid and \ is auto incrementing" @@ -439,8 +439,9 @@ fn get_column_type(tpe: &str, arity: ColumnArity) -> ColumnType { data_type => ColumnTypeFamily::Unsupported(data_type.into()), }; ColumnType { - raw: tpe.to_string(), - family: family, + data_type: tpe.to_string(), + full_data_type: tpe.to_string(), + family, arity, } } From 2254da7266642e8270c8f8fc0361064ea952bb78 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 28 Apr 2020 11:37:39 +0200 Subject: [PATCH 02/20] more notes, add data_type and full_data_type to sql schema column type instead of just raw --- .../introspection-connector/src/lib.rs | 10 ++ .../src/calculate_datamodel.rs | 78 +++++++++++++- .../sql-introspection-connector/src/lib.rs | 4 +- .../src/misc_helpers.rs | 3 +- .../tests/common_unit_tests/mod.rs | 20 ++-- .../identify_version/mod.rs | 85 ++++++--------- .../tests/test_harness/test_api.rs | 5 + .../tests/postgres_introspection_tests.rs | 100 +++++++++--------- .../tests/resources/schema.json | 12 ++- .../tests/serialization_tests.rs | 36 ++++--- .../tests/sqlite_introspection_tests.rs | 36 ++++--- 11 files changed, 243 insertions(+), 146 deletions(-) diff --git a/introspection-engine/connectors/introspection-connector/src/lib.rs b/introspection-engine/connectors/introspection-connector/src/lib.rs index c20a25cae72c..e689484c666d 100644 --- a/introspection-engine/connectors/introspection-connector/src/lib.rs +++ b/introspection-engine/connectors/introspection-connector/src/lib.rs @@ -25,12 +25,22 @@ pub struct DatabaseMetadata { pub size_in_bytes: usize, } +#[derive(Serialize, Deserialize, Debug)] +pub enum Version { + NON_PRISMA, + PRISMA_1, + PRISMA_1_1, + PRISMA_2, +} + #[derive(Debug)] pub struct IntrospectionResult { /// Datamodel pub datamodel: Datamodel, /// warnings pub warnings: Vec, + /// version + pub version: Version, } #[derive(Serialize, Deserialize, Debug)] diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index f099ad2daa15..186f346e9cd4 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -3,20 +3,44 @@ use crate::misc_helpers::*; use crate::sanitize_datamodel_names::sanitize_datamodel_names; use crate::SqlIntrospectionResult; use datamodel::{dml, Datamodel, FieldType, Model}; -use introspection_connector::IntrospectionResult; +use introspection_connector::{IntrospectionResult, Version}; +use quaint::connector::SqlFamily; use sql_schema_describer::*; use tracing::debug; /// Calculate a data model from a database schema. -pub fn calculate_model(schema: &SqlSchema) -> SqlIntrospectionResult { +pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrospectionResult { debug!("Calculating data model."); + let has_migration_table = schema.tables.iter().any(|table| is_migration_table(&table)); + let has_prisma_1_join_table = schema.tables.iter().any(|table| is_prisma_1_point_0_join_table(&table)); + let has_prisma_1_1_or_2_join_table = schema + .tables + .iter() + .any(|table| is_prisma_1_point_1_or_2_join_table(&table)); + let mut uses_on_delete = false; //should check all foreign keys -> needs default onDelete option + let mut always_has_created_at_updated_at = false; //should check all models + let mut uses_non_prisma_types = false; // should check all scalar fields and needs mapping SQLFamily -> Types + + //Currently from Migration Engine + //Types positive list, complicated by enums -.- + + // SQLITE Types + // "BOOLEAN","DATE","REAL","INTEGER","TEXT" + // POSTGRES Types + // Array types are only a P2 thing on Postgres + // "boolean", "timestamp(3)", "Decimal(65,30)", "integer", "text" + // native enums are only a P2 thing "ENUM_NAME" + // MYSQL Types + // "boolean","datetime(3)", "Decimal(65,30)", "int", "varchar()", + // native enums are only a P2 thing "ENUM()" + let mut data_model = Datamodel::new(); for table in schema .tables .iter() .filter(|table| !is_migration_table(&table)) - .filter(|table| !is_prisma_1_point_1_join_table(&table)) + .filter(|table| !is_prisma_1_point_1_or_2_join_table(&table)) .filter(|table| !is_prisma_1_point_0_join_table(&table)) { debug!("Calculating model: {}", table.name); @@ -91,7 +115,7 @@ pub fn calculate_model(schema: &SqlSchema) -> SqlIntrospectionResult SqlIntrospectionResult Version::PRISMA_2, + SqlFamily::Sqlite => Version::NON_PRISMA, + SqlFamily::Mysql if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::PRISMA_2, + SqlFamily::Mysql + if !has_migration_table + && !uses_on_delete + && !uses_non_prisma_types + && always_has_created_at_updated_at + && !has_prisma_1_1_or_2_join_table => + { + Version::PRISMA_1 + } + SqlFamily::Mysql + if !has_migration_table + && !uses_on_delete + && !uses_non_prisma_types + && always_has_created_at_updated_at + && !has_prisma_1_join_table => + { + Version::PRISMA_1_1 + } + SqlFamily::Mysql => Version::NON_PRISMA, + SqlFamily::Postgres if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::PRISMA_2, + SqlFamily::Postgres + if !has_migration_table + && !uses_on_delete + && !uses_non_prisma_types + && always_has_created_at_updated_at + && !has_prisma_1_1_or_2_join_table => + { + Version::PRISMA_1 + } + SqlFamily::Postgres + if !has_migration_table + && !uses_on_delete + && !uses_non_prisma_types + && always_has_created_at_updated_at + && !has_prisma_1_join_table => + { + Version::PRISMA_1_1 + } + SqlFamily::Postgres => Version::NON_PRISMA, + }; + Ok(IntrospectionResult { datamodel: data_model, warnings, + version, }) } diff --git a/introspection-engine/connectors/sql-introspection-connector/src/lib.rs b/introspection-engine/connectors/sql-introspection-connector/src/lib.rs index c050b01d58e3..6d0318fd9224 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/lib.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/lib.rs @@ -85,7 +85,9 @@ impl IntrospectionConnector for SqlIntrospectionConnector { let sql_schema = self.catch(self.describe()).await?; tracing::debug!("SQL Schema Describer is done: {:?}", sql_schema); - let introspection_result = calculate_datamodel::calculate_model(&sql_schema).unwrap(); + let family = self.connection_info.sql_family(); + + let introspection_result = calculate_datamodel::calculate_datamodel(&sql_schema, &family).unwrap(); tracing::debug!("Calculating datamodel is done: {:?}", sql_schema); Ok(introspection_result) } diff --git a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs index fab603d2cd27..5e5cd48cb223 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs @@ -9,11 +9,12 @@ use tracing::debug; //checks +//todo make this more targeted pub fn is_migration_table(table: &Table) -> bool { table.name == "_Migration" } -pub(crate) fn is_prisma_1_point_1_join_table(table: &Table) -> bool { +pub(crate) fn is_prisma_1_point_1_or_2_join_table(table: &Table) -> bool { table.columns.len() == 2 && table.indices.len() >= 2 && common_prisma_m_to_n_relation_conditions(table) } diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs index 59dde82a123c..0c1690cfb861 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs @@ -4,7 +4,7 @@ use datamodel::{ }; use pretty_assertions::assert_eq; use prisma_value::PrismaValue; -use sql_introspection_connector::calculate_datamodel::calculate_model; +use sql_introspection_connector::calculate_datamodel::calculate_datamodel; use sql_schema_describer::*; #[test] @@ -100,7 +100,7 @@ fn a_data_model_can_be_generated_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -207,7 +207,7 @@ fn arity_is_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -365,7 +365,7 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -517,7 +517,7 @@ fn primary_key_is_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -602,7 +602,7 @@ fn uniqueness_is_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -827,7 +827,7 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, expected_data_model); } @@ -942,7 +942,7 @@ fn multi_field_uniques_are_preserved_when_generating_data_model_from_a_schema() enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -1143,7 +1143,7 @@ fn foreign_keys_are_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -1180,7 +1180,7 @@ fn enums_are_preserved_when_generating_data_model_from_a_schema() { }], sequences: vec![], }; - let introspection_result = calculate_model(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index def6c5cced99..5623b32c9883 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -2,56 +2,6 @@ use crate::*; use barrel::types; use test_harness::*; -// Enum (NON_PRISMA, PRISMA_1, PRISMA_1_1, PRISMA_2) - -//Testing -// SQLITE -// -> PRISMA_2: Migration Table, no-onDelete, no non-default types (D) -// -> NON_PRISMA: fallthrough - -// MYSQL -// -> PRISMA_2: Migration Table, no-onDelete, no non-default types (D) -// -> PRISMA_1: No Migration Table, no-onDelete, all relation tables with Id, createdAt/updatedAt always exist, no non-default types (D) -// -> PRISMA_1_1: No Migration Table, no-onDelete, all relation tables without Id, no non-default types (D) -// -> NON_PRISMA: fall through - -// POSTGRES -// -> PRISMA_2: Migration Table, no-onDelete, no non-default types (D) -// -> PRISMA_1: No Migration Table, no-onDelete, all relation tables with Id, createdAt/updatedAt always exist, no non-default types (D) -// -> PRISMA_1_1: No Migration Table, no-onDelete, all relation tables without Id, no non-default types (D) -// -> NON_PRISMA: fall through - -#[test_each_connector(tags("mysql"))] -async fn introspecting_a_table_enums_should_work(api: &TestApi) {} - -#[test_each_connector(tags("postgresql"))] -async fn introspecting_a_table_with_an_enum_default_value_that_is_an_empty_string_should_work(api: &TestApi) { - api.barrel() - .execute(|migration| { - migration.create_table("Book", |t| { - t.add_column("id", types::primary()); - t.inject_custom("color ENUM ( 'black', '') Not Null default ''"); - }); - }) - .await; - - let dm = r#" - model Book { - color Book_color @default(EMPTY_ENUM_VALUE) - id Int @default(autoincrement()) @id - } - - enum Book_color{ - black - EMPTY_ENUM_VALUE @map("") - } - - "#; - - let result = dbg!(api.introspect().await); - custom_assert(&result, dm); -} - #[test_each_connector(tags("sqlite"))] async fn introspecting_a_table_enums_should_return_alphabetically_even_when_in_different_order(api: &TestApi) { api.barrel() @@ -62,6 +12,37 @@ async fn introspecting_a_table_enums_should_return_alphabetically_even_when_in_d }) .await; - let result = dbg!(api.introspect().await); - custom_assert(&result4, dm); + let result = dbg!(api.introspect_version().await); + custom_assert(&result, ""); } + +// #[test_each_connector(tags("mysql"))] +// async fn introspecting_a_table_enums_should_work(api: &TestApi) {} + +// #[test_each_connector(tags("postgresql"))] +// async fn introspecting_a_table_with_an_enum_default_value_that_is_an_empty_string_should_work(api: &TestApi) { +// api.barrel() +// .execute(|migration| { +// migration.create_table("Book", |t| { +// t.add_column("id", types::primary()); +// t.inject_custom("color ENUM ( 'black', '') Not Null default ''"); +// }); +// }) +// .await; +// +// let dm = r#" +// model Book { +// color Book_color @default(EMPTY_ENUM_VALUE) +// id Int @default(autoincrement()) @id +// } +// +// enum Book_color{ +// black +// EMPTY_ENUM_VALUE @map("") +// } +// +// "#; +// +// let result = dbg!(api.introspect().await); +// custom_assert(&result, dm); +// } diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs b/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs index b541fb19c4ac..f46e3dd61118 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs @@ -30,6 +30,11 @@ impl TestApi { datamodel::render_datamodel_to_string(&introspection_result.datamodel).expect("Datamodel rendering failed") } + pub async fn introspect_version(&self) -> String { + let introspection_result = self.introspection_connector.introspect().await.unwrap(); + introspection_result.version.to_string() + } + pub async fn introspection_warnings(&self) -> String { let introspection_result = self.introspection_connector.introspect().await.unwrap(); serde_json::to_string(&introspection_result.warnings).unwrap() diff --git a/libs/sql-schema-describer/tests/postgres_introspection_tests.rs b/libs/sql-schema-describer/tests/postgres_introspection_tests.rs index 11892fd8fd2f..3159b04fcfa1 100644 --- a/libs/sql-schema-describer/tests/postgres_introspection_tests.rs +++ b/libs/sql-schema-describer/tests/postgres_introspection_tests.rs @@ -69,7 +69,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_bin_col".into(), tpe: ColumnType { - raw: "_bytea".into(), + data_type: "_bytea".into(), family: ColumnTypeFamily::Binary, arity: ColumnArity::List, }, @@ -79,7 +79,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_bool_col".into(), tpe: ColumnType { - raw: "_bool".into(), + data_type: "_bool".into(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::List, }, @@ -89,7 +89,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_date_col".into(), tpe: ColumnType { - raw: "_date".into(), + data_type: "_date".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::List, }, @@ -99,7 +99,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_double_col".into(), tpe: ColumnType { - raw: "_float8".into(), + data_type: "_float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::List, }, @@ -109,7 +109,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_float_col".into(), tpe: ColumnType { - raw: "_float8".into(), + data_type: "_float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::List, }, @@ -119,7 +119,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_int_col".into(), tpe: ColumnType { - raw: "_int4".into(), + data_type: "_int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::List, }, @@ -129,7 +129,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_text_col".into(), tpe: ColumnType { - raw: "_text".into(), + data_type: "_text".into(), family: ColumnTypeFamily::String, arity: ColumnArity::List, }, @@ -139,7 +139,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_varchar_col".into(), tpe: ColumnType { - raw: "_varchar".into(), + data_type: "_varchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::List, }, @@ -149,7 +149,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "binary_col".into(), tpe: ColumnType { - raw: "bytea".into(), + data_type: "bytea".into(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -159,7 +159,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "boolean_col".into(), tpe: ColumnType { - raw: "bool".into(), + data_type: "bool".into(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::Required, }, @@ -169,7 +169,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "date_time_col".into(), tpe: ColumnType { - raw: "date".into(), + data_type: "date".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -180,7 +180,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "double_col".into(), tpe: ColumnType { - raw: "float8".into(), + data_type: "float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -191,7 +191,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "float_col".into(), tpe: ColumnType { - raw: "float8".into(), + data_type: "float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -202,7 +202,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "int_col".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -213,7 +213,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "primary_col".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -227,7 +227,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "string1_col".into(), tpe: ColumnType { - raw: "text".into(), + data_type: "text".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -238,7 +238,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "string2_col".into(), tpe: ColumnType { - raw: "varchar".into(), + data_type: "varchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -249,7 +249,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bigint_col".into(), tpe: ColumnType { - raw: "int8".into(), + data_type: "int8".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -260,7 +260,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bigserial_col".into(), tpe: ColumnType { - raw: "int8".into(), + data_type: "int8".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -274,7 +274,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bit_col".into(), tpe: ColumnType { - raw: "bit".into(), + data_type: "bit".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -285,7 +285,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bit_varying_col".into(), tpe: ColumnType { - raw: "varbit".into(), + data_type: "varbit".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -296,7 +296,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "box_col".into(), tpe: ColumnType { - raw: "box".into(), + data_type: "box".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -307,7 +307,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "char_col".into(), tpe: ColumnType { - raw: "bpchar".into(), + data_type: "bpchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -318,7 +318,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "circle_col".into(), tpe: ColumnType { - raw: "circle".into(), + data_type: "circle".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -329,7 +329,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "interval_col".into(), tpe: ColumnType { - raw: "interval".into(), + data_type: "interval".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -340,7 +340,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "line_col".into(), tpe: ColumnType { - raw: "line".into(), + data_type: "line".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -351,7 +351,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "lseg_col".into(), tpe: ColumnType { - raw: "lseg".into(), + data_type: "lseg".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -362,7 +362,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "numeric_col".into(), tpe: ColumnType { - raw: "numeric".into(), + data_type: "numeric".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -373,7 +373,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "path_col".into(), tpe: ColumnType { - raw: "path".into(), + data_type: "path".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -384,7 +384,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "pg_lsn_col".into(), tpe: ColumnType { - raw: "pg_lsn".into(), + data_type: "pg_lsn".into(), family: ColumnTypeFamily::LogSequenceNumber, arity: ColumnArity::Required, }, @@ -395,7 +395,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "polygon_col".into(), tpe: ColumnType { - raw: "polygon".into(), + data_type: "polygon".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -406,7 +406,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "smallint_col".into(), tpe: ColumnType { - raw: "int2".into(), + data_type: "int2".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -417,7 +417,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "smallserial_col".into(), tpe: ColumnType { - raw: "int2".into(), + data_type: "int2".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -431,7 +431,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "serial_col".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -445,7 +445,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "time_col".into(), tpe: ColumnType { - raw: "time".into(), + data_type: "time".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -456,7 +456,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "time_with_zone_col".into(), tpe: ColumnType { - raw: "timetz".into(), + data_type: "timetz".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -467,7 +467,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "timestamp_col".into(), tpe: ColumnType { - raw: "timestamp".into(), + data_type: "timestamp".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -478,7 +478,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "timestamp_with_zone_col".into(), tpe: ColumnType { - raw: "timestamptz".into(), + data_type: "timestamptz".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -489,7 +489,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "tsquery_col".into(), tpe: ColumnType { - raw: "tsquery".into(), + data_type: "tsquery".into(), family: ColumnTypeFamily::TextSearch, arity: ColumnArity::Required, }, @@ -500,7 +500,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "tsvector_col".into(), tpe: ColumnType { - raw: "tsvector".into(), + data_type: "tsvector".into(), family: ColumnTypeFamily::TextSearch, arity: ColumnArity::Required, }, @@ -511,7 +511,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "txid_col".into(), tpe: ColumnType { - raw: "txid_snapshot".into(), + data_type: "txid_snapshot".into(), family: ColumnTypeFamily::TransactionId, arity: ColumnArity::Required, }, @@ -522,7 +522,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "json_col".into(), tpe: ColumnType { - raw: "json".into(), + data_type: "json".into(), family: ColumnTypeFamily::Json, arity: ColumnArity::Required, }, @@ -533,7 +533,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "jsonb_col".into(), tpe: ColumnType { - raw: "jsonb".into(), + data_type: "jsonb".into(), family: ColumnTypeFamily::Json, arity: ColumnArity::Required, }, @@ -544,7 +544,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "uuid_col".into(), tpe: ColumnType { - raw: "uuid".into(), + data_type: "uuid".into(), family: ColumnTypeFamily::Uuid, arity: ColumnArity::Required, }, @@ -607,7 +607,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -617,7 +617,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_cascade".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -627,7 +627,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_restrict".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -637,7 +637,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_default".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -647,7 +647,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_null".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -657,7 +657,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "id".into(), tpe: ColumnType { - raw: "int4".into(), + data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, diff --git a/libs/sql-schema-describer/tests/resources/schema.json b/libs/sql-schema-describer/tests/resources/schema.json index bcdce83e0d26..e36730103f0b 100644 --- a/libs/sql-schema-describer/tests/resources/schema.json +++ b/libs/sql-schema-describer/tests/resources/schema.json @@ -6,7 +6,8 @@ { "name": "column1", "tpe": { - "raw": "integer", + "data_type": "integer", + "full_data_type": "integer", "family": "int", "arity": "required" }, @@ -16,7 +17,8 @@ { "name": "column2", "tpe": { - "raw": "varchar(255)", + "data_type": "varchar(255)", + "full_data_type": "varchar(255)", "family": "string", "arity": "nullable" }, @@ -28,7 +30,8 @@ { "name": "column3", "tpe": { - "raw": "integer", + "data_type": "integer", + "full_data_type": "integer", "family": "int", "arity": "required" }, @@ -69,7 +72,8 @@ { "name": "id", "tpe": { - "raw": "integer", + "data_type": "integer", + "full_data_type": "integer", "family": "int", "arity": "required" }, diff --git a/libs/sql-schema-describer/tests/serialization_tests.rs b/libs/sql-schema-describer/tests/serialization_tests.rs index 1e4263f0bac1..01d4655139f0 100644 --- a/libs/sql-schema-describer/tests/serialization_tests.rs +++ b/libs/sql-schema-describer/tests/serialization_tests.rs @@ -27,7 +27,8 @@ fn database_schema_is_serializable() { Column { name: "column1".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -37,7 +38,8 @@ fn database_schema_is_serializable() { Column { name: "column2".to_string(), tpe: ColumnType { - raw: "varchar(255)".to_string(), + data_type: "varchar(255)".to_string(), + full_data_type: "varchar(255)".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Nullable, }, @@ -47,7 +49,8 @@ fn database_schema_is_serializable() { Column { name: "column3".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -77,7 +80,8 @@ fn database_schema_is_serializable() { columns: vec![Column { name: "id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -122,7 +126,8 @@ fn database_schema_without_primary_key_is_serializable() { columns: vec![Column { name: "column1".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -170,7 +175,8 @@ fn database_schema_is_serializable_for_every_column_type_family() { .map(|(i, family)| Column { name: format!("column{}", i + 1), tpe: ColumnType { - raw: "raw type".to_string(), + data_type: "raw type".to_string(), + full_data_type: "raw type".to_string(), family: family.to_owned(), arity: ColumnArity::Nullable, }, @@ -210,7 +216,8 @@ fn database_schema_is_serializable_for_every_column_arity() { .map(|(i, arity)| Column { name: format!("column{}", i + 1), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: arity.to_owned(), }, @@ -251,7 +258,8 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column1".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -261,7 +269,8 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column2".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -271,7 +280,8 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column3".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -281,7 +291,8 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column4".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -291,7 +302,8 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column5".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, diff --git a/libs/sql-schema-describer/tests/sqlite_introspection_tests.rs b/libs/sql-schema-describer/tests/sqlite_introspection_tests.rs index 9382cc50ec2e..e9b1ba6f0a58 100644 --- a/libs/sql-schema-describer/tests/sqlite_introspection_tests.rs +++ b/libs/sql-schema-describer/tests/sqlite_introspection_tests.rs @@ -28,7 +28,8 @@ async fn sqlite_column_types_must_work() { Column { name: "int_col".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -38,7 +39,8 @@ async fn sqlite_column_types_must_work() { Column { name: "int4_col".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -48,7 +50,8 @@ async fn sqlite_column_types_must_work() { Column { name: "text_col".to_string(), tpe: ColumnType { - raw: "TEXT".to_string(), + data_type: "TEXT".to_string(), + full_data_type: "TEXT".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -58,7 +61,8 @@ async fn sqlite_column_types_must_work() { Column { name: "real_col".to_string(), tpe: ColumnType { - raw: "REAL".to_string(), + data_type: "REAL".to_string(), + full_data_type: "REAL".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -68,7 +72,8 @@ async fn sqlite_column_types_must_work() { Column { name: "primary_col".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -78,7 +83,8 @@ async fn sqlite_column_types_must_work() { Column { name: "decimal_col".to_string(), tpe: ColumnType { - raw: "decimal (5, 3)".to_string(), + data_type: "decimal (5, 3)".to_string(), + full_data_type: "decimal (5, 3)".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -131,7 +137,8 @@ async fn sqlite_foreign_key_on_delete_must_be_handled() { Column { name: "city".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -141,7 +148,8 @@ async fn sqlite_foreign_key_on_delete_must_be_handled() { Column { name: "city_cascade".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -151,7 +159,8 @@ async fn sqlite_foreign_key_on_delete_must_be_handled() { Column { name: "city_restrict".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -161,7 +170,8 @@ async fn sqlite_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_default".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -171,7 +181,8 @@ async fn sqlite_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_null".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -181,7 +192,8 @@ async fn sqlite_foreign_key_on_delete_must_be_handled() { Column { name: "id".to_string(), tpe: ColumnType { - raw: "INTEGER".to_string(), + data_type: "INTEGER".to_string(), + full_data_type: "INTEGER".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, From 4f05f84f3ba7678310e8f1193635e00443c9d2a5 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 30 Apr 2020 13:12:55 +0200 Subject: [PATCH 03/20] start sqlite tests --- .../introspection-connector/src/lib.rs | 10 +- .../src/calculate_datamodel.rs | 32 +++-- .../tests/common_unit_tests/mod.rs | 97 ++++++++----- .../identify_version/mod.rs | 22 ++- .../tests/test_harness/test_api.rs | 6 +- libs/datamodel/core/src/dml/model.rs | 12 ++ .../tests/introspection_tests.rs | 39 ++++-- .../tests/mysql_introspection_tests.rs | 132 ++++++++++++------ .../tests/postgres_introspection_tests.rs | 50 +++++++ 9 files changed, 286 insertions(+), 114 deletions(-) diff --git a/introspection-engine/connectors/introspection-connector/src/lib.rs b/introspection-engine/connectors/introspection-connector/src/lib.rs index e689484c666d..af0a574271b9 100644 --- a/introspection-engine/connectors/introspection-connector/src/lib.rs +++ b/introspection-engine/connectors/introspection-connector/src/lib.rs @@ -25,12 +25,12 @@ pub struct DatabaseMetadata { pub size_in_bytes: usize, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, PartialEq)] pub enum Version { - NON_PRISMA, - PRISMA_1, - PRISMA_1_1, - PRISMA_2, + NonPrisma, + Prisma1, + Prisma11, + Prisma2, } #[derive(Debug)] diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 186f346e9cd4..e9432ae4c33c 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -18,8 +18,8 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp .tables .iter() .any(|table| is_prisma_1_point_1_or_2_join_table(&table)); - let mut uses_on_delete = false; //should check all foreign keys -> needs default onDelete option - let mut always_has_created_at_updated_at = false; //should check all models + let mut uses_on_delete = false; + let mut always_has_created_at_updated_at = false; let mut uses_non_prisma_types = false; // should check all scalar fields and needs mapping SQLFamily -> Types //Currently from Migration Engine @@ -47,6 +47,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp let mut model = Model::new(table.name.clone(), None); for column in &table.columns { + // todo check actually used columntypes here let field = calculate_scalar_field(&table, &column); model.add_field(field); } @@ -60,6 +61,9 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp .iter() .any(|c| matches!(model_copy.find_field(c).unwrap().field_type, FieldType::Unsupported(_))) }) { + if foreign_key.on_delete_action != ForeignKeyAction::SetNull { + uses_on_delete = true + } model.add_field(calculate_relation_field(schema, table, foreign_key)); } @@ -75,6 +79,10 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp model.id_fields = table.primary_key_columns(); } + if !model.has_created_at_and_updated_at() { + always_has_created_at_updated_at = false + } + data_model.add_model(model); } @@ -145,9 +153,9 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp debug!("Done calculating data model {:?}", data_model); let version = match family { - SqlFamily::Sqlite if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::PRISMA_2, - SqlFamily::Sqlite => Version::NON_PRISMA, - SqlFamily::Mysql if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::PRISMA_2, + SqlFamily::Sqlite if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, + SqlFamily::Sqlite => Version::NonPrisma, + SqlFamily::Mysql if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Mysql if !has_migration_table && !uses_on_delete @@ -155,7 +163,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp && always_has_created_at_updated_at && !has_prisma_1_1_or_2_join_table => { - Version::PRISMA_1 + Version::Prisma1 } SqlFamily::Mysql if !has_migration_table @@ -164,10 +172,10 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp && always_has_created_at_updated_at && !has_prisma_1_join_table => { - Version::PRISMA_1_1 + Version::Prisma11 } - SqlFamily::Mysql => Version::NON_PRISMA, - SqlFamily::Postgres if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::PRISMA_2, + SqlFamily::Mysql => Version::NonPrisma, + SqlFamily::Postgres if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Postgres if !has_migration_table && !uses_on_delete @@ -175,7 +183,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp && always_has_created_at_updated_at && !has_prisma_1_1_or_2_join_table => { - Version::PRISMA_1 + Version::Prisma1 } SqlFamily::Postgres if !has_migration_table @@ -184,9 +192,9 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp && always_has_created_at_updated_at && !has_prisma_1_join_table => { - Version::PRISMA_1_1 + Version::Prisma11 } - SqlFamily::Postgres => Version::NON_PRISMA, + SqlFamily::Postgres => Version::NonPrisma, }; Ok(IntrospectionResult { diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs index 0c1690cfb861..1bb0b67607d6 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/common_unit_tests/mod.rs @@ -4,6 +4,7 @@ use datamodel::{ }; use pretty_assertions::assert_eq; use prisma_value::PrismaValue; +use quaint::connector::SqlFamily; use sql_introspection_connector::calculate_datamodel::calculate_datamodel; use sql_schema_describer::*; @@ -82,7 +83,8 @@ fn a_data_model_can_be_generated_from_a_schema() { .map(|family| Column { name: family.to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: family.to_owned(), arity: ColumnArity::Nullable, }, @@ -100,7 +102,7 @@ fn a_data_model_can_be_generated_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -169,7 +171,8 @@ fn arity_is_preserved_when_generating_data_model_from_a_schema() { Column { name: "optional".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -179,7 +182,8 @@ fn arity_is_preserved_when_generating_data_model_from_a_schema() { Column { name: "required".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -189,7 +193,8 @@ fn arity_is_preserved_when_generating_data_model_from_a_schema() { Column { name: "list".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::List, }, @@ -207,7 +212,7 @@ fn arity_is_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -306,7 +311,8 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "no_default".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -316,7 +322,8 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "int_default".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -326,7 +333,8 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "bool_default".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::Nullable, }, @@ -336,7 +344,8 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "float_default".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Nullable, }, @@ -346,7 +355,8 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "string_default".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Nullable, }, @@ -365,7 +375,7 @@ fn defaults_are_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -457,7 +467,8 @@ fn primary_key_is_preserved_when_generating_data_model_from_a_schema() { columns: vec![Column { name: "primary".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -476,7 +487,8 @@ fn primary_key_is_preserved_when_generating_data_model_from_a_schema() { columns: vec![Column { name: "primary".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -495,7 +507,8 @@ fn primary_key_is_preserved_when_generating_data_model_from_a_schema() { columns: vec![Column { name: "primary".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -517,7 +530,7 @@ fn primary_key_is_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -573,7 +586,8 @@ fn uniqueness_is_preserved_when_generating_data_model_from_a_schema() { Column { name: "non_unique".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -583,7 +597,8 @@ fn uniqueness_is_preserved_when_generating_data_model_from_a_schema() { Column { name: "unique".to_string(), tpe: ColumnType { - raw: "raw".to_string(), + data_type: "raw".to_string(), + full_data_type: "raw".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -602,7 +617,7 @@ fn uniqueness_is_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -750,7 +765,8 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( Column { name: "id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -760,7 +776,8 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( Column { name: "name".to_string(), tpe: ColumnType { - raw: "text".to_string(), + data_type: "text".to_string(), + full_data_type: "text".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -781,7 +798,8 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( Column { name: "id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -791,7 +809,8 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( Column { name: "city-id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -801,7 +820,8 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( Column { name: "city-name".to_string(), tpe: ColumnType { - raw: "text".to_string(), + data_type: "text".to_string(), + full_data_type: "text".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -827,7 +847,7 @@ fn compound_foreign_keys_are_preserved_when_generating_data_model_from_a_schema( enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, expected_data_model); } @@ -900,7 +920,8 @@ fn multi_field_uniques_are_preserved_when_generating_data_model_from_a_schema() Column { name: "id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -910,7 +931,8 @@ fn multi_field_uniques_are_preserved_when_generating_data_model_from_a_schema() Column { name: "name".to_string(), tpe: ColumnType { - raw: "text".to_string(), + data_type: "text".to_string(), + full_data_type: "text".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -920,7 +942,8 @@ fn multi_field_uniques_are_preserved_when_generating_data_model_from_a_schema() Column { name: "lastname".to_string(), tpe: ColumnType { - raw: "text".to_string(), + data_type: "text".to_string(), + full_data_type: "text".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -942,7 +965,7 @@ fn multi_field_uniques_are_preserved_when_generating_data_model_from_a_schema() enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -1077,7 +1100,8 @@ fn foreign_keys_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -1087,7 +1111,8 @@ fn foreign_keys_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "name".to_string(), tpe: ColumnType { - raw: "text".to_string(), + data_type: "text".to_string(), + full_data_type: "text".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -1108,7 +1133,8 @@ fn foreign_keys_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -1118,7 +1144,8 @@ fn foreign_keys_are_preserved_when_generating_data_model_from_a_schema() { Column { name: "city_id".to_string(), tpe: ColumnType { - raw: "integer".to_string(), + data_type: "integer".to_string(), + full_data_type: "integer".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -1143,7 +1170,7 @@ fn foreign_keys_are_preserved_when_generating_data_model_from_a_schema() { enums: vec![], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } @@ -1180,7 +1207,7 @@ fn enums_are_preserved_when_generating_data_model_from_a_schema() { }], sequences: vec![], }; - let introspection_result = calculate_datamodel(&schema).expect("calculate data model"); + let introspection_result = calculate_datamodel(&schema, &SqlFamily::Postgres).expect("calculate data model"); assert_eq!(introspection_result.datamodel, ref_data_model); } diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index 5623b32c9883..b2ebd6bdbbc8 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -1,9 +1,27 @@ use crate::*; use barrel::types; +use introspection_connector::Version; use test_harness::*; #[test_each_connector(tags("sqlite"))] -async fn introspecting_a_table_enums_should_return_alphabetically_even_when_in_different_order(api: &TestApi) { +async fn introspect_sqlite_prisma2(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("_Migration", |t| { + t.add_column("id", types::primary()); + }); + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma2); +} + +#[test_each_connector(tags("sqlite"))] +async fn introspect_sqlite_non_prisma(api: &TestApi) { api.barrel() .execute(|migration| { migration.create_table("Book", |t| { @@ -13,7 +31,7 @@ async fn introspecting_a_table_enums_should_return_alphabetically_even_when_in_d .await; let result = dbg!(api.introspect_version().await); - custom_assert(&result, ""); + assert_eq!(result, Version::NonPrisma); } // #[test_each_connector(tags("mysql"))] diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs b/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs index f46e3dd61118..bfe3818bdf37 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/test_harness/test_api.rs @@ -1,5 +1,5 @@ use super::misc_helpers::*; -use introspection_connector::{DatabaseMetadata, IntrospectionConnector}; +use introspection_connector::{DatabaseMetadata, IntrospectionConnector, Version}; use quaint::{ prelude::{Queryable, SqlFamily}, single::Quaint, @@ -30,9 +30,9 @@ impl TestApi { datamodel::render_datamodel_to_string(&introspection_result.datamodel).expect("Datamodel rendering failed") } - pub async fn introspect_version(&self) -> String { + pub async fn introspect_version(&self) -> Version { let introspection_result = self.introspection_connector.introspect().await.unwrap(); - introspection_result.version.to_string() + introspection_result.version } pub async fn introspection_warnings(&self) -> String { diff --git a/libs/datamodel/core/src/dml/model.rs b/libs/datamodel/core/src/dml/model.rs index e22de6d0f152..45c816d1cf86 100644 --- a/libs/datamodel/core/src/dml/model.rs +++ b/libs/datamodel/core/src/dml/model.rs @@ -252,6 +252,18 @@ impl Model { pub fn has_index(&self, index: &IndexDefinition) -> bool { self.indices.iter().any(|own_index| own_index == index) } + + pub fn has_created_at_and_updated_at(&self) -> bool { + /// Finds a field by name. + fn has_field(model: &Model, name: &str) -> bool { + match model.find_field(name) { + Some(f) => f.field_type == FieldType::Base(ScalarType::DateTime, None), + None => false, + } + } + + has_field(self, "createdAt") && has_field(self, "updatedAt") + } } impl WithName for Model { diff --git a/libs/sql-schema-describer/tests/introspection_tests.rs b/libs/sql-schema-describer/tests/introspection_tests.rs index 09d25167b291..c7786840be7a 100644 --- a/libs/sql-schema-describer/tests/introspection_tests.rs +++ b/libs/sql-schema-describer/tests/introspection_tests.rs @@ -47,7 +47,8 @@ async fn is_required_must_work(api: &TestApi) { Column { name: "column1".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -57,7 +58,8 @@ async fn is_required_must_work(api: &TestApi) { Column { name: "column2".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -96,7 +98,8 @@ async fn foreign_keys_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "city".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -178,7 +181,8 @@ async fn multi_column_foreign_keys_must_work(api: &TestApi) { Column { name: "city".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -188,7 +192,8 @@ async fn multi_column_foreign_keys_must_work(api: &TestApi) { Column { name: "city_name".to_string(), tpe: ColumnType { - raw: varchar_type(api.sql_family(), 255), + data_type: varchar_type(api.sql_family(), 255), + full_data_type: varchar_type(api.sql_family(), 255), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -249,7 +254,8 @@ async fn names_with_hyphens_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "column-1".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -293,7 +299,8 @@ async fn composite_primary_keys_must_work(api: &TestApi) { Column { name: "id".to_string(), tpe: ColumnType { - raw: exp_int.to_string(), + data_type: exp_int.to_string(), + full_data_type: exp_int.to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -303,7 +310,8 @@ async fn composite_primary_keys_must_work(api: &TestApi) { Column { name: "name".to_string(), tpe: ColumnType { - raw: exp_varchar.to_string(), + data_type: exp_varchar.to_string(), + full_data_type: exp_varchar.to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -349,7 +357,8 @@ async fn indices_must_work(api: &TestApi) { Column { name: "count".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -359,7 +368,8 @@ async fn indices_must_work(api: &TestApi) { Column { name: "id".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -413,7 +423,8 @@ async fn column_uniqueness_must_be_detected(api: &TestApi) { Column { name: "uniq1".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -423,7 +434,8 @@ async fn column_uniqueness_must_be_detected(api: &TestApi) { Column { name: "uniq2".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -493,7 +505,8 @@ async fn defaults_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "id".to_string(), tpe: ColumnType { - raw: int_type(api.sql_family()), + data_type: int_type(api.sql_family()), + full_data_type: int_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, diff --git a/libs/sql-schema-describer/tests/mysql_introspection_tests.rs b/libs/sql-schema-describer/tests/mysql_introspection_tests.rs index 5fae55a78606..0eb1f49d5133 100644 --- a/libs/sql-schema-describer/tests/mysql_introspection_tests.rs +++ b/libs/sql-schema-describer/tests/mysql_introspection_tests.rs @@ -63,7 +63,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "primary_col".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -74,7 +75,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "int_col".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -85,7 +87,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "smallint_col".to_string(), tpe: ColumnType { - raw: "smallint".to_string(), + data_type: "smallint".to_string(), + full_data_type: "smallint".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -96,7 +99,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "tinyint4_col".to_string(), tpe: ColumnType { - raw: "tinyint".to_string(), + data_type: "tinyint".to_string(), + full_data_type: "tinyint".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -106,7 +110,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "tinyint1_col".to_string(), tpe: ColumnType { - raw: "tinyint".to_string(), + data_type: "tinyint".to_string(), + full_data_type: "tinyint".to_string(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::Required, }, @@ -117,7 +122,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "mediumint_col".to_string(), tpe: ColumnType { - raw: "mediumint".to_string(), + data_type: "mediumint".to_string(), + full_data_type: "mediumint".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -128,7 +134,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "bigint_col".to_string(), tpe: ColumnType { - raw: "bigint".to_string(), + data_type: "bigint".to_string(), + full_data_type: "bigint".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -139,7 +146,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "decimal_col".to_string(), tpe: ColumnType { - raw: "decimal".to_string(), + data_type: "decimal".to_string(), + full_data_type: "decimal".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -150,7 +158,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "numeric_col".to_string(), tpe: ColumnType { - raw: "decimal".to_string(), + data_type: "decimal".to_string(), + full_data_type: "decimal".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -161,7 +170,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "float_col".to_string(), tpe: ColumnType { - raw: "float".to_string(), + data_type: "float".to_string(), + full_data_type: "float".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -172,7 +182,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "double_col".to_string(), tpe: ColumnType { - raw: "double".to_string(), + data_type: "double".to_string(), + full_data_type: "double".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -183,7 +194,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "date_col".to_string(), tpe: ColumnType { - raw: "date".to_string(), + data_type: "date".to_string(), + full_data_type: "date".to_string(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -194,7 +206,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "time_col".to_string(), tpe: ColumnType { - raw: "time".to_string(), + data_type: "time".to_string(), + full_data_type: "time".to_string(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -205,7 +218,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "datetime_col".to_string(), tpe: ColumnType { - raw: "datetime".to_string(), + data_type: "datetime".to_string(), + full_data_type: "datetime".to_string(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -216,7 +230,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "timestamp_col".to_string(), tpe: ColumnType { - raw: "timestamp".to_string(), + data_type: "timestamp".to_string(), + full_data_type: "timestamp".to_string(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -227,7 +242,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "year_col".to_string(), tpe: ColumnType { - raw: "year".to_string(), + data_type: "year".to_string(), + full_data_type: "year".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -238,7 +254,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "char_col".to_string(), tpe: ColumnType { - raw: "char".to_string(), + data_type: "char".to_string(), + full_data_type: "char".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -249,7 +266,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "varchar_col".to_string(), tpe: ColumnType { - raw: "varchar".to_string(), + data_type: "varchar".to_string(), + full_data_type: "varchar".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -260,7 +278,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "text_col".to_string(), tpe: ColumnType { - raw: "text".to_string(), + data_type: "text".to_string(), + full_data_type: "text".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -271,7 +290,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "tinytext_col".to_string(), tpe: ColumnType { - raw: "tinytext".to_string(), + data_type: "tinytext".to_string(), + full_data_type: "tinytext".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -282,7 +302,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "mediumtext_col".to_string(), tpe: ColumnType { - raw: "mediumtext".to_string(), + data_type: "mediumtext".to_string(), + full_data_type: "mediumtext".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -293,7 +314,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "longtext_col".to_string(), tpe: ColumnType { - raw: "longtext".to_string(), + data_type: "longtext".to_string(), + full_data_type: "longtext".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -304,7 +326,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "enum_col".to_string(), tpe: ColumnType { - raw: "enum".to_string(), + data_type: "enum".to_string(), + full_data_type: "enum".to_string(), family: ColumnTypeFamily::Enum("User_enum_col".into()), arity: ColumnArity::Required, }, @@ -315,7 +338,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "set_col".to_string(), tpe: ColumnType { - raw: "set".to_string(), + data_type: "set".to_string(), + full_data_type: "set".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -326,7 +350,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "binary_col".to_string(), tpe: ColumnType { - raw: "binary".to_string(), + data_type: "binary".to_string(), + full_data_type: "binary".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -337,7 +362,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "varbinary_col".to_string(), tpe: ColumnType { - raw: "varbinary".to_string(), + data_type: "varbinary".to_string(), + full_data_type: "varbinary".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -348,7 +374,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "blob_col".to_string(), tpe: ColumnType { - raw: "blob".to_string(), + data_type: "blob".to_string(), + full_data_type: "blob".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -359,7 +386,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "tinyblob_col".to_string(), tpe: ColumnType { - raw: "tinyblob".to_string(), + data_type: "tinyblob".to_string(), + full_data_type: "tinyblob".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -370,7 +398,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "mediumblob_col".to_string(), tpe: ColumnType { - raw: "mediumblob".to_string(), + data_type: "mediumblob".to_string(), + full_data_type: "mediumblob".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -381,7 +410,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "longblob_col".to_string(), tpe: ColumnType { - raw: "longblob".to_string(), + data_type: "longblob".to_string(), + full_data_type: "longblob".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -392,7 +422,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "geometry_col".to_string(), tpe: ColumnType { - raw: "geometry".to_string(), + data_type: "geometry".to_string(), + full_data_type: "geometry".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -403,7 +434,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "point_col".to_string(), tpe: ColumnType { - raw: "point".to_string(), + data_type: "point".to_string(), + full_data_type: "point".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -414,7 +446,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "linestring_col".to_string(), tpe: ColumnType { - raw: "linestring".to_string(), + data_type: "linestring".to_string(), + full_data_type: "linestring".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -425,7 +458,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "polygon_col".to_string(), tpe: ColumnType { - raw: "polygon".to_string(), + data_type: "polygon".to_string(), + full_data_type: "polygon".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -436,7 +470,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "multipoint_col".to_string(), tpe: ColumnType { - raw: "multipoint".to_string(), + data_type: "multipoint".to_string(), + full_data_type: "multipoint".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -447,7 +482,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "multilinestring_col".to_string(), tpe: ColumnType { - raw: "multilinestring".to_string(), + data_type: "multilinestring".to_string(), + full_data_type: "multilinestring".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -458,7 +494,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "multipolygon_col".to_string(), tpe: ColumnType { - raw: "multipolygon".to_string(), + data_type: "multipolygon".to_string(), + full_data_type: "multipolygon".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -469,7 +506,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "geometrycollection_col".to_string(), tpe: ColumnType { - raw: "geometrycollection".to_string(), + data_type: "geometrycollection".to_string(), + full_data_type: "geometrycollection".to_string(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -480,7 +518,8 @@ async fn all_mysql_column_types_must_work() { Column { name: "json_col".to_string(), tpe: ColumnType { - raw: "json".to_string(), + data_type: "json".to_string(), + full_data_type: "json".to_string(), family: ColumnTypeFamily::Json, arity: ColumnArity::Required, }, @@ -537,7 +576,8 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { Column { name: "city".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -547,7 +587,8 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { Column { name: "city_cascade".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -557,7 +598,8 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { Column { name: "city_restrict".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -567,7 +609,8 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_null".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -577,7 +620,8 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { Column { name: "id".to_string(), tpe: ColumnType { - raw: "int".to_string(), + data_type: "int".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, diff --git a/libs/sql-schema-describer/tests/postgres_introspection_tests.rs b/libs/sql-schema-describer/tests/postgres_introspection_tests.rs index 3159b04fcfa1..de1b62eb1daa 100644 --- a/libs/sql-schema-describer/tests/postgres_introspection_tests.rs +++ b/libs/sql-schema-describer/tests/postgres_introspection_tests.rs @@ -70,6 +70,7 @@ async fn all_postgres_column_types_must_work() { name: "array_bin_col".into(), tpe: ColumnType { data_type: "_bytea".into(), + full_data_type: "_bytea".into(), family: ColumnTypeFamily::Binary, arity: ColumnArity::List, }, @@ -80,6 +81,7 @@ async fn all_postgres_column_types_must_work() { name: "array_bool_col".into(), tpe: ColumnType { data_type: "_bool".into(), + full_data_type: "_bool".into(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::List, }, @@ -90,6 +92,7 @@ async fn all_postgres_column_types_must_work() { name: "array_date_col".into(), tpe: ColumnType { data_type: "_date".into(), + full_data_type: "_date".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::List, }, @@ -100,6 +103,7 @@ async fn all_postgres_column_types_must_work() { name: "array_double_col".into(), tpe: ColumnType { data_type: "_float8".into(), + full_data_type: "_float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::List, }, @@ -110,6 +114,7 @@ async fn all_postgres_column_types_must_work() { name: "array_float_col".into(), tpe: ColumnType { data_type: "_float8".into(), + full_data_type: "_float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::List, }, @@ -120,6 +125,7 @@ async fn all_postgres_column_types_must_work() { name: "array_int_col".into(), tpe: ColumnType { data_type: "_int4".into(), + full_data_type: "_int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::List, }, @@ -130,6 +136,7 @@ async fn all_postgres_column_types_must_work() { name: "array_text_col".into(), tpe: ColumnType { data_type: "_text".into(), + full_data_type: "_text".into(), family: ColumnTypeFamily::String, arity: ColumnArity::List, }, @@ -140,6 +147,7 @@ async fn all_postgres_column_types_must_work() { name: "array_varchar_col".into(), tpe: ColumnType { data_type: "_varchar".into(), + full_data_type: "_varchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::List, }, @@ -150,6 +158,7 @@ async fn all_postgres_column_types_must_work() { name: "binary_col".into(), tpe: ColumnType { data_type: "bytea".into(), + full_data_type: "bytea".into(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -160,6 +169,7 @@ async fn all_postgres_column_types_must_work() { name: "boolean_col".into(), tpe: ColumnType { data_type: "bool".into(), + full_data_type: "bool".into(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::Required, }, @@ -170,6 +180,7 @@ async fn all_postgres_column_types_must_work() { name: "date_time_col".into(), tpe: ColumnType { data_type: "date".into(), + full_data_type: "date".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -181,6 +192,7 @@ async fn all_postgres_column_types_must_work() { name: "double_col".into(), tpe: ColumnType { data_type: "float8".into(), + full_data_type: "float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -192,6 +204,7 @@ async fn all_postgres_column_types_must_work() { name: "float_col".into(), tpe: ColumnType { data_type: "float8".into(), + full_data_type: "float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -203,6 +216,7 @@ async fn all_postgres_column_types_must_work() { name: "int_col".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -214,6 +228,7 @@ async fn all_postgres_column_types_must_work() { name: "primary_col".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -228,6 +243,7 @@ async fn all_postgres_column_types_must_work() { name: "string1_col".into(), tpe: ColumnType { data_type: "text".into(), + full_data_type: "text".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -239,6 +255,7 @@ async fn all_postgres_column_types_must_work() { name: "string2_col".into(), tpe: ColumnType { data_type: "varchar".into(), + full_data_type: "varchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -250,6 +267,7 @@ async fn all_postgres_column_types_must_work() { name: "bigint_col".into(), tpe: ColumnType { data_type: "int8".into(), + full_data_type: "int8".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -261,6 +279,7 @@ async fn all_postgres_column_types_must_work() { name: "bigserial_col".into(), tpe: ColumnType { data_type: "int8".into(), + full_data_type: "int8".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -275,6 +294,7 @@ async fn all_postgres_column_types_must_work() { name: "bit_col".into(), tpe: ColumnType { data_type: "bit".into(), + full_data_type: "bit".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -286,6 +306,7 @@ async fn all_postgres_column_types_must_work() { name: "bit_varying_col".into(), tpe: ColumnType { data_type: "varbit".into(), + full_data_type: "varbit".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -297,6 +318,7 @@ async fn all_postgres_column_types_must_work() { name: "box_col".into(), tpe: ColumnType { data_type: "box".into(), + full_data_type: "box".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -308,6 +330,7 @@ async fn all_postgres_column_types_must_work() { name: "char_col".into(), tpe: ColumnType { data_type: "bpchar".into(), + full_data_type: "bpchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -319,6 +342,7 @@ async fn all_postgres_column_types_must_work() { name: "circle_col".into(), tpe: ColumnType { data_type: "circle".into(), + full_data_type: "circle".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -330,6 +354,7 @@ async fn all_postgres_column_types_must_work() { name: "interval_col".into(), tpe: ColumnType { data_type: "interval".into(), + full_data_type: "interval".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -341,6 +366,7 @@ async fn all_postgres_column_types_must_work() { name: "line_col".into(), tpe: ColumnType { data_type: "line".into(), + full_data_type: "line".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -352,6 +378,7 @@ async fn all_postgres_column_types_must_work() { name: "lseg_col".into(), tpe: ColumnType { data_type: "lseg".into(), + full_data_type: "lseg".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -363,6 +390,7 @@ async fn all_postgres_column_types_must_work() { name: "numeric_col".into(), tpe: ColumnType { data_type: "numeric".into(), + full_data_type: "numeric".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -374,6 +402,7 @@ async fn all_postgres_column_types_must_work() { name: "path_col".into(), tpe: ColumnType { data_type: "path".into(), + full_data_type: "path".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -385,6 +414,7 @@ async fn all_postgres_column_types_must_work() { name: "pg_lsn_col".into(), tpe: ColumnType { data_type: "pg_lsn".into(), + full_data_type: "pg_lsn".into(), family: ColumnTypeFamily::LogSequenceNumber, arity: ColumnArity::Required, }, @@ -396,6 +426,7 @@ async fn all_postgres_column_types_must_work() { name: "polygon_col".into(), tpe: ColumnType { data_type: "polygon".into(), + full_data_type: "polygon".into(), family: ColumnTypeFamily::Geometric, arity: ColumnArity::Required, }, @@ -407,6 +438,7 @@ async fn all_postgres_column_types_must_work() { name: "smallint_col".into(), tpe: ColumnType { data_type: "int2".into(), + full_data_type: "int2".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -418,6 +450,7 @@ async fn all_postgres_column_types_must_work() { name: "smallserial_col".into(), tpe: ColumnType { data_type: "int2".into(), + full_data_type: "int2".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -432,6 +465,7 @@ async fn all_postgres_column_types_must_work() { name: "serial_col".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -446,6 +480,7 @@ async fn all_postgres_column_types_must_work() { name: "time_col".into(), tpe: ColumnType { data_type: "time".into(), + full_data_type: "time".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -457,6 +492,7 @@ async fn all_postgres_column_types_must_work() { name: "time_with_zone_col".into(), tpe: ColumnType { data_type: "timetz".into(), + full_data_type: "timetz".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -468,6 +504,7 @@ async fn all_postgres_column_types_must_work() { name: "timestamp_col".into(), tpe: ColumnType { data_type: "timestamp".into(), + full_data_type: "timestamp".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -479,6 +516,7 @@ async fn all_postgres_column_types_must_work() { name: "timestamp_with_zone_col".into(), tpe: ColumnType { data_type: "timestamptz".into(), + full_data_type: "timestamptz".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, }, @@ -490,6 +528,7 @@ async fn all_postgres_column_types_must_work() { name: "tsquery_col".into(), tpe: ColumnType { data_type: "tsquery".into(), + full_data_type: "tsquery".into(), family: ColumnTypeFamily::TextSearch, arity: ColumnArity::Required, }, @@ -501,6 +540,7 @@ async fn all_postgres_column_types_must_work() { name: "tsvector_col".into(), tpe: ColumnType { data_type: "tsvector".into(), + full_data_type: "tsvector".into(), family: ColumnTypeFamily::TextSearch, arity: ColumnArity::Required, }, @@ -512,6 +552,7 @@ async fn all_postgres_column_types_must_work() { name: "txid_col".into(), tpe: ColumnType { data_type: "txid_snapshot".into(), + full_data_type: "txid_snapshot".into(), family: ColumnTypeFamily::TransactionId, arity: ColumnArity::Required, }, @@ -523,6 +564,7 @@ async fn all_postgres_column_types_must_work() { name: "json_col".into(), tpe: ColumnType { data_type: "json".into(), + full_data_type: "json".into(), family: ColumnTypeFamily::Json, arity: ColumnArity::Required, }, @@ -534,6 +576,7 @@ async fn all_postgres_column_types_must_work() { name: "jsonb_col".into(), tpe: ColumnType { data_type: "jsonb".into(), + full_data_type: "jsonb".into(), family: ColumnTypeFamily::Json, arity: ColumnArity::Required, }, @@ -545,6 +588,7 @@ async fn all_postgres_column_types_must_work() { name: "uuid_col".into(), tpe: ColumnType { data_type: "uuid".into(), + full_data_type: "uuid".into(), family: ColumnTypeFamily::Uuid, arity: ColumnArity::Required, }, @@ -608,6 +652,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { name: "city".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -618,6 +663,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { name: "city_cascade".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -628,6 +674,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { name: "city_restrict".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -638,6 +685,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { name: "city_set_default".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -648,6 +696,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { name: "city_set_null".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -658,6 +707,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { name: "id".into(), tpe: ColumnType { data_type: "int4".into(), + full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, From 71be0efa35457e530627ce5a046375f9b6be452e Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 30 Apr 2020 15:07:02 +0200 Subject: [PATCH 04/20] start fixing test cases --- .../identify_version/mod.rs | 69 ++++++++++--------- .../rpc_calls/get_database_description.rs | 6 +- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index b2ebd6bdbbc8..564a6e117e60 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -3,6 +3,21 @@ use barrel::types; use introspection_connector::Version; use test_harness::*; +//Sqlite +#[test_each_connector(tags("sqlite"))] +async fn introspect_sqlite_non_prisma(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::NonPrisma); +} + #[test_each_connector(tags("sqlite"))] async fn introspect_sqlite_prisma2(api: &TestApi) { api.barrel() @@ -20,8 +35,10 @@ async fn introspect_sqlite_prisma2(api: &TestApi) { assert_eq!(result, Version::Prisma2); } -#[test_each_connector(tags("sqlite"))] -async fn introspect_sqlite_non_prisma(api: &TestApi) { +//Postgres + +#[test_each_connector(tags("postgres"))] +async fn introspect_postgres_non_prisma(api: &TestApi) { api.barrel() .execute(|migration| { migration.create_table("Book", |t| { @@ -34,33 +51,23 @@ async fn introspect_sqlite_non_prisma(api: &TestApi) { assert_eq!(result, Version::NonPrisma); } -// #[test_each_connector(tags("mysql"))] -// async fn introspecting_a_table_enums_should_work(api: &TestApi) {} +#[test_each_connector(tags("postgres"))] +async fn introspect_postgres_prisma2(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("_Migration", |t| { + t.add_column("id", types::primary()); + }); + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma2); +} -// #[test_each_connector(tags("postgresql"))] -// async fn introspecting_a_table_with_an_enum_default_value_that_is_an_empty_string_should_work(api: &TestApi) { -// api.barrel() -// .execute(|migration| { -// migration.create_table("Book", |t| { -// t.add_column("id", types::primary()); -// t.inject_custom("color ENUM ( 'black', '') Not Null default ''"); -// }); -// }) -// .await; -// -// let dm = r#" -// model Book { -// color Book_color @default(EMPTY_ENUM_VALUE) -// id Int @default(autoincrement()) @id -// } -// -// enum Book_color{ -// black -// EMPTY_ENUM_VALUE @map("") -// } -// -// "#; -// -// let result = dbg!(api.introspect().await); -// custom_assert(&result, dm); -// } +//Prisma1 +//Prisma11 +//Prisma2 diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs b/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs index 2b3442402d5f..1a61b1479095 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs @@ -6,7 +6,7 @@ async fn database_description_for_mysql_should_work(api: &TestApi) { let barrel = api.barrel(); setup(&barrel, api.db_name()).await; let result = dbg!(api.get_database_description().await); - assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"raw\":\"int\",\"family\":\"int\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"raw\":\"text\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":null},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[]}".to_string()); + assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"dataType\":\"int\",\"fullDataType\":\"int(11)\",\"family\":\"int\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"dataType\":\"text\",\"fullDataType\":\"text\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":null},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[]}".to_string()); } #[test_each_connector(tags("postgres"))] @@ -14,7 +14,7 @@ async fn database_description_for_postgres_should_work(api: &TestApi) { let barrel = api.barrel(); setup(&barrel, api.schema_name()).await; let result = dbg!(api.get_database_description().await); - assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"raw\":\"int4\",\"family\":\"int\",\"arity\":\"required\"},\"default\":{\"SEQUENCE\":\"nextval(\'\\\"Blog_id_seq\\\"\'::regclass)\"},\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"raw\":\"text\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":{\"name\":\"Blog_id_seq\",\"initialValue\":1,\"allocationSize\":1}},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[{\"name\":\"Blog_id_seq\",\"initialValue\":1,\"allocationSize\":1}]}".to_string()); + assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"dataType\":\"integer\",\"fullDataType\":\"int4\",\"family\":\"int\",\"arity\":\"required\"},\"default\":{\"SEQUENCE\":\"nextval(\'\\\"Blog_id_seq\\\"\'::regclass)\"},\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"dataType\":\"text\",\"fullDataType\":\"text\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":{\"name\":\"Blog_id_seq\",\"initialValue\":1,\"allocationSize\":1}},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[{\"name\":\"Blog_id_seq\",\"initialValue\":1,\"allocationSize\":1}]}".to_string()); } #[test_each_connector(tags("sqlite"))] @@ -22,7 +22,7 @@ async fn database_description_for_sqlite_should_work(api: &TestApi) { let barrel = api.barrel(); setup(&barrel, api.schema_name()).await; let result = dbg!(api.get_database_description().await); - assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"raw\":\"INTEGER\",\"family\":\"int\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"raw\":\"TEXT\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":null},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[]}".to_string()); + assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"dataType\":\"INTEGER\",\"fullDataType\":\"INTEGER\",\"family\":\"int\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"dataType\":\"TEXT\",\"fullDataType\":\"TEXT\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":null},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[]}".to_string()); } async fn setup(barrel: &BarrelMigrationExecutor, db_name: &str) { From 7caa321165ca05e7c60ccfaa4ffa7071b9617a4e Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 May 2020 10:48:31 +0200 Subject: [PATCH 05/20] fix test failure due to differing mysql8 images --- .../tests/rpc_calls/get_database_description.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs b/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs index 1a61b1479095..52216c4cfe86 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/rpc_calls/get_database_description.rs @@ -1,7 +1,7 @@ use crate::{test_harness::*, BarrelMigrationExecutor}; use barrel::types; -#[test_each_connector(tags("mysql"))] +#[test_each_connector(tags("mysql_5_6", "mariadb"))] async fn database_description_for_mysql_should_work(api: &TestApi) { let barrel = api.barrel(); setup(&barrel, api.db_name()).await; @@ -9,6 +9,14 @@ async fn database_description_for_mysql_should_work(api: &TestApi) { assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"dataType\":\"int\",\"fullDataType\":\"int(11)\",\"family\":\"int\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"dataType\":\"text\",\"fullDataType\":\"text\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":null},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[]}".to_string()); } +#[test_each_connector(tags("mysql_8"))] +async fn database_description_for_mysql_8_should_work(api: &TestApi) { + let barrel = api.barrel(); + setup(&barrel, api.db_name()).await; + let result = dbg!(api.get_database_description().await); + assert_eq!(result, "{\"tables\":[{\"name\":\"Blog\",\"columns\":[{\"name\":\"id\",\"tpe\":{\"dataType\":\"int\",\"fullDataType\":\"int\",\"family\":\"int\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":true},{\"name\":\"string\",\"tpe\":{\"dataType\":\"text\",\"fullDataType\":\"text\",\"family\":\"string\",\"arity\":\"required\"},\"default\":null,\"autoIncrement\":false}],\"indices\":[],\"primaryKey\":{\"columns\":[\"id\"],\"sequence\":null},\"foreignKeys\":[]}],\"enums\":[],\"sequences\":[]}".to_string()); +} + #[test_each_connector(tags("postgres"))] async fn database_description_for_postgres_should_work(api: &TestApi) { let barrel = api.barrel(); From da4e49c22c292271ef59d2910c5224d0c743c7d8 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 May 2020 13:27:05 +0200 Subject: [PATCH 06/20] adjust tests to datatype / full datatype --- .../identify_version/mod.rs | 3 +- .../tests/introspection_tests.rs | 79 +++++++++++-------- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index 564a6e117e60..5c40e7edcb73 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -43,12 +43,13 @@ async fn introspect_postgres_non_prisma(api: &TestApi) { .execute(|migration| { migration.create_table("Book", |t| { t.add_column("id", types::primary()); + t.inject_custom("location point"); }); }) .await; let result = dbg!(api.introspect_version().await); - assert_eq!(result, Version::NonPrisma); + assert_eq!(result, Version::NonPrisma); //todo could also be P1 or P11 } #[test_each_connector(tags("postgres"))] diff --git a/libs/sql-schema-describer/tests/introspection_tests.rs b/libs/sql-schema-describer/tests/introspection_tests.rs index c7786840be7a..2de904e987ad 100644 --- a/libs/sql-schema-describer/tests/introspection_tests.rs +++ b/libs/sql-schema-describer/tests/introspection_tests.rs @@ -14,22 +14,38 @@ use crate::common::*; use crate::test_api::*; use prisma_value::PrismaValue; -fn int_type(db_type: SqlFamily) -> String { +fn int_full_data_type(db_type: SqlFamily) -> String { match db_type { SqlFamily::Postgres => "int4".to_string(), SqlFamily::Sqlite => "INTEGER".to_string(), + SqlFamily::Mysql => "int(11)".to_string(), + } +} + +fn int_data_type(db_type: SqlFamily) -> String { + match db_type { + SqlFamily::Postgres => "integer".to_string(), + SqlFamily::Sqlite => "INTEGER".to_string(), SqlFamily::Mysql => "int".to_string(), } } -fn varchar_type(db_type: SqlFamily, length: u64) -> String { +fn varchar_data_type(db_type: SqlFamily, length: u64) -> String { match db_type { - SqlFamily::Postgres => "varchar".to_string(), + SqlFamily::Postgres => "character varying".to_string(), SqlFamily::Mysql => "varchar".to_string(), SqlFamily::Sqlite => format!("VARCHAR({})", length), } } +fn varchar_full_data_type(db_type: SqlFamily, length: u64) -> String { + match db_type { + SqlFamily::Postgres => "varchar".to_string(), + SqlFamily::Mysql => format!("varchar({})", length), + SqlFamily::Sqlite => format!("VARCHAR({})", length), + } +} + #[test_each_connector] async fn is_required_must_work(api: &TestApi) { api.barrel() @@ -47,8 +63,8 @@ async fn is_required_must_work(api: &TestApi) { Column { name: "column1".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -58,8 +74,8 @@ async fn is_required_must_work(api: &TestApi) { Column { name: "column2".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -98,8 +114,8 @@ async fn foreign_keys_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "city".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -181,8 +197,8 @@ async fn multi_column_foreign_keys_must_work(api: &TestApi) { Column { name: "city".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -192,8 +208,8 @@ async fn multi_column_foreign_keys_must_work(api: &TestApi) { Column { name: "city_name".to_string(), tpe: ColumnType { - data_type: varchar_type(api.sql_family(), 255), - full_data_type: varchar_type(api.sql_family(), 255), + data_type: varchar_data_type(api.sql_family(), 255), + full_data_type: varchar_full_data_type(api.sql_family(), 255), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -254,8 +270,8 @@ async fn names_with_hyphens_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "column-1".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -290,17 +306,12 @@ async fn composite_primary_keys_must_work(api: &TestApi) { let schema = api.describe().await.expect("describe failed"); let table = schema.get_table("User").expect("couldn't get User table"); - let (exp_int, exp_varchar) = match api.sql_family() { - SqlFamily::Sqlite => ("INTEGER", "VARCHAR(255)"), - SqlFamily::Mysql => ("int", "varchar"), - SqlFamily::Postgres => ("int4", "varchar"), - }; let mut expected_columns = vec![ Column { name: "id".to_string(), tpe: ColumnType { - data_type: exp_int.to_string(), - full_data_type: exp_int.to_string(), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -310,8 +321,8 @@ async fn composite_primary_keys_must_work(api: &TestApi) { Column { name: "name".to_string(), tpe: ColumnType { - data_type: exp_varchar.to_string(), - full_data_type: exp_varchar.to_string(), + data_type: varchar_data_type(api.sql_family(), 255), + full_data_type: varchar_full_data_type(api.sql_family(), 255), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -357,8 +368,8 @@ async fn indices_must_work(api: &TestApi) { Column { name: "count".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -368,8 +379,8 @@ async fn indices_must_work(api: &TestApi) { Column { name: "id".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -423,8 +434,8 @@ async fn column_uniqueness_must_be_detected(api: &TestApi) { Column { name: "uniq1".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -434,8 +445,8 @@ async fn column_uniqueness_must_be_detected(api: &TestApi) { Column { name: "uniq2".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -505,8 +516,8 @@ async fn defaults_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "id".to_string(), tpe: ColumnType { - data_type: int_type(api.sql_family()), - full_data_type: int_type(api.sql_family()), + data_type: int_data_type(api.sql_family()), + full_data_type: int_full_data_type(api.sql_family()), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, From 6f9c8ba70e7c0ad0f7eec655eb3bb59a6b579453 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 May 2020 16:58:25 +0200 Subject: [PATCH 07/20] special case mysql8 --- .../tests/introspection_tests.rs | 96 ++++++++++--------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/libs/sql-schema-describer/tests/introspection_tests.rs b/libs/sql-schema-describer/tests/introspection_tests.rs index 2de904e987ad..8e3aaa8a1b0b 100644 --- a/libs/sql-schema-describer/tests/introspection_tests.rs +++ b/libs/sql-schema-describer/tests/introspection_tests.rs @@ -14,35 +14,39 @@ use crate::common::*; use crate::test_api::*; use prisma_value::PrismaValue; -fn int_full_data_type(db_type: SqlFamily) -> String { - match db_type { - SqlFamily::Postgres => "int4".to_string(), - SqlFamily::Sqlite => "INTEGER".to_string(), - SqlFamily::Mysql => "int(11)".to_string(), +fn int_full_data_type(api: &TestApi) -> String { + match (api.sql_family(), api.connector_name()) { + (SqlFamily::Postgres, _) => "int4".to_string(), + (SqlFamily::Sqlite, _) => "INTEGER".to_string(), + (SqlFamily::Mysql, "mysql8") => "int".to_string(), + (SqlFamily::Mysql, _) => "int(11)".to_string(), } } -fn int_data_type(db_type: SqlFamily) -> String { - match db_type { - SqlFamily::Postgres => "integer".to_string(), - SqlFamily::Sqlite => "INTEGER".to_string(), - SqlFamily::Mysql => "int".to_string(), +fn int_data_type(api: &TestApi) -> String { + match (api.sql_family(), api.connector_name()) { + (SqlFamily::Postgres, _) => "integer".to_string(), + (SqlFamily::Sqlite, _) => "INTEGER".to_string(), + (SqlFamily::Mysql, "mysql8") => "int".to_string(), + (SqlFamily::Mysql, _) => "int".to_string(), } } -fn varchar_data_type(db_type: SqlFamily, length: u64) -> String { - match db_type { - SqlFamily::Postgres => "character varying".to_string(), - SqlFamily::Mysql => "varchar".to_string(), - SqlFamily::Sqlite => format!("VARCHAR({})", length), +fn varchar_data_type(api: &TestApi, length: u64) -> String { + match (api.sql_family(), api.connector_name()) { + (SqlFamily::Postgres, _) => "character varying".to_string(), + (SqlFamily::Sqlite, _) => format!("VARCHAR({})", length), + (SqlFamily::Mysql, "mysql8") => "varchar".to_string(), + (SqlFamily::Mysql, _) => "varchar".to_string(), } } -fn varchar_full_data_type(db_type: SqlFamily, length: u64) -> String { - match db_type { - SqlFamily::Postgres => "varchar".to_string(), - SqlFamily::Mysql => format!("varchar({})", length), - SqlFamily::Sqlite => format!("VARCHAR({})", length), +fn varchar_full_data_type(api: &TestApi, length: u64) -> String { + match (api.sql_family(), api.connector_name()) { + (SqlFamily::Postgres, _) => "varchar".to_string(), + (SqlFamily::Sqlite, _) => format!("VARCHAR({})", length), + (SqlFamily::Mysql, "mysql8") => format!("varchar({})", length), + (SqlFamily::Mysql, _) => format!("varchar({})", length), } } @@ -63,8 +67,8 @@ async fn is_required_must_work(api: &TestApi) { Column { name: "column1".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -74,8 +78,8 @@ async fn is_required_must_work(api: &TestApi) { Column { name: "column2".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -114,8 +118,8 @@ async fn foreign_keys_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "city".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -197,8 +201,8 @@ async fn multi_column_foreign_keys_must_work(api: &TestApi) { Column { name: "city".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -208,8 +212,8 @@ async fn multi_column_foreign_keys_must_work(api: &TestApi) { Column { name: "city_name".to_string(), tpe: ColumnType { - data_type: varchar_data_type(api.sql_family(), 255), - full_data_type: varchar_full_data_type(api.sql_family(), 255), + data_type: varchar_data_type(api, 255), + full_data_type: varchar_full_data_type(api, 255), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -270,8 +274,8 @@ async fn names_with_hyphens_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "column-1".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -310,8 +314,8 @@ async fn composite_primary_keys_must_work(api: &TestApi) { Column { name: "id".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -321,8 +325,8 @@ async fn composite_primary_keys_must_work(api: &TestApi) { Column { name: "name".to_string(), tpe: ColumnType { - data_type: varchar_data_type(api.sql_family(), 255), - full_data_type: varchar_full_data_type(api.sql_family(), 255), + data_type: varchar_data_type(api, 255), + full_data_type: varchar_full_data_type(api, 255), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -368,8 +372,8 @@ async fn indices_must_work(api: &TestApi) { Column { name: "count".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -379,8 +383,8 @@ async fn indices_must_work(api: &TestApi) { Column { name: "id".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -434,8 +438,8 @@ async fn column_uniqueness_must_be_detected(api: &TestApi) { Column { name: "uniq1".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -445,8 +449,8 @@ async fn column_uniqueness_must_be_detected(api: &TestApi) { Column { name: "uniq2".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -516,8 +520,8 @@ async fn defaults_must_work(api: &TestApi) { let expected_columns = vec![Column { name: "id".to_string(), tpe: ColumnType { - data_type: int_data_type(api.sql_family()), - full_data_type: int_full_data_type(api.sql_family()), + data_type: int_data_type(api), + full_data_type: int_full_data_type(api), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, From d80bfc3eac10a8b8177e01b487f629cc5bac4c52 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 May 2020 18:52:03 +0200 Subject: [PATCH 08/20] tests and start matching on data types --- .../src/calculate_datamodel.rs | 79 +++++++---- .../identify_version/mod.rs | 134 +++++++++++++++++- libs/datamodel/core/src/dml/model.rs | 5 +- 3 files changed, 184 insertions(+), 34 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index e9432ae4c33c..0802b454b907 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -12,28 +12,43 @@ use tracing::debug; pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrospectionResult { debug!("Calculating data model."); - let has_migration_table = schema.tables.iter().any(|table| is_migration_table(&table)); + let migration_table = schema.tables.iter().any(|table| is_migration_table(&table)); let has_prisma_1_join_table = schema.tables.iter().any(|table| is_prisma_1_point_0_join_table(&table)); let has_prisma_1_1_or_2_join_table = schema .tables .iter() .any(|table| is_prisma_1_point_1_or_2_join_table(&table)); let mut uses_on_delete = false; - let mut always_has_created_at_updated_at = false; - let mut uses_non_prisma_types = false; // should check all scalar fields and needs mapping SQLFamily -> Types + let mut always_has_created_at_updated_at = true; + let mut uses_non_prisma_types = false; + //todo always specific id types, no compound ids, always an id //Currently from Migration Engine //Types positive list, complicated by enums -.- - // SQLITE Types - // "BOOLEAN","DATE","REAL","INTEGER","TEXT" - // POSTGRES Types - // Array types are only a P2 thing on Postgres - // "boolean", "timestamp(3)", "Decimal(65,30)", "integer", "text" - // native enums are only a P2 thing "ENUM_NAME" - // MYSQL Types - // "boolean","datetime(3)", "Decimal(65,30)", "int", "varchar()", - // native enums are only a P2 thing "ENUM()" + let sqlite_types = vec![ + ("BOOLEAN", "BOOLEAN"), + ("DATE", "DATE"), + ("REAL", "REAL"), + ("INTEGER", "INTEGER"), + ("TEXT", "TEXT"), + ]; + let postgres_types = vec![ + ("boolean", "bool"), + ("timestamp without time zone", "timestamp"), + ("numeric", "numeric"), + ("integer", "int4"), + ("text", "text"), + ]; + let mysql_types = vec![ + ("tinyint", "tinyint(1)"), + ("datetime", "datetime(3)"), + ("decimal", "decimal(65,30)"), + ("int", "int"), + ("int", "int(11)"), + ("varchar", "varchar(191)"), + ("text", "text"), + ]; let mut data_model = Datamodel::new(); for table in schema @@ -47,7 +62,14 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp let mut model = Model::new(table.name.clone(), None); for column in &table.columns { - // todo check actually used columntypes here + println!("DT: {}, FDT: {}", &column.tpe.data_type, &column.tpe.full_data_type); + match (&column.tpe.data_type, &column.tpe.full_data_type, family) { + (dt, fdt, SqlFamily::Postgres) if !postgres_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Mysql) if !mysql_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Sqlite) if !sqlite_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, + _ => (), + }; + let field = calculate_scalar_field(&table, &column); model.add_field(field); } @@ -83,6 +105,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp always_has_created_at_updated_at = false } + println!("{:?}", model); data_model.add_model(model); } @@ -152,12 +175,18 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp debug!("Done calculating data model {:?}", data_model); + println!("MigrationTable: {}", migration_table); + println!("UsesOnDelete: {}", uses_on_delete); + println!("UsesNonPrismaTypes: {}", uses_non_prisma_types); + println!("AlwaysCreatedAtUpdatedAt: {}", always_has_created_at_updated_at); + println!("Prisma11Or2JoinTable: {}", has_prisma_1_1_or_2_join_table); + let version = match family { - SqlFamily::Sqlite if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, + SqlFamily::Sqlite if migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Sqlite => Version::NonPrisma, - SqlFamily::Mysql if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, + SqlFamily::Mysql if migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Mysql - if !has_migration_table + if !migration_table && !uses_on_delete && !uses_non_prisma_types && always_has_created_at_updated_at @@ -166,31 +195,23 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp Version::Prisma1 } SqlFamily::Mysql - if !has_migration_table - && !uses_on_delete - && !uses_non_prisma_types - && always_has_created_at_updated_at - && !has_prisma_1_join_table => + if !migration_table && !uses_on_delete && !uses_non_prisma_types && !has_prisma_1_join_table => { Version::Prisma11 } SqlFamily::Mysql => Version::NonPrisma, - SqlFamily::Postgres if has_migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Postgres - if !has_migration_table + if !migration_table && !uses_on_delete && !uses_non_prisma_types && always_has_created_at_updated_at - && !has_prisma_1_1_or_2_join_table => + && !has_prisma_1_join_table => { Version::Prisma1 } + SqlFamily::Postgres if migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Postgres - if !has_migration_table - && !uses_on_delete - && !uses_non_prisma_types - && always_has_created_at_updated_at - && !has_prisma_1_join_table => + if !migration_table && !uses_on_delete && !uses_non_prisma_types && !has_prisma_1_1_or_2_join_table => { Version::Prisma11 } diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index 5c40e7edcb73..9e96183957ce 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -18,6 +18,24 @@ async fn introspect_sqlite_non_prisma(api: &TestApi) { assert_eq!(result, Version::NonPrisma); } +#[test_each_connector(tags("sqlite"))] +async fn introspect_sqlite_non_prisma_due_to_types(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("_Migration", |t| { + t.add_column("id", types::primary()); + }); + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("point geometric"); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::NonPrisma); +} + #[test_each_connector(tags("sqlite"))] async fn introspect_sqlite_prisma2(api: &TestApi) { api.barrel() @@ -49,7 +67,46 @@ async fn introspect_postgres_non_prisma(api: &TestApi) { .await; let result = dbg!(api.introspect_version().await); - assert_eq!(result, Version::NonPrisma); //todo could also be P1 or P11 + assert_eq!(result, Version::NonPrisma); +} + +#[test_each_connector(tags("postgres"))] +async fn introspect_postgres_prisma_1(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("createdAt timestamp(3)"); + t.inject_custom("updatedAt timestamp(3)"); + t.inject_custom("string text"); + t.inject_custom("int Integer"); + t.inject_custom("float Decimal(65,30)"); + t.inject_custom("boolean boolean"); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma1); +} + +#[test_each_connector(tags("postgres"))] +async fn introspect_postgres_prisma_1_1(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("date timestamp(3)"); + t.inject_custom("string text"); + t.inject_custom("int Integer"); + t.inject_custom("float Decimal(65,30)"); + t.inject_custom("boolean boolean"); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma11); } #[test_each_connector(tags("postgres"))] @@ -69,6 +126,75 @@ async fn introspect_postgres_prisma2(api: &TestApi) { assert_eq!(result, Version::Prisma2); } -//Prisma1 -//Prisma11 -//Prisma2 +//Mysql + +#[test_each_connector(tags("mysql"))] +async fn introspect_mysql_non_prisma(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("location point"); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::NonPrisma); +} + +#[test_each_connector(tags("mysql"))] +async fn introspect_mysql_prisma_1(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("createdAt datetime(3)"); + t.inject_custom("updatedAt datetime(3)"); + t.inject_custom("string_column text"); + t.inject_custom("integer_column int"); + t.inject_custom("float_column Decimal(65,30)"); + t.inject_custom("boolean_column boolean"); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma1); +} + +#[test_each_connector(tags("mysql"))] +async fn introspect_mysql_prisma_1_1(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + t.inject_custom("datetime_column datetime(3)"); + t.inject_custom("string_column text"); + t.inject_custom("integer_column int"); + t.inject_custom("float_column Decimal(65,30)"); + t.inject_custom("boolean_column boolean"); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma11); +} + +#[test_each_connector(tags("mysql"))] +async fn introspect_mysql_prisma2(api: &TestApi) { + api.barrel() + .execute(|migration| { + migration.create_table("_Migration", |t| { + t.add_column("id", types::primary()); + }); + migration.create_table("Book", |t| { + t.add_column("id", types::primary()); + }); + }) + .await; + + let result = dbg!(api.introspect_version().await); + assert_eq!(result, Version::Prisma2); +} diff --git a/libs/datamodel/core/src/dml/model.rs b/libs/datamodel/core/src/dml/model.rs index 45c816d1cf86..fb383c0d75f3 100644 --- a/libs/datamodel/core/src/dml/model.rs +++ b/libs/datamodel/core/src/dml/model.rs @@ -256,7 +256,10 @@ impl Model { pub fn has_created_at_and_updated_at(&self) -> bool { /// Finds a field by name. fn has_field(model: &Model, name: &str) -> bool { - match model.find_field(name) { + match model + .find_field(name) + .or(model.find_field(name.to_lowercase().as_ref())) + { Some(f) => f.field_type == FieldType::Base(ScalarType::DateTime, None), None => false, } From 24b9bf5f209458aaa70e44fdd55e7b57f8099ccd Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 6 May 2020 10:57:30 +0200 Subject: [PATCH 09/20] test fixes --- .../tests/mysql_introspection_tests.rs | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/libs/sql-schema-describer/tests/mysql_introspection_tests.rs b/libs/sql-schema-describer/tests/mysql_introspection_tests.rs index 0eb1f49d5133..507e71c1c655 100644 --- a/libs/sql-schema-describer/tests/mysql_introspection_tests.rs +++ b/libs/sql-schema-describer/tests/mysql_introspection_tests.rs @@ -64,7 +64,7 @@ async fn all_mysql_column_types_must_work() { name: "primary_col".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -76,7 +76,7 @@ async fn all_mysql_column_types_must_work() { name: "int_col".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -88,7 +88,7 @@ async fn all_mysql_column_types_must_work() { name: "smallint_col".to_string(), tpe: ColumnType { data_type: "smallint".to_string(), - full_data_type: "smallint".to_string(), + full_data_type: "smallint(6)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -100,7 +100,7 @@ async fn all_mysql_column_types_must_work() { name: "tinyint4_col".to_string(), tpe: ColumnType { data_type: "tinyint".to_string(), - full_data_type: "tinyint".to_string(), + full_data_type: "tinyint(4)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -111,7 +111,7 @@ async fn all_mysql_column_types_must_work() { name: "tinyint1_col".to_string(), tpe: ColumnType { data_type: "tinyint".to_string(), - full_data_type: "tinyint".to_string(), + full_data_type: "tinyint(1)".to_string(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::Required, }, @@ -123,7 +123,7 @@ async fn all_mysql_column_types_must_work() { name: "mediumint_col".to_string(), tpe: ColumnType { data_type: "mediumint".to_string(), - full_data_type: "mediumint".to_string(), + full_data_type: "mediumint(9)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -135,7 +135,7 @@ async fn all_mysql_column_types_must_work() { name: "bigint_col".to_string(), tpe: ColumnType { data_type: "bigint".to_string(), - full_data_type: "bigint".to_string(), + full_data_type: "bigint(20)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -147,7 +147,7 @@ async fn all_mysql_column_types_must_work() { name: "decimal_col".to_string(), tpe: ColumnType { data_type: "decimal".to_string(), - full_data_type: "decimal".to_string(), + full_data_type: "decimal(10,0)".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -159,7 +159,7 @@ async fn all_mysql_column_types_must_work() { name: "numeric_col".to_string(), tpe: ColumnType { data_type: "decimal".to_string(), - full_data_type: "decimal".to_string(), + full_data_type: "decimal(10,0)".to_string(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, }, @@ -243,7 +243,7 @@ async fn all_mysql_column_types_must_work() { name: "year_col".to_string(), tpe: ColumnType { data_type: "year".to_string(), - full_data_type: "year".to_string(), + full_data_type: "year(4)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -255,7 +255,7 @@ async fn all_mysql_column_types_must_work() { name: "char_col".to_string(), tpe: ColumnType { data_type: "char".to_string(), - full_data_type: "char".to_string(), + full_data_type: "char(1)".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -267,7 +267,7 @@ async fn all_mysql_column_types_must_work() { name: "varchar_col".to_string(), tpe: ColumnType { data_type: "varchar".to_string(), - full_data_type: "varchar".to_string(), + full_data_type: "varchar(255)".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -327,7 +327,7 @@ async fn all_mysql_column_types_must_work() { name: "enum_col".to_string(), tpe: ColumnType { data_type: "enum".to_string(), - full_data_type: "enum".to_string(), + full_data_type: "enum(\'a\',\'b\')".to_string(), family: ColumnTypeFamily::Enum("User_enum_col".into()), arity: ColumnArity::Required, }, @@ -339,7 +339,7 @@ async fn all_mysql_column_types_must_work() { name: "set_col".to_string(), tpe: ColumnType { data_type: "set".to_string(), - full_data_type: "set".to_string(), + full_data_type: "set(\'a\',\'b\')".to_string(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, }, @@ -351,7 +351,7 @@ async fn all_mysql_column_types_must_work() { name: "binary_col".to_string(), tpe: ColumnType { data_type: "binary".to_string(), - full_data_type: "binary".to_string(), + full_data_type: "binary(1)".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -363,7 +363,7 @@ async fn all_mysql_column_types_must_work() { name: "varbinary_col".to_string(), tpe: ColumnType { data_type: "varbinary".to_string(), - full_data_type: "varbinary".to_string(), + full_data_type: "varbinary(255)".to_string(), family: ColumnTypeFamily::Binary, arity: ColumnArity::Required, }, @@ -577,7 +577,7 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { name: "city".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -588,7 +588,7 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { name: "city_cascade".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -599,7 +599,7 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { name: "city_restrict".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -610,7 +610,7 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { name: "city_set_null".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, @@ -621,7 +621,7 @@ async fn mysql_foreign_key_on_delete_must_be_handled() { name: "id".to_string(), tpe: ColumnType { data_type: "int".to_string(), - full_data_type: "int".to_string(), + full_data_type: "int(11)".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, From 508f620ac0f961741394d6c1566403fc92a7bb63 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 6 May 2020 11:58:38 +0200 Subject: [PATCH 10/20] fix postgres tests --- .../tests/postgres_introspection_tests.rs | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/libs/sql-schema-describer/tests/postgres_introspection_tests.rs b/libs/sql-schema-describer/tests/postgres_introspection_tests.rs index de1b62eb1daa..2de5f678d083 100644 --- a/libs/sql-schema-describer/tests/postgres_introspection_tests.rs +++ b/libs/sql-schema-describer/tests/postgres_introspection_tests.rs @@ -69,7 +69,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_bin_col".into(), tpe: ColumnType { - data_type: "_bytea".into(), + data_type: "ARRAY".into(), full_data_type: "_bytea".into(), family: ColumnTypeFamily::Binary, arity: ColumnArity::List, @@ -80,7 +80,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_bool_col".into(), tpe: ColumnType { - data_type: "_bool".into(), + data_type: "ARRAY".into(), full_data_type: "_bool".into(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::List, @@ -91,7 +91,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_date_col".into(), tpe: ColumnType { - data_type: "_date".into(), + data_type: "ARRAY".into(), full_data_type: "_date".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::List, @@ -102,7 +102,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_double_col".into(), tpe: ColumnType { - data_type: "_float8".into(), + data_type: "ARRAY".into(), full_data_type: "_float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::List, @@ -113,7 +113,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_float_col".into(), tpe: ColumnType { - data_type: "_float8".into(), + data_type: "ARRAY".into(), full_data_type: "_float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::List, @@ -124,7 +124,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_int_col".into(), tpe: ColumnType { - data_type: "_int4".into(), + data_type: "ARRAY".into(), full_data_type: "_int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::List, @@ -135,7 +135,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_text_col".into(), tpe: ColumnType { - data_type: "_text".into(), + data_type: "ARRAY".into(), full_data_type: "_text".into(), family: ColumnTypeFamily::String, arity: ColumnArity::List, @@ -146,7 +146,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "array_varchar_col".into(), tpe: ColumnType { - data_type: "_varchar".into(), + data_type: "ARRAY".into(), full_data_type: "_varchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::List, @@ -168,7 +168,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "boolean_col".into(), tpe: ColumnType { - data_type: "bool".into(), + data_type: "boolean".into(), full_data_type: "bool".into(), family: ColumnTypeFamily::Boolean, arity: ColumnArity::Required, @@ -191,7 +191,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "double_col".into(), tpe: ColumnType { - data_type: "float8".into(), + data_type: "double precision".into(), full_data_type: "float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, @@ -203,7 +203,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "float_col".into(), tpe: ColumnType { - data_type: "float8".into(), + data_type: "double precision".into(), full_data_type: "float8".into(), family: ColumnTypeFamily::Float, arity: ColumnArity::Required, @@ -215,7 +215,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "int_col".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -227,7 +227,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "primary_col".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -254,7 +254,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "string2_col".into(), tpe: ColumnType { - data_type: "varchar".into(), + data_type: "character varying".into(), full_data_type: "varchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, @@ -266,7 +266,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bigint_col".into(), tpe: ColumnType { - data_type: "int8".into(), + data_type: "bigint".into(), full_data_type: "int8".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -278,7 +278,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bigserial_col".into(), tpe: ColumnType { - data_type: "int8".into(), + data_type: "bigint".into(), full_data_type: "int8".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -305,7 +305,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "bit_varying_col".into(), tpe: ColumnType { - data_type: "varbit".into(), + data_type: "bit varying".into(), full_data_type: "varbit".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, @@ -329,7 +329,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "char_col".into(), tpe: ColumnType { - data_type: "bpchar".into(), + data_type: "character".into(), full_data_type: "bpchar".into(), family: ColumnTypeFamily::String, arity: ColumnArity::Required, @@ -437,7 +437,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "smallint_col".into(), tpe: ColumnType { - data_type: "int2".into(), + data_type: "smallint".into(), full_data_type: "int2".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -449,7 +449,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "smallserial_col".into(), tpe: ColumnType { - data_type: "int2".into(), + data_type: "smallint".into(), full_data_type: "int2".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -464,7 +464,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "serial_col".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, @@ -479,7 +479,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "time_col".into(), tpe: ColumnType { - data_type: "time".into(), + data_type: "time without time zone".into(), full_data_type: "time".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, @@ -491,7 +491,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "time_with_zone_col".into(), tpe: ColumnType { - data_type: "timetz".into(), + data_type: "time with time zone".into(), full_data_type: "timetz".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, @@ -503,7 +503,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "timestamp_col".into(), tpe: ColumnType { - data_type: "timestamp".into(), + data_type: "timestamp without time zone".into(), full_data_type: "timestamp".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, @@ -515,7 +515,7 @@ async fn all_postgres_column_types_must_work() { Column { name: "timestamp_with_zone_col".into(), tpe: ColumnType { - data_type: "timestamptz".into(), + data_type: "timestamp with time zone".into(), full_data_type: "timestamptz".into(), family: ColumnTypeFamily::DateTime, arity: ColumnArity::Required, @@ -651,7 +651,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -662,7 +662,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_cascade".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -673,7 +673,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_restrict".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -684,7 +684,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_default".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -695,7 +695,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "city_set_null".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -706,7 +706,7 @@ async fn postgres_foreign_key_on_delete_must_be_handled() { Column { name: "id".into(), tpe: ColumnType { - data_type: "int4".into(), + data_type: "integer".into(), full_data_type: "int4".into(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, From edb0f1ccb92d91d5c0275618f7b8c8952e06c885 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 6 May 2020 15:10:32 +0200 Subject: [PATCH 11/20] adjust serialization tests --- .../resources/schema-all-column-arities.json | 9 +++-- .../schema-all-column-type-families.json | 36 ++++++++++++------- .../schema-all-foreign-key-actions.json | 15 +++++--- .../resources/schema-without-primary-key.json | 3 +- .../tests/resources/schema.json | 16 ++++----- .../tests/serialization_tests.rs | 16 ++++----- 6 files changed, 58 insertions(+), 37 deletions(-) diff --git a/libs/sql-schema-describer/tests/resources/schema-all-column-arities.json b/libs/sql-schema-describer/tests/resources/schema-all-column-arities.json index 890e82e36d1c..d047cec5e485 100644 --- a/libs/sql-schema-describer/tests/resources/schema-all-column-arities.json +++ b/libs/sql-schema-describer/tests/resources/schema-all-column-arities.json @@ -6,7 +6,8 @@ { "name": "column1", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "required" }, @@ -16,7 +17,8 @@ { "name": "column2", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, @@ -26,7 +28,8 @@ { "name": "column3", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "list" }, diff --git a/libs/sql-schema-describer/tests/resources/schema-all-column-type-families.json b/libs/sql-schema-describer/tests/resources/schema-all-column-type-families.json index 66b52c0bab72..09b6134aeeb0 100644 --- a/libs/sql-schema-describer/tests/resources/schema-all-column-type-families.json +++ b/libs/sql-schema-describer/tests/resources/schema-all-column-type-families.json @@ -6,7 +6,8 @@ { "name": "column1", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "int", "arity": "nullable" }, @@ -16,7 +17,8 @@ { "name": "column2", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "float", "arity": "nullable" }, @@ -26,7 +28,8 @@ { "name": "column3", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "boolean", "arity": "nullable" }, @@ -36,7 +39,8 @@ { "name": "column4", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "string", "arity": "nullable" }, @@ -46,7 +50,8 @@ { "name": "column5", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "dateTime", "arity": "nullable" }, @@ -56,7 +61,8 @@ { "name": "column6", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "binary", "arity": "nullable" }, @@ -66,7 +72,8 @@ { "name": "column7", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "json", "arity": "nullable" }, @@ -76,7 +83,8 @@ { "name": "column8", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "uuid", "arity": "nullable" }, @@ -86,7 +94,8 @@ { "name": "column9", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "geometric", "arity": "nullable" }, @@ -96,7 +105,8 @@ { "name": "column10", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "logSequenceNumber", "arity": "nullable" }, @@ -106,7 +116,8 @@ { "name": "column11", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "textSearch", "arity": "nullable" }, @@ -116,7 +127,8 @@ { "name": "column12", "tpe": { - "raw": "raw type", + "dataType": "raw type", + "fullDataType": "full raw type", "family": "transactionId", "arity": "nullable" }, diff --git a/libs/sql-schema-describer/tests/resources/schema-all-foreign-key-actions.json b/libs/sql-schema-describer/tests/resources/schema-all-foreign-key-actions.json index 85a1c23c68a8..fdf4d0af69db 100644 --- a/libs/sql-schema-describer/tests/resources/schema-all-foreign-key-actions.json +++ b/libs/sql-schema-describer/tests/resources/schema-all-foreign-key-actions.json @@ -6,7 +6,8 @@ { "name": "column1", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, @@ -16,7 +17,8 @@ { "name": "column2", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, @@ -26,7 +28,8 @@ { "name": "column3", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, @@ -36,7 +39,8 @@ { "name": "column4", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, @@ -46,7 +50,8 @@ { "name": "column5", "tpe": { - "raw": "int", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, diff --git a/libs/sql-schema-describer/tests/resources/schema-without-primary-key.json b/libs/sql-schema-describer/tests/resources/schema-without-primary-key.json index 5a876ef88b68..6166cfba7012 100644 --- a/libs/sql-schema-describer/tests/resources/schema-without-primary-key.json +++ b/libs/sql-schema-describer/tests/resources/schema-without-primary-key.json @@ -6,7 +6,8 @@ { "name": "column1", "tpe": { - "raw": "integer", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "nullable" }, diff --git a/libs/sql-schema-describer/tests/resources/schema.json b/libs/sql-schema-describer/tests/resources/schema.json index e36730103f0b..62106d415fa0 100644 --- a/libs/sql-schema-describer/tests/resources/schema.json +++ b/libs/sql-schema-describer/tests/resources/schema.json @@ -6,8 +6,8 @@ { "name": "column1", "tpe": { - "data_type": "integer", - "full_data_type": "integer", + "dataType": "integer", + "fullDataType": "int", "family": "int", "arity": "required" }, @@ -17,8 +17,8 @@ { "name": "column2", "tpe": { - "data_type": "varchar(255)", - "full_data_type": "varchar(255)", + "dataType": "varchar(255)", + "fullDataType": "varchar(255)", "family": "string", "arity": "nullable" }, @@ -30,8 +30,8 @@ { "name": "column3", "tpe": { - "data_type": "integer", - "full_data_type": "integer", + "dataType": "integer", + "fullDataType": "integer", "family": "int", "arity": "required" }, @@ -72,8 +72,8 @@ { "name": "id", "tpe": { - "data_type": "integer", - "full_data_type": "integer", + "dataType": "integer", + "fullDataType": "integer", "family": "int", "arity": "required" }, diff --git a/libs/sql-schema-describer/tests/serialization_tests.rs b/libs/sql-schema-describer/tests/serialization_tests.rs index 01d4655139f0..e557806937c9 100644 --- a/libs/sql-schema-describer/tests/serialization_tests.rs +++ b/libs/sql-schema-describer/tests/serialization_tests.rs @@ -28,7 +28,7 @@ fn database_schema_is_serializable() { name: "column1".to_string(), tpe: ColumnType { data_type: "integer".to_string(), - full_data_type: "integer".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Required, }, @@ -176,7 +176,7 @@ fn database_schema_is_serializable_for_every_column_type_family() { name: format!("column{}", i + 1), tpe: ColumnType { data_type: "raw type".to_string(), - full_data_type: "raw type".to_string(), + full_data_type: "full raw type".to_string(), family: family.to_owned(), arity: ColumnArity::Nullable, }, @@ -216,7 +216,7 @@ fn database_schema_is_serializable_for_every_column_arity() { .map(|(i, arity)| Column { name: format!("column{}", i + 1), tpe: ColumnType { - data_type: "int".to_string(), + data_type: "integer".to_string(), full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: arity.to_owned(), @@ -258,7 +258,7 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column1".to_string(), tpe: ColumnType { - data_type: "int".to_string(), + data_type: "integer".to_string(), full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -269,7 +269,7 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column2".to_string(), tpe: ColumnType { - data_type: "int".to_string(), + data_type: "integer".to_string(), full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -280,7 +280,7 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column3".to_string(), tpe: ColumnType { - data_type: "int".to_string(), + data_type: "integer".to_string(), full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -291,7 +291,7 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column4".to_string(), tpe: ColumnType { - data_type: "int".to_string(), + data_type: "integer".to_string(), full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, @@ -302,7 +302,7 @@ fn database_schema_is_serializable_for_every_foreign_key_action() { Column { name: "column5".to_string(), tpe: ColumnType { - data_type: "int".to_string(), + data_type: "integer".to_string(), full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, From aaa1720ec5862c5f9b0b15a3da2295a6cf21eabc Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 6 May 2020 15:38:39 +0200 Subject: [PATCH 12/20] fix --- libs/sql-schema-describer/tests/serialization_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sql-schema-describer/tests/serialization_tests.rs b/libs/sql-schema-describer/tests/serialization_tests.rs index e557806937c9..85ed5f1a05bb 100644 --- a/libs/sql-schema-describer/tests/serialization_tests.rs +++ b/libs/sql-schema-describer/tests/serialization_tests.rs @@ -127,7 +127,7 @@ fn database_schema_without_primary_key_is_serializable() { name: "column1".to_string(), tpe: ColumnType { data_type: "integer".to_string(), - full_data_type: "integer".to_string(), + full_data_type: "int".to_string(), family: ColumnTypeFamily::Int, arity: ColumnArity::Nullable, }, From e4b247d09ac05ff1b1575b987fa5bc26b74d995b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 7 May 2020 16:34:36 +0200 Subject: [PATCH 13/20] handle additional data types, list tables and relay table. --- .../src/calculate_datamodel.rs | 20 +++++++++++++------ .../src/misc_helpers.rs | 13 +++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 0802b454b907..46ee3ce92f08 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -1,5 +1,6 @@ use crate::commenting_out_guardrails::commenting_out_guardrails; use crate::misc_helpers::*; +use crate::misc_helpers::{is_prisma_1_or_11_list_table, is_relay_table}; use crate::sanitize_datamodel_names::sanitize_datamodel_names; use crate::SqlIntrospectionResult; use datamodel::{dml, Datamodel, FieldType, Model}; @@ -22,10 +23,6 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp let mut always_has_created_at_updated_at = true; let mut uses_non_prisma_types = false; - //todo always specific id types, no compound ids, always an id - //Currently from Migration Engine - //Types positive list, complicated by enums -.- - let sqlite_types = vec![ ("BOOLEAN", "BOOLEAN"), ("DATE", "DATE"), @@ -47,7 +44,13 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp ("int", "int"), ("int", "int(11)"), ("varchar", "varchar(191)"), + ("char", "char(25)"), + ("char", "char(36)"), + ("varchar", "varchar(25)"), + ("varchar", "varchar(36)"), ("text", "text"), + ("mediumtext", "mediumtext"), + ("int", "int(4)"), ]; let mut data_model = Datamodel::new(); @@ -83,8 +86,11 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp .iter() .any(|c| matches!(model_copy.find_field(c).unwrap().field_type, FieldType::Unsupported(_))) }) { + println!("{:?}", foreign_key); if foreign_key.on_delete_action != ForeignKeyAction::SetNull { - uses_on_delete = true + if !is_prisma_1_or_11_list_table(table) && foreign_key.on_delete_action != ForeignKeyAction::Cascade { + uses_on_delete = true + } } model.add_field(calculate_relation_field(schema, table, foreign_key)); } @@ -101,7 +107,8 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp model.id_fields = table.primary_key_columns(); } - if !model.has_created_at_and_updated_at() { + if !is_prisma_1_or_11_list_table(table) && !is_relay_table(table) && !model.has_created_at_and_updated_at() { + println!("Who am I: {}", table.name); always_has_created_at_updated_at = false } @@ -218,6 +225,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp SqlFamily::Postgres => Version::NonPrisma, }; + println!("VERSION: {:?}", version); Ok(IntrospectionResult { datamodel: data_model, warnings, diff --git a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs index 5e5cd48cb223..117034ebcf9a 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs @@ -9,11 +9,22 @@ use tracing::debug; //checks -//todo make this more targeted +//todo tighten this condition pub fn is_migration_table(table: &Table) -> bool { table.name == "_Migration" } +//todo tighten this condition +pub(crate) fn is_prisma_1_or_11_list_table(table: &Table) -> bool { + table.name == "_RelayId" +} + +//todo tighten this condition +pub(crate) fn is_relay_table(table: &Table) -> bool { + println!("{:?}", table); + table.columns.len() == 3 && table.indices.len() >= 1 && table.columns[0].name.to_lowercase() == "nodeid" +} + pub(crate) fn is_prisma_1_point_1_or_2_join_table(table: &Table) -> bool { table.columns.len() == 2 && table.indices.len() >= 2 && common_prisma_m_to_n_relation_conditions(table) } From 2c159c42fba55fb080a5c25ba9caed485714bb00 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 7 May 2020 17:05:58 +0200 Subject: [PATCH 14/20] conditions for relay and listtables tightened --- .../src/misc_helpers.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs index 117034ebcf9a..41f2c1808513 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs @@ -14,15 +14,18 @@ pub fn is_migration_table(table: &Table) -> bool { table.name == "_Migration" } -//todo tighten this condition -pub(crate) fn is_prisma_1_or_11_list_table(table: &Table) -> bool { +pub(crate) fn is_relay_table(table: &Table) -> bool { table.name == "_RelayId" + && table.columns[0].name == "id" + && table.columns[1].name.to_lowercase() == "stablemodelidentifier" } -//todo tighten this condition -pub(crate) fn is_relay_table(table: &Table) -> bool { - println!("{:?}", table); - table.columns.len() == 3 && table.indices.len() >= 1 && table.columns[0].name.to_lowercase() == "nodeid" +pub(crate) fn is_prisma_1_or_11_list_table(table: &Table) -> bool { + table.columns.len() == 3 + && table.indices.len() >= 1 + && table.columns[0].name.to_lowercase() == "nodeid" + && table.columns[1].name == "position" + && table.columns[2].name == "value" } pub(crate) fn is_prisma_1_point_1_or_2_join_table(table: &Table) -> bool { From 6d8bae281237055a05b09720957b18f6161680e9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 10 May 2020 12:23:43 +0200 Subject: [PATCH 15/20] check for p1 not having inline relations --- .../src/calculate_datamodel.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 46ee3ce92f08..593b5325e4d4 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -22,6 +22,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp let mut uses_on_delete = false; let mut always_has_created_at_updated_at = true; let mut uses_non_prisma_types = false; + let mut has_inline_relations = false; let sqlite_types = vec![ ("BOOLEAN", "BOOLEAN"), @@ -30,6 +31,8 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp ("INTEGER", "INTEGER"), ("TEXT", "TEXT"), ]; + + //todo postgres p1 or p11 tests let postgres_types = vec![ ("boolean", "bool"), ("timestamp without time zone", "timestamp"), @@ -86,7 +89,9 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp .iter() .any(|c| matches!(model_copy.find_field(c).unwrap().field_type, FieldType::Unsupported(_))) }) { - println!("{:?}", foreign_key); + if !is_prisma_1_or_11_list_table(table) { + has_inline_relations = true; + } if foreign_key.on_delete_action != ForeignKeyAction::SetNull { if !is_prisma_1_or_11_list_table(table) && foreign_key.on_delete_action != ForeignKeyAction::Cascade { uses_on_delete = true @@ -108,11 +113,9 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp } if !is_prisma_1_or_11_list_table(table) && !is_relay_table(table) && !model.has_created_at_and_updated_at() { - println!("Who am I: {}", table.name); always_has_created_at_updated_at = false } - println!("{:?}", model); data_model.add_model(model); } @@ -185,6 +188,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp println!("MigrationTable: {}", migration_table); println!("UsesOnDelete: {}", uses_on_delete); println!("UsesNonPrismaTypes: {}", uses_non_prisma_types); + println!("HasInlineRelations: {}", has_inline_relations); println!("AlwaysCreatedAtUpdatedAt: {}", always_has_created_at_updated_at); println!("Prisma11Or2JoinTable: {}", has_prisma_1_1_or_2_join_table); @@ -197,7 +201,8 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp && !uses_on_delete && !uses_non_prisma_types && always_has_created_at_updated_at - && !has_prisma_1_1_or_2_join_table => + && !has_prisma_1_1_or_2_join_table + && !has_inline_relations => { Version::Prisma1 } @@ -212,7 +217,8 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp && !uses_on_delete && !uses_non_prisma_types && always_has_created_at_updated_at - && !has_prisma_1_join_table => + && !has_prisma_1_join_table + && !has_inline_relations => { Version::Prisma1 } From b9fbe614952512a5359f3a1f78e65666fb76a9e0 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 May 2020 09:02:24 +0200 Subject: [PATCH 16/20] add tests, consider warnings, consider inline relation tables --- .../src/calculate_datamodel.rs | 35 ++++++++++++++----- .../src/misc_helpers.rs | 1 - .../identify_version/mod.rs | 35 +++++++++++++++++++ 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 593b5325e4d4..1bdb61e0cb12 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -92,7 +92,10 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp if !is_prisma_1_or_11_list_table(table) { has_inline_relations = true; } - if foreign_key.on_delete_action != ForeignKeyAction::SetNull { + println!("{:?}", foreign_key.on_delete_action); + if !(foreign_key.on_delete_action == ForeignKeyAction::NoAction + || foreign_key.on_delete_action == ForeignKeyAction::SetNull) + { if !is_prisma_1_or_11_list_table(table) && foreign_key.on_delete_action != ForeignKeyAction::Cascade { uses_on_delete = true } @@ -193,38 +196,54 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp println!("Prisma11Or2JoinTable: {}", has_prisma_1_1_or_2_join_table); let version = match family { - SqlFamily::Sqlite if migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, + SqlFamily::Sqlite if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { + Version::Prisma2 + } SqlFamily::Sqlite => Version::NonPrisma, - SqlFamily::Mysql if migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, + SqlFamily::Mysql if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { + Version::Prisma2 + } SqlFamily::Mysql if !migration_table && !uses_on_delete && !uses_non_prisma_types && always_has_created_at_updated_at && !has_prisma_1_1_or_2_join_table - && !has_inline_relations => + && !has_inline_relations + && warnings.is_empty() => { Version::Prisma1 } SqlFamily::Mysql - if !migration_table && !uses_on_delete && !uses_non_prisma_types && !has_prisma_1_join_table => + if !migration_table + && !uses_on_delete + && !uses_non_prisma_types + && !has_prisma_1_join_table + && warnings.is_empty() => { Version::Prisma11 } SqlFamily::Mysql => Version::NonPrisma, + SqlFamily::Postgres if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { + Version::Prisma2 + } SqlFamily::Postgres if !migration_table && !uses_on_delete && !uses_non_prisma_types && always_has_created_at_updated_at && !has_prisma_1_join_table - && !has_inline_relations => + && !has_inline_relations + && warnings.is_empty() => { Version::Prisma1 } - SqlFamily::Postgres if migration_table && !uses_on_delete && !uses_non_prisma_types => Version::Prisma2, SqlFamily::Postgres - if !migration_table && !uses_on_delete && !uses_non_prisma_types && !has_prisma_1_1_or_2_join_table => + if !migration_table + && !uses_on_delete + && !uses_non_prisma_types + && !has_prisma_1_1_or_2_join_table + && warnings.is_empty() => { Version::Prisma11 } diff --git a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs index 41f2c1808513..dee20ebc6535 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs @@ -22,7 +22,6 @@ pub(crate) fn is_relay_table(table: &Table) -> bool { pub(crate) fn is_prisma_1_or_11_list_table(table: &Table) -> bool { table.columns.len() == 3 - && table.indices.len() >= 1 && table.columns[0].name.to_lowercase() == "nodeid" && table.columns[1].name == "position" && table.columns[2].name == "value" diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index 9e96183957ce..779715224ee6 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -83,6 +83,17 @@ async fn introspect_postgres_prisma_1(api: &TestApi) { t.inject_custom("float Decimal(65,30)"); t.inject_custom("boolean boolean"); }); + migration.create_table("_RelayId", |t| { + t.add_column("id", types::primary()); + t.inject_custom("stableModelIdentifier Integer"); + }); + + migration.create_table("Book_tags", |t| { + t.add_column("nodeid", types::primary()); + t.add_column("position", types::integer()); + t.add_column("value", types::integer()); + t.inject_custom("FOREIGN KEY (\"nodeid\") REFERENCES \"Book\"(\"id\")"); + }); }) .await; @@ -102,6 +113,18 @@ async fn introspect_postgres_prisma_1_1(api: &TestApi) { t.inject_custom("float Decimal(65,30)"); t.inject_custom("boolean boolean"); }); + + migration.create_table("Page", |t| { + t.add_column("id", types::primary()); + t.inject_custom("string text"); + t.add_column("bookid", types::integer()); + t.inject_custom("FOREIGN KEY (\"bookid\") REFERENCES \"Book\"(\"id\")"); + }); + + migration.create_table("_RelayId", |t| { + t.add_column("id", types::primary()); + t.inject_custom("stableModelIdentifier Integer"); + }); }) .await; @@ -156,6 +179,12 @@ async fn introspect_mysql_prisma_1(api: &TestApi) { t.inject_custom("float_column Decimal(65,30)"); t.inject_custom("boolean_column boolean"); }); + migration.create_table("_RelayId", |t| { + t.add_column("id", types::primary()); + t.inject_custom("stableModelIdentifier int"); + }); + + //todo scalar list table }) .await; @@ -175,6 +204,12 @@ async fn introspect_mysql_prisma_1_1(api: &TestApi) { t.inject_custom("float_column Decimal(65,30)"); t.inject_custom("boolean_column boolean"); }); + migration.create_table("_RelayId", |t| { + t.add_column("id", types::primary()); + t.inject_custom("stableModelIdentifier int"); + }); + + //todo inline relation table }) .await; From d4a8b8d8e110af8bd2430453bd1d0f84ac146185 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 May 2020 10:16:00 +0200 Subject: [PATCH 17/20] clean ups --- .../src/calculate_datamodel.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 1bdb61e0cb12..5100fe0005d2 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -32,7 +32,6 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp ("TEXT", "TEXT"), ]; - //todo postgres p1 or p11 tests let postgres_types = vec![ ("boolean", "bool"), ("timestamp without time zone", "timestamp"), @@ -68,7 +67,6 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp let mut model = Model::new(table.name.clone(), None); for column in &table.columns { - println!("DT: {}, FDT: {}", &column.tpe.data_type, &column.tpe.full_data_type); match (&column.tpe.data_type, &column.tpe.full_data_type, family) { (dt, fdt, SqlFamily::Postgres) if !postgres_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, (dt, fdt, SqlFamily::Mysql) if !mysql_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, @@ -92,7 +90,6 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp if !is_prisma_1_or_11_list_table(table) { has_inline_relations = true; } - println!("{:?}", foreign_key.on_delete_action); if !(foreign_key.on_delete_action == ForeignKeyAction::NoAction || foreign_key.on_delete_action == ForeignKeyAction::SetNull) { @@ -187,14 +184,6 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp deduplicate_field_names(&mut data_model); debug!("Done calculating data model {:?}", data_model); - - println!("MigrationTable: {}", migration_table); - println!("UsesOnDelete: {}", uses_on_delete); - println!("UsesNonPrismaTypes: {}", uses_non_prisma_types); - println!("HasInlineRelations: {}", has_inline_relations); - println!("AlwaysCreatedAtUpdatedAt: {}", always_has_created_at_updated_at); - println!("Prisma11Or2JoinTable: {}", has_prisma_1_1_or_2_join_table); - let version = match family { SqlFamily::Sqlite if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { Version::Prisma2 @@ -250,7 +239,6 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp SqlFamily::Postgres => Version::NonPrisma, }; - println!("VERSION: {:?}", version); Ok(IntrospectionResult { datamodel: data_model, warnings, From f25e0d3013175ccf36de0200cd437eeb0fcb9ed7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 May 2020 11:47:02 +0200 Subject: [PATCH 18/20] more cleanups --- .../sql-introspection-connector/src/calculate_datamodel.rs | 1 + .../sql-introspection-connector/src/misc_helpers.rs | 1 - .../tests/db_specific_introspection/identify_version/mod.rs | 4 ---- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 5100fe0005d2..25ce9c25f015 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -13,6 +13,7 @@ use tracing::debug; pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrospectionResult { debug!("Calculating data model."); + // Detect the version of the database let migration_table = schema.tables.iter().any(|table| is_migration_table(&table)); let has_prisma_1_join_table = schema.tables.iter().any(|table| is_prisma_1_point_0_join_table(&table)); let has_prisma_1_1_or_2_join_table = schema diff --git a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs index dee20ebc6535..2b1b79afaeab 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/misc_helpers.rs @@ -9,7 +9,6 @@ use tracing::debug; //checks -//todo tighten this condition pub fn is_migration_table(table: &Table) -> bool { table.name == "_Migration" } diff --git a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs index 779715224ee6..45f1f9ee0f8a 100644 --- a/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs +++ b/introspection-engine/connectors/sql-introspection-connector/tests/db_specific_introspection/identify_version/mod.rs @@ -183,8 +183,6 @@ async fn introspect_mysql_prisma_1(api: &TestApi) { t.add_column("id", types::primary()); t.inject_custom("stableModelIdentifier int"); }); - - //todo scalar list table }) .await; @@ -208,8 +206,6 @@ async fn introspect_mysql_prisma_1_1(api: &TestApi) { t.add_column("id", types::primary()); t.inject_custom("stableModelIdentifier int"); }); - - //todo inline relation table }) .await; From ad65bc29552243f7b0da5d126329faffeb88eb61 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 May 2020 14:47:57 +0200 Subject: [PATCH 19/20] cleanup idea after review --- .../src/calculate_datamodel.rs | 127 +------------ .../sql-introspection-connector/src/lib.rs | 1 + .../src/version_checker.rs | 169 ++++++++++++++++++ libs/datamodel/core/src/dml/model.rs | 2 +- 4 files changed, 179 insertions(+), 120 deletions(-) create mode 100644 introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs diff --git a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs index 25ce9c25f015..bf98fcfbcffd 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/calculate_datamodel.rs @@ -1,10 +1,10 @@ use crate::commenting_out_guardrails::commenting_out_guardrails; use crate::misc_helpers::*; -use crate::misc_helpers::{is_prisma_1_or_11_list_table, is_relay_table}; use crate::sanitize_datamodel_names::sanitize_datamodel_names; +use crate::version_checker::VersionChecker; use crate::SqlIntrospectionResult; use datamodel::{dml, Datamodel, FieldType, Model}; -use introspection_connector::{IntrospectionResult, Version}; +use introspection_connector::IntrospectionResult; use quaint::connector::SqlFamily; use sql_schema_describer::*; use tracing::debug; @@ -13,48 +13,7 @@ use tracing::debug; pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrospectionResult { debug!("Calculating data model."); - // Detect the version of the database - let migration_table = schema.tables.iter().any(|table| is_migration_table(&table)); - let has_prisma_1_join_table = schema.tables.iter().any(|table| is_prisma_1_point_0_join_table(&table)); - let has_prisma_1_1_or_2_join_table = schema - .tables - .iter() - .any(|table| is_prisma_1_point_1_or_2_join_table(&table)); - let mut uses_on_delete = false; - let mut always_has_created_at_updated_at = true; - let mut uses_non_prisma_types = false; - let mut has_inline_relations = false; - - let sqlite_types = vec![ - ("BOOLEAN", "BOOLEAN"), - ("DATE", "DATE"), - ("REAL", "REAL"), - ("INTEGER", "INTEGER"), - ("TEXT", "TEXT"), - ]; - - let postgres_types = vec![ - ("boolean", "bool"), - ("timestamp without time zone", "timestamp"), - ("numeric", "numeric"), - ("integer", "int4"), - ("text", "text"), - ]; - let mysql_types = vec![ - ("tinyint", "tinyint(1)"), - ("datetime", "datetime(3)"), - ("decimal", "decimal(65,30)"), - ("int", "int"), - ("int", "int(11)"), - ("varchar", "varchar(191)"), - ("char", "char(25)"), - ("char", "char(36)"), - ("varchar", "varchar(25)"), - ("varchar", "varchar(36)"), - ("text", "text"), - ("mediumtext", "mediumtext"), - ("int", "int(4)"), - ]; + let mut version_check = VersionChecker::new(family.clone(), schema); let mut data_model = Datamodel::new(); for table in schema @@ -68,13 +27,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp let mut model = Model::new(table.name.clone(), None); for column in &table.columns { - match (&column.tpe.data_type, &column.tpe.full_data_type, family) { - (dt, fdt, SqlFamily::Postgres) if !postgres_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, - (dt, fdt, SqlFamily::Mysql) if !mysql_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, - (dt, fdt, SqlFamily::Sqlite) if !sqlite_types.contains(&(dt, fdt)) => uses_non_prisma_types = true, - _ => (), - }; - + version_check.uses_non_prisma_type(&column.tpe); let field = calculate_scalar_field(&table, &column); model.add_field(field); } @@ -88,16 +41,8 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp .iter() .any(|c| matches!(model_copy.find_field(c).unwrap().field_type, FieldType::Unsupported(_))) }) { - if !is_prisma_1_or_11_list_table(table) { - has_inline_relations = true; - } - if !(foreign_key.on_delete_action == ForeignKeyAction::NoAction - || foreign_key.on_delete_action == ForeignKeyAction::SetNull) - { - if !is_prisma_1_or_11_list_table(table) && foreign_key.on_delete_action != ForeignKeyAction::Cascade { - uses_on_delete = true - } - } + version_check.has_inline_relations(table); + version_check.uses_on_delete(foreign_key, table); model.add_field(calculate_relation_field(schema, table, foreign_key)); } @@ -113,9 +58,7 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp model.id_fields = table.primary_key_columns(); } - if !is_prisma_1_or_11_list_table(table) && !is_relay_table(table) && !model.has_created_at_and_updated_at() { - always_has_created_at_updated_at = false - } + version_check.always_has_created_at_updated_at(table, &model); data_model.add_model(model); } @@ -185,65 +128,11 @@ pub fn calculate_datamodel(schema: &SqlSchema, family: &SqlFamily) -> SqlIntrosp deduplicate_field_names(&mut data_model); debug!("Done calculating data model {:?}", data_model); - let version = match family { - SqlFamily::Sqlite if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { - Version::Prisma2 - } - SqlFamily::Sqlite => Version::NonPrisma, - SqlFamily::Mysql if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { - Version::Prisma2 - } - SqlFamily::Mysql - if !migration_table - && !uses_on_delete - && !uses_non_prisma_types - && always_has_created_at_updated_at - && !has_prisma_1_1_or_2_join_table - && !has_inline_relations - && warnings.is_empty() => - { - Version::Prisma1 - } - SqlFamily::Mysql - if !migration_table - && !uses_on_delete - && !uses_non_prisma_types - && !has_prisma_1_join_table - && warnings.is_empty() => - { - Version::Prisma11 - } - SqlFamily::Mysql => Version::NonPrisma, - SqlFamily::Postgres if migration_table && !uses_on_delete && !uses_non_prisma_types && warnings.is_empty() => { - Version::Prisma2 - } - SqlFamily::Postgres - if !migration_table - && !uses_on_delete - && !uses_non_prisma_types - && always_has_created_at_updated_at - && !has_prisma_1_join_table - && !has_inline_relations - && warnings.is_empty() => - { - Version::Prisma1 - } - SqlFamily::Postgres - if !migration_table - && !uses_on_delete - && !uses_non_prisma_types - && !has_prisma_1_1_or_2_join_table - && warnings.is_empty() => - { - Version::Prisma11 - } - SqlFamily::Postgres => Version::NonPrisma, - }; Ok(IntrospectionResult { datamodel: data_model, + version: version_check.version(&warnings), warnings, - version, }) } diff --git a/introspection-engine/connectors/sql-introspection-connector/src/lib.rs b/introspection-engine/connectors/sql-introspection-connector/src/lib.rs index 6d0318fd9224..3f2cee58318c 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/lib.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/lib.rs @@ -4,6 +4,7 @@ mod error; mod misc_helpers; mod sanitize_datamodel_names; mod schema_describer_loading; +mod version_checker; use introspection_connector::{ ConnectorError, ConnectorResult, DatabaseMetadata, IntrospectionConnector, IntrospectionResult, diff --git a/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs b/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs new file mode 100644 index 000000000000..e490ec41fc9e --- /dev/null +++ b/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs @@ -0,0 +1,169 @@ +use crate::misc_helpers::{ + is_migration_table, is_prisma_1_or_11_list_table, is_prisma_1_point_0_join_table, + is_prisma_1_point_1_or_2_join_table, is_relay_table, +}; +use datamodel::Model; +use introspection_connector::{Version, Warning}; +use quaint::connector::SqlFamily; +use sql_schema_describer::{ColumnType, ForeignKey, ForeignKeyAction, SqlSchema, Table}; + +pub struct VersionChecker { + sql_family: SqlFamily, + migration_table: bool, + has_prisma_1_join_table: bool, + has_prisma_1_1_or_2_join_table: bool, + uses_on_delete: bool, + always_has_created_at_updated_at: bool, + uses_non_prisma_types: bool, + has_inline_relations: bool, +} + +impl VersionChecker { + pub fn new(sql_family: SqlFamily, schema: &SqlSchema) -> VersionChecker { + VersionChecker { + sql_family, + migration_table: schema.tables.iter().any(|table| is_migration_table(&table)), + has_prisma_1_join_table: schema.tables.iter().any(|table| is_prisma_1_point_0_join_table(&table)), + has_prisma_1_1_or_2_join_table: schema + .tables + .iter() + .any(|table| is_prisma_1_point_1_or_2_join_table(&table)), + uses_on_delete: false, + always_has_created_at_updated_at: true, + uses_non_prisma_types: false, + has_inline_relations: false, + } + } + + pub fn uses_non_prisma_type(&mut self, tpe: &ColumnType) { + let sqlite_types = vec![ + ("BOOLEAN", "BOOLEAN"), + ("DATE", "DATE"), + ("REAL", "REAL"), + ("INTEGER", "INTEGER"), + ("TEXT", "TEXT"), + ]; + + let postgres_types = vec![ + ("boolean", "bool"), + ("timestamp without time zone", "timestamp"), + ("numeric", "numeric"), + ("integer", "int4"), + ("text", "text"), + ]; + let mysql_types = vec![ + ("tinyint", "tinyint(1)"), + ("datetime", "datetime(3)"), + ("decimal", "decimal(65,30)"), + ("int", "int"), + ("int", "int(11)"), + ("varchar", "varchar(191)"), + ("char", "char(25)"), + ("char", "char(36)"), + ("varchar", "varchar(25)"), + ("varchar", "varchar(36)"), + ("text", "text"), + ("mediumtext", "mediumtext"), + ("int", "int(4)"), + ]; + + match (&tpe.data_type, &tpe.full_data_type, self.sql_family) { + (dt, fdt, SqlFamily::Postgres) if !postgres_types.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Mysql) if !mysql_types.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Sqlite) if !sqlite_types.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, + _ => (), + }; + } + + pub fn has_inline_relations(&mut self, table: &Table) { + if !is_prisma_1_or_11_list_table(table) { + self.has_inline_relations = true; + } + } + + pub fn uses_on_delete(&mut self, fk: &ForeignKey, table: &Table) { + if !(fk.on_delete_action == ForeignKeyAction::NoAction || fk.on_delete_action == ForeignKeyAction::SetNull) { + if !is_prisma_1_or_11_list_table(table) && fk.on_delete_action != ForeignKeyAction::Cascade { + self.uses_on_delete = true + } + } + } + + pub fn always_has_created_at_updated_at(&mut self, table: &Table, model: &Model) { + if !is_prisma_1_or_11_list_table(table) && !is_relay_table(table) && !model.has_created_at_and_updated_at() { + self.always_has_created_at_updated_at = false + } + } + + pub fn version(&self, warnings: &Vec) -> Version { + match self.sql_family { + SqlFamily::Sqlite + if self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && warnings.is_empty() => + { + Version::Prisma2 + } + SqlFamily::Sqlite => Version::NonPrisma, + SqlFamily::Mysql + if self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && warnings.is_empty() => + { + Version::Prisma2 + } + SqlFamily::Mysql + if !self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && self.always_has_created_at_updated_at + && !self.has_prisma_1_1_or_2_join_table + && !self.has_inline_relations + && warnings.is_empty() => + { + Version::Prisma1 + } + SqlFamily::Mysql + if !self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && !self.has_prisma_1_join_table + && warnings.is_empty() => + { + Version::Prisma11 + } + SqlFamily::Mysql => Version::NonPrisma, + SqlFamily::Postgres + if self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && warnings.is_empty() => + { + Version::Prisma2 + } + SqlFamily::Postgres + if !self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && self.always_has_created_at_updated_at + && !self.has_prisma_1_join_table + && !self.has_inline_relations + && warnings.is_empty() => + { + Version::Prisma1 + } + SqlFamily::Postgres + if !self.migration_table + && !self.uses_on_delete + && !self.uses_non_prisma_types + && !self.has_prisma_1_1_or_2_join_table + && warnings.is_empty() => + { + Version::Prisma11 + } + SqlFamily::Postgres => Version::NonPrisma, + } + } +} diff --git a/libs/datamodel/core/src/dml/model.rs b/libs/datamodel/core/src/dml/model.rs index fb383c0d75f3..396966534aae 100644 --- a/libs/datamodel/core/src/dml/model.rs +++ b/libs/datamodel/core/src/dml/model.rs @@ -258,7 +258,7 @@ impl Model { fn has_field(model: &Model, name: &str) -> bool { match model .find_field(name) - .or(model.find_field(name.to_lowercase().as_ref())) + .or_else(|| model.find_field(name.to_lowercase().as_ref())) { Some(f) => f.field_type == FieldType::Base(ScalarType::DateTime, None), None => false, From cea5a6932fd99f8c7212ab1cf7c681bbf3034b0d Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 11 May 2020 14:57:10 +0200 Subject: [PATCH 20/20] types as const --- .../src/version_checker.rs | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs b/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs index e490ec41fc9e..8578bb96b2c3 100644 --- a/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs +++ b/introspection-engine/connectors/sql-introspection-connector/src/version_checker.rs @@ -18,6 +18,37 @@ pub struct VersionChecker { has_inline_relations: bool, } +const SQLITE_TYPES: [(&'static str, &'static str); 5] = [ + ("BOOLEAN", "BOOLEAN"), + ("DATE", "DATE"), + ("REAL", "REAL"), + ("INTEGER", "INTEGER"), + ("TEXT", "TEXT"), +]; + +const POSTGRES_TYPES: [(&'static str, &'static str); 5] = [ + ("boolean", "bool"), + ("timestamp without time zone", "timestamp"), + ("numeric", "numeric"), + ("integer", "int4"), + ("text", "text"), +]; +const MYSQL_TYPES: [(&'static str, &'static str); 13] = [ + ("tinyint", "tinyint(1)"), + ("datetime", "datetime(3)"), + ("decimal", "decimal(65,30)"), + ("int", "int"), + ("int", "int(11)"), + ("varchar", "varchar(191)"), + ("char", "char(25)"), + ("char", "char(36)"), + ("varchar", "varchar(25)"), + ("varchar", "varchar(36)"), + ("text", "text"), + ("mediumtext", "mediumtext"), + ("int", "int(4)"), +]; + impl VersionChecker { pub fn new(sql_family: SqlFamily, schema: &SqlSchema) -> VersionChecker { VersionChecker { @@ -36,41 +67,10 @@ impl VersionChecker { } pub fn uses_non_prisma_type(&mut self, tpe: &ColumnType) { - let sqlite_types = vec![ - ("BOOLEAN", "BOOLEAN"), - ("DATE", "DATE"), - ("REAL", "REAL"), - ("INTEGER", "INTEGER"), - ("TEXT", "TEXT"), - ]; - - let postgres_types = vec![ - ("boolean", "bool"), - ("timestamp without time zone", "timestamp"), - ("numeric", "numeric"), - ("integer", "int4"), - ("text", "text"), - ]; - let mysql_types = vec![ - ("tinyint", "tinyint(1)"), - ("datetime", "datetime(3)"), - ("decimal", "decimal(65,30)"), - ("int", "int"), - ("int", "int(11)"), - ("varchar", "varchar(191)"), - ("char", "char(25)"), - ("char", "char(36)"), - ("varchar", "varchar(25)"), - ("varchar", "varchar(36)"), - ("text", "text"), - ("mediumtext", "mediumtext"), - ("int", "int(4)"), - ]; - match (&tpe.data_type, &tpe.full_data_type, self.sql_family) { - (dt, fdt, SqlFamily::Postgres) if !postgres_types.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, - (dt, fdt, SqlFamily::Mysql) if !mysql_types.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, - (dt, fdt, SqlFamily::Sqlite) if !sqlite_types.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Postgres) if !POSTGRES_TYPES.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Mysql) if !MYSQL_TYPES.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, + (dt, fdt, SqlFamily::Sqlite) if !SQLITE_TYPES.contains(&(dt, fdt)) => self.uses_non_prisma_types = true, _ => (), }; }