From 1d8c4d9b827b07bbe997188485c8fde6ce40efc3 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Mon, 20 May 2024 13:44:04 +0200 Subject: [PATCH 01/14] feat(query-structure): Add support for UUIDv7 --- Cargo.lock | 11 +++++- Cargo.toml | 2 +- query-engine/query-structure/Cargo.toml | 2 +- .../query-structure/src/default_value.rs | 39 +++++++++++++------ .../query-structure/src/field/scalar.rs | 11 +++++- 5 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d7dff484d83..fcf4d1c2642e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,6 +177,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "atomic-shim" version = "0.2.0" @@ -6079,10 +6085,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ + "atomic", "getrandom 0.2.11", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 2a3077fbf0eb..04d2fd79ac30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ tokio = { version = "1.25", features = [ ] } chrono = { version = "0.4", features = ["serde"] } user-facing-errors = { path = "./libs/user-facing-errors" } -uuid = { version = "1", features = ["serde", "v4"] } +uuid = { version = "1", features = ["serde", "v4", "v7"] } indoc = "2.0.1" indexmap = { version = "2.2.2", features = ["serde"] } itertools = "0.12" diff --git a/query-engine/query-structure/Cargo.toml b/query-engine/query-structure/Cargo.toml index f990c48ffd4b..847d97bee2ff 100644 --- a/query-engine/query-structure/Cargo.toml +++ b/query-engine/query-structure/Cargo.toml @@ -22,4 +22,4 @@ features = ["js"] [features] # Support for generating default UUID, CUID, nanoid and datetime values. -default_generators = ["uuid/v4", "cuid", "nanoid"] +default_generators = ["uuid/v4", "uuid/v7", "cuid", "nanoid"] diff --git a/query-engine/query-structure/src/default_value.rs b/query-engine/query-structure/src/default_value.rs index 9eaf6828d1c8..0187dcd852e6 100644 --- a/query-engine/query-structure/src/default_value.rs +++ b/query-engine/query-structure/src/default_value.rs @@ -45,7 +45,7 @@ impl DefaultKind { /// Does this match @default(uuid(_))? pub fn is_uuid(&self) -> bool { - matches!(self, DefaultKind::Expression(generator) if generator.name == "uuid") + matches!(self, DefaultKind::Expression(generator) if generator.name.starts_with("uuid")) } pub fn unwrap_single(self) -> PrismaValue { @@ -186,8 +186,8 @@ impl ValueGenerator { ValueGenerator::new("cuid".to_owned(), vec![]).unwrap() } - pub fn new_uuid() -> Self { - ValueGenerator::new("uuid".to_owned(), vec![]).unwrap() + pub fn new_uuid(version: u8) -> Self { + ValueGenerator::new(format!("uuid({version})"), vec![]).unwrap() } pub fn new_nanoid(length: Option) -> Self { @@ -196,7 +196,7 @@ impl ValueGenerator { format!("nanoid({length})"), vec![(None, PrismaValue::Int(length.into()))], ) - .unwrap() + .unwrap() } else { ValueGenerator::new("nanoid()".to_owned(), vec![]).unwrap() } @@ -238,7 +238,7 @@ impl ValueGenerator { #[derive(Clone, Copy, PartialEq)] pub enum ValueGeneratorFn { - Uuid, + Uuid(u8), Cuid, Nanoid(Option), Now, @@ -251,7 +251,8 @@ impl ValueGeneratorFn { fn new(name: &str) -> std::result::Result { match name { "cuid" => Ok(Self::Cuid), - "uuid" => Ok(Self::Uuid), + "uuid" | "uuid(4)" => Ok(Self::Uuid(4)), + "uuid(7)" => Ok(Self::Uuid(7)), "now" => Ok(Self::Now), "autoincrement" => Ok(Self::Autoincrement), "sequence" => Ok(Self::Autoincrement), @@ -265,7 +266,7 @@ impl ValueGeneratorFn { #[cfg(feature = "default_generators")] fn invoke(&self) -> Option { match self { - Self::Uuid => Some(Self::generate_uuid()), + Self::Uuid(version) => Some(Self::generate_uuid(*version)), Self::Cuid => Some(Self::generate_cuid()), Self::Nanoid(length) => Some(Self::generate_nanoid(length)), Self::Now => Some(Self::generate_now()), @@ -282,8 +283,16 @@ impl ValueGeneratorFn { } #[cfg(feature = "default_generators")] - fn generate_uuid() -> PrismaValue { - PrismaValue::Uuid(uuid::Uuid::new_v4()) + fn generate_uuid(version: u8) -> PrismaValue { + PrismaValue::Uuid(match version { + 4 => uuid::Uuid::new_v4(), + 7 => { + let now = chrono::Utc::now(); + let timestamp = uuid::Timestamp::from_unix(uuid::NoContext, now.timestamp() as u64, now.timestamp_subsec_nanos()); + uuid::Uuid::new_v7(timestamp) + } + _ => panic!("Unknown UUID version: {}", version), + }) } #[cfg(feature = "default_generators")] @@ -337,8 +346,16 @@ mod tests { } #[test] - fn default_value_is_uuid() { - let uuid_default = DefaultValue::new_expression(ValueGenerator::new_uuid()); + fn default_value_is_uuidv4() { + let uuid_default = DefaultValue::new_expression(ValueGenerator::new_uuid(4)); + + assert!(uuid_default.is_uuid()); + assert!(!uuid_default.is_autoincrement()); + } + + #[test] + fn default_value_is_uuidv7() { + let uuid_default = DefaultValue::new_expression(ValueGenerator::new_uuid(7)); assert!(uuid_default.is_uuid()); assert!(!uuid_default.is_autoincrement()); diff --git a/query-engine/query-structure/src/field/scalar.rs b/query-engine/query-structure/src/field/scalar.rs index 8aeb9c7f47aa..5fc10acddd13 100644 --- a/query-engine/query-structure/src/field/scalar.rs +++ b/query-engine/query-structure/src/field/scalar.rs @@ -244,8 +244,15 @@ pub fn dml_default_kind(default_value: &ast::Expression, scalar_type: Option { DefaultKind::Expression(ValueGenerator::new_sequence(Vec::new())) } - ast::Expression::Function(funcname, _args, _) if funcname == "uuid" => { - DefaultKind::Expression(ValueGenerator::new_uuid()) + ast::Expression::Function(funcname, args, _) if funcname == "uuid" => { + let version = args + .arguments + .first() + .and_then(|arg| arg.value.as_numeric_value()) + .map(|(val, _)| val.parse::().unwrap()) + .unwrap_or(4); + + DefaultKind::Expression(ValueGenerator::new_uuid(version)) } ast::Expression::Function(funcname, _args, _) if funcname == "cuid" => { DefaultKind::Expression(ValueGenerator::new_cuid()) From 13b844121b30ff960e4aaac9e149f2b1a23df7e8 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Mon, 20 May 2024 13:58:32 +0200 Subject: [PATCH 02/14] feat(psl): Add support for UUIDv7 --- psl/parser-database/src/attributes/default.rs | 49 ++++++++++++++----- psl/psl/tests/attributes/id_negative.rs | 24 +++++++++ psl/psl/tests/attributes/id_positive.rs | 39 +++++++++++++++ 3 files changed, 99 insertions(+), 13 deletions(-) diff --git a/psl/parser-database/src/attributes/default.rs b/psl/parser-database/src/attributes/default.rs index e2be240f152c..6c3288c50cbd 100644 --- a/psl/parser-database/src/attributes/default.rs +++ b/psl/parser-database/src/attributes/default.rs @@ -192,14 +192,16 @@ fn validate_model_builtin_scalar_type_default( } (ScalarType::Int, ast::Expression::Function(funcname, funcargs, _)) | (ScalarType::BigInt, ast::Expression::Function(funcname, funcargs, _)) - if funcname == FN_AUTOINCREMENT => - { - validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) - } - (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) - if funcname == FN_UUID || funcname == FN_CUID => - { - validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + if funcname == FN_AUTOINCREMENT => + { + validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => + { + validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_UUID => { + validate_uuid_args(&funcargs.arguments, accept, ctx) } (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_NANOID => { validate_nanoid_args(&funcargs.arguments, accept, ctx) @@ -242,11 +244,14 @@ fn validate_composite_builtin_scalar_type_default( ) { match (scalar_type, value) { // Functions - (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) - if funcname == FN_UUID || funcname == FN_CUID => - { - validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) - } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => + { + validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_UUID => + { + validate_uuid_args(&funcargs.arguments, accept, ctx) + } (ScalarType::DateTime, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_NOW => { validate_empty_function_args(FN_NOW, &funcargs.arguments, accept, ctx) } @@ -379,6 +384,24 @@ fn validate_dbgenerated_args(args: &[ast::Argument], accept: AcceptFn<'_>, ctx: } } +fn validate_uuid_args(args: &[ast::Argument], accept: AcceptFn<'_>, ctx: &mut Context<'_>) { + let mut bail = || ctx.push_attribute_validation_error("`uuid()` takes a single Int argument."); + + if args.len() > 1 { + bail() + } + + match args.first().map(|arg| &arg.value) { + Some(ast::Expression::NumericValue(val, _)) if ![4u8, 7u8].contains(&val.parse::().unwrap()) => { + ctx.push_attribute_validation_error( + "`uuid()` takes either no argument, or a single integer argument which is either 4 or 7.", + ); + } + None | Some(ast::Expression::NumericValue(_, _)) => accept(ctx), + _ => bail(), + } +} + fn validate_nanoid_args(args: &[ast::Argument], accept: AcceptFn<'_>, ctx: &mut Context<'_>) { let mut bail = || ctx.push_attribute_validation_error("`nanoid()` takes a single Int argument."); diff --git a/psl/psl/tests/attributes/id_negative.rs b/psl/psl/tests/attributes/id_negative.rs index ce4a1ccbaa4d..84bdcc5b7cbe 100644 --- a/psl/psl/tests/attributes/id_negative.rs +++ b/psl/psl/tests/attributes/id_negative.rs @@ -44,6 +44,30 @@ fn id_should_error_multiple_ids_are_provided() { expect_error(dml, &expectation) } +#[test] +fn id_should_error_on_invalid_uuid_version() { + let dml = indoc! {r#" + model Model { + id Int @id + internalId String @id @default(uuid(1)) + } + "#}; + + let expectation = expect![[r#" + error: Error validating model "Model": `uuid()` takes either no argument, or a single integer argument which is either 4 or 7.. + --> schema.prisma:1 +  |  +  |  +  1 | model Model { +  2 |  id Int @id +  3 |  internalId String @id @default(uuid(1)) +  4 | } +  |  + "#]]; + + expect_error(dml, &expectation) +} + #[test] fn id_must_error_when_single_and_multi_field_id_is_used() { let dml = indoc! {r#" diff --git a/psl/psl/tests/attributes/id_positive.rs b/psl/psl/tests/attributes/id_positive.rs index 396c334f94fd..e81c1305c274 100644 --- a/psl/psl/tests/attributes/id_positive.rs +++ b/psl/psl/tests/attributes/id_positive.rs @@ -70,6 +70,45 @@ fn should_allow_string_ids_with_uuid() { model.assert_id_on_fields(&["id"]); } +#[test] +fn should_allow_string_ids_with_uuid_version_specified() { + let dml = indoc! {r#" + model ModelA { + id String @id @default(uuid(4)) + } + + model ModelB { + id String @id @default(uuid(7)) + } + "#}; + + let schema = psl::parse_schema(dml).unwrap(); + + { + let model = schema.assert_has_model("ModelA"); + + model + .assert_has_scalar_field("id") + .assert_scalar_type(ScalarType::String) + .assert_default_value() + .assert_uuid(); + + model.assert_id_on_fields(&["id"]); + } + + { + let model = schema.assert_has_model("ModelB"); + + model + .assert_has_scalar_field("id") + .assert_scalar_type(ScalarType::String) + .assert_default_value() + .assert_uuid(); + + model.assert_id_on_fields(&["id"]); + } +} + #[test] fn should_allow_string_ids_without_default() { let dml = indoc! {r#" From d292155bd7420ae2428532be691e439fd7bb9738 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 21 May 2024 11:04:31 +0200 Subject: [PATCH 03/14] fixup! feat(psl): Add support for UUIDv7 --- psl/psl/tests/attributes/id_negative.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/psl/psl/tests/attributes/id_negative.rs b/psl/psl/tests/attributes/id_negative.rs index 84bdcc5b7cbe..97bd97f0f5a4 100644 --- a/psl/psl/tests/attributes/id_negative.rs +++ b/psl/psl/tests/attributes/id_negative.rs @@ -48,19 +48,17 @@ fn id_should_error_multiple_ids_are_provided() { fn id_should_error_on_invalid_uuid_version() { let dml = indoc! {r#" model Model { - id Int @id - internalId String @id @default(uuid(1)) + id String @id @default(uuid(1)) } "#}; let expectation = expect![[r#" - error: Error validating model "Model": `uuid()` takes either no argument, or a single integer argument which is either 4 or 7.. + error: Error parsing attribute "@default": `uuid()` takes either no argument, or a single integer argument which is either 4 or 7. --> schema.prisma:1  |   |   1 | model Model { -  2 |  id Int @id -  3 |  internalId String @id @default(uuid(1)) +  3 |  id String @id @default(uuid(1))  4 | }  |  "#]]; From be2f8decb33ea58833815169711d42be66fb56c0 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 21 May 2024 11:05:01 +0200 Subject: [PATCH 04/14] fixup! feat(psl): Add support for UUIDv7 --- psl/parser-database/src/attributes/default.rs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/psl/parser-database/src/attributes/default.rs b/psl/parser-database/src/attributes/default.rs index 6c3288c50cbd..eeef7f4fe004 100644 --- a/psl/parser-database/src/attributes/default.rs +++ b/psl/parser-database/src/attributes/default.rs @@ -196,10 +196,9 @@ fn validate_model_builtin_scalar_type_default( { validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) } - (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => - { - validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) - } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => { + validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + } (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_UUID => { validate_uuid_args(&funcargs.arguments, accept, ctx) } @@ -244,14 +243,12 @@ fn validate_composite_builtin_scalar_type_default( ) { match (scalar_type, value) { // Functions - (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => - { - validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) - } - (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_UUID => - { - validate_uuid_args(&funcargs.arguments, accept, ctx) - } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => { + validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + } + (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_UUID => { + validate_uuid_args(&funcargs.arguments, accept, ctx) + } (ScalarType::DateTime, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_NOW => { validate_empty_function_args(FN_NOW, &funcargs.arguments, accept, ctx) } From 302cceb2879b40440cea035b7277bdbc344a2d86 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 21 May 2024 12:00:58 +0200 Subject: [PATCH 05/14] fixup! feat(psl): Add support for UUIDv7 --- psl/parser-database/src/attributes/default.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/psl/parser-database/src/attributes/default.rs b/psl/parser-database/src/attributes/default.rs index eeef7f4fe004..d1f6b887fa22 100644 --- a/psl/parser-database/src/attributes/default.rs +++ b/psl/parser-database/src/attributes/default.rs @@ -192,10 +192,10 @@ fn validate_model_builtin_scalar_type_default( } (ScalarType::Int, ast::Expression::Function(funcname, funcargs, _)) | (ScalarType::BigInt, ast::Expression::Function(funcname, funcargs, _)) - if funcname == FN_AUTOINCREMENT => - { - validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) - } + if funcname == FN_AUTOINCREMENT => + { + validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) + } (ScalarType::String, ast::Expression::Function(funcname, funcargs, _)) if funcname == FN_CUID => { validate_empty_function_args(funcname, &funcargs.arguments, accept, ctx) } From 3641680042594d6f96f082bb8b112787a99a6cd1 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 21 May 2024 12:01:13 +0200 Subject: [PATCH 06/14] fixup! feat(query-structure): Add support for UUIDv7 --- query-engine/query-structure/src/default_value.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/query-engine/query-structure/src/default_value.rs b/query-engine/query-structure/src/default_value.rs index 0187dcd852e6..8a2d0dc76397 100644 --- a/query-engine/query-structure/src/default_value.rs +++ b/query-engine/query-structure/src/default_value.rs @@ -196,7 +196,7 @@ impl ValueGenerator { format!("nanoid({length})"), vec![(None, PrismaValue::Int(length.into()))], ) - .unwrap() + .unwrap() } else { ValueGenerator::new("nanoid()".to_owned(), vec![]).unwrap() } @@ -288,7 +288,8 @@ impl ValueGeneratorFn { 4 => uuid::Uuid::new_v4(), 7 => { let now = chrono::Utc::now(); - let timestamp = uuid::Timestamp::from_unix(uuid::NoContext, now.timestamp() as u64, now.timestamp_subsec_nanos()); + let timestamp = + uuid::Timestamp::from_unix(uuid::NoContext, now.timestamp() as u64, now.timestamp_subsec_nanos()); uuid::Uuid::new_v7(timestamp) } _ => panic!("Unknown UUID version: {}", version), From 4eb8aaa1079621e99e240cc3a38918e8e3fd5beb Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 21 May 2024 12:17:22 +0200 Subject: [PATCH 07/14] fixup! fixup! feat(psl): Add support for UUIDv7 --- psl/psl/tests/attributes/id_negative.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/psl/psl/tests/attributes/id_negative.rs b/psl/psl/tests/attributes/id_negative.rs index 97bd97f0f5a4..ef5d26064018 100644 --- a/psl/psl/tests/attributes/id_negative.rs +++ b/psl/psl/tests/attributes/id_negative.rs @@ -54,12 +54,11 @@ fn id_should_error_on_invalid_uuid_version() { let expectation = expect![[r#" error: Error parsing attribute "@default": `uuid()` takes either no argument, or a single integer argument which is either 4 or 7. - --> schema.prisma:1 + --> schema.prisma:2  |   |   1 | model Model { -  3 |  id String @id @default(uuid(1)) -  4 | } +  2 |  id String @id @default(uuid(1))  |  "#]]; From d006af38194d25f20d7fdfb6b6f025b8a8febb36 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 21 May 2024 14:47:40 +0200 Subject: [PATCH 08/14] fixup! feat(psl): Add support for UUIDv7 --- psl/psl/tests/attributes/id_negative.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/psl/psl/tests/attributes/id_negative.rs b/psl/psl/tests/attributes/id_negative.rs index ef5d26064018..bc3c9785118c 100644 --- a/psl/psl/tests/attributes/id_negative.rs +++ b/psl/psl/tests/attributes/id_negative.rs @@ -56,9 +56,8 @@ fn id_should_error_on_invalid_uuid_version() { error: Error parsing attribute "@default": `uuid()` takes either no argument, or a single integer argument which is either 4 or 7. --> schema.prisma:2  |  -  |  -  1 | model Model { -  2 |  id String @id @default(uuid(1)) +  1 | model Model { +  2 |  id String @id @default(uuid(1))  |  "#]]; From 46047f6cd27659bb683378f3e9eba6f820ee3cd9 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Thu, 23 May 2024 10:28:18 +0200 Subject: [PATCH 09/14] fixup! feat(psl): Add support for UUIDv7 --- psl/psl/tests/common/asserts.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/psl/psl/tests/common/asserts.rs b/psl/psl/tests/common/asserts.rs index 4278f5cb77e5..f92e36432b83 100644 --- a/psl/psl/tests/common/asserts.rs +++ b/psl/psl/tests/common/asserts.rs @@ -631,9 +631,7 @@ impl DefaultValueAssert for ast::Expression { #[track_caller] fn assert_uuid(&self) -> &Self { - assert!( - matches!(self, ast::Expression::Function(name, args, _) if name == "uuid" && args.arguments.is_empty()) - ); + assert!(matches!(self, ast::Expression::Function(name, args, _) if name == "uuid")); self } From 63c787e0d9d3670fea68fd35dab8f572df9b4bc9 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Thu, 23 May 2024 16:57:35 +0200 Subject: [PATCH 10/14] fixup! feat(psl): Add support for UUIDv7 --- psl/psl/tests/common/asserts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psl/psl/tests/common/asserts.rs b/psl/psl/tests/common/asserts.rs index f92e36432b83..e75df7c2cd7b 100644 --- a/psl/psl/tests/common/asserts.rs +++ b/psl/psl/tests/common/asserts.rs @@ -631,7 +631,7 @@ impl DefaultValueAssert for ast::Expression { #[track_caller] fn assert_uuid(&self) -> &Self { - assert!(matches!(self, ast::Expression::Function(name, args, _) if name == "uuid")); + assert!(matches!(self, ast::Expression::Function(name, _, _) if name == "uuid")); self } From ecec186f1600ebe453d67200b2510e75b72d4827 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 21 Jun 2024 17:39:27 +0200 Subject: [PATCH 11/14] fixup! feat(query-structure): Add support for UUIDv7 --- query-engine/query-structure/src/default_value.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/query-engine/query-structure/src/default_value.rs b/query-engine/query-structure/src/default_value.rs index 8a2d0dc76397..605224909e31 100644 --- a/query-engine/query-structure/src/default_value.rs +++ b/query-engine/query-structure/src/default_value.rs @@ -286,12 +286,7 @@ impl ValueGeneratorFn { fn generate_uuid(version: u8) -> PrismaValue { PrismaValue::Uuid(match version { 4 => uuid::Uuid::new_v4(), - 7 => { - let now = chrono::Utc::now(); - let timestamp = - uuid::Timestamp::from_unix(uuid::NoContext, now.timestamp() as u64, now.timestamp_subsec_nanos()); - uuid::Uuid::new_v7(timestamp) - } + 7 => uuid::Uuid::now_v7(), _ => panic!("Unknown UUID version: {}", version), }) } From 63834b2ca6f9dd0723e875b002abe51f96b21513 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Fri, 21 Jun 2024 17:54:44 +0200 Subject: [PATCH 12/14] feat(query-engine): Add test for UUIDv7 functionality --- .../tests/writes/ids/uuid_create_graphql.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs index 5efd17555673..6730a375a2cd 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs @@ -68,4 +68,60 @@ mod uuid_create_graphql { Ok(()) } + + fn schema_3() -> String { + let schema = indoc! { + r#"model Todo { + #id(id, String, @id, @default(uuid(7))) + title String + }"# + }; + + schema.to_owned() + } + + // "Creating an item with an id field of model UUIDv7 and retrieving it" should "work" + #[connector_test(schema(schema_3))] + async fn create_uuid_v7_and_retrieve_it_should_work(runner: Runner) -> TestResult<()> { + let res = run_query_json!( + &runner, + r#"mutation { + createOneTodo(data: { title: "the title" }){ + id + } + }"# + ); + + let uuid = match &res["data"]["createOneTodo"]["id"] { + serde_json::Value::String(str) => str, + _ => unreachable!(), + }; + + // Validate that this is a valid UUIDv7 value + { + let uuid = uuid::Uuid::parse_str(uuid.as_str()).expect("Expected valid UUID but couldn't parse it."); + assert_eq!( + uuid.get_version().expect("Expected UUIDv7 but got something else."), + uuid::Version::SortRand + ); + } + + // Test findMany + let res = run_query_json!(&runner, "query { findManyTodo() { id }}"); + if let serde_json::Value::String(str) = &res["data"]["findManyTodo"][0]["id"] { + assert_eq!(str, uuid); + } else { + panic!("Expected UUID but got something else."); + } + + // Test findUnique + let res = run_query_json!(&runner, "query { findUniqueTodo() { id }}"); + if let serde_json::Value::String(str) = &res["data"]["findUniqueTodo"][0]["id"] { + assert_eq!(str, uuid); + } else { + panic!("Expected UUID but got something else."); + } + + Ok(()) + } } From 7a2fbdf50a15d617b6d197ec2a34c9bfdba9292c Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 25 Jun 2024 09:56:00 +0200 Subject: [PATCH 13/14] fixup! feat(query-engine): Add test for UUIDv7 functionality --- .../tests/writes/ids/uuid_create_graphql.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs index 6730a375a2cd..8e491f466987 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs @@ -107,7 +107,10 @@ mod uuid_create_graphql { } // Test findMany - let res = run_query_json!(&runner, "query { findManyTodo() { id }}"); + let res = run_query_json!( + &runner, + r#"query { findManyTodo(where: { title: "the title" }) { id }}"# + ); if let serde_json::Value::String(str) = &res["data"]["findManyTodo"][0]["id"] { assert_eq!(str, uuid); } else { @@ -115,8 +118,11 @@ mod uuid_create_graphql { } // Test findUnique - let res = run_query_json!(&runner, "query { findUniqueTodo() { id }}"); - if let serde_json::Value::String(str) = &res["data"]["findUniqueTodo"][0]["id"] { + let res = run_query_json!( + &runner, + r#"query { findUniqueTodo(where: { title: "the title" }) { id }}"# + ); + if let serde_json::Value::String(str) = &res["data"]["findUniqueTodo"]["id"] { assert_eq!(str, uuid); } else { panic!("Expected UUID but got something else."); From 81642e5123fc2b89317b74914e2cb54365d25c06 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 25 Jun 2024 10:27:35 +0200 Subject: [PATCH 14/14] fixup! feat(query-engine): Add test for UUIDv7 functionality --- .../query-engine-tests/tests/writes/ids/uuid_create_graphql.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs index 8e491f466987..afacaa5292b5 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/ids/uuid_create_graphql.rs @@ -120,7 +120,7 @@ mod uuid_create_graphql { // Test findUnique let res = run_query_json!( &runner, - r#"query { findUniqueTodo(where: { title: "the title" }) { id }}"# + format!(r#"query {{ findUniqueTodo(where: {{ id: "{}" }}) {{ id }} }}"#, uuid) ); if let serde_json::Value::String(str) = &res["data"]["findUniqueTodo"]["id"] { assert_eq!(str, uuid);