diff --git a/crates/tests/databases-tests/src/postgres/explain_tests.rs b/crates/tests/databases-tests/src/postgres/explain_tests.rs index 29459b684..8c93710d2 100644 --- a/crates/tests/databases-tests/src/postgres/explain_tests.rs +++ b/crates/tests/databases-tests/src/postgres/explain_tests.rs @@ -53,3 +53,33 @@ mod query { insta::assert_snapshot!(result.details.query); } } + +#[cfg(test)] +mod mutation { + use super::super::common::create_router; + use tests_common::assert::is_contained_in_lines; + use tests_common::request::run_mutation_explain; + + #[tokio::test] + async fn delete_playlist_track() { + let result = run_mutation_explain(create_router().await, "delete_playlist_track").await; + // is_contained_in_lines(vec!["Aggregate", "Scan", "35"], result.details.plan); + insta::assert_snapshot!(result + .details + .get("delete_playlist_track SQL Mutation") + .unwrap()); + } + + #[tokio::test] + async fn insert_artist_album() { + let result = run_mutation_explain(create_router().await, "insert_artist_album").await; + // is_contained_in_lines(vec!["Aggregate", "Scan", "35"], result.details.plan); + let queries = vec![ + result.details.get("insert_artist SQL Mutation").unwrap(), + "\n\n\n", + result.details.get("insert_album SQL Mutation").unwrap(), + ] + .concat(); + insta::assert_snapshot!(queries); + } +} diff --git a/crates/tests/databases-tests/src/postgres/mutation_tests.rs b/crates/tests/databases-tests/src/postgres/mutation_tests.rs index a4923438a..0b041d1eb 100644 --- a/crates/tests/databases-tests/src/postgres/mutation_tests.rs +++ b/crates/tests/databases-tests/src/postgres/mutation_tests.rs @@ -6,7 +6,7 @@ mod basic { use tests_common::request::{run_mutation, run_query}; #[tokio::test] - async fn delete_playlist() { + async fn delete_playlist_track() { let ndc_metadata = create_fresh_ndc_metadata( common::CONNECTION_STRING, common::CHINOOK_NDC_METADATA_PATH_V2, @@ -17,7 +17,7 @@ mod basic { let result = run_mutation( tests_common::router::create_router_from_ndc_metadata(&ndc_metadata.ndc_metadata_path) .await, - "delete_playlist", + "delete_playlist_track", ) .await; diff --git a/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__explain_tests__mutation__delete_playlist_track.snap b/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__explain_tests__mutation__delete_playlist_track.snap new file mode 100644 index 000000000..073749c48 --- /dev/null +++ b/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__explain_tests__mutation__delete_playlist_track.snap @@ -0,0 +1,40 @@ +--- +source: crates/tests/databases-tests/src/postgres/explain_tests.rs +expression: "result.details.get(\"delete_playlist_track SQL Mutation\").unwrap()" +--- +EXPLAIN WITH "%0_NATIVE_QUERY_delete_playlist_track" AS ( + DELETE FROM + public."PlaylistTrack" + WHERE + "TrackId" = 90 RETURNING * +) +SELECT + row_to_json("%2_universe") AS "universe" +FROM + ( + SELECT + * + FROM + ( + SELECT + json_build_array( + json_build_object( + '__value', + coalesce(json_agg(row_to_json("%3_returning")), '[]') + ) + ) AS "returning" + FROM + ( + SELECT + "%1_delete_playlist_track"."PlaylistId" AS "playlist_id" + FROM + "%0_NATIVE_QUERY_delete_playlist_track" AS "%1_delete_playlist_track" + ) AS "%3_returning" + ) AS "%3_returning" + CROSS JOIN ( + SELECT + COUNT(*) AS "affected_rows" + FROM + "%0_NATIVE_QUERY_delete_playlist_track" AS "%1_delete_playlist_track" + ) AS "%4_aggregates" + ) AS "%2_universe" diff --git a/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__explain_tests__mutation__insert_artist_album.snap b/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__explain_tests__mutation__insert_artist_album.snap new file mode 100644 index 000000000..3430b46f8 --- /dev/null +++ b/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__explain_tests__mutation__insert_artist_album.snap @@ -0,0 +1,106 @@ +--- +source: crates/tests/databases-tests/src/postgres/explain_tests.rs +expression: queries +--- +EXPLAIN WITH "%0_NATIVE_QUERY_insert_artist" AS ( + INSERT INTO + public."Artist" + VALUES + (276, cast($1 as varchar)) RETURNING * +) +SELECT + row_to_json("%2_universe") AS "universe" +FROM + ( + SELECT + * + FROM + ( + SELECT + json_build_array( + json_build_object( + '__value', + coalesce(json_agg(row_to_json("%3_returning")), '[]') + ) + ) AS "returning" + FROM + ( + SELECT + "%1_insert_artist"."ArtistId" AS "artist_id", + "%1_insert_artist"."Name" AS "name" + FROM + "%0_NATIVE_QUERY_insert_artist" AS "%1_insert_artist" + ) AS "%3_returning" + ) AS "%3_returning" + CROSS JOIN ( + SELECT + COUNT(*) AS "affected_rows" + FROM + "%0_NATIVE_QUERY_insert_artist" AS "%1_insert_artist" + ) AS "%4_aggregates" + ) AS "%2_universe" + + +EXPLAIN WITH "%0_NATIVE_QUERY_insert_album" AS ( + INSERT INTO + public."Album" + VALUES +(348, cast($1 as varchar), 276) RETURNING * +) +SELECT + row_to_json("%6_universe") AS "universe" +FROM + ( + SELECT + * + FROM + ( + SELECT + json_build_array( + json_build_object( + '__value', + coalesce(json_agg(row_to_json("%7_returning")), '[]') + ) + ) AS "returning" + FROM + ( + SELECT + "%1_insert_album"."AlbumId" AS "album_id", + "%1_insert_album"."Title" AS "title", + "%2_RELATIONSHIP_artist"."artist" AS "artist" + FROM + "%0_NATIVE_QUERY_insert_album" AS "%1_insert_album" + LEFT OUTER JOIN LATERAL ( + SELECT + row_to_json("%2_RELATIONSHIP_artist") AS "artist" + FROM + ( + SELECT + * + FROM + ( + SELECT + coalesce(json_agg(row_to_json("%4_rows")), '[]') AS "rows" + FROM + ( + SELECT + "%3_Artist"."Name" AS "name" + FROM + "public"."Artist" AS "%3_Artist" + WHERE + ( + "%1_insert_album"."ArtistId" = "%3_Artist"."ArtistId" + ) + ) AS "%4_rows" + ) AS "%4_rows" + ) AS "%2_RELATIONSHIP_artist" + ) AS "%2_RELATIONSHIP_artist" ON ('true') + ) AS "%7_returning" + ) AS "%7_returning" + CROSS JOIN ( + SELECT + COUNT(*) AS "affected_rows" + FROM + "%0_NATIVE_QUERY_insert_album" AS "%1_insert_album" + ) AS "%8_aggregates" + ) AS "%6_universe" diff --git a/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__mutation_tests__basic__delete_playlist.snap b/crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__mutation_tests__basic__delete_playlist_track.snap similarity index 100% rename from crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__mutation_tests__basic__delete_playlist.snap rename to crates/tests/databases-tests/src/postgres/snapshots/databases_tests__postgres__mutation_tests__basic__delete_playlist_track.snap diff --git a/crates/tests/tests-common/goldenfiles/mutations/delete_playlist.json b/crates/tests/tests-common/goldenfiles/mutations/delete_playlist_track.json similarity index 100% rename from crates/tests/tests-common/goldenfiles/mutations/delete_playlist.json rename to crates/tests/tests-common/goldenfiles/mutations/delete_playlist_track.json diff --git a/crates/tests/tests-common/src/request.rs b/crates/tests/tests-common/src/request.rs index dac5ce287..d7a402b61 100644 --- a/crates/tests/tests-common/src/request.rs +++ b/crates/tests/tests-common/src/request.rs @@ -16,6 +16,11 @@ pub async fn run_query422(router: axum::Router, testname: &str) -> ndc_sdk::mode run_against_server(router, "query", testname, StatusCode::UNPROCESSABLE_ENTITY).await } +#[derive(Clone, Debug, PartialEq, Deserialize)] +pub struct InexactExplainResponse { + pub details: std::collections::BTreeMap, +} + #[derive(Clone, Debug, PartialEq, Deserialize)] pub struct ExactExplainResponse { pub details: ExplainDetails, @@ -34,6 +39,17 @@ pub async fn run_query_explain(router: axum::Router, testname: &str) -> ExactExp run_against_server(router, "query/explain", testname, StatusCode::OK).await } +/// Run a mutation against the server, get the result, and compare against the snapshot. +pub async fn run_mutation_explain(router: axum::Router, testname: &str) -> InexactExplainResponse { + run_against_server( + router, + "mutation/explain", + &format!("mutations/{}", testname), + StatusCode::OK, + ) + .await +} + /// Run a mutation against the server, get the result, and compare against the snapshot. pub async fn run_mutation( router: axum::Router,