Repository navigation
Conversation
dimitrovmaksim
left a comment
There was a problem hiding this comment.
Thanks for the clear report and the fix.
A few things before merge:
- Scope. The change also covers nullable references to entities with
id: Int8!.type_from_fieldmaps them toi64, so they get the non-nullable accessors too, as in graph-cli.
That means "Every other field's accessors are unchanged" isn't accurate. Please mention this case in the description and commit message. The inline comment on the test adds it to
test_nullable_primitive_fields. - Boolean build failure. On master, a mapping that reads a nullable
Booleandoesn't compile under asc 0.19.23:ERROR AS200: Conversion from type 'usize' to 'bool' requires an explicit castat the getter'sreturn null. Fori32/i64thatreturn nullcompiles to0, so the getter change only matters at runtime forBoolean. ForInt,Int8and
Timestampthe fix is the setter change. Worth a sentence in the description. - Commit trailers. Could you drop the
Co-Authored-By:andClaude-Session:trailers from the commit message? I'd like to keep AI attribution out of the commit history, and reviewers can't open the session link
There was a problem hiding this comment.
nullable is now true only when param_type is Nullable, so the other => other.to_string() arm can't be reached. It only existed for the old case of a primitive with a nullable GraphQL field. Binding the pattern directly removes the dead arm and the duplicated comment:
| let set_code = if let TypeExpr::Nullable(n) = ¶m_type { | |
| let inner_type = n.inner.to_string(); |
| // Nullability comes from the AssemblyScript type, not the GraphQL | ||
| // field: `type_from_field` never makes a primitive nullable, so a | ||
| // nullable `Int` or `Boolean` gets the non-nullable getter, as | ||
| // graph-cli generates it. |
There was a problem hiding this comment.
Nit: one line is enough. With the setter change below, this is the only copy.
| // graph-cli generates it. | |
| // AS primitives can't be nullable, so take nullability from the AS type. |
| } | ||
|
|
||
| #[test] | ||
| fn test_nullable_primitive_fields() { |
There was a problem hiding this comment.
This misses nullable references to Int8-id entities, which this PR also changes: they map to i64, so they now get the non-nullable setter (assigning id 0 stores it instead of unsetting the field). The getter changes only in source; master's return null already compiled to 0. Here's a version that covers them and trims the comment:
- // AssemblyScript primitives cannot be nullable, so a nullable field of a
- // primitive type gets the non-nullable accessors, as in graph-cli: the
- // getter returns the type's default and the setter always stores the
- // value. A nullable setter would unset the field when given 0 or false.
+ // Nullable primitives, incl. Int8-id entity refs, get non-nullable accessors.
let schema = r#"
@@
at: Timestamp
+ counter: Counter
name: String
}
+
+ type Counter @entity(immutable: true) {
+ id: Int8!
+ }
"#;
@@
- assert_eq!(classes.len(), 1);
+ assert_eq!(classes.len(), 2);
@@
- for (field, default) in [("side", "0"), ("flag", "false"), ("big", "0"), ("at", "0")] {
+ for (field, default) in [
+ ("side", "0"),
+ ("flag", "false"),
+ ("big", "0"),
+ ("at", "0"),
+ ("counter", "0"),
+ ] {`gnd codegen` took an accessor's nullability from the GraphQL field, so a nullable `Int`, `Boolean`, `Int8` or `Timestamp` field, or a nullable reference to an entity with `id: Int8!`, got a setter that unsets the field when it is given 0 or false, and the store held null. graph-cli decides from the AssemblyScript type, which `type_from_field` already keeps non-nullable for all of these, and generates the non-nullable getter and setter. Take nullability from the type expression in both, as graph-cli does. Fixes graphprotocol#6759
5161a52 to
8f389ad
Compare
|
Thanks for the review. All of it is in the amended commit:
|
Fixes #6759.
gnd codegengenerates nullable accessors for nullable fields whose AssemblyScript type is a primitive:Int,Boolean,Int8andTimestamp, and references to entities withid: Int8!, which map toi64. The setter then starts withif (!value) { this.unset(...) }, so setting such a field to0orfalseunsets it, and the store holdsnull. graph-cli stores the value.graph-cli takes an accessor's nullability from the AssemblyScript type (
returnType instanceof tsCodegen.NullableType), and_typeFromGraphQlnever makes a primitive nullable. gnd'stype_from_fieldapplies the same rule, butgenerate_field_getterandgenerate_field_setterusedfield.is_nullable. This PR takes nullability from the type expression in both, so for these fields gnd now generates what graph-cli does: the getter returns the type's default and the setter always stores the value. Nullable fields whose AssemblyScript type is not a primitive keep the nullable accessors.For
Int,Int8,Timestampand the Int8-id references, the fix is the setter change: on master the getter'sreturn nullalready compiles to0fori32andi64. ForBooleanthe getter change matters as well: on master a mapping that reads a nullableBooleandoesn't compile under asc 0.19.23 (ERROR AS200: Conversion from type 'usize' to 'bool' requires an explicit castat the getter'sreturn null).Testing
test_nullable_primitive_fieldsingnd/src/codegen/schema.rscoversInt,Boolean,Int8,Timestampand a nullable reference to an Int8-id entity. A nullableStringis the control and keeps the nullable accessors.codegen/schema.rs,codegen/types.rs,codegen/typescript.rsandshared/sanitize.rsin a standalone crate (graphql-tools 0.5.1, Rust 1.94.0 fromrust-toolchain.toml) and ran their unit tests:schema.rstests pass, and so do thetypes.rs,typescript.rsandsanitize.rstests;masterwith only the new test added, the 17 existing tests pass and the new one fails at its first field,side, whose getter returnsnull;this.unset('side')).cargo clippy --all-targetswithRUSTFLAGS="-D warnings"and the workspace's clippy lint settings is clean on those files.cargo test -p gndor thecodegen_verificationgolden tests. None of their fixture schemas has a field of typeInt,Boolean,Int8orTimestamp, or an entity with anInt8id, so their expected output doesn't change.