From 36f92fe21d1f83d8e47fa7d662ab64ddcff6e493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Houl=C3=A9?= <13155277+tomhoule@users.noreply.github.com> Date: Wed, 23 Aug 2023 13:20:31 +0200 Subject: [PATCH] query-tests-setup: lift constraints on ConnectorTag (#4159) In the effort to run connector-test-kit-rs with the new node-based drivers, we want to dispatch requests to an external process when running the query engine test suite. This is naturally implemented with a new type that shells out to that external process to implement `ConnectorTagInterface`. Since we do not want to start a new process every time `ConnectorTag::try_from()` is called (at least once per test) and we are going to want asynchronous communication with the child process (required by some tests), we have to change the entry points that construct `ConnectorTag`s. We will need either a static method on `ConnectorTagInterface` (forbidden by enum_dispatch) or separate connector instantiation (sync, from the tag strings) from initialization (async, will involve IO). Changes in this PR ================== The first entry point is the `TryFrom<(&str, Option<&str>)>` impl for `ConnectorTag`. It is replaced by a `TryFrom<(&str, Option<&str>)>` impl for `ConnectorVersion`. There is no longer a shared responsibility: `ConnectorVersion` is the exhaustive view of the connectors to test that the test suite knows about, and `ConnectorTagInterface` is a bag of connector-specific functions. This lets us remove the `enum_dispatch` dependency, which helps because it was another thing preventing defining static methods on `ConnectorTagInterface`. The second entrypoint is `ConnectorTag::all()`, which turned out to be dead code, so this commit removes it. If you look at the diff, these two changes add up to a nice amount of deleted code in query-tests-setup, and more importantly, a less constraining interface to implement for a connector tag that will need async initialization. --- Cargo.lock | 13 - .../query-engine-tests/src/utils/querying.rs | 2 +- .../tests/new/interactive_tx.rs | 4 +- .../query-engine-tests/tests/new/metrics.rs | 2 +- .../query-engine-tests/tests/new/occ.rs | 2 +- .../tests/new/regressions/prisma_15607.rs | 9 +- .../filters/field_reference/json_filter.rs | 2 +- .../queries/filters/insensitive_filters.rs | 4 +- .../tests/queries/filters/json_filters.rs | 4 +- .../order_by_dependent.rs | 4 +- .../order_by_dependent_pagination.rs | 6 +- .../query-engine-tests/tests/queries/views.rs | 14 +- .../writes/top_level_mutations/update_many.rs | 4 +- .../query-tests-setup/Cargo.toml | 1 - .../query-tests-setup/src/config.rs | 39 +- .../src/connector_tag/cockroachdb.rs | 83 +--- .../src/connector_tag/mod.rs | 355 ++++++++++++------ .../src/connector_tag/mongodb.rs | 89 +---- .../src/connector_tag/mysql.rs | 91 +---- .../src/connector_tag/postgres.rs | 126 +------ .../src/connector_tag/sql_server.rs | 93 +---- .../src/connector_tag/sqlite.rs | 46 +-- .../src/connector_tag/vitess.rs | 74 +--- .../src/datamodel_rendering/mod.rs | 12 +- .../query-tests-setup/src/lib.rs | 23 +- .../query-tests-setup/src/runner/mod.rs | 15 +- query-engine/js-connectors/src/proxy.rs | 11 +- .../tests/test_api/mod.rs | 2 +- 28 files changed, 397 insertions(+), 733 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 535adb0d320f..027ea5ddc862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1149,18 +1149,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "enum_dispatch" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.28", -] - [[package]] name = "enumflags2" version = "0.7.7" @@ -3693,7 +3681,6 @@ version = "0.1.0" dependencies = [ "async-trait", "colored", - "enum_dispatch", "enumflags2", "hyper", "indexmap 1.9.3", diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/src/utils/querying.rs b/query-engine/connector-test-kit-rs/query-engine-tests/src/utils/querying.rs index 7be12336f366..ac77c6f77d84 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/src/utils/querying.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/src/utils/querying.rs @@ -14,7 +14,7 @@ macro_rules! match_connector_result { let connector = $runner.connector_version(); - let mut results = match connector { + let mut results = match &connector { $( $( $matcher )|+ $( if $pred )? => $result ),* diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/interactive_tx.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/interactive_tx.rs index 7442b1172265..1a6523986f4c 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/interactive_tx.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/interactive_tx.rs @@ -233,7 +233,7 @@ mod interactive_tx { let res = runner.commit_tx(tx_id.clone()).await?; - if matches!(runner.connector(), ConnectorTag::MongoDb(_)) { + if matches!(runner.connector_version(), ConnectorVersion::MongoDb(_)) { assert!(res.is_err()); let err = res.err().unwrap(); let known_err = err.as_known().unwrap(); @@ -248,7 +248,7 @@ mod interactive_tx { &runner, "query { findManyTestModel { id }}", // Postgres and Mongo abort transactions, data is lost. - Postgres(_) | MongoDb(_) | CockroachDb => vec![r#"{"data":{"findManyTestModel":[]}}"#], + Postgres(_) | MongoDb(_) | CockroachDb(_) => vec![r#"{"data":{"findManyTestModel":[]}}"#], // Partial data still there because a batch will not be auto-rolled back by other connectors. _ => vec![r#"{"data":{"findManyTestModel":[{"id":1},{"id":2}]}}"#] ); diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/metrics.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/metrics.rs index 04e2830146e7..260fd58e61fd 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/metrics.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/metrics.rs @@ -30,7 +30,7 @@ mod metrics { Sqlite => assert_eq!(total_queries, 9), SqlServer(_) => assert_eq!(total_queries, 17), MongoDb(_) => assert_eq!(total_queries, 5), - CockroachDb => (), // not deterministic + CockroachDb(_) => (), // not deterministic MySql(_) => assert_eq!(total_queries, 12), Vitess(_) => assert_eq!(total_queries, 11), Postgres(_) => assert_eq!(total_queries, 7), diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/occ.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/occ.rs index 242ff691d9ec..dc247f98f948 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/occ.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/occ.rs @@ -246,7 +246,7 @@ mod occ { // MongoDB is different here and seems to only do one create with all the upserts // where as all the sql databases will do one create and one upsert - let expected = if matches!(runner.connector(), ConnectorTag::MongoDb(_)) { + let expected = if matches!(runner.connector_version(), ConnectorVersion::MongoDb(_)) { serde_json::json!({ "data": { "findFirstResource": { diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/prisma_15607.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/prisma_15607.rs index 870b0fc23376..3ab34b12010a 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/prisma_15607.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/prisma_15607.rs @@ -5,8 +5,8 @@ use indoc::indoc; use query_engine_tests::{ - query_core::TxId, render_test_datamodel, setup_metrics, test_tracing_subscriber, ConnectorTag, LogEmit, - QueryResult, Runner, TestError, TestLogCapture, TestResult, TryFrom, WithSubscriber, CONFIG, ENV_LOG_LEVEL, + query_core::TxId, render_test_datamodel, setup_metrics, test_tracing_subscriber, LogEmit, QueryResult, Runner, + TestError, TestLogCapture, TestResult, WithSubscriber, CONFIG, ENV_LOG_LEVEL, }; use std::future::Future; use tokio::sync::mpsc; @@ -61,8 +61,7 @@ impl Actor { let (query_sender, mut query_receiver) = mpsc::channel(100); let (response_sender, response_receiver) = mpsc::channel(100); - - let tag = ConnectorTag::try_from(("sqlserver", None))?; + let (tag, version) = query_tests_setup::CONFIG.test_connector()?; let datamodel = render_test_datamodel( "sql_server_deadlocks_test", @@ -73,7 +72,7 @@ impl Actor { Some("READ COMMITTED"), ); - let mut runner = Runner::load(datamodel, &[], tag, setup_metrics(), log_capture).await?; + let mut runner = Runner::load(datamodel, &[], version, tag, setup_metrics(), log_capture).await?; tokio::spawn(async move { while let Some(message) = query_receiver.recv().await { diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/json_filter.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/json_filter.rs index 9006d00bae84..1fe86702ef5b 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/json_filter.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/field_reference/json_filter.rs @@ -462,7 +462,7 @@ mod json_filter { fn json_path(runner: &Runner) -> &'static str { match runner.connector_version() { - ConnectorVersion::Postgres(_) | ConnectorVersion::CockroachDb => r#"path: ["a", "b"]"#, + ConnectorVersion::Postgres(_) | ConnectorVersion::CockroachDb(_) => r#"path: ["a", "b"]"#, ConnectorVersion::MySql(_) => r#"path: "$.a.b""#, x => unreachable!("JSON filtering is not supported on {:?}", x), } diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/insensitive_filters.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/insensitive_filters.rs index 84a55910dffb..c8a519d90dcb 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/insensitive_filters.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/insensitive_filters.rs @@ -145,7 +145,7 @@ mod insensitive { r#"query { findManyTestModel(where: { str: { gte: "aÆB", mode: insensitive } }) { str }}"#, MongoDb(_) => vec![r#"{"data":{"findManyTestModel":[{"str":"æ"},{"str":"Æ"},{"str":"bar"},{"str":"aÆB"},{"str":"AÆB"},{"str":"aæB"}]}}"#], // Cockroach, https://github.com/cockroachdb/cockroach/issues/71313 - CockroachDb => vec![r#"{"data":{"findManyTestModel":[{"str":"æ"},{"str":"Æ"},{"str":"bar"},{"str":"aÆB"},{"str":"AÆB"},{"str":"aæB"}]}}"#], + CockroachDb(_) => vec![r#"{"data":{"findManyTestModel":[{"str":"æ"},{"str":"Æ"},{"str":"bar"},{"str":"aÆB"},{"str":"AÆB"},{"str":"aæB"}]}}"#], _ => vec![r#"{"data":{"findManyTestModel":[{"str":"æ"},{"str":"Æ"},{"str":"bar"},{"str":"aÆB"},{"str":"AÆB"},{"str":"aæB"},{"str":"aB"}]}}"#] ); @@ -154,7 +154,7 @@ mod insensitive { r#"query { findManyTestModel(where: { str: { lt: "aÆB", mode: insensitive } }) { str }}"#, MongoDb(_) => vec![r#"{"data":{"findManyTestModel":[{"str":"A"},{"str":"aB"}]}}"#], // https://github.com/cockroachdb/cockroach/issues/71313 - CockroachDb => vec![r#"{"data":{"findManyTestModel":[{"str":"A"},{"str":"aB"}]}}"#], + CockroachDb(_) => vec![r#"{"data":{"findManyTestModel":[{"str":"A"},{"str":"aB"}]}}"#], _ => vec![r#"{"data":{"findManyTestModel":[{"str":"A"}]}}"#] ); diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/json_filters.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/json_filters.rs index ed9e9b487694..cb264d681c23 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/json_filters.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/filters/json_filters.rs @@ -3,7 +3,7 @@ use query_engine_tests::*; #[test_suite(schema(schemas::json), capabilities(JsonFiltering), exclude(MySql(5.6)))] mod json_filters { use indoc::indoc; - use query_engine_tests::{assert_error, is_one_of, run_query, MySqlVersion, Runner}; + use query_engine_tests::{assert_error, is_one_of, run_query, Runner}; fn pg_json() -> String { let schema = indoc! { @@ -895,7 +895,7 @@ mod json_filters { fn json_path(runner: &Runner) -> &'static str { match runner.connector_version() { - ConnectorVersion::Postgres(_) | ConnectorVersion::CockroachDb => r#"path: ["a", "b"]"#, + ConnectorVersion::Postgres(_) | ConnectorVersion::CockroachDb(_) => r#"path: ["a", "b"]"#, ConnectorVersion::MySql(_) => r#"path: "$.a.b""#, x => unreachable!("JSON filtering is not supported on {:?}", x), } diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent.rs index 93dcc263e025..357051280efc 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent.rs @@ -244,7 +244,7 @@ mod order_by_dependent { } }"#, MongoDb(_) | Sqlite => vec![r#"{"data":{"findManyModelA":[{"id":3,"b":null},{"id":4,"b":null},{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":2,"b":{"c":{"a":{"id":4}}}}]}}"#], - MySql(_) | CockroachDb => vec![ + MySql(_) | CockroachDb(_) => vec![ r#"{"data":{"findManyModelA":[{"id":4,"b":null},{"id":3,"b":null},{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":2,"b":{"c":{"a":{"id":4}}}}]}}"#, r#"{"data":{"findManyModelA":[{"id":3,"b":null},{"id":4,"b":null},{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":2,"b":{"c":{"a":{"id":4}}}}]}}"#, ], @@ -276,7 +276,7 @@ mod order_by_dependent { } }"#, MongoDb(_) | Sqlite => vec![r#"{"data":{"findManyModelA":[{"id":2,"b":{"c":{"a":{"id":4}}}},{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":3,"b":null},{"id":4,"b":null}]}}"#], - MySql(_) | CockroachDb => vec![ + MySql(_) | CockroachDb(_) => vec![ r#"{"data":{"findManyModelA":[{"id":2,"b":{"c":{"a":{"id":4}}}},{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":4,"b":null},{"id":3,"b":null}]}}"#, r#"{"data":{"findManyModelA":[{"id":2,"b":{"c":{"a":{"id":4}}}},{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":3,"b":null},{"id":4,"b":null}]}}"#, ], diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent_pagination.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent_pagination.rs index 8823ae42ad26..ab0820ef0a35 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent_pagination.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/order_and_pagination/order_by_dependent_pagination.rs @@ -97,7 +97,7 @@ mod order_by_dependent_pag { } }"#, // Depends on how null values are handled. - MongoDb(_) | Sqlite | MySql(_) | CockroachDb => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"id":1}},{"id":2,"b":{"id":2}}]}}"#], + MongoDb(_) | Sqlite | MySql(_) | CockroachDb(_) => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"id":1}},{"id":2,"b":{"id":2}}]}}"#], _ => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"id":1}},{"id":2,"b":{"id":2}},{"id":3,"b":null}]}}"#] ); @@ -166,7 +166,7 @@ mod order_by_dependent_pag { } }"#, // Depends on how null values are handled. - MongoDb(_) | Sqlite | MySql(_) | CockroachDb => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"c":{"id":1}}}]}}"#], + MongoDb(_) | Sqlite | MySql(_) | CockroachDb(_) => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"c":{"id":1}}}]}}"#], _ => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"c":{"id":1}}},{"id":2,"b":{"c":null}},{"id":3,"b":null}]}}"#] ); @@ -248,7 +248,7 @@ mod order_by_dependent_pag { } }"#, // Depends on how null values are handled. - MongoDb(_) | MySql(_) | Sqlite | CockroachDb => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":2,"b":{"c":{"a":{"id":4}}}}]}}"#], + MongoDb(_) | MySql(_) | Sqlite | CockroachDb(_) => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":2,"b":{"c":{"a":{"id":4}}}}]}}"#], _ => vec![r#"{"data":{"findManyModelA":[{"id":1,"b":{"c":{"a":{"id":3}}}},{"id":2,"b":{"c":{"a":{"id":4}}}},{"id":3,"b":null},{"id":4,"b":null}]}}"#] ); diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/views.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/views.rs index cb4d567e3989..11ab7e2350ab 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/views.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/queries/views.rs @@ -136,23 +136,23 @@ mod views { // schema name must be the name of the test in which it's called. async fn migrate_view_sql(runner: &Runner, schema_name: &str) -> String { - match runner.connector() { - ConnectorTag::Postgres(_) - | ConnectorTag::Cockroach(_) + match runner.connector_version() { + ConnectorVersion::Postgres(_) + | ConnectorVersion::CockroachDb(_) => { r#"CREATE VIEW "TestView" AS SELECT "TestModel".id, "TestModel"."firstName", "TestModel"."lastName", CONCAT("TestModel"."firstName", ' ', "TestModel"."lastName") as "fullName" From "TestModel""#.to_owned() } - ConnectorTag::MySql(_) | ConnectorTag::Vitess(_) + ConnectorVersion::MySql(_) | ConnectorVersion::Vitess(_) => { r#"CREATE VIEW TestView AS SELECT TestModel.*, CONCAT(TestModel.firstName, ' ', TestModel.lastName) AS "fullName" FROM TestModel"#.to_owned() }, - ConnectorTag::Sqlite(_) => { + ConnectorVersion::Sqlite => { r#"CREATE VIEW TestView AS SELECT TestModel.*, TestModel.firstName || ' ' || TestModel.lastName AS "fullName" FROM TestModel"#.to_owned() } - ConnectorTag::SqlServer(_) => { + ConnectorVersion::SqlServer(_) => { format!(r#"CREATE VIEW [views_{schema_name}].[TestView] AS SELECT [views_{schema_name}].[TestModel].[id], [views_{schema_name}].[TestModel].[firstName], [views_{schema_name}].[TestModel].[lastName], CONCAT([views_{schema_name}].[TestModel].[firstName], ' ', [views_{schema_name}].[TestModel].[lastName]) as "fullName" FROM [views_{schema_name}].[TestModel];"#) }, - ConnectorTag::MongoDb(_) => unreachable!(), + ConnectorVersion::MongoDb(_) => unreachable!(), } } diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/top_level_mutations/update_many.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/top_level_mutations/update_many.rs index 35479f5a3af5..41f023bd6516 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/top_level_mutations/update_many.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/top_level_mutations/update_many.rs @@ -4,7 +4,7 @@ use query_engine_tests::*; #[test_suite(schema(schema))] mod update_many { use indoc::indoc; - use query_engine_tests::{is_one_of, run_query, run_query_json, ConnectorTag}; + use query_engine_tests::{is_one_of, run_query, run_query_json}; fn schema() -> String { let schema = indoc! { @@ -297,7 +297,7 @@ mod update_many { let count = &res["data"]["updateManyTestModel"]["count"]; // MySql does not count incrementing a null so the count is different - if !matches!(runner.connector(), ConnectorTag::MySql(_)) { + if !matches!(runner.connector_version(), ConnectorVersion::MySql(_)) { assert_eq!(count, 3); } diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml b/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml index e23419e139ae..be09bc26ac40 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml +++ b/query-engine/connector-test-kit-rs/query-tests-setup/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" serde_json.workspace = true prisma-models = { path = "../../prisma-models" } once_cell = "1" -enum_dispatch = "0.3" qe-setup = { path = "../qe-setup" } request-handlers = { path = "../../request-handlers" } tokio.workspace = true diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/config.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/config.rs index 13930e2d6e49..8807b4e0dbd8 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/config.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/config.rs @@ -1,4 +1,7 @@ -use crate::{ConnectorTag, ConnectorTagInterface, TestResult}; +use crate::{ + CockroachDbConnectorTag, ConnectorTag, ConnectorVersion, MongoDbConnectorTag, MySqlConnectorTag, + PostgresConnectorTag, SqlServerConnectorTag, SqliteConnectorTag, TestResult, VitessConnectorTag, +}; use serde::Deserialize; use std::{convert::TryFrom, env, fs::File, io::Read, path::PathBuf}; @@ -117,11 +120,22 @@ impl TestConfig { exit_with_message("A test connector is required but was not set."); } - match self.test_connector_tag() { - Ok(tag) if tag.is_versioned() && self.connector_version.is_none() => { + match self.test_connector().map(|(_, v)| v) { + Ok(ConnectorVersion::Vitess(None)) + | Ok(ConnectorVersion::MySql(None)) + | Ok(ConnectorVersion::SqlServer(None)) + | Ok(ConnectorVersion::MongoDb(None)) + | Ok(ConnectorVersion::CockroachDb(None)) + | Ok(ConnectorVersion::Postgres(None)) => { exit_with_message("The current test connector requires a version to be set to run."); } - Ok(_) => (), + Ok(ConnectorVersion::Vitess(Some(_))) + | Ok(ConnectorVersion::MySql(Some(_))) + | Ok(ConnectorVersion::SqlServer(Some(_))) + | Ok(ConnectorVersion::MongoDb(Some(_))) + | Ok(ConnectorVersion::CockroachDb(Some(_))) + | Ok(ConnectorVersion::Postgres(Some(_))) + | Ok(ConnectorVersion::Sqlite) => (), Err(err) => exit_with_message(&err.to_string()), } } @@ -130,7 +144,7 @@ impl TestConfig { self.connector.as_str() } - pub fn connector_version(&self) -> Option<&str> { + pub(crate) fn connector_version(&self) -> Option<&str> { self.connector_version.as_ref().map(AsRef::as_ref) } @@ -138,8 +152,19 @@ impl TestConfig { self.is_ci } - pub fn test_connector_tag(&self) -> TestResult { - ConnectorTag::try_from((self.connector(), self.connector_version())) + pub fn test_connector(&self) -> TestResult<(ConnectorTag, ConnectorVersion)> { + let version = ConnectorVersion::try_from((self.connector(), self.connector_version()))?; + let tag = match version { + ConnectorVersion::SqlServer(_) => &SqlServerConnectorTag as ConnectorTag, + ConnectorVersion::Postgres(_) => &PostgresConnectorTag, + ConnectorVersion::MySql(_) => &MySqlConnectorTag, + ConnectorVersion::MongoDb(_) => &MongoDbConnectorTag, + ConnectorVersion::Sqlite => &SqliteConnectorTag, + ConnectorVersion::CockroachDb(_) => &CockroachDbConnectorTag, + ConnectorVersion::Vitess(_) => &VitessConnectorTag, + }; + + Ok((tag, version)) } } diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/cockroachdb.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/cockroachdb.rs index 55bc7762de16..b10878043362 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/cockroachdb.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/cockroachdb.rs @@ -1,20 +1,10 @@ use super::*; -use crate::{datamodel_rendering::SqlDatamodelRenderer, TestResult}; +use crate::{datamodel_rendering::SqlDatamodelRenderer, BoxFuture}; use psl::datamodel_connector::ConnectorCapabilities; +use quaint::{prelude::Queryable, single::Quaint}; #[derive(Debug, Default, Clone)] -pub struct CockroachDbConnectorTag { - version: Option, -} - -impl PartialEq for CockroachDbConnectorTag { - fn eq(&self, other: &Self) -> bool { - match (self.version, other.version) { - (None, None) | (Some(_), None) | (None, Some(_)) => true, - (Some(v1), Some(v2)) => v1 == v2, - } - } -} +pub(crate) struct CockroachDbConnectorTag; #[derive(Debug, Clone, Copy, PartialEq)] pub enum CockroachDbVersion { @@ -52,6 +42,13 @@ impl Default for CockroachDbVersion { } impl ConnectorTagInterface for CockroachDbConnectorTag { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>> { + Box::pin(async move { + let conn = Quaint::new(connection_url).await?; + Ok(conn.raw_cmd(query).await?) + }) + } + fn datamodel_provider(&self) -> &'static str { "cockroachdb" } @@ -60,67 +57,7 @@ impl ConnectorTagInterface for CockroachDbConnectorTag { Box::new(SqlDatamodelRenderer::new()) } - fn connection_string( - &self, - database: &str, - is_ci: bool, - _is_multi_schema: bool, - _: Option<&'static str>, - ) -> String { - // Use the same database and schema name for CockroachDB - unfortunately CockroachDB - // can't handle 1 schema per test in a database well at this point in time. - match self.version { - Some(CockroachDbVersion::V221) if is_ci => { - format!("postgresql://prisma@test-db-cockroachdb-22-1:26257/{database}?schema={database}") - } - Some(CockroachDbVersion::V222) if is_ci => { - format!("postgresql://prisma@test-db-cockroachdb-22-2:26259/{database}?schema={database}") - } - Some(CockroachDbVersion::V221) => { - format!("postgresql://prisma@127.0.0.1:26257/{database}?schema={database}") - } - Some(CockroachDbVersion::V222) => { - format!("postgresql://prisma@127.0.0.1:26259/{database}?schema={database}") - } - - None => unreachable!("A versioned connector must have a concrete version to run."), - } - } - fn capabilities(&self) -> ConnectorCapabilities { psl::builtin_connectors::COCKROACH.capabilities() } - - fn as_parse_pair(&self) -> (String, Option) { - let version = self.version.as_ref().map(ToString::to_string); - ("cockroachdb".to_owned(), version) - } - - fn is_versioned(&self) -> bool { - true - } -} - -impl CockroachDbConnectorTag { - #[track_caller] - pub fn new(version: Option<&str>) -> TestResult { - let version = match version { - Some(v) => Some(CockroachDbVersion::try_from(v)?), - None => None, - }; - - Ok(Self { version }) - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![ - Self { - version: Some(CockroachDbVersion::V221), - }, - Self { - version: Some(CockroachDbVersion::V222), - }, - ] - } } diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mod.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mod.rs index 3adf0962c1ba..dd0fe17e79b6 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mod.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mod.rs @@ -6,21 +6,22 @@ mod sql_server; mod sqlite; mod vitess; -pub use mongodb::*; pub use mysql::*; -pub use postgres::*; -pub use sql_server::*; -pub use sqlite::*; -pub use vitess::*; - -use crate::{datamodel_rendering::DatamodelRenderer, TestError, CONFIG}; -use cockroachdb::*; -use enum_dispatch::enum_dispatch; + +pub(crate) use cockroachdb::*; +pub(crate) use mongodb::*; +pub(crate) use postgres::*; +pub(crate) use sql_server::*; +pub(crate) use sqlite::*; +pub(crate) use vitess::*; + +use crate::{datamodel_rendering::DatamodelRenderer, BoxFuture, TestError, CONFIG}; use psl::datamodel_connector::ConnectorCapabilities; use std::{convert::TryFrom, fmt}; -#[enum_dispatch] pub trait ConnectorTagInterface { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>>; + /// The name of the datamodel provider for this connector. /// Must match valid datamodel provider strings. fn datamodel_provider(&self) -> &'static str; @@ -28,29 +29,9 @@ pub trait ConnectorTagInterface { /// Returns the renderer to be used for templating the datamodel (the models portion). fn datamodel_renderer(&self) -> Box; - /// The connection string to use to connect to the test database and version. - /// - `test_database` is the database to connect to, which is an implementation detail of the - /// implementing connector, like a file or a schema. - /// - `is_ci` signals whether or not the test run is done on CI or not. May be important if local - /// test run connection strings and CI connection strings differ because of networking. - fn connection_string( - &self, - test_database: &str, - is_ci: bool, - is_multi_schema: bool, - isolation_level: Option<&'static str>, - ) -> String; - /// Capabilities of the implementing connector. fn capabilities(&self) -> ConnectorCapabilities; - /// Serialization of the connector. Expected to return `(tag_name, version)`. - /// Todo: Think of something better. - fn as_parse_pair(&self) -> (String, Option); - - /// Must return `true` if the connector family is versioned (e.g. Postgres9, Postgres10, ...), false otherwise. - fn is_versioned(&self) -> bool; - /// Defines where relational constraints are handled: /// - "prisma" is handled in the Query Engine core /// - "foreignKeys" lets the database handle them @@ -59,18 +40,161 @@ pub trait ConnectorTagInterface { } } -#[enum_dispatch(ConnectorTagInterface)] -#[derive(Debug, Clone, PartialEq)] -pub enum ConnectorTag { - SqlServer(SqlServerConnectorTag), - Postgres(PostgresConnectorTag), - MySql(MySqlConnectorTag), - MongoDb(MongoDbConnectorTag), - Sqlite(SqliteConnectorTag), - Vitess(VitessConnectorTag), - Cockroach(CockroachDbConnectorTag), +/// The connection string to use to connect to the test database and version. +/// - `test_database` is the database to connect to, which is an implementation detail of the +/// implementing connector, like a file or a schema. +/// - `is_ci` signals whether or not the test run is done on CI or not. May be important if local +/// test run connection strings and CI connection strings differ because of networking. +pub(crate) fn connection_string( + version: &ConnectorVersion, + database: &str, + is_ci: bool, + is_multi_schema: bool, + isolation_level: Option<&'static str>, +) -> String { + match version { + ConnectorVersion::SqlServer(v) => { + let database = if is_multi_schema { + format!("database={database};schema=dbo") + } else { + format!("database=master;schema={database}") + }; + + let isolation_level = isolation_level.unwrap_or("READ UNCOMMITTED"); + + match v { + Some(SqlServerVersion::V2017) if is_ci => format!("sqlserver://test-db-sqlserver-2017:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), + Some(SqlServerVersion::V2017) => format!("sqlserver://127.0.0.1:1434;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), + + Some(SqlServerVersion::V2019) if is_ci => format!("sqlserver://test-db-sqlserver-2019:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), + Some(SqlServerVersion::V2019) => format!("sqlserver://127.0.0.1:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), + + Some(SqlServerVersion::V2022) if is_ci => format!("sqlserver://test-db-sqlserver-2022:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), + Some(SqlServerVersion::V2022) => format!("sqlserver://127.0.0.1:1435;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), + + None => unreachable!("A versioned connector must have a concrete version to run."), + } + } + ConnectorVersion::Postgres(v) => { + let database = if is_multi_schema { + database.to_string() + } else { + format!("db?schema={database}") + }; + + match v { + Some(PostgresVersion::V9) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-9:5432/{database}") + } + Some(PostgresVersion::V10) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-10:5432/{database}") + } + Some(PostgresVersion::V11) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-11:5432/{database}") + } + Some(PostgresVersion::V12) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-12:5432/{database}") + } + Some(PostgresVersion::V13) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-13:5432/{database}") + } + Some(PostgresVersion::V14) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-14:5432/{database}") + } + Some(PostgresVersion::V15) if is_ci => { + format!("postgresql://postgres:prisma@test-db-postgres-15:5432/{database}") + } + Some(PostgresVersion::PgBouncer) if is_ci => { + format!("postgresql://postgres:prisma@test-db-pgbouncer:6432/{database}&pgbouncer=true") + } + + Some(PostgresVersion::V9) => format!("postgresql://postgres:prisma@127.0.0.1:5431/{database}"), + Some(PostgresVersion::V10) => format!("postgresql://postgres:prisma@127.0.0.1:5432/{database}"), + Some(PostgresVersion::V11) => format!("postgresql://postgres:prisma@127.0.0.1:5433/{database}"), + Some(PostgresVersion::V12) => format!("postgresql://postgres:prisma@127.0.0.1:5434/{database}"), + Some(PostgresVersion::V13) => format!("postgresql://postgres:prisma@127.0.0.1:5435/{database}"), + Some(PostgresVersion::V14) => format!("postgresql://postgres:prisma@127.0.0.1:5437/{database}"), + Some(PostgresVersion::V15) => format!("postgresql://postgres:prisma@127.0.0.1:5438/{database}"), + Some(PostgresVersion::PgBouncer) => { + format!("postgresql://postgres:prisma@127.0.0.1:6432/db?{database}&pgbouncer=true") + } + + None => unreachable!("A versioned connector must have a concrete version to run."), + } + } + ConnectorVersion::MySql(v) => match v { + Some(MySqlVersion::V5_6) if is_ci => format!("mysql://root:prisma@test-db-mysql-5-6:3306/{database}"), + Some(MySqlVersion::V5_7) if is_ci => format!("mysql://root:prisma@test-db-mysql-5-7:3306/{database}"), + Some(MySqlVersion::V8) if is_ci => format!("mysql://root:prisma@test-db-mysql-8:3306/{database}"), + Some(MySqlVersion::MariaDb) if is_ci => { + format!("mysql://root:prisma@test-db-mysql-mariadb:3306/{database}") + } + Some(MySqlVersion::V5_6) => format!("mysql://root:prisma@127.0.0.1:3309/{database}"), + Some(MySqlVersion::V5_7) => format!("mysql://root:prisma@127.0.0.1:3306/{database}"), + Some(MySqlVersion::V8) => format!("mysql://root:prisma@127.0.0.1:3307/{database}"), + Some(MySqlVersion::MariaDb) => { + format!("mysql://root:prisma@127.0.0.1:3308/{database}") + } + + None => unreachable!("A versioned connector must have a concrete version to run."), + }, + ConnectorVersion::MongoDb(v) => match v { + Some(MongoDbVersion::V4_2) if is_ci => format!( + "mongodb://prisma:prisma@test-db-mongodb-4-2:27016/{database}?authSource=admin&retryWrites=true" + ), + Some(MongoDbVersion::V4_2) => { + format!("mongodb://prisma:prisma@127.0.0.1:27016/{database}?authSource=admin&retryWrites=true") + } + Some(MongoDbVersion::V4_4) if is_ci => format!( + "mongodb://prisma:prisma@test-db-mongodb-4-4:27017/{database}?authSource=admin&retryWrites=true" + ), + Some(MongoDbVersion::V4_4) => { + format!("mongodb://prisma:prisma@127.0.0.1:27017/{database}?authSource=admin&retryWrites=true") + } + Some(MongoDbVersion::V5) if is_ci => { + format!("mongodb://prisma:prisma@test-db-mongodb-5:27018/{database}?authSource=admin&retryWrites=true") + } + Some(MongoDbVersion::V5) => { + format!("mongodb://prisma:prisma@127.0.0.1:27018/{database}?authSource=admin&retryWrites=true") + } + None => unreachable!("A versioned connector must have a concrete version to run."), + }, + ConnectorVersion::Sqlite => { + let workspace_root = std::env::var("WORKSPACE_ROOT") + .unwrap_or_else(|_| ".".to_owned()) + .trim_end_matches('/') + .to_owned(); + + format!("file://{workspace_root}/db/{database}.db") + } + ConnectorVersion::CockroachDb(v) => { + // Use the same database and schema name for CockroachDB - unfortunately CockroachDB + // can't handle 1 schema per test in a database well at this point in time. + match v { + Some(CockroachDbVersion::V221) if is_ci => { + format!("postgresql://prisma@test-db-cockroachdb-22-1:26257/{database}?schema={database}") + } + Some(CockroachDbVersion::V222) if is_ci => { + format!("postgresql://prisma@test-db-cockroachdb-22-2:26259/{database}?schema={database}") + } + Some(CockroachDbVersion::V221) => { + format!("postgresql://prisma@127.0.0.1:26257/{database}?schema={database}") + } + Some(CockroachDbVersion::V222) => { + format!("postgresql://prisma@127.0.0.1:26259/{database}?schema={database}") + } + + None => unreachable!("A versioned connector must have a concrete version to run."), + } + } + ConnectorVersion::Vitess(Some(VitessVersion::V5_7)) => "mysql://root@localhost:33577/test".into(), + ConnectorVersion::Vitess(Some(VitessVersion::V8_0)) => "mysql://root@localhost:33807/test".into(), + ConnectorVersion::Vitess(None) => unreachable!("A versioned connector must have a concrete version to run."), + } } +pub type ConnectorTag = &'static (dyn ConnectorTagInterface + Send + Sync); + #[derive(Debug, Clone)] pub enum ConnectorVersion { SqlServer(Option), @@ -78,37 +202,43 @@ pub enum ConnectorVersion { MySql(Option), MongoDb(Option), Sqlite, - CockroachDb, + CockroachDb(Option), Vitess(Option), } -impl From<&ConnectorTag> for ConnectorVersion { - fn from(connector: &ConnectorTag) -> Self { - match connector { - ConnectorTag::SqlServer(c) => ConnectorVersion::SqlServer(c.version()), - ConnectorTag::Postgres(c) => ConnectorVersion::Postgres(c.version()), - ConnectorTag::MySql(c) => ConnectorVersion::MySql(c.version()), - ConnectorTag::MongoDb(c) => ConnectorVersion::MongoDb(c.version()), - ConnectorTag::Sqlite(_) => ConnectorVersion::Sqlite, - ConnectorTag::Cockroach(_) => ConnectorVersion::CockroachDb, - ConnectorTag::Vitess(c) => ConnectorVersion::Vitess(c.version()), +impl ConnectorVersion { + fn matches_pattern(&self, pat: &ConnectorVersion) -> bool { + use ConnectorVersion::*; + + fn versions_match(opt_a: &Option, opt_b: &Option) -> bool { + match (opt_a, opt_b) { + (None, None) | (None, Some(_)) | (Some(_), None) => true, + (Some(a), Some(b)) => a == b, + } } - } -} -impl fmt::Display for ConnectorTag { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let printable = match self { - Self::SqlServer(_) => "SQL Server", - Self::Postgres(_) => "PostgreSQL", - Self::MySql(_) => "MySQL", - Self::MongoDb(_) => "MongoDB", - Self::Sqlite(_) => "SQLite", - Self::Vitess(_) => "Vitess", - Self::Cockroach(_) => "CockroachDB", - }; + match (self, pat) { + (SqlServer(a), SqlServer(b)) => versions_match(a, b), + (Postgres(a), Postgres(b)) => versions_match(a, b), + (MySql(a), MySql(b)) => versions_match(a, b), + (MongoDb(a), MongoDb(b)) => versions_match(a, b), + (CockroachDb(a), CockroachDb(b)) => versions_match(a, b), + (Vitess(a), Vitess(b)) => versions_match(a, b), + (Sqlite, Sqlite) => true, - write!(f, "{printable}") + (MongoDb(..), _) + | (_, MongoDb(..)) + | (SqlServer(..), _) + | (_, SqlServer(..)) + | (Sqlite, _) + | (_, Sqlite) + | (CockroachDb(..), _) + | (_, CockroachDb(..)) + | (Vitess(..), _) + | (_, Vitess(..)) + | (Postgres(..), _) + | (_, Postgres(..)) => false, + } } } @@ -136,79 +266,60 @@ impl fmt::Display for ConnectorVersion { Some(v) => format!("Vitess ({v})"), None => "Vitess (unknown)".to_string(), }, - Self::CockroachDb => "CockroachDB".to_string(), + Self::CockroachDb(_) => "CockroachDB".to_string(), }; write!(f, "{printable}") } } -impl ConnectorTag { - /// Returns all possible connector tags. - pub fn all() -> Vec { - SqlServerConnectorTag::all() - .into_iter() - .map(Self::SqlServer) - .chain(PostgresConnectorTag::all().into_iter().map(Self::Postgres)) - .chain(MySqlConnectorTag::all().into_iter().map(Self::MySql)) - .chain(MongoDbConnectorTag::all().into_iter().map(Self::MongoDb)) - .chain(SqliteConnectorTag::all().into_iter().map(Self::Sqlite)) - .chain(CockroachDbConnectorTag::all().into_iter().map(Self::Cockroach)) - .collect() - } - - /// Determines whether or not a test should run for the given enabled connectors and capabilities - /// a connector is required to have. - pub(crate) fn should_run( - only: &[(&str, Option<&str>)], - exclude: &[(&str, Option<&str>)], - capabilities: ConnectorCapabilities, - ) -> bool { - let connector = CONFIG.test_connector_tag().unwrap(); - - if !capabilities.is_empty() && !connector.capabilities().contains(capabilities) { - println!("Connector excluded. Missing required capability."); - return false; - } +/// Determines whether or not a test should run for the given enabled connectors and capabilities +/// a connector is required to have. +pub(crate) fn should_run( + only: &[(&str, Option<&str>)], + exclude: &[(&str, Option<&str>)], + capabilities: ConnectorCapabilities, +) -> bool { + let (connector, version) = CONFIG.test_connector().unwrap(); - if !only.is_empty() { - return only - .iter() - .any(|only| ConnectorTag::try_from(*only).unwrap() == connector); - } + if !capabilities.is_empty() && !connector.capabilities().contains(capabilities) { + println!("Connector excluded. Missing required capability."); + return false; + } - if exclude + if !only.is_empty() { + return only .iter() - .any(|excl| ConnectorTag::try_from(*excl).unwrap() == connector) - { - println!("Connector excluded. Skipping test."); - return false; - } + .any(|only| ConnectorVersion::try_from(*only).unwrap().matches_pattern(&version)); + } - // FIXME: This skips vitess unless explicitly opted in. Replace with `true` when fixing - // https://github.com/prisma/client-planning/issues/332 - !matches!(connector, ConnectorTag::Vitess(_)) + if exclude + .iter() + .any(|excl| ConnectorVersion::try_from(*excl).unwrap().matches_pattern(&version)) + { + println!("Connector excluded. Skipping test."); + return false; } + + // FIXME: This skips vitess unless explicitly opted in. Replace with `true` when fixing + // https://github.com/prisma/client-planning/issues/332 + !matches!(version, ConnectorVersion::Vitess(_)) } -impl TryFrom<(&str, Option<&str>)> for ConnectorTag { +impl TryFrom<(&str, Option<&str>)> for ConnectorVersion { type Error = TestError; #[track_caller] - fn try_from(value: (&str, Option<&str>)) -> Result { - let (connector, version) = value; - - let tag = match connector.to_lowercase().as_str() { - "sqlite" => Self::Sqlite(SqliteConnectorTag::new()), - "sqlserver" => Self::SqlServer(SqlServerConnectorTag::new(version)?), - "cockroachdb" => Self::Cockroach(CockroachDbConnectorTag::new(version)?), - "postgres" => Self::Postgres(PostgresConnectorTag::new(version)?), - "mysql" => Self::MySql(MySqlConnectorTag::new(version)?), - "mongodb" => Self::MongoDb(MongoDbConnectorTag::new(version)?), - "vitess" => Self::Vitess(VitessConnectorTag::new(version)?), + fn try_from((connector, version): (&str, Option<&str>)) -> Result { + Ok(match connector.to_lowercase().as_str() { + "sqlite" => ConnectorVersion::Sqlite, + "sqlserver" => ConnectorVersion::SqlServer(version.map(SqlServerVersion::try_from).transpose()?), + "cockroachdb" => ConnectorVersion::CockroachDb(version.map(CockroachDbVersion::try_from).transpose()?), + "postgres" => ConnectorVersion::Postgres(version.map(PostgresVersion::try_from).transpose()?), + "mysql" => ConnectorVersion::MySql(version.map(MySqlVersion::try_from).transpose()?), + "mongodb" => ConnectorVersion::MongoDb(version.map(MongoDbVersion::try_from).transpose()?), + "vitess" => ConnectorVersion::Vitess(version.map(|v| v.parse()).transpose()?), _ => return Err(TestError::parse_error(format!("Unknown connector tag `{connector}`"))), - }; - - Ok(tag) + }) } } diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mongodb.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mongodb.rs index 28cde8b05f06..bcb11819f747 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mongodb.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mongodb.rs @@ -1,13 +1,15 @@ use super::*; -use crate::{MongoDbSchemaRenderer, TestError, TestResult}; +use crate::{MongoDbSchemaRenderer, TestError}; use psl::builtin_connectors::MONGODB; #[derive(Debug, Default, Clone)] -pub struct MongoDbConnectorTag { - version: Option, -} +pub(crate) struct MongoDbConnectorTag; impl ConnectorTagInterface for MongoDbConnectorTag { + fn raw_execute(&self, _query: &str, _connection_url: &str) -> BoxFuture> { + panic!("raw_execute is not supported for MongoDB yet"); + } + fn datamodel_provider(&self) -> &'static str { "mongodb" } @@ -16,49 +18,10 @@ impl ConnectorTagInterface for MongoDbConnectorTag { Box::new(MongoDbSchemaRenderer::new()) } - fn connection_string( - &self, - database: &str, - is_ci: bool, - _is_multi_schema: bool, - _: Option<&'static str>, - ) -> String { - match self.version { - Some(MongoDbVersion::V4_2) if is_ci => format!( - "mongodb://prisma:prisma@test-db-mongodb-4-2:27016/{database}?authSource=admin&retryWrites=true" - ), - Some(MongoDbVersion::V4_2) => { - format!("mongodb://prisma:prisma@127.0.0.1:27016/{database}?authSource=admin&retryWrites=true") - } - Some(MongoDbVersion::V4_4) if is_ci => format!( - "mongodb://prisma:prisma@test-db-mongodb-4-4:27017/{database}?authSource=admin&retryWrites=true" - ), - Some(MongoDbVersion::V4_4) => { - format!("mongodb://prisma:prisma@127.0.0.1:27017/{database}?authSource=admin&retryWrites=true") - } - Some(MongoDbVersion::V5) if is_ci => { - format!("mongodb://prisma:prisma@test-db-mongodb-5:27018/{database}?authSource=admin&retryWrites=true") - } - Some(MongoDbVersion::V5) => { - format!("mongodb://prisma:prisma@127.0.0.1:27018/{database}?authSource=admin&retryWrites=true") - } - None => unreachable!("A versioned connector must have a concrete version to run."), - } - } - fn capabilities(&self) -> ConnectorCapabilities { MONGODB.capabilities() } - fn as_parse_pair(&self) -> (String, Option) { - let version = self.version.as_ref().map(ToString::to_string); - ("mongodb".to_owned(), version) - } - - fn is_versioned(&self) -> bool { - true - } - fn relation_mode(&self) -> &'static str { "prisma" } @@ -71,46 +34,6 @@ pub enum MongoDbVersion { V5, } -impl MongoDbConnectorTag { - pub fn new(version: Option<&str>) -> TestResult { - let version = match version { - Some(v) => Some(MongoDbVersion::try_from(v)?), - None => None, - }; - - Ok(Self { version }) - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![ - Self { - version: Some(MongoDbVersion::V4_2), - }, - Self { - version: Some(MongoDbVersion::V4_4), - }, - Self { - version: Some(MongoDbVersion::V5), - }, - ] - } - - /// Get a reference to the mongo db connector tag's version. - pub fn version(&self) -> Option { - self.version - } -} - -impl PartialEq for MongoDbConnectorTag { - fn eq(&self, other: &Self) -> bool { - match (self.version, other.version) { - (None, None) | (Some(_), None) | (None, Some(_)) => true, - (Some(v1), Some(v2)) => v1 == v2, - } - } -} - impl TryFrom<&str> for MongoDbVersion { type Error = TestError; diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mysql.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mysql.rs index 900c3e713831..85cf1c34e6e2 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mysql.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/mysql.rs @@ -1,19 +1,18 @@ use super::*; -use crate::{datamodel_rendering::SqlDatamodelRenderer, TestError, TestResult}; +use crate::{datamodel_rendering::SqlDatamodelRenderer, BoxFuture, TestError}; +use quaint::{prelude::Queryable, single::Quaint}; #[derive(Debug, Default, Clone)] -pub struct MySqlConnectorTag { - version: Option, -} +pub(crate) struct MySqlConnectorTag; -impl MySqlConnectorTag { - /// Get a reference to the MySQL connector tag's version. - pub fn version(&self) -> Option { - self.version +impl ConnectorTagInterface for MySqlConnectorTag { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>> { + Box::pin(async move { + let conn = Quaint::new(connection_url).await?; + Ok(conn.raw_cmd(query).await?) + }) } -} -impl ConnectorTagInterface for MySqlConnectorTag { fn datamodel_provider(&self) -> &'static str { "mysql" } @@ -22,43 +21,9 @@ impl ConnectorTagInterface for MySqlConnectorTag { Box::new(SqlDatamodelRenderer::new()) } - fn connection_string( - &self, - database: &str, - is_ci: bool, - _is_multi_schema: bool, - _: Option<&'static str>, - ) -> String { - match self.version { - Some(MySqlVersion::V5_6) if is_ci => format!("mysql://root:prisma@test-db-mysql-5-6:3306/{database}"), - Some(MySqlVersion::V5_7) if is_ci => format!("mysql://root:prisma@test-db-mysql-5-7:3306/{database}"), - Some(MySqlVersion::V8) if is_ci => format!("mysql://root:prisma@test-db-mysql-8:3306/{database}"), - Some(MySqlVersion::MariaDb) if is_ci => { - format!("mysql://root:prisma@test-db-mysql-mariadb:3306/{database}") - } - Some(MySqlVersion::V5_6) => format!("mysql://root:prisma@127.0.0.1:3309/{database}"), - Some(MySqlVersion::V5_7) => format!("mysql://root:prisma@127.0.0.1:3306/{database}"), - Some(MySqlVersion::V8) => format!("mysql://root:prisma@127.0.0.1:3307/{database}"), - Some(MySqlVersion::MariaDb) => { - format!("mysql://root:prisma@127.0.0.1:3308/{database}") - } - - None => unreachable!("A versioned connector must have a concrete version to run."), - } - } - fn capabilities(&self) -> ConnectorCapabilities { psl::builtin_connectors::MYSQL.capabilities() } - - fn as_parse_pair(&self) -> (String, Option) { - let version = self.version.as_ref().map(ToString::to_string); - ("mysql".to_owned(), version) - } - - fn is_versioned(&self) -> bool { - true - } } #[derive(Debug, Clone, Copy, PartialEq)] @@ -69,44 +34,6 @@ pub enum MySqlVersion { MariaDb, } -impl MySqlConnectorTag { - pub fn new(version: Option<&str>) -> TestResult { - let version = match version { - Some(v) => Some(MySqlVersion::try_from(v)?), - None => None, - }; - - Ok(Self { version }) - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![ - Self { - version: Some(MySqlVersion::V5_6), - }, - Self { - version: Some(MySqlVersion::V5_7), - }, - Self { - version: Some(MySqlVersion::V8), - }, - Self { - version: Some(MySqlVersion::MariaDb), - }, - ] - } -} - -impl PartialEq for MySqlConnectorTag { - fn eq(&self, other: &Self) -> bool { - match (self.version, other.version) { - (None, None) | (Some(_), None) | (None, Some(_)) => true, - (Some(v1), Some(v2)) => v1 == v2, - } - } -} - impl TryFrom<&str> for MySqlVersion { type Error = TestError; diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/postgres.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/postgres.rs index a2e20a361354..039231a3f74e 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/postgres.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/postgres.rs @@ -1,12 +1,18 @@ use super::*; -use crate::{datamodel_rendering::SqlDatamodelRenderer, TestError, TestResult}; +use crate::{datamodel_rendering::SqlDatamodelRenderer, BoxFuture, TestError}; +use quaint::{prelude::Queryable, single::Quaint}; #[derive(Debug, Default, Clone)] -pub struct PostgresConnectorTag { - version: Option, -} +pub(crate) struct PostgresConnectorTag; impl ConnectorTagInterface for PostgresConnectorTag { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>> { + Box::pin(async move { + let conn = Quaint::new(connection_url).await?; + Ok(conn.raw_cmd(query).await?) + }) + } + fn datamodel_provider(&self) -> &'static str { "postgres" } @@ -15,66 +21,9 @@ impl ConnectorTagInterface for PostgresConnectorTag { Box::new(SqlDatamodelRenderer::new()) } - fn connection_string(&self, database: &str, is_ci: bool, is_multi_schema: bool, _: Option<&'static str>) -> String { - let database = if is_multi_schema { - database.to_string() - } else { - format!("db?schema={database}") - }; - - match self.version { - Some(PostgresVersion::V9) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-9:5432/{database}") - } - Some(PostgresVersion::V10) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-10:5432/{database}") - } - Some(PostgresVersion::V11) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-11:5432/{database}") - } - Some(PostgresVersion::V12) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-12:5432/{database}") - } - Some(PostgresVersion::V13) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-13:5432/{database}") - } - Some(PostgresVersion::V14) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-14:5432/{database}") - } - Some(PostgresVersion::V15) if is_ci => { - format!("postgresql://postgres:prisma@test-db-postgres-15:5432/{database}") - } - Some(PostgresVersion::PgBouncer) if is_ci => { - format!("postgresql://postgres:prisma@test-db-pgbouncer:6432/{database}&pgbouncer=true") - } - - Some(PostgresVersion::V9) => format!("postgresql://postgres:prisma@127.0.0.1:5431/{database}"), - Some(PostgresVersion::V10) => format!("postgresql://postgres:prisma@127.0.0.1:5432/{database}"), - Some(PostgresVersion::V11) => format!("postgresql://postgres:prisma@127.0.0.1:5433/{database}"), - Some(PostgresVersion::V12) => format!("postgresql://postgres:prisma@127.0.0.1:5434/{database}"), - Some(PostgresVersion::V13) => format!("postgresql://postgres:prisma@127.0.0.1:5435/{database}"), - Some(PostgresVersion::V14) => format!("postgresql://postgres:prisma@127.0.0.1:5437/{database}"), - Some(PostgresVersion::V15) => format!("postgresql://postgres:prisma@127.0.0.1:5438/{database}"), - Some(PostgresVersion::PgBouncer) => { - format!("postgresql://postgres:prisma@127.0.0.1:6432/db?{database}&pgbouncer=true") - } - - None => unreachable!("A versioned connector must have a concrete version to run."), - } - } - fn capabilities(&self) -> ConnectorCapabilities { psl::builtin_connectors::POSTGRES.capabilities() } - - fn as_parse_pair(&self) -> (String, Option) { - let version = self.version.as_ref().map(ToString::to_string); - ("postgres".to_owned(), version) - } - - fn is_versioned(&self) -> bool { - true - } } #[derive(Debug, Clone, Copy, PartialEq)] @@ -89,61 +38,6 @@ pub enum PostgresVersion { PgBouncer, } -impl PostgresConnectorTag { - pub fn new(version: Option<&str>) -> TestResult { - let version = match version { - Some(v) => Some(PostgresVersion::try_from(v)?), - None => None, - }; - - Ok(Self { version }) - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![ - Self { - version: Some(PostgresVersion::V9), - }, - Self { - version: Some(PostgresVersion::V10), - }, - Self { - version: Some(PostgresVersion::V11), - }, - Self { - version: Some(PostgresVersion::V12), - }, - Self { - version: Some(PostgresVersion::V13), - }, - Self { - version: Some(PostgresVersion::V14), - }, - Self { - version: Some(PostgresVersion::V15), - }, - Self { - version: Some(PostgresVersion::PgBouncer), - }, - ] - } - - /// Get a reference to the postgres connector tag's version. - pub fn version(&self) -> Option { - self.version - } -} - -impl PartialEq for PostgresConnectorTag { - fn eq(&self, other: &Self) -> bool { - match (self.version, other.version) { - (None, None) | (Some(_), None) | (None, Some(_)) => true, - (Some(v1), Some(v2)) => v1 == v2, - } - } -} - impl TryFrom<&str> for PostgresVersion { type Error = TestError; diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sql_server.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sql_server.rs index 523e349f2866..17b84ed6c8a3 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sql_server.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sql_server.rs @@ -1,12 +1,19 @@ +use quaint::{prelude::Queryable, single::Quaint}; + use super::*; -use crate::{datamodel_rendering::SqlDatamodelRenderer, TestError, TestResult}; +use crate::{datamodel_rendering::SqlDatamodelRenderer, BoxFuture, TestError}; #[derive(Debug, Default, Clone)] -pub struct SqlServerConnectorTag { - version: Option, -} +pub(crate) struct SqlServerConnectorTag; impl ConnectorTagInterface for SqlServerConnectorTag { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>> { + Box::pin(async move { + let conn = Quaint::new(connection_url).await?; + Ok(conn.raw_cmd(query).await?) + }) + } + fn datamodel_provider(&self) -> &'static str { "sqlserver" } @@ -15,47 +22,9 @@ impl ConnectorTagInterface for SqlServerConnectorTag { Box::new(SqlDatamodelRenderer::new()) } - fn connection_string( - &self, - database: &str, - is_ci: bool, - is_multi_schema: bool, - isolation_level: Option<&'static str>, - ) -> String { - let database = if is_multi_schema { - format!("database={database};schema=dbo") - } else { - format!("database=master;schema={database}") - }; - - let isolation_level = isolation_level.unwrap_or("READ UNCOMMITTED"); - - match self.version { - Some(SqlServerVersion::V2017) if is_ci => format!("sqlserver://test-db-sqlserver-2017:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), - Some(SqlServerVersion::V2017) => format!("sqlserver://127.0.0.1:1434;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), - - Some(SqlServerVersion::V2019) if is_ci => format!("sqlserver://test-db-sqlserver-2019:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), - Some(SqlServerVersion::V2019) => format!("sqlserver://127.0.0.1:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), - - Some(SqlServerVersion::V2022) if is_ci => format!("sqlserver://test-db-sqlserver-2022:1433;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), - Some(SqlServerVersion::V2022) => format!("sqlserver://127.0.0.1:1435;{database};user=SA;password=;trustServerCertificate=true;isolationLevel={isolation_level}"), - - None => unreachable!("A versioned connector must have a concrete version to run."), - } - } - fn capabilities(&self) -> ConnectorCapabilities { psl::builtin_connectors::MSSQL.capabilities() } - - fn as_parse_pair(&self) -> (String, Option) { - let version = self.version.as_ref().map(ToString::to_string); - ("sqlserver".to_owned(), version) - } - - fn is_versioned(&self) -> bool { - true - } } #[derive(Debug, Clone, Copy, PartialEq)] @@ -65,46 +34,6 @@ pub enum SqlServerVersion { V2022, } -impl SqlServerConnectorTag { - pub fn new(version: Option<&str>) -> TestResult { - let version = match version { - Some(v) => Some(SqlServerVersion::try_from(v)?), - None => None, - }; - - Ok(Self { version }) - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![ - Self { - version: Some(SqlServerVersion::V2017), - }, - Self { - version: Some(SqlServerVersion::V2019), - }, - Self { - version: Some(SqlServerVersion::V2022), - }, - ] - } - - /// Get a reference to the sql server connector tag's version. - pub fn version(&self) -> Option { - self.version - } -} - -impl PartialEq for SqlServerConnectorTag { - fn eq(&self, other: &Self) -> bool { - match (self.version, other.version) { - (None, None) | (Some(_), None) | (None, Some(_)) => true, - (Some(v1), Some(v2)) => v1 == v2, - } - } -} - impl TryFrom<&str> for SqlServerVersion { type Error = TestError; diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sqlite.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sqlite.rs index 038d8127291d..16b16cf5ba22 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sqlite.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/sqlite.rs @@ -1,10 +1,18 @@ use super::*; -use crate::SqlDatamodelRenderer; +use crate::{BoxFuture, SqlDatamodelRenderer}; +use quaint::{prelude::Queryable, single::Quaint}; -#[derive(Debug, Default, Clone, PartialEq)] +#[derive(Debug, Default)] pub struct SqliteConnectorTag; impl ConnectorTagInterface for SqliteConnectorTag { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>> { + Box::pin(async move { + let conn = Quaint::new(connection_url).await?; + Ok(conn.raw_cmd(query).await?) + }) + } + fn datamodel_provider(&self) -> &'static str { "sqlite" } @@ -13,41 +21,7 @@ impl ConnectorTagInterface for SqliteConnectorTag { Box::new(SqlDatamodelRenderer::new()) } - fn connection_string( - &self, - database: &str, - _is_ci: bool, - _is_multi_schema: bool, - _: Option<&'static str>, - ) -> String { - let workspace_root = std::env::var("WORKSPACE_ROOT") - .unwrap_or_else(|_| ".".to_owned()) - .trim_end_matches('/') - .to_owned(); - - format!("file://{workspace_root}/db/{database}.db") - } - fn capabilities(&self) -> ConnectorCapabilities { psl::builtin_connectors::SQLITE.capabilities() } - - fn as_parse_pair(&self) -> (String, Option) { - ("sqlite".to_owned(), None) - } - - fn is_versioned(&self) -> bool { - false - } -} - -impl SqliteConnectorTag { - pub fn new() -> Self { - Self - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![Self::new()] - } } diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/vitess.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/vitess.rs index f8c228649372..7afb78bab630 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/vitess.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/connector_tag/vitess.rs @@ -1,13 +1,19 @@ use super::*; -use crate::{SqlDatamodelRenderer, TestResult}; +use crate::{BoxFuture, SqlDatamodelRenderer}; +use quaint::{prelude::Queryable, single::Quaint}; use std::{fmt::Display, str::FromStr}; #[derive(Debug, Default, Clone)] -pub struct VitessConnectorTag { - version: Option, -} +pub(crate) struct VitessConnectorTag; impl ConnectorTagInterface for VitessConnectorTag { + fn raw_execute<'a>(&'a self, query: &'a str, connection_url: &'a str) -> BoxFuture<'a, Result<(), TestError>> { + Box::pin(async move { + let conn = Quaint::new(connection_url).await?; + Ok(conn.raw_cmd(query).await?) + }) + } + fn datamodel_provider(&self) -> &'static str { "mysql" } @@ -16,33 +22,10 @@ impl ConnectorTagInterface for VitessConnectorTag { Box::new(SqlDatamodelRenderer::new()) } - fn connection_string( - &self, - _database: &str, - _is_ci: bool, - _is_multi_schema: bool, - _: Option<&'static str>, - ) -> String { - match self.version { - Some(VitessVersion::V5_7) => "mysql://root@localhost:33577/test".into(), - Some(VitessVersion::V8_0) => "mysql://root@localhost:33807/test".into(), - None => unreachable!("A versioned connector must have a concrete version to run."), - } - } - fn capabilities(&self) -> ConnectorCapabilities { psl::builtin_connectors::MYSQL.capabilities() } - fn as_parse_pair(&self) -> (String, Option) { - let version = self.version.as_ref().map(ToString::to_string); - ("vitess".to_owned(), version) - } - - fn is_versioned(&self) -> bool { - true - } - fn relation_mode(&self) -> &'static str { "prisma" } @@ -54,43 +37,6 @@ pub enum VitessVersion { V8_0, } -impl VitessConnectorTag { - pub fn new(version: Option<&str>) -> TestResult { - let version = match version { - Some(v) => Some(v.parse()?), - None => None, - }; - - Ok(Self { version }) - } - - /// Returns all versions of this connector. - pub fn all() -> Vec { - vec![ - Self { - version: Some(VitessVersion::V5_7), - }, - Self { - version: Some(VitessVersion::V8_0), - }, - ] - } - - /// Get a reference to the vitess connector tag's version. - pub fn version(&self) -> Option { - self.version - } -} - -impl PartialEq for VitessConnectorTag { - fn eq(&self, other: &Self) -> bool { - match (self.version, other.version) { - (None, None) | (Some(_), None) | (None, Some(_)) => true, - (Some(v1), Some(v2)) => v1 == v2, - } - } -} - impl FromStr for VitessVersion { type Err = TestError; diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/datamodel_rendering/mod.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/datamodel_rendering/mod.rs index e4eb97ec808b..ea7360c56fa6 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/datamodel_rendering/mod.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/datamodel_rendering/mod.rs @@ -4,7 +4,7 @@ mod sql_renderer; pub use mongodb_renderer::*; pub use sql_renderer::*; -use crate::{templating, ConnectorTagInterface, DatamodelFragment, IdFragment, M2mFragment, CONFIG}; +use crate::{connection_string, templating, DatamodelFragment, IdFragment, M2mFragment, CONFIG}; use indoc::indoc; use itertools::Itertools; use once_cell::sync::Lazy; @@ -36,7 +36,7 @@ pub fn render_test_datamodel( db_schemas: &[&str], isolation_level: Option<&'static str>, ) -> String { - let tag = CONFIG.test_connector_tag().unwrap(); + let (tag, version) = CONFIG.test_connector().unwrap(); let preview_features = render_preview_features(excluded_features); let is_multi_schema = !db_schemas.is_empty(); @@ -62,7 +62,13 @@ pub fn render_test_datamodel( }} "#}, tag.datamodel_provider(), - tag.connection_string(test_database, CONFIG.is_ci(), is_multi_schema, isolation_level), + connection_string( + &version, + test_database, + CONFIG.is_ci(), + is_multi_schema, + isolation_level + ), relation_mode_override.unwrap_or_else(|| tag.relation_mode().to_string()), schema_def, preview_features diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/lib.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/lib.rs index 098de16f81bd..0cdf3d1d3ef6 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/lib.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/lib.rs @@ -148,12 +148,12 @@ fn run_relation_link_test_impl( let test_db_name = format!("{suite_name}_{test_name}_{i}"); let template = dm.datamodel().to_owned(); - if !ConnectorTag::should_run(only, exclude, required_capabilities_for_test) { + if !should_run(only, exclude, required_capabilities_for_test) { continue; } let datamodel = render_test_datamodel(&test_db_name, template, &[], None, Default::default(), None); - let connector = CONFIG.test_connector_tag().unwrap(); + let (connector_tag, version) = CONFIG.test_connector().unwrap(); let metrics = setup_metrics(); let metrics_for_subscriber = metrics.clone(); let (log_capture, log_tx) = TestLogCapture::new(); @@ -161,7 +161,7 @@ fn run_relation_link_test_impl( run_with_tokio( async move { println!("Used datamodel:\n {}", datamodel.yellow()); - let runner = Runner::load(datamodel.clone(), &[], connector, metrics, log_capture) + let runner = Runner::load(datamodel.clone(), &[], version, connector_tag, metrics, log_capture) .await .unwrap(); @@ -243,7 +243,7 @@ fn run_connector_test_impl( referential_override: Option, test_fn: &dyn Fn(Runner) -> BoxFuture<'static, TestResult<()>>, ) { - if !ConnectorTag::should_run(only, exclude, capabilities) { + if !should_run(only, exclude, capabilities) { return; } @@ -256,7 +256,7 @@ fn run_connector_test_impl( db_schemas, None, ); - let connector = CONFIG.test_connector_tag().unwrap(); + let (connector_tag, version) = CONFIG.test_connector().unwrap(); let metrics = crate::setup_metrics(); let metrics_for_subscriber = metrics.clone(); @@ -265,9 +265,16 @@ fn run_connector_test_impl( crate::run_with_tokio( async { println!("Used datamodel:\n {}", datamodel.yellow()); - let runner = Runner::load(datamodel.clone(), db_schemas, connector, metrics, log_capture) - .await - .unwrap(); + let runner = Runner::load( + datamodel.clone(), + db_schemas, + version, + connector_tag, + metrics, + log_capture, + ) + .await + .unwrap(); test_fn(runner).await.unwrap(); diff --git a/query-engine/connector-test-kit-rs/query-tests-setup/src/runner/mod.rs b/query-engine/connector-test-kit-rs/query-tests-setup/src/runner/mod.rs index cfafde36f01b..6e6c030b7988 100644 --- a/query-engine/connector-test-kit-rs/query-tests-setup/src/runner/mod.rs +++ b/query-engine/connector-test-kit-rs/query-tests-setup/src/runner/mod.rs @@ -4,7 +4,6 @@ pub use json_adapter::*; use crate::{ConnectorTag, ConnectorVersion, QueryResult, TestLogCapture, TestResult, ENGINE_PROTOCOL}; use colored::Colorize; -use quaint::{prelude::Queryable, single::Quaint}; use query_core::{ protocol::EngineProtocol, schema::{self, QuerySchemaRef}, @@ -25,6 +24,7 @@ pub(crate) type Executor = Box; pub struct Runner { executor: Executor, query_schema: QuerySchemaRef, + version: ConnectorVersion, connector_tag: ConnectorTag, connection_url: String, current_tx_id: Option, @@ -41,6 +41,7 @@ impl Runner { pub async fn load( datamodel: String, db_schemas: &[&str], + connector_version: ConnectorVersion, connector_tag: ConnectorTag, metrics: MetricRegistry, log_capture: TestLogCapture, @@ -55,6 +56,7 @@ impl Runner { let query_schema: QuerySchemaRef = Arc::new(schema::build(Arc::new(schema), true)); Ok(Self { + version: connector_version, executor, query_schema, connector_tag, @@ -143,12 +145,7 @@ impl Runner { let query = query.into(); tracing::debug!("Raw execute: {}", query.clone().green()); - if matches!(self.connector_tag, ConnectorTag::MongoDb(_)) { - panic!("raw_execute is not supported for MongoDB yet"); - } - - let conn = Quaint::new(&self.connection_url).await?; - conn.raw_cmd(&query).await?; + self.connector_tag.raw_execute(&query, &self.connection_url).await?; Ok(()) } @@ -274,8 +271,8 @@ impl Runner { self.log_capture.get_logs().await } - pub fn connector_version(&self) -> ConnectorVersion { - ConnectorVersion::from(self.connector()) + pub fn connector_version(&self) -> &ConnectorVersion { + &self.version } pub fn protocol(&self) -> EngineProtocol { diff --git a/query-engine/js-connectors/src/proxy.rs b/query-engine/js-connectors/src/proxy.rs index 4d81f0436aef..8d3346851bfe 100644 --- a/query-engine/js-connectors/src/proxy.rs +++ b/query-engine/js-connectors/src/proxy.rs @@ -591,7 +591,7 @@ mod proxy_test { let json_value = serde_json::Value::String(s.to_string()); let quaint_value = js_value_to_quaint(json_value, column_type); - let date = NaiveDate::from_ymd(2023, 01, 01); + let date = NaiveDate::from_ymd_opt(2023, 01, 01).unwrap(); assert_eq!(quaint_value, QuaintValue::Date(Some(date))); } @@ -606,7 +606,7 @@ mod proxy_test { let json_value = serde_json::Value::String(s.to_string()); let quaint_value = js_value_to_quaint(json_value, column_type); - let time: NaiveTime = NaiveTime::from_hms(23, 59, 59); + let time: NaiveTime = NaiveTime::from_hms_opt(23, 59, 59).unwrap(); assert_eq!(quaint_value, QuaintValue::Time(Some(time))); } @@ -621,7 +621,10 @@ mod proxy_test { let json_value = serde_json::Value::String(s.to_string()); let quaint_value = js_value_to_quaint(json_value, column_type); - let datetime = NaiveDate::from_ymd(2023, 01, 01).and_hms(23, 59, 59); + let datetime = NaiveDate::from_ymd_opt(2023, 01, 01) + .unwrap() + .and_hms_opt(23, 59, 59) + .unwrap(); let datetime = DateTime::from_utc(datetime, Utc); assert_eq!(quaint_value, QuaintValue::DateTime(Some(datetime))); } @@ -642,7 +645,7 @@ mod proxy_test { null ] }); - let json_value = serde_json::Value::from(json.clone()); + let json_value = json.clone(); let quaint_value = js_value_to_quaint(json_value, column_type); assert_eq!(quaint_value, QuaintValue::Json(Some(json.clone()))); } diff --git a/schema-engine/sql-schema-describer/tests/test_api/mod.rs b/schema-engine/sql-schema-describer/tests/test_api/mod.rs index 433ae0c0aae4..1c10bfc23609 100644 --- a/schema-engine/sql-schema-describer/tests/test_api/mod.rs +++ b/schema-engine/sql-schema-describer/tests/test_api/mod.rs @@ -181,7 +181,7 @@ impl SqlSchemaAssertionsExt for SqlSchema { fn assert_not_namespace(&self, namespace_name: &str) -> &Self { self.walk_namespaces() .find(|ns| ns.name() == namespace_name) - .and_then::<(), _>(|_x| panic!("Found unexpected namespace '{namespace_name}'")); + .map::<(), _>(|_x| panic!("Found unexpected namespace '{namespace_name}'")); self } }