-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Default scalar field values #2997
Changes from all commits
c2bc030
e7c8663
cf9eaee
9048193
c86e686
e1792f3
21e6185
1221729
b3944f3
0c3f6d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,11 @@ type CollectionFieldDescription struct { | |
// | ||
// Otherwise will be [None]. | ||
RelationName immutable.Option[string] | ||
|
||
// DefaultValue contains the default value for this field. | ||
// | ||
// This value has no effect on views. | ||
DefaultValue any | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. todo: Please test and document what happens when this is set on a View - and consider adding a validation rule to prevent that (as it makes no sense to me) (and test that, including on Patch). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added a test to show the current behavior. Since it has no effect on the results of the view, I think allowing it is better than having the schema definition and view definition languages diverge and have slightly different rules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay cheers, I'm happy with that :) - can you please document that the property is ignored for views on the directive, and on this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
|
||
func (f FieldID) String() string { | ||
|
@@ -50,6 +55,7 @@ type collectionFieldDescription struct { | |
Name string | ||
ID FieldID | ||
RelationName immutable.Option[string] | ||
DefaultValue any | ||
|
||
// Properties below this line are unmarshalled using custom logic in [UnmarshalJSON] | ||
Kind json.RawMessage | ||
|
@@ -64,6 +70,7 @@ func (f *CollectionFieldDescription) UnmarshalJSON(bytes []byte) error { | |
|
||
f.Name = descMap.Name | ||
f.ID = descMap.ID | ||
f.DefaultValue = descMap.DefaultValue | ||
f.RelationName = descMap.RelationName | ||
kind, err := parseFieldKind(descMap.Kind) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
"sort" | ||
"strings" | ||
|
||
gql "github.com/sourcenetwork/graphql-go" | ||
"github.com/sourcenetwork/graphql-go/language/ast" | ||
gqlp "github.com/sourcenetwork/graphql-go/language/parser" | ||
"github.com/sourcenetwork/graphql-go/language/source" | ||
|
@@ -26,6 +27,29 @@ | |
"github.com/sourcenetwork/defradb/internal/request/graphql/schema/types" | ||
) | ||
|
||
const ( | ||
typeID string = "ID" | ||
typeBoolean string = "Boolean" | ||
typeInt string = "Int" | ||
typeFloat string = "Float" | ||
typeDateTime string = "DateTime" | ||
typeString string = "String" | ||
typeBlob string = "Blob" | ||
typeJSON string = "JSON" | ||
) | ||
|
||
// this mapping is used to check that the default prop value | ||
// matches the field type | ||
var TypeToDefaultPropName = map[string]string{ | ||
typeString: types.DefaultDirectivePropString, | ||
typeBoolean: types.DefaultDirectivePropBool, | ||
typeInt: types.DefaultDirectivePropInt, | ||
typeFloat: types.DefaultDirectivePropFloat, | ||
typeDateTime: types.DefaultDirectivePropDateTime, | ||
typeJSON: types.DefaultDirectivePropJSON, | ||
typeBlob: types.DefaultDirectivePropBlob, | ||
} | ||
|
||
// FromString parses a GQL SDL string into a set of collection descriptions. | ||
func FromString(ctx context.Context, schemaString string) ( | ||
[]client.CollectionDefinition, | ||
|
@@ -369,6 +393,39 @@ | |
}, nil | ||
} | ||
|
||
func defaultFromAST( | ||
field *ast.FieldDefinition, | ||
directive *ast.Directive, | ||
) (any, error) { | ||
astNamed, ok := field.Type.(*ast.Named) | ||
if !ok { | ||
return nil, NewErrDefaultValueNotAllowed(field.Name.Value, field.Type.String()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. todo: Please add tests for this error condition There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
propName, ok := TypeToDefaultPropName[astNamed.Name.Value] | ||
if !ok { | ||
return nil, NewErrDefaultValueNotAllowed(field.Name.Value, astNamed.Name.Value) | ||
} | ||
var value any | ||
for _, arg := range directive.Arguments { | ||
if propName != arg.Name.Value { | ||
return nil, NewErrDefaultValueInvalid(field.Name.Value, propName, arg.Name.Value) | ||
} | ||
switch t := arg.Value.(type) { | ||
case *ast.IntValue: | ||
value = gql.Int.ParseLiteral(arg.Value) | ||
case *ast.FloatValue: | ||
value = gql.Float.ParseLiteral(arg.Value) | ||
case *ast.BooleanValue: | ||
value = t.Value | ||
case *ast.StringValue: | ||
value = t.Value | ||
default: | ||
value = arg.Value.GetValue() | ||
} | ||
} | ||
return value, nil | ||
} | ||
|
||
func fieldsFromAST( | ||
field *ast.FieldDefinition, | ||
hostObjectName string, | ||
|
@@ -392,6 +449,16 @@ | |
} | ||
hostMap[field.Name.Value] = cType | ||
|
||
var defaultValue any | ||
for _, directive := range field.Directives { | ||
if directive.Name.Value == types.DefaultDirectiveLabel { | ||
defaultValue, err = defaultFromAST(field, directive) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
} | ||
} | ||
|
||
schemaFieldDescriptions := []client.SchemaFieldDescription{} | ||
collectionFieldDescriptions := []client.CollectionFieldDescription{} | ||
|
||
|
@@ -467,7 +534,8 @@ | |
collectionFieldDescriptions = append( | ||
collectionFieldDescriptions, | ||
client.CollectionFieldDescription{ | ||
Name: field.Name.Value, | ||
Name: field.Name.Value, | ||
DefaultValue: defaultValue, | ||
}, | ||
) | ||
} | ||
|
@@ -529,17 +597,6 @@ | |
} | ||
|
||
func astTypeToKind(t ast.Type) (client.FieldKind, error) { | ||
const ( | ||
typeID string = "ID" | ||
typeBoolean string = "Boolean" | ||
typeInt string = "Int" | ||
typeFloat string = "Float" | ||
typeDateTime string = "DateTime" | ||
typeString string = "String" | ||
typeBlob string = "Blob" | ||
typeJSON string = "JSON" | ||
) | ||
|
||
Comment on lines
-532
to
-542
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. praise: Thanks for moving |
||
switch astTypeVal := t.(type) { | ||
case *ast.List: | ||
switch innerAstTypeVal := astTypeVal.Type.(type) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
todo: Please test the PatchCollection behaviour for this new property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done