Skip to content
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

refactor: Index field directive #2994

Merged
merged 4 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 95 additions & 74 deletions internal/request/graphql/schema/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@

for _, directive := range field.Directives {
if directive.Name.Value == types.IndexDirectiveLabel {
index, err := fieldIndexFromAST(field, directive)
index, err := indexFromAST(directive, field)
if err != nil {
return client.CollectionDefinition{}, err
}
Expand Down Expand Up @@ -164,7 +164,7 @@

for _, directive := range def.Directives {
if directive.Name.Value == types.IndexDirectiveLabel {
index, err := indexFromAST(directive)
index, err := indexFromAST(directive, nil)
if err != nil {
return client.CollectionDefinition{}, err
}
Expand Down Expand Up @@ -239,110 +239,131 @@
return true
}

func fieldIndexFromAST(field *ast.FieldDefinition, directive *ast.Directive) (client.IndexDescription, error) {
desc := client.IndexDescription{
Fields: []client.IndexedFieldDescription{
{
Name: field.Name.Value,
},
},
}
func indexFromAST(directive *ast.Directive, fieldDef *ast.FieldDefinition) (client.IndexDescription, error) {
var name string
var unique bool

var direction *ast.EnumValue
var includes *ast.ListValue

for _, arg := range directive.Arguments {
switch arg.Name.Value {
case types.IndexDirectivePropName:
nameVal, ok := arg.Value.(*ast.StringValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
desc.Name = nameVal.Value
if !IsValidIndexName(desc.Name) {
return client.IndexDescription{}, NewErrIndexWithInvalidName(desc.Name)
name = nameVal.Value
if !IsValidIndexName(name) {
return client.IndexDescription{}, NewErrIndexWithInvalidName(name)
}
case types.IndexDirectivePropUnique:
boolVal, ok := arg.Value.(*ast.BooleanValue)

case types.IndexDirectivePropIncludes:
includesVal, ok := arg.Value.(*ast.ListValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
desc.Unique = boolVal.Value
includes = includesVal

case types.IndexDirectivePropDirection:
dirVal, ok := arg.Value.(*ast.EnumValue)
directionVal, ok := arg.Value.(*ast.EnumValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
if dirVal.Value == types.FieldOrderDESC {
desc.Fields[0].Descending = true
direction = directionVal

case types.IndexDirectivePropUnique:
uniqueVal, ok := arg.Value.(*ast.BooleanValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
unique = uniqueVal.Value

default:
return client.IndexDescription{}, ErrIndexWithUnknownArg
}
}
return desc, nil
}

func indexFromAST(directive *ast.Directive) (client.IndexDescription, error) {
desc := client.IndexDescription{}
var directions *ast.ListValue
for _, arg := range directive.Arguments {
switch arg.Name.Value {
case types.IndexDirectivePropName:
nameVal, ok := arg.Value.(*ast.StringValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
desc.Name = nameVal.Value
if !IsValidIndexName(desc.Name) {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
case types.IndexDirectivePropFields:
fieldsVal, ok := arg.Value.(*ast.ListValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
for _, field := range fieldsVal.Values {
fieldVal, ok := field.(*ast.StringValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
desc.Fields = append(desc.Fields, client.IndexedFieldDescription{
Name: fieldVal.Value,
})
}
case types.IndexDirectivePropDirections:
var ok bool
directions, ok = arg.Value.(*ast.ListValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
var containsField bool
var fields []client.IndexedFieldDescription

if includes != nil {
for _, include := range includes.Values {
field, err := indexFieldFromAST(include, direction)
if err != nil {
return client.IndexDescription{}, err
}
case types.IndexDirectivePropUnique:
boolVal, ok := arg.Value.(*ast.BooleanValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
if fieldDef != nil && fieldDef.Name.Value == field.Name {
containsField = true

Check warning on line 297 in internal/request/graphql/schema/collection.go

View check run for this annotation

Codecov / codecov/patch

internal/request/graphql/schema/collection.go#L297

Added line #L297 was not covered by tests
}
desc.Unique = boolVal.Value
default:
return client.IndexDescription{}, ErrIndexWithUnknownArg
fields = append(fields, field)
}
}
if len(desc.Fields) == 0 {

// implicitly add the field if it is not already in the list
if !containsField && fieldDef != nil {
field := client.IndexedFieldDescription{
Name: fieldDef.Name.Value,
}
if direction != nil {
field.Descending = direction.Value == types.FieldOrderDESC
}
fields = append(fields, field)
}

if len(fields) == 0 {
return client.IndexDescription{}, ErrIndexMissingFields
}
if directions != nil {
if len(directions.Values) != len(desc.Fields) {
return client.IndexDescription{}, ErrIndexWithInvalidArg
}
for i := range desc.Fields {
dirVal, ok := directions.Values[i].(*ast.EnumValue)

return client.IndexDescription{
Name: name,
Fields: fields,
Unique: unique,
}, nil
}

func indexFieldFromAST(value ast.Value, defaultDirection *ast.EnumValue) (client.IndexedFieldDescription, error) {
argTypeObject, ok := value.(*ast.ObjectValue)
if !ok {
return client.IndexedFieldDescription{}, ErrIndexWithInvalidArg
}

var name string
var direction *ast.EnumValue

for _, field := range argTypeObject.Fields {
switch field.Name.Value {
case types.IndexFieldInputName:
nameVal, ok := field.Value.(*ast.StringValue)
if !ok {
return client.IndexDescription{}, ErrIndexWithInvalidArg
return client.IndexedFieldDescription{}, ErrIndexWithInvalidArg

Check warning on line 339 in internal/request/graphql/schema/collection.go

View check run for this annotation

Codecov / codecov/patch

internal/request/graphql/schema/collection.go#L339

Added line #L339 was not covered by tests
}
if dirVal.Value == types.FieldOrderASC {
desc.Fields[i].Descending = false
} else if dirVal.Value == types.FieldOrderDESC {
desc.Fields[i].Descending = true
name = nameVal.Value

case types.IndexFieldInputDirection:
directionVal, ok := field.Value.(*ast.EnumValue)
if !ok {
return client.IndexedFieldDescription{}, ErrIndexWithInvalidArg

Check warning on line 346 in internal/request/graphql/schema/collection.go

View check run for this annotation

Codecov / codecov/patch

internal/request/graphql/schema/collection.go#L346

Added line #L346 was not covered by tests
}
direction = directionVal

default:
return client.IndexedFieldDescription{}, ErrIndexWithUnknownArg

Check warning on line 351 in internal/request/graphql/schema/collection.go

View check run for this annotation

Codecov / codecov/patch

internal/request/graphql/schema/collection.go#L350-L351

Added lines #L350 - L351 were not covered by tests
}
}
return desc, nil

var descending bool
if direction == nil && defaultDirection != nil {
direction = defaultDirection

Check warning on line 357 in internal/request/graphql/schema/collection.go

View check run for this annotation

Codecov / codecov/patch

internal/request/graphql/schema/collection.go#L357

Added line #L357 was not covered by tests
}
if direction != nil {
descending = direction.Value == types.FieldOrderDESC
}

return client.IndexedFieldDescription{
Name: name,
Descending: descending,
}, nil
}

func fieldsFromAST(
Expand Down
Loading
Loading