Example #1
0
func parseRequest(s []string) (ast.Value, bool, error) {

	pairs := make([][2]*ast.Term, len(s))
	nonGround := false

	for i := range s {

		var k *ast.Term
		var v *ast.Term
		var err error

		if s[i][0] == ':' {
			k = ast.NewTerm(ast.EmptyRef())
			v, err = ast.ParseTerm(s[i][1:])
		} else {
			v, err = ast.ParseTerm(s[i])
			if err == nil {
				k = ast.NewTerm(ast.EmptyRef())
			} else {
				vs := strings.SplitN(s[i], ":", 2)
				if len(vs) != 2 {
					return nil, false, errRequestPathFormat
				}
				k, err = ast.ParseTerm(ast.RequestRootDocument.String() + "." + vs[0])
				if err != nil {
					return nil, false, errRequestPathFormat
				}
				v, err = ast.ParseTerm(vs[1])
			}
		}

		if err != nil {
			return nil, false, err
		}

		pairs[i] = [...]*ast.Term{k, v}

		if !nonGround {
			ast.WalkVars(v, func(x ast.Var) bool {
				if x.Equal(ast.DefaultRootDocument.Value) {
					return false
				}
				nonGround = true
				return true
			})
		}
	}

	request, err := topdown.MakeRequest(pairs)
	if err != nil {
		return nil, false, err
	}

	return request, nonGround, nil
}
Example #2
0
// Build initializes the references' index by walking the store for the reference and
// creating the index that maps values to bindings.
func (ind *indices) Build(ctx context.Context, store Store, txn Transaction, ref ast.Ref) error {
	index := newBindingIndex()
	ind.registerTriggers(store)
	err := iterStorage(ctx, store, txn, ref, ast.EmptyRef(), ast.NewValueMap(), func(bindings *ast.ValueMap, val interface{}) {
		index.Add(val, bindings)
	})
	if err != nil {
		return err
	}
	hashCode := ref.Hash()
	head := ind.table[hashCode]
	entry := &indicesNode{
		key:  ref,
		val:  index,
		next: head,
	}
	ind.table[hashCode] = entry
	return nil
}
Example #3
0
func TestMakeRequest(t *testing.T) {

	tests := []struct {
		note     string
		request  [][2]string
		expected interface{}
	}{
		{"var", [][2]string{{`hello`, `"world"`}}, `{"hello": "world"}`},
		{"multiple vars", [][2]string{{`a`, `"a"`}, {`b`, `"b"`}}, `{"a": "a", "b": "b"}`},
		{"multiple overlapping vars",
			[][2]string{{`a.b.c`, `"c"`}, {`a.b.d`, `"d"`}, {`x.y`, `[]`}},
			`{"a": {"b": {"c": "c", "d": "d"}}, "x": {"y": []}}`},
		{"ref value",
			[][2]string{{"foo.bar", "data.com.example.widgets[i]"}},
			`{"foo": {"bar": data.com.example.widgets[i]}}`},
		{"non-object", [][2]string{{"", "[1,2,3]"}}, "[1,2,3]"},
		{"non-object conflict",
			[][2]string{{"", "[1,2,3]"}, {"a.b", "true"}},
			fmt.Errorf("conflicting request values: check request parameters")},
		{"conflicting vars",
			[][2]string{{`a.b`, `"c"`}, {`a.b.d`, `"d"`}},
			fmt.Errorf("conflicting request value request.a.b.d: check request parameters")},
		{"conflicting vars-2",
			[][2]string{{`a.b`, `{"c":[]}`}, {`a.b.c`, `["d"]`}},
			fmt.Errorf("conflicting request value request.a.b.c: check request parameters")},
		{"conflicting vars-3",
			[][2]string{{"a", "100"}, {`a.b`, `"c"`}},
			fmt.Errorf("conflicting request value request.a.b: check request parameters")},
		{"conflicting vars-4",
			[][2]string{{`a.b`, `"c"`}, {`a`, `100`}},
			fmt.Errorf("conflicting request value request.a: check request parameters")},
		{"bad path",
			[][2]string{{`a[1]`, `1`}},
			fmt.Errorf("invalid request path: invalid path request.a[1]: path elements must be strings"),
		},
	}

	for i, tc := range tests {

		pairs := make([][2]*ast.Term, len(tc.request))

		for j := range tc.request {
			var k *ast.Term
			if len(tc.request[j][0]) == 0 {
				k = ast.NewTerm(ast.EmptyRef())
			} else {
				k = ast.MustParseTerm("request." + tc.request[j][0])
			}
			v := ast.MustParseTerm(tc.request[j][1])
			pairs[j] = [...]*ast.Term{k, v}
		}

		request, err := MakeRequest(pairs)

		switch e := tc.expected.(type) {
		case error:
			if err == nil {
				t.Errorf("%v (#%d): Expected error %v but got: %v", tc.note, i+1, e, request)
				continue
			}
			if err.Error() != e.Error() {
				t.Errorf("%v (#%d): Expected error %v but got: %v", tc.note, i+1, e, err)
			}
		case string:
			if err != nil {
				t.Errorf("%v (#%d): Unexpected error: %v", tc.note, i+1, err)
				continue
			}
			expected := ast.MustParseTerm(e)
			if !expected.Value.Equal(request) {
				t.Errorf("%v (#%d): Expected request to equal %v but got: %v", tc.note, i+1, expected, request)
			}
		}
	}
}