Skip to content

Commit

Permalink
refactor: Extract query schema errors to dedicated file (sourcenetwor…
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewSisley committed Jan 17, 2023
1 parent d9a4419 commit a1a5fb6
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 43 deletions.
12 changes: 3 additions & 9 deletions query/graphql/schema/descriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/client/request"
"github.com/sourcenetwork/defradb/errors"
)

var (
Expand Down Expand Up @@ -167,7 +166,7 @@ func (g *Generator) CreateDescriptions(
// let's make sure its an _id field, otherwise
// we might have an error here
if !strings.HasSuffix(fname, "_id") {
return nil, errors.New(fmt.Sprintf("Error: found a duplicate field '%s' for type %s", fname, t.Name()))
return nil, NewErrDuplicateField(fname, t.Name())
}
continue
}
Expand All @@ -186,18 +185,13 @@ func (g *Generator) CreateDescriptions(
rel := g.manager.Relations.getRelationByDescription(
fname, schemaName, t.Name())
if rel == nil {
return nil, errors.New(fmt.Sprintf(
"Field missing associated relation. FieldName: %s, SchemaType: %s, ObjectType: %s",
fname,
field.Type.Name(),
t.Name(),
))
return nil, NewErrFieldMissingRelation(field.Type.Name(), fname, t.Name())
}
fd.RelationName = rel.name

_, fieldRelationType, ok := rel.GetField(schemaName, fname)
if !ok {
return nil, errors.New("relation is missing field")
return nil, NewErrRelationMissingField(field.Type.Name(), fname)
}

fd.RelationType = rel.Kind() | fieldRelationType
Expand Down
100 changes: 100 additions & 0 deletions query/graphql/schema/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2022 Democratized Data Foundation
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package schema

import "github.com/sourcenetwork/defradb/errors"

const (
errDuplicateField string = "duplicate field"
errFieldMissingRelation string = "field missing associated relation"
errRelationMissingField string = "relation missing field"
errAggregateTargetNotFound string = "aggregate target not found"
errSchemaTypeAlreadyExist string = "schema type already exists"
errObjectNotFoundDuringThunk string = "object not found whilst executing fields thunk"
errTypeNotFound string = "no type found for given name"
errRelationNotFound string = "no relation found"
)

var (
ErrDuplicateField = errors.New(errDuplicateField)
ErrFieldMissingRelation = errors.New(errFieldMissingRelation)
ErrRelationMissingField = errors.New(errRelationMissingField)
ErrAggregateTargetNotFound = errors.New(errAggregateTargetNotFound)
ErrSchemaTypeAlreadyExist = errors.New(errSchemaTypeAlreadyExist)
ErrObjectNotFoundDuringThunk = errors.New(errObjectNotFoundDuringThunk)
ErrTypeNotFound = errors.New(errTypeNotFound)
ErrRelationNotFound = errors.New(errRelationNotFound)
ErrRelationMutlipleTypes = errors.New("relation type can only be either One or Many, not both")
ErrRelationMissingTypes = errors.New("relation is missing its defined types and fields")
ErrRelationInvalidType = errors.New("relation has an invalid type to be finalize")
ErrMultipleRelationPrimaries = errors.New("relation can only have a single field set as primary")
)

func NewErrDuplicateField(objectName, fieldName string) error {
return errors.New(
errDuplicateField,
errors.NewKV("Object", objectName),
errors.NewKV("Field", fieldName),
)
}

func NewErrFieldMissingRelation(objectName, fieldName string, objectType string) error {
return errors.New(
errFieldMissingRelation,
errors.NewKV("Object", objectName),
errors.NewKV("Field", fieldName),
errors.NewKV("ObjectType", objectType),
)
}

func NewErrRelationMissingField(objectName, fieldName string) error {
return errors.New(
errRelationMissingField,
errors.NewKV("Object", objectName),
errors.NewKV("Field", fieldName),
)
}

func NewErrAggregateTargetNotFound(objectName, target string) error {
return errors.New(
errAggregateTargetNotFound,
errors.NewKV("Object", objectName),
errors.NewKV("Target", target),
)
}

func NewErrSchemaTypeAlreadyExist(name string) error {
return errors.New(
errSchemaTypeAlreadyExist,
errors.NewKV("Name", name),
)
}

func NewErrObjectNotFoundDuringThunk(object string) error {
return errors.New(
errObjectNotFoundDuringThunk,
errors.NewKV("Object", object),
)
}

func NewErrTypeNotFound(typeName string) error {
return errors.New(
errTypeNotFound,
errors.NewKV("Type", typeName),
)
}

func NewErrRelationNotFound(relationName string) error {
return errors.New(
errRelationNotFound,
errors.NewKV("RelationName", relationName),
)
}
33 changes: 9 additions & 24 deletions query/graphql/schema/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"github.com/graphql-go/graphql/language/source"

"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/errors"

"github.com/sourcenetwork/defradb/client/request"
schemaTypes "github.com/sourcenetwork/defradb/query/graphql/schema/types"
Expand Down Expand Up @@ -303,11 +302,7 @@ func (g *Generator) createExpandedFieldAggregate(
filterTypeName = targeted.Type.Name() + "FilterArg"
}
} else {
return errors.New(fmt.Sprintf(
"Aggregate target not found. HostObject: {%s}, Target: {%s}",
obj.Name(),
target,
))
return NewErrAggregateTargetNotFound(obj.Name(), target)
}
}

Expand Down Expand Up @@ -386,7 +381,7 @@ func (g *Generator) buildTypesFromAST(
case *ast.ObjectDefinition:
// check if type exists
if _, ok := g.manager.schema.TypeMap()[defType.Name.Value]; ok {
return nil, errors.New(fmt.Sprintf("Schema type already exists: %s", defType.Name.Value))
return nil, NewErrSchemaTypeAlreadyExist(defType.Name.Value)
}

objconf := gql.ObjectConfig{}
Expand Down Expand Up @@ -487,10 +482,7 @@ func (g *Generator) buildTypesFromAST(

gqlType, ok := g.manager.schema.TypeMap()[defType.Name.Value]
if !ok {
return nil, errors.New(fmt.Sprintf(
"object not found whilst executing fields thunk: %s",
defType.Name.Value,
))
return nil, NewErrObjectNotFoundDuringThunk(defType.Name.Value)
}

fields[request.GroupFieldName] = &gql.Field{
Expand Down Expand Up @@ -530,10 +522,7 @@ func getRelationshipName(
if argument.Name.Value == "name" {
name, isString := argument.Value.GetValue().(string)
if !isString {
return "", errors.New(fmt.Sprintf(
"Relationship name must be of type string, but was: %v",
argument.Value.GetKind(),
))
return "", client.NewErrUnexpectedType[string]("Relationship name", argument.Value.GetValue())
}
return name, nil
}
Expand Down Expand Up @@ -947,7 +936,7 @@ func appendCommitChildGroupField() {
// The latter two are wrappers, and need to be further extracted
func astNodeToGqlType(typeMap map[string]gql.Type, t ast.Type) (gql.Type, error) {
if t == nil {
return nil, errors.New("type can't be nil")
return nil, client.NewErrUninitializeProperty("astNodeToGqlType", "t")
}

switch astTypeVal := t.(type) {
Expand All @@ -974,7 +963,7 @@ func astNodeToGqlType(typeMap map[string]gql.Type, t ast.Type) (gql.Type, error)
name := t.(*ast.Named).Name.Value
ttype, ok := typeMap[name]
if !ok {
return nil, errors.New(fmt.Sprintf("No type found for given name: %s", name))
return nil, NewErrTypeNotFound(name)
}

return ttype, nil
Expand Down Expand Up @@ -1013,7 +1002,7 @@ func (g *Generator) GenerateMutationInputForGQLType(obj *gql.Object) ([]*gql.Fie
typeName := obj.Name()
filter, ok := g.manager.schema.TypeMap()[typeName+"FilterArg"].(*gql.InputObject)
if !ok {
return nil, errors.New("missing filter arg for mutation type generation " + typeName)
return nil, NewErrTypeNotFound(typeName + "FilterArg")
}

return g.genTypeMutationFields(obj, filter)
Expand Down Expand Up @@ -1192,17 +1181,13 @@ func (g *Generator) genLeafFilterArgInput(obj gql.Type) *gql.InputObject {
operatorType, hasOperatorType := g.manager.schema.TypeMap()[operatorBlockName]
if !hasOperatorType {
// This should be impossible
return nil, errors.New("operator block not found", errors.NewKV("Name", operatorBlockName))
return nil, NewErrTypeNotFound(operatorBlockName)
}

operatorObject, isInputObj := operatorType.(*gql.InputObject)
if !isInputObj {
// This should be impossible
return nil, errors.New(
"invalid cast",
errors.NewKV("Expected type", "*gql.InputObject"),
errors.NewKV("Actual type", fmt.Sprintf("%T", operatorType)),
)
return nil, client.NewErrUnexpectedType[*gql.InputObject]("operatorType", operatorType)
}

for f, field := range operatorObject.Fields() {
Expand Down
15 changes: 7 additions & 8 deletions query/graphql/schema/relations.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"strings"

"github.com/sourcenetwork/defradb/client"
"github.com/sourcenetwork/defradb/errors"
)

// type uint8 uint8
Expand Down Expand Up @@ -47,7 +46,7 @@ func (rm *RelationManager) GetRelations() {}
func (rm *RelationManager) GetRelation(name string) (*Relation, error) {
rel, ok := rm.relations[name]
if !ok {
return nil, errors.New("no relation found")
return nil, NewErrRelationNotFound(name)
}
return rel, nil
}
Expand Down Expand Up @@ -105,12 +104,12 @@ func (rm *RelationManager) RegisterSingle(
relType client.RelationType,
) (bool, error) {
if name == "" {
return false, errors.New("relation name must be non empty")
return false, client.NewErrUninitializeProperty("RegisterSingle", "name")
}

// make sure the relation type is ONLY One or Many, not both
if relType.IsSet(client.Relation_Type_ONE) == relType.IsSet(client.Relation_Type_MANY) {
return false, errors.New("relation type can only be either One or Many, not both")
return false, ErrRelationMutlipleTypes
}

// make a copy of rel type, one goes to the relation.relType, and the other goes into the []types.
Expand Down Expand Up @@ -200,14 +199,14 @@ type Relation struct {
func (r *Relation) finalize() error {
// make sure all the types/fields are set
if len(r.types) != 2 || len(r.schemaTypes) != 2 || len(r.fields) != 2 {
return errors.New("relation is missing its defined types and fields")
return ErrRelationMissingTypes
}

// make sure its one of One-to-One, One-to-Many, Many-to-Many
if !r.relType.IsSet(client.Relation_Type_ONEONE) &&
!r.relType.IsSet(client.Relation_Type_ONEMANY) &&
!r.relType.IsSet(client.Relation_Type_MANYMANY) {
return errors.New("relation has an invalid type to be finalize")
return ErrRelationInvalidType
}

// make sure we have a primary set if its a one-to-one or many-to-many
Expand All @@ -218,7 +217,7 @@ func (r *Relation) finalize() error {

// both types have primary set
if aBit.IsSet(client.Relation_Type_Primary) {
return errors.New("relation can only have a single field set as primary")
return ErrMultipleRelationPrimaries
} else if !xBit.IsSet(client.Relation_Type_Primary) {
// neither type has primary set, auto add to
// lexicographically first one by schema type name
Expand Down Expand Up @@ -320,7 +319,7 @@ func (r Relation) GetFieldFromSchemaType(schemaType string) (string, client.Rela

func genRelationName(t1, t2 string) (string, error) {
if t1 == "" || t2 == "" {
return "", errors.New("relation types cannot be empty")
return "", client.NewErrUninitializeProperty("genRelationName", "relation types")
}
t1 = strings.ToLower(t1)
t2 = strings.ToLower(t2)
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/schema/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func TestSchemaSimpleErrorsGivenDuplicateSchema(t *testing.T) {
}
}
`,
ExpectedError: "Schema type already exists",
ExpectedError: "schema type already exists",
}

ExecuteQueryTestCase(t, test)
Expand Down Expand Up @@ -136,7 +136,7 @@ func TestSchemaSimpleErrorsGivenTypeWithInvalidFieldType(t *testing.T) {
}
}
`,
ExpectedError: "No type found for given name",
ExpectedError: "no type found for given name",
}

ExecuteQueryTestCase(t, test)
Expand Down

0 comments on commit a1a5fb6

Please sign in to comment.