Skip to content

Commit

Permalink
Implement scalar list defaults proposal in datamodel
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhoule committed Jun 1, 2022
1 parent 6f44ae8 commit b2c0912
Show file tree
Hide file tree
Showing 5 changed files with 325 additions and 82 deletions.
65 changes: 55 additions & 10 deletions libs/datamodel/core/tests/attributes/default_composite_negative.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,75 @@
use crate::common::*;

#[test]
fn must_error_if_default_value_for_list() {
fn must_error_on_list_default_value_for_singular() {
let dml = indoc! {r#"
datasource db {
provider = "postgres"
url = "postgres://"
provider = "mongodb"
url = env("DATABASE_URL")
}
type Composite {
rel String[] @default(["hello"])
type Model {
rel String @default(["hello"])
}
"#};

let error = datamodel::parse_schema(dml).map(drop).unwrap_err();
let expectation = expect![[r#"
error: Error parsing attribute "@default": The default value of a non-list field cannot be a list.
--> schema.prisma:7
 | 
 6 | type Model {
 7 |  rel String @default(["hello"])
 | 
"#]];
expect_error(dml, &expectation);
}

#[test]
fn must_error_on_singular_default_value_for_list() {
let dml = indoc! {r#"
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
type Model {
rel String[] @default("hello")
}
"#};

let expectation = expect![[r#"
[1;91merror[0m: [1mError parsing attribute "@default": Cannot set a default value on list field.[0m
[1;91merror[0m: [1mError parsing attribute "@default": The default value of a list field must be a list.[0m
--> schema.prisma:7
 | 
[1;94m 6 | [0mtype Composite {
[1;94m 7 | [0m rel String[] @[1;91mdefault(["hello"])[0m
[1;94m 6 | [0mtype Model {
[1;94m 7 | [0m rel String[] @[1;91mdefault("hello")[0m
 | 
"#]];
expect_error(dml, &expectation);
}

expectation.assert_eq(&error)
#[test]
fn must_error_on_bad_value_inside_list_default() {
let dml = indoc! {r#"
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
type Model {
rel String[] @default(["hello", 101, "dalmatians"])
}
"#};

let expectation = expect![[r#"
error: Error parsing attribute "@default": Expected a String value, but found `101`.
--> schema.prisma:7
 | 
 6 | type Model {
 7 |  rel String[] @default(["hello", 101, "dalmatians"])
 | 
"#]];
expect_error(dml, &expectation);
}

#[test]
Expand Down
59 changes: 53 additions & 6 deletions libs/datamodel/core/tests/attributes/default_negative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn must_error_if_default_value_for_relation_field() {
}

#[test]
fn must_error_if_default_value_for_list() {
fn must_error_on_list_default_value_for_singular() {
let dml = indoc! {r#"
datasource db {
provider = "postgres"
Expand All @@ -37,22 +37,69 @@ fn must_error_if_default_value_for_list() {
model Model {
id Int @id
rel String[] @default(["hello"])
rel String @default(["hello"])
}
"#};

let error = datamodel::parse_schema(dml).map(drop).unwrap_err();
let expectation = expect![[r#"
error: Error parsing attribute "@default": The default value of a non-list field cannot be a list.
--> schema.prisma:8
 | 
 7 |  id Int @id
 8 |  rel String @default(["hello"])
 | 
"#]];
expect_error(dml, &expectation);
}

#[test]
fn must_error_on_singular_default_value_for_list() {
let dml = indoc! {r#"
datasource db {
provider = "postgres"
url = "postgres://"
}
model Model {
id Int @id
rel String[] @default("hello")
}
"#};

let expectation = expect![[r#"
[1;91merror[0m: [1mError parsing attribute "@default": Cannot set a default value on list field.[0m
[1;91merror[0m: [1mError parsing attribute "@default": The default value of a list field must be a list.[0m
--> schema.prisma:8
 | 
 7 |  id Int @id
[1;94m 8 | [0m rel String[] @[1;91mdefault(["hello"])[0m
[1;94m 8 | [0m rel String[] @[1;91mdefault("hello")[0m
 | 
"#]];
expect_error(dml, &expectation);
}

expectation.assert_eq(&error)
#[test]
fn must_error_on_bad_value_inside_list_default() {
let dml = indoc! {r#"
datasource db {
provider = "postgres"
url = "postgres://"
}
model Model {
id Int @id
rel String[] @default(["hello", 101, "dalmatians"])
}
"#};

let expectation = expect![[r#"
error: Error parsing attribute "@default": Expected a String value, but found `101`.
--> schema.prisma:8
 | 
 7 |  id Int @id
 8 |  rel String[] @default(["hello", 101, "dalmatians"])
 | 
"#]];
expect_error(dml, &expectation);
}

#[test]
Expand Down
78 changes: 78 additions & 0 deletions libs/datamodel/core/tests/attributes/default_positive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,81 @@ fn mongodb_auto_id() {
.assert_has_scalar_field("id")
.assert_default_value(DefaultValue::new_expression(ValueGenerator::new_auto()));
}

#[test]
fn scalar_list_defaults_with_decimal() {
let dml = indoc! {r#"
datasource db {
provider = "postgresql"
url = "postgres://"
}
enum Color {
RED
GREEN
BLUE
}
model Model {
id Int @id
int_empty Int[] @default([])
int Int[] @default([0, 1, 1, 2, 3, 5, 8, 13, 21])
float Float[] @default([3.20, 4.20, 3.14, 0, 9.9999999, 1000.7])
string String[] @default(["Arrabiata", "Carbonara", "Al Ragù"])
boolean Boolean[] @default([false, true ,true, true])
dateTime DateTime[] @default(["2019-06-17T14:20:57Z", "2020-09-*1T20:00:00+02:00"])
colors Color[] @default([GREEN, BLUE])
colors_empty Color[] @default([])
bytes Bytes[] @default(["aGVsbG8gd29ybGQ="])
json Json[] @default(["{ \"a\": [\"b\"] }", "3"])
decimal Decimal[] @default(["121.10299000124800000001", "0.4", "1.1", "-68.0"])
}
"#};

assert_valid(dml);
}

#[test]
fn scalar_list_defaults_with_composite_types() {
let dml = indoc! {r#"
datasource db {
provider = "mongodb"
url = "mongodb://"
}
enum Color {
RED
GREEN
BLUE
}
model Model {
id Int @id @map("_id")
int_empty Int[] @default([])
int Int[] @default([0, 1, 1, 2, 3, 5, 8, 13, 21])
float Float[] @default([3.20, 4.20, 3.14, 0, 9.9999999, 1000.7])
string String[] @default(["Arrabiata", "Carbonara", "Al Ragù"])
boolean Boolean[] @default([false, true ,true, true])
dateTime DateTime[] @default(["2019-06-17T14:20:57Z", "2020-09-*1T20:00:00+02:00"])
colors Color[] @default([GREEN, BLUE])
colors_empty Color[] @default([])
bytes Bytes[] @default(["aGVsbG8gd29ybGQ="])
json Json[] @default(["{ \"a\": [\"b\"] }", "3"])
}
type CompositeT {
int_empty Int[] @default([])
int Int[] @default([0, 1, 1, 2, 3, 5, 8, 13, 21])
float Float[] @default([3.20, 4.20, 3.14, 0, 9.9999999, 1000.7])
string String[] @default(["Arrabiata", "Carbonara", "Al Ragù"])
boolean Boolean[] @default([false, true ,true, true])
dateTime DateTime[] @default(["2019-06-17T14:20:57Z", "2020-09-*1T20:00:00+02:00"])
bytes Bytes[] @default(["aGVsbG8gd29ybGQ="])
colors Color[] @default([GREEN, BLUE])
colors_empty Color[] @default([])
json Json[] @default(["{ \"a\": [\"b\"] }", "3"])
}
"#};

assert_valid(dml);
}
12 changes: 2 additions & 10 deletions libs/datamodel/diagnostics/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ enum DatamodelErrorKind {
#[error("Argument \"{}\" is missing in generator block \"{}\".", argument_name, generator_name)]
GeneratorArgumentNotFound { argument_name: String, generator_name: String, span: Span },

#[error("Error parsing attribute \"{}\": {}", attribute_name, message)]
AttributeValidationError { message: String, attribute_name: String, span: Span },

#[error("Attribute \"@{}\" is defined twice.", attribute_name)]
DuplicateAttributeError { attribute_name: String, span: Span },

Expand Down Expand Up @@ -228,12 +225,8 @@ impl DatamodelError {
}

pub fn new_attribute_validation_error(message: &str, attribute_name: &str, span: Span) -> DatamodelError {
DatamodelErrorKind::AttributeValidationError {
message: String::from(message),
attribute_name: String::from(attribute_name),
span,
}
.into()
let msg = format!("Error parsing attribute \"{attribute_name}\": {message}");
Self::new(msg.into(), span)
}

pub fn new_duplicate_attribute_error(attribute_name: &str, span: Span) -> DatamodelError {
Expand Down Expand Up @@ -613,7 +606,6 @@ impl DatamodelError {
DatamodelErrorKind::ArgumentCountMismatch { span, .. } => *span,
DatamodelErrorKind::SourceArgumentNotFound { span, .. } => *span,
DatamodelErrorKind::GeneratorArgumentNotFound { span, .. } => *span,
DatamodelErrorKind::AttributeValidationError { span, .. } => *span,
DatamodelErrorKind::AttributeNotKnownError { span, .. } => *span,
DatamodelErrorKind::ReservedScalarTypeError { span, .. } => *span,
DatamodelErrorKind::DatasourceProviderNotKnownError { span, .. } => *span,
Expand Down

0 comments on commit b2c0912

Please sign in to comment.