Skip to content
This repository has been archived by the owner on Aug 28, 2021. It is now read-only.

Commit

Permalink
Pipe through ValueReader in ngql (#3633)
Browse files Browse the repository at this point in the history
This is in preparation for passing in a ValueReader to collection
constructors.
  • Loading branch information
arv authored Aug 23, 2017
1 parent 1f5ce92 commit 3e4fc56
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 28 deletions.
16 changes: 9 additions & 7 deletions go/ngql/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1110,8 +1110,9 @@ func (suite *QueryGraphQLSuite) TestSetWithComplexKeys() {
}

func (suite *QueryGraphQLSuite) TestInputToNomsValue() {
var vr types.ValueReader
test := func(expected types.Value, val interface{}) {
suite.True(expected.Equals(InputToNomsValue(val, types.TypeOf(expected))))
suite.True(expected.Equals(InputToNomsValue(vr, val, types.TypeOf(expected))))
}

test(types.Number(42), int(42))
Expand Down Expand Up @@ -1173,19 +1174,19 @@ func (suite *QueryGraphQLSuite) TestInputToNomsValue() {
val := map[string]interface{}{
"x": float64(42),
}
suite.Equal(expected, InputToNomsValue(val, expectedType))
suite.Equal(expected, InputToNomsValue(vr, val, expectedType))

val = map[string]interface{}{
"x": float64(42),
"a": nil,
}
suite.Equal(expected, InputToNomsValue(val, expectedType))
suite.Equal(expected, InputToNomsValue(vr, val, expectedType))

val = map[string]interface{}{
"x": nil,
}
suite.Panics(func() {
InputToNomsValue(val, expectedType)
InputToNomsValue(vr, val, expectedType)
})
}

Expand Down Expand Up @@ -1483,16 +1484,17 @@ func (suite *QueryGraphQLSuite) TestNameFunc() {

func TestGetListElementsWithSet(t *testing.T) {
assert := assert.New(t)
var vr types.ValueReader
v := types.NewSet(types.Number(0), types.Number(1), types.Number(2))
r := getListElements(v, map[string]interface{}{})
r := getListElements(vr, v, map[string]interface{}{})
assert.Equal([]interface{}{float64(0), float64(1), float64(2)}, r)

r = getListElements(v, map[string]interface{}{
r = getListElements(vr, v, map[string]interface{}{
atKey: 1,
})
assert.Equal([]interface{}{float64(1), float64(2)}, r)

r = getListElements(v, map[string]interface{}{
r = getListElements(vr, v, map[string]interface{}{
countKey: 2,
})
assert.Equal([]interface{}{float64(0), float64(1)}, r)
Expand Down
46 changes: 25 additions & 21 deletions go/ngql/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ type getFieldFn func(v interface{}, fieldName string, ctx context.Context) types
// When a field name is resolved, it may take key:value arguments. A
// getSubvaluesFn handles returning one or more *noms* values whose presence is
// indicated by the provided arguments.
type getSubvaluesFn func(v types.Value, args map[string]interface{}) interface{}
type getSubvaluesFn func(vr types.ValueReader, v types.Value, args map[string]interface{}) interface{}

// GraphQL requires all memberTypes in a Union to be Structs, so when a noms
// union contains a scalar, we represent it in that context as a "boxed" value.
Expand Down Expand Up @@ -404,7 +404,7 @@ var listArgs = graphql.FieldConfigArgument{
countKey: &graphql.ArgumentConfig{Type: graphql.Int},
}

func getListElements(v types.Value, args map[string]interface{}) interface{} {
func getListElements(vr types.ValueReader, v types.Value, args map[string]interface{}) interface{} {
l := v.(types.Collection)
idx := 0
count := int(l.Len())
Expand Down Expand Up @@ -450,10 +450,10 @@ func getListElements(v types.Value, args map[string]interface{}) interface{} {
return values
}

func getSetElements(v types.Value, args map[string]interface{}) interface{} {
func getSetElements(vr types.ValueReader, v types.Value, args map[string]interface{}) interface{} {
s := v.(types.Set)

iter, nomsKey, nomsThrough, count, singleExactMatch := getCollectionArgs(s, args, iteratorFactory{
iter, nomsKey, nomsThrough, count, singleExactMatch := getCollectionArgs(vr, s, args, iteratorFactory{
IteratorFrom: func(from types.Value) interface{} {
return s.IteratorFrom(from)
},
Expand Down Expand Up @@ -497,7 +497,7 @@ func getSetElements(v types.Value, args map[string]interface{}) interface{} {
return values
}

func getCollectionArgs(col types.Collection, args map[string]interface{}, factory iteratorFactory) (iter interface{}, nomsKey, nomsThrough types.Value, count uint64, singleExactMatch bool) {
func getCollectionArgs(vr types.ValueReader, col types.Collection, args map[string]interface{}, factory iteratorFactory) (iter interface{}, nomsKey, nomsThrough types.Value, count uint64, singleExactMatch bool) {
typ := types.TypeOf(col)
length := col.Len()
nomsKeyType := typ.Desc.(types.CompoundDesc).ElemTypes[0]
Expand All @@ -507,7 +507,7 @@ func getCollectionArgs(col types.Collection, args map[string]interface{}, factor
nomsKeys := make(types.ValueSlice, len(slice))
for i, v := range slice {
var nomsValue types.Value
nomsValue = InputToNomsValue(v, nomsKeyType)
nomsValue = InputToNomsValue(vr, v, nomsKeyType)
nomsKeys[i] = nomsValue
}
count = uint64(len(slice))
Expand All @@ -518,12 +518,12 @@ func getCollectionArgs(col types.Collection, args map[string]interface{}, factor
return
}

nomsThrough = getThroughArg(nomsKeyType, args)
nomsThrough = getThroughArg(vr, nomsKeyType, args)

count, singleExactMatch = getCountArg(length, args)

if key, ok := args[keyKey]; ok {
nomsKey = InputToNomsValue(key, nomsKeyType)
nomsKey = InputToNomsValue(vr, key, nomsKeyType)
iter = factory.IteratorFrom(nomsKey)
} else if at, ok := args[atKey]; ok {
idx := at.(int)
Expand All @@ -546,10 +546,10 @@ func getCollectionArgs(col types.Collection, args map[string]interface{}, factor

type mapAppender func(slice []interface{}, k, v types.Value) []interface{}

func getMapElements(v types.Value, args map[string]interface{}, app mapAppender) (interface{}, error) {
func getMapElements(vr types.ValueReader, v types.Value, args map[string]interface{}, app mapAppender) (interface{}, error) {
m := v.(types.Map)

iter, nomsKey, nomsThrough, count, singleExactMatch := getCollectionArgs(m, args, iteratorFactory{
iter, nomsKey, nomsThrough, count, singleExactMatch := getCollectionArgs(vr, m, args, iteratorFactory{
IteratorFrom: func(from types.Value) interface{} {
return m.IteratorFrom(from)
},
Expand Down Expand Up @@ -612,9 +612,9 @@ func getCountArg(count uint64, args map[string]interface{}) (c uint64, singleExa
return count, false
}

func getThroughArg(nomsKeyType *types.Type, args map[string]interface{}) types.Value {
func getThroughArg(vr types.ValueReader, nomsKeyType *types.Type, args map[string]interface{}) types.Value {
if through, ok := args[throughKey]; ok {
return InputToNomsValue(through, nomsKeyType)
return InputToNomsValue(vr, through, nomsKeyType)
}
return nil
}
Expand Down Expand Up @@ -819,7 +819,8 @@ func (tc *TypeConverter) listAndSetToGraphQLObject(nomsType *types.Type) *graphq
Args: args,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
c := p.Source.(types.Collection)
return getSubvalues(c, p.Args), nil
vr := p.Context.Value(vrKey).(types.ValueReader)
return getSubvalues(vr, c, p.Args), nil
},
}
fields[valuesKey] = valuesField
Expand Down Expand Up @@ -862,7 +863,8 @@ func (tc *TypeConverter) mapToGraphQLObject(nomsType *types.Type) *graphql.Objec
Args: args,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
c := p.Source.(types.Collection)
return getMapElements(c, p.Args, mapAppendEntry)
vr := p.Context.Value(vrKey).(types.ValueReader)
return getMapElements(vr, c, p.Args, mapAppendEntry)
},
}
fields[entriesKey] = entriesField
Expand All @@ -873,15 +875,17 @@ func (tc *TypeConverter) mapToGraphQLObject(nomsType *types.Type) *graphql.Objec
Args: args,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
c := p.Source.(types.Collection)
return getMapElements(c, p.Args, mapAppendKey)
vr := p.Context.Value(vrKey).(types.ValueReader)
return getMapElements(vr, c, p.Args, mapAppendKey)
},
}
fields[valuesKey] = &graphql.Field{
Type: graphql.NewList(valueType),
Args: args,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
c := p.Source.(types.Collection)
return getMapElements(c, p.Args, mapAppendValue)
vr := p.Context.Value(vrKey).(types.ValueReader)
return getMapElements(vr, c, p.Args, mapAppendValue)
},
}
}
Expand Down Expand Up @@ -955,7 +959,7 @@ func MaybeGetScalar(v types.Value) interface{} {

// InputToNomsValue converts a GraphQL input value (as used in arguments and
// variables) to a Noms value.
func InputToNomsValue(arg interface{}, nomsType *types.Type) types.Value {
func InputToNomsValue(vr types.ValueReader, arg interface{}, nomsType *types.Type) types.Value {
switch nomsType.TargetKind() {
case types.BoolKind:
return types.Bool(arg.(bool))
Expand All @@ -971,7 +975,7 @@ func InputToNomsValue(arg interface{}, nomsType *types.Type) types.Value {
sl := arg.([]interface{})
vs := make(types.ValueSlice, len(sl))
for i, v := range sl {
vs[i] = InputToNomsValue(v, elemType)
vs[i] = InputToNomsValue(vr, v, elemType)
}
if nomsType.TargetKind() == types.ListKind {
return types.NewList(vs...)
Expand All @@ -985,8 +989,8 @@ func InputToNomsValue(arg interface{}, nomsType *types.Type) types.Value {
kvs := make(types.ValueSlice, 2*len(sl))
for i, v := range sl {
v := v.(map[string]interface{})
kvs[2*i] = InputToNomsValue(v["key"], keyType)
kvs[2*i+1] = InputToNomsValue(v["value"], valType)
kvs[2*i] = InputToNomsValue(vr, v["key"], keyType)
kvs[2*i+1] = InputToNomsValue(vr, v["value"], valType)
}
return types.NewMap(kvs...)
case types.StructKind:
Expand All @@ -995,7 +999,7 @@ func InputToNomsValue(arg interface{}, nomsType *types.Type) types.Value {
m := arg.(map[string]interface{})
desc.IterFields(func(name string, t *types.Type, optional bool) {
if m[name] != nil || !optional {
data[name] = InputToNomsValue(m[name], t)
data[name] = InputToNomsValue(vr, m[name], t)
}
})
return types.NewStruct(desc.Name, data)
Expand Down

0 comments on commit 3e4fc56

Please sign in to comment.