Showing with 493 additions and 129 deletions.
  1. +3 −2 cmd/dgraph/main.go
  2. +0 −96 gql/scalar_types.go
  3. +7 −14 gql/schema.go
  4. +4 −2 gql/schema_test.go
  5. +6 −5 query/query.go
  6. +32 −5 query/query_test.go
  7. +22 −5 {gql → types}/definitions.go
  8. +276 −0 types/scalar_types.go
  9. +143 −0 types/scalar_types_test.go
5 changes: 3 additions & 2 deletions cmd/dgraph/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/dgraph-io/dgraph/query/graph"
"github.com/dgraph-io/dgraph/rdf"
"github.com/dgraph-io/dgraph/store"
"github.com/dgraph-io/dgraph/types"
"github.com/dgraph-io/dgraph/uid"
"github.com/dgraph-io/dgraph/worker"
"github.com/dgraph-io/dgraph/x"
Expand Down Expand Up @@ -280,8 +281,8 @@ func validateTypes(nquads []rdf.NQuad) error {
for _, nquad := range nquads {
if t := gql.SchemaType(nquad.Predicate); t != nil && t.IsScalar() {
// Currently, only scalar types are present
stype := t.(gql.Scalar)
if _, err := stype.ParseType(nquad.ObjectValue); err != nil {
stype := t.(types.Scalar)
if _, err := stype.Unmarshaler.FromText(nquad.ObjectValue); err != nil {
return err
}
}
Expand Down
96 changes: 0 additions & 96 deletions gql/scalar_types.go

This file was deleted.

21 changes: 7 additions & 14 deletions gql/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import (
"encoding/json"
"fmt"
"io/ioutil"

"github.com/dgraph-io/dgraph/types"
)

// schema stores the types for all predicates in the system.
var schema = make(map[string]Type)
var schema = make(map[string]types.Type)

// LoadSchema loads the schema and checks for errors.
func LoadSchema(fileName string) error {
Expand All @@ -37,25 +39,16 @@ func LoadSchema(fileName string) error {
}
// go over schema file values and assign appropriate types from type system
for k, v := range s {
switch v {
case "int":
schema[k] = intType
case "float":
schema[k] = floatType
case "string":
schema[k] = stringType
case "bool":
schema[k] = booleanType
case "id":
schema[k] = idType
default:
t := types.TypeForName(v)
if t == nil {
return fmt.Errorf("Unknown type:%v in input schema file for predicate:%v", v, k)
}
schema[k] = t
}
return nil
}

// SchemaType fetches types for a predicate from schema map
func SchemaType(p string) Type {
func SchemaType(p string) types.Type {
return schema[p]
}
6 changes: 4 additions & 2 deletions gql/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package gql
import (
"os"
"testing"

"github.com/dgraph-io/dgraph/types"
)

func createSchemaFile() (*os.File, error) {
Expand Down Expand Up @@ -67,11 +69,11 @@ func TestSchemaType(t *testing.T) {
t.Error(err)
}
typ := SchemaType("name")
if _, ok := typ.(Scalar); !ok {
if _, ok := typ.(types.Scalar); !ok {
t.Error("Type assertion failed for predicate:name")
}
typ = SchemaType("age")
if _, ok := typ.(Scalar); !ok {
if _, ok := typ.(types.Scalar); !ok {
t.Error("Type assertion failed for predicate:age")
}
}
11 changes: 6 additions & 5 deletions query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/dgraph-io/dgraph/gql"
"github.com/dgraph-io/dgraph/query/graph"
"github.com/dgraph-io/dgraph/task"
"github.com/dgraph-io/dgraph/types"
"github.com/dgraph-io/dgraph/worker"
"github.com/dgraph-io/dgraph/x"
"github.com/google/flatbuffers/go"
Expand Down Expand Up @@ -112,7 +113,7 @@ func (l *Latency) ToMap() map[string]string {
}

type params struct {
AttrType gql.Type
AttrType types.Type
Alias string
Count int
Offset int
Expand Down Expand Up @@ -283,8 +284,8 @@ func postTraverse(sg *SubGraph) (map[uint64]interface{}, error) {
return result, fmt.Errorf("Unknown Scalar:%v. Leaf predicate:'%v' must be"+
" one of the scalar types defined in the schema.", sg.Params.AttrType, sg.Attr)
}
stype := sg.Params.AttrType.(gql.Scalar)
lval, err := stype.ParseType(val)
stype := sg.Params.AttrType.(types.Scalar)
lval, err := stype.Unmarshaler.FromText(val)
if err != nil {
return result, err
}
Expand Down Expand Up @@ -434,8 +435,8 @@ func (sg *SubGraph) preTraverse(uid uint64, dst *graph.Node) error {
return fmt.Errorf("Unknown Scalar:%v. Leaf predicate:'%v' must be"+
" one of the scalar types defined in the schema.", pc.Params.AttrType, pc.Attr)
}
stype := pc.Params.AttrType.(gql.Scalar)
if _, err := stype.ParseType(v); err != nil {
stype := pc.Params.AttrType.(types.Scalar)
if _, err := stype.Unmarshaler.FromText(v); err != nil {
return err
}
}
Expand Down
37 changes: 32 additions & 5 deletions query/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/dgraph-io/dgraph/query/graph"
"github.com/dgraph-io/dgraph/store"
"github.com/dgraph-io/dgraph/task"
"github.com/dgraph-io/dgraph/types"
"github.com/dgraph-io/dgraph/worker"
"github.com/dgraph-io/dgraph/x"
)
Expand Down Expand Up @@ -609,25 +610,51 @@ func TestPostTraverse(t *testing.T) {

actorMap := m["actor"].(map[string]interface{})

if _, success := actorMap["name"].(string); !success {
if _, success := actorMap["name"].(types.StringType); !success {
t.Errorf("Expected type coercion to string for: %v\n", actorMap["name"])
}
// Note: although, int and int32 have same size, they are treated as different types in go
// GraphQL spec mentions integer type to be int32
if _, success := actorMap["age"].(int32); !success {
if _, success := actorMap["age"].(types.Int32Type); !success {
t.Errorf("Expected type coercion to int32 for: %v\n", actorMap["age"])
}
if _, success := actorMap["sword_present"].(bool); !success {
if _, success := actorMap["sword_present"].(types.BoolType); !success {
t.Errorf("Expected type coercion to bool for: %v\n", actorMap["sword_present"])
}
if _, success := actorMap["survival_rate"].(float64); !success {
if _, success := actorMap["survival_rate"].(types.FloatType); !success {
t.Errorf("Expected type coercion to float64 for: %v\n", actorMap["survival_rate"])
}
friendMap := actorMap["friend"].([]interface{})
friend := friendMap[0].(map[string]interface{})
if _, success := friend["name"].(string); !success {
if _, success := friend["name"].(types.StringType); !success {
t.Errorf("Expected type coercion to string for: %v\n", friend["name"])
}

// Test that the types marshal to json correctly
js, err := json.Marshal(val)
if err != nil {
t.Errorf("Error marshaling json: %v\n", err)
}
var mp map[string]interface{}
err = json.Unmarshal(js, &mp)
if err != nil {
t.Error(err)
}

actorMap = mp["actor"].(map[string]interface{})
if _, success := actorMap["name"].(string); !success {
t.Errorf("Expected json type string for: %v\n", actorMap["name"])
}
// json parses ints as floats
if _, success := actorMap["age"].(float64); !success {
t.Errorf("Expected json type int for: %v\n", actorMap["age"])
}
if _, success := actorMap["sword_present"].(bool); !success {
t.Errorf("Expected json type bool for: %v\n", actorMap["sword_present"])
}
if _, success := actorMap["survival_rate"].(float64); !success {
t.Errorf("Expected json type float64 for: %v\n", actorMap["survival_rate"])
}
}
}

Expand Down
27 changes: 22 additions & 5 deletions gql/definitions.go → types/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
* limitations under the License.
*/

package gql
package types

import "fmt"
import (
"encoding"
"encoding/json"
"fmt"
)

// Type interface is the wrapper interface for all types
type Type interface {
Expand All @@ -29,11 +33,24 @@ type Type interface {
type Scalar struct {
Name string // name of scalar type
Description string // short description
ParseType ParseTypeFunc
// to unmarshal the binary/text representation of the type.
Unmarshaler Unmarshaler
}

// ParseTypeFunc is a function that parses and does coercion for Scalar types.
type ParseTypeFunc func(input []byte) (interface{}, error)
// TypeValue is the interface that all scalar type values need to implement.
type TypeValue interface {
encoding.TextMarshaler
encoding.BinaryMarshaler
json.Marshaler
}

// Unmarshaler type is for unmarshaling a TypeValue from binary/text format.
type Unmarshaler interface {
// FromBinary unmarshals the data from a binary format.
FromBinary(data []byte) (TypeValue, error)
// FromText unmarshals the data from a text format.
FromText(data []byte) (TypeValue, error)
}

// String function to implement string interface
func (s Scalar) String() string {
Expand Down
Loading