-
Notifications
You must be signed in to change notification settings - Fork 245
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e21db88
commit b1285c0
Showing
1 changed file
with
311 additions
and
2 deletions.
There are no files selected for viewing
313 changes: 311 additions & 2 deletions
313
...test-kit-rs/query-engine-tests/tests/writes/top_level_mutations/update_many_and_return.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,313 @@ | ||
use query_engine_tests::*; | ||
|
||
#[test_suite(capabilities(UpdateMany, UpdateReturning))] | ||
mod update_many_and_return {} | ||
#[test_suite(schema(schema), capabilities(UpdateReturning))] | ||
mod update_many_and_return { | ||
use indoc::indoc; | ||
use query_engine_tests::{is_one_of, run_query, run_query_json}; | ||
|
||
fn schema() -> String { | ||
let schema = indoc! { | ||
r#"model TestModel { | ||
#id(id, Int, @id) | ||
optStr String? | ||
optInt Int? | ||
optFloat Float? | ||
}"# | ||
}; | ||
|
||
schema.to_owned() | ||
} | ||
|
||
// "An updateManyAndReturn mutation" should "update the records matching the where clause" | ||
#[connector_test] | ||
async fn update_recs_matching_where(runner: Runner) -> TestResult<()> { | ||
create_row(&runner, r#"{ id: 1, optStr: "str1" }"#).await?; | ||
create_row(&runner, r#"{ id: 2, optStr: "str2" }"#).await?; | ||
|
||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { | ||
updateManyTestModelAndReturn( | ||
where: { optStr: { equals: "str1" } } | ||
data: { optStr: { set: "str1new" }, optInt: { set: 1 }, optFloat: { multiply: 2 } } | ||
) { | ||
optStr optInt optFloat | ||
} | ||
}"#), | ||
@r###"{"data":{"updateManyTestModelAndReturn":[{"optStr":"str1new","optInt":1,"optFloat":null}]}}"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
// "An updateMany mutation" should "update the records matching the where clause using shorthands" | ||
#[connector_test] | ||
async fn update_recs_matching_where_shorthands(runner: Runner) -> TestResult<()> { | ||
create_row(&runner, r#"{ id: 1, optStr: "str1" }"#).await?; | ||
create_row(&runner, r#"{ id: 2, optStr: "str2" }"#).await?; | ||
|
||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { | ||
updateManyTestModelAndReturn( | ||
where: { optStr: "str1" } | ||
data: { optStr: "str1new", optInt: null, optFloat: { multiply: 2 } } | ||
) { | ||
optStr optInt optFloat | ||
} | ||
}"#), | ||
@r###"{"data":{"updateManyTestModelAndReturn":[{"optStr":"str1new","optInt":null,"optFloat":null}]}}"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
// "An updateManyAndReturn mutation" should "update all items if the where clause is empty" | ||
#[connector_test] | ||
async fn update_all_items_if_where_empty(runner: Runner) -> TestResult<()> { | ||
create_row(&runner, r#"{ id: 2, optStr: "str2", optInt: 2 }"#).await?; | ||
create_row(&runner, r#"{ id: 3, optStr: "str3", optInt: 3, optFloat: 3.1 }"#).await?; | ||
|
||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { | ||
updateManyTestModelAndReturn( | ||
where: { } | ||
data: { optStr: { set: "updated" }, optFloat: { divide: 2 }, optInt: { decrement: 1 } } | ||
){ | ||
optStr optInt optFloat | ||
} | ||
}"#), | ||
@r###"{"data":{"updateManyTestModelAndReturn":[{"optStr":"updated","optInt":1,"optFloat":null},{"optStr":"updated","optInt":2,"optFloat":1.55}]}}"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
// "An updateManyAndReturn mutation" should "correctly apply all number operations for Int" | ||
#[connector_test(exclude(CockroachDb))] | ||
async fn apply_number_ops_for_int(runner: Runner) -> TestResult<()> { | ||
create_row(&runner, r#"{ id: 1, optStr: "str1" }"#).await?; | ||
create_row(&runner, r#"{ id: 2, optStr: "str2", optInt: 2 }"#).await?; | ||
create_row(&runner, r#"{ id: 3, optStr: "str3", optInt: 3, optFloat: 3.1 }"#).await?; | ||
|
||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "increment", "10").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":12},{"optInt":13}]"#, | ||
r#"[{"optInt":10},{"optInt":12},{"optInt":13}]"# | ||
] | ||
); | ||
|
||
// optInts before this op are now: null/10, 12, 13 | ||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "decrement", "10").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":2},{"optInt":3}]"#, | ||
r#"[{"optInt":0},{"optInt":2},{"optInt":3}]"# | ||
] | ||
); | ||
|
||
// optInts before this op are now: null/0, 2, 3 | ||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "multiply", "2").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":4},{"optInt":6}]"#, | ||
r#"[{"optInt":0},{"optInt":4},{"optInt":6}]"# | ||
] | ||
); | ||
|
||
// Todo: Mongo divisions are broken | ||
if !matches!(runner.connector_version(), ConnectorVersion::MongoDb(_)) { | ||
// optInts before this op are now: null/0, 4, 6 | ||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "divide", "3").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":1},{"optInt":2}]"#, | ||
r#"[{"optInt":0},{"optInt":1},{"optInt":2}]"# | ||
] | ||
); | ||
} | ||
|
||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "set", "5").await?, | ||
[ | ||
r#"[{"optInt":5},{"optInt":5},{"optInt":5}]"#, | ||
r#"[{"optInt":5},{"optInt":5},{"optInt":5}]"# | ||
] | ||
); | ||
|
||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "set", "null").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":null},{"optInt":null}]"#, | ||
r#"[{"optInt":null},{"optInt":null},{"optInt":null}]"# | ||
] | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
// CockroachDB does not support the "divide" operator as is. | ||
// See https://github.com/cockroachdb/cockroach/issues/41448. | ||
#[connector_test(only(CockroachDb))] | ||
async fn apply_number_ops_for_int_cockroach(runner: Runner) -> TestResult<()> { | ||
create_row(&runner, r#"{ id: 1, optStr: "str1" }"#).await?; | ||
create_row(&runner, r#"{ id: 2, optStr: "str2", optInt: 2 }"#).await?; | ||
create_row(&runner, r#"{ id: 3, optStr: "str3", optInt: 3, optFloat: 3.1 }"#).await?; | ||
|
||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "increment", "10").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":12},{"optInt":13}]"#, | ||
r#"[{"optInt":10},{"optInt":12},{"optInt":13}]"# | ||
] | ||
); | ||
|
||
// optInts before this op are now: null/10, 12, 13 | ||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "decrement", "10").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":2},{"optInt":3}]"#, | ||
r#"[{"optInt":0},{"optInt":2},{"optInt":3}]"# | ||
] | ||
); | ||
|
||
// optInts before this op are now: null/0, 2, 3 | ||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "multiply", "2").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":4},{"optInt":6}]"#, | ||
r#"[{"optInt":0},{"optInt":4},{"optInt":6}]"# | ||
] | ||
); | ||
|
||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "set", "5").await?, | ||
[ | ||
r#"[{"optInt":5},{"optInt":5},{"optInt":5}]"#, | ||
r#"[{"optInt":5},{"optInt":5},{"optInt":5}]"# | ||
] | ||
); | ||
|
||
is_one_of!( | ||
query_number_operation(&runner, "optInt", "set", "null").await?, | ||
[ | ||
r#"[{"optInt":null},{"optInt":null},{"optInt":null}]"#, | ||
r#"[{"optInt":null},{"optInt":null},{"optInt":null}]"# | ||
] | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
// "An updateManyAndReturn mutation" should "correctly apply all number operations for Float" | ||
#[connector_test] | ||
async fn apply_number_ops_for_float(runner: Runner) -> TestResult<()> { | ||
create_row(&runner, r#"{ id: 1, optStr: "str1" }"#).await?; | ||
create_row(&runner, r#"{ id: 2, optStr: "str2", optFloat: 2 }"#).await?; | ||
create_row(&runner, r#"{ id: 3, optStr: "str3", optFloat: 3.1 }"#).await?; | ||
|
||
insta::assert_snapshot!( | ||
query_number_operation(&runner, "optFloat", "increment", "1.1").await?, | ||
@r###"[{"optFloat":null},{"optFloat":3.1},{"optFloat":4.2}]"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
query_number_operation(&runner, "optFloat", "decrement", "1.1").await?, | ||
@r###"[{"optFloat":null},{"optFloat":2.0},{"optFloat":3.1}]"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
query_number_operation(&runner, "optFloat", "multiply", "5.5").await?, | ||
@r###"[{"optFloat":null},{"optFloat":11.0},{"optFloat":17.05}]"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
query_number_operation(&runner, "optFloat", "divide", "2").await?, | ||
@r###"[{"optFloat":null},{"optFloat":5.5},{"optFloat":8.525}]"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
query_number_operation(&runner, "optFloat", "set", "5").await?, | ||
@r###"[{"optFloat":5.0},{"optFloat":5.0},{"optFloat":5.0}]"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
query_number_operation(&runner, "optFloat", "set", "null").await?, | ||
@r###"[{"optFloat":null},{"optFloat":null},{"optFloat":null}]"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn query_number_operation(runner: &Runner, field: &str, op: &str, value: &str) -> TestResult<String> { | ||
let res = run_query_json!( | ||
runner, | ||
format!( | ||
r#"mutation {{ | ||
updateManyTestModelAndReturn( | ||
where: {{}} | ||
data: {{ {field}: {{ {op}: {value} }} }} | ||
){{ | ||
{field} | ||
}} | ||
}}"# | ||
) | ||
); | ||
|
||
Ok(res["data"]["updateManyTestModelAndReturn"].to_string()) | ||
} | ||
|
||
async fn create_row(runner: &Runner, data: &str) -> TestResult<()> { | ||
runner | ||
.query(format!("mutation {{ createOneTestModel(data: {data}) {{ id }} }}")) | ||
.await? | ||
.assert_success(); | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
#[test_suite(schema(json_opt), exclude(MySql(5.6)), capabilities(Json))] | ||
mod json_update_many_and_return { | ||
use query_engine_tests::{assert_error, run_query}; | ||
|
||
#[connector_test(capabilities(AdvancedJsonNullability))] | ||
async fn update_json_adv(runner: Runner) -> TestResult<()> { | ||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { createOneTestModel(data: { id: 1 }) { json }}"#), | ||
@r###"{"data":{"createOneTestModel":{"json":null}}}"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { updateManyTestModelAndReturn(where: { id: 1 }, data: { json: "{}" }) { json }}"#), | ||
@r###"{"data":{"updateManyTestModelAndReturn":[{"json":"{}"}]}}"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { updateManyTestModelAndReturn(where: { id: 1 }, data: { json: JsonNull }) { json }}"#), | ||
@r###"{"data":{"updateManyTestModelAndReturn":[{"json":"null"}]}}"### | ||
); | ||
|
||
insta::assert_snapshot!( | ||
run_query!(&runner, r#"mutation { updateManyTestModelAndReturn(where: { id: 1 }, data: { json: DbNull }) { json }}"#), | ||
@r###"{"data":{"updateManyTestModelAndReturn":[{"json":null}]}}"### | ||
); | ||
|
||
Ok(()) | ||
} | ||
|
||
#[connector_test(capabilities(AdvancedJsonNullability))] | ||
async fn update_json_errors(runner: Runner) -> TestResult<()> { | ||
assert_error!( | ||
&runner, | ||
r#"mutation { | ||
updateManyTestModelAndReturn(where: { id: 1 }, data: { json: AnyNull }) { | ||
id | ||
} | ||
}"#, | ||
2009, | ||
"`AnyNull` is not a valid `NullableJsonNullValueInput`" | ||
); | ||
|
||
Ok(()) | ||
} | ||
} |