Exemple #1
0
func main() {
	// To see how most of this works, see hello_world -- this just add in a transaction
	store, err := cayley.NewMemoryGraph()
	if err != nil {
		log.Fatalln(err)
	}

	// Create a transaction of work to do
	// NOTE: the transaction is independent of the storage type, so comes from cayley rather than store
	t := cayley.NewTransaction()
	t.AddQuad(quad.Make("food", "is", "good", nil))
	t.AddQuad(quad.Make("phrase of the day", "is of course", "Hello World!", nil))
	t.AddQuad(quad.Make("cats", "are", "awesome", nil))
	t.AddQuad(quad.Make("cats", "are", "scary", nil))
	t.AddQuad(quad.Make("cats", "want to", "kill you", nil))

	// Apply the transaction
	err = store.ApplyTransaction(t)
	if err != nil {
		log.Fatalln(err)
	}

	p := cayley.StartPath(store, quad.String("cats")).Out(quad.String("are"))

	err = p.Iterate(nil).EachValue(nil, func(v quad.Value) {
		fmt.Println("cats are", v.Native())
	})
	if err != nil {
		log.Fatalln(err)
	}
}
Exemple #2
0
func toQuadValue(v value) quad.Value {
	if v == nil {
		return nil
	}
	switch d := v.(type) {
	case string:
		return quad.Raw(d) // compatibility
	case int64:
		return quad.Int(d)
	case float64:
		return quad.Float(d)
	case bool:
		return quad.Bool(d)
	case time.Time:
		return quad.Time(d)
	case bson.M: // TODO(dennwc): use raw document instead?
		so, ok := d["val"]
		if !ok {
			clog.Errorf("Error: Empty value in map: %v", v)
			return nil
		}
		s := so.(string)
		if len(d) == 1 {
			return quad.String(s)
		}
		if o, ok := d["iri"]; ok && o.(bool) {
			return quad.IRI(s)
		} else if o, ok := d["bnode"]; ok && o.(bool) {
			return quad.BNode(s)
		} else if o, ok := d["lang"]; ok && o.(string) != "" {
			return quad.LangString{
				Value: quad.String(s),
				Lang:  o.(string),
			}
		} else if o, ok := d["type"]; ok && o.(string) != "" {
			return quad.TypedString{
				Value: quad.String(s),
				Type:  quad.IRI(o.(string)),
			}
		}
		return quad.String(s)
	case []byte:
		var p proto.Value
		if err := p.Unmarshal(d); err != nil {
			clog.Errorf("Error: Couldn't decode value: %v", err)
			return nil
		}
		return p.ToNative()
	default:
		panic(fmt.Errorf("unsupported type: %T", v))
	}
}
Exemple #3
0
func main() {
	// File for your new BoltDB. Use path to regular file and not temporary in the real world
	tmpfile, err := ioutil.TempFile("", "example")
	if err != nil {
		log.Fatal(err)
	}

	defer os.Remove(tmpfile.Name()) // clean up

	// Initialize the database
	graph.InitQuadStore("bolt", tmpfile.Name(), nil)

	// Open and use the database
	store, err := cayley.NewGraph("bolt", tmpfile.Name(), nil)
	if err != nil {
		log.Fatalln(err)
	}

	store.AddQuad(quad.Make("phrase of the day", "is of course", "Hello BoltDB!", "demo graph"))

	// Now we create the path, to get to our data
	p := cayley.StartPath(store, quad.String("phrase of the day")).Out(quad.String("is of course"))

	// This is more advanced example of the query.
	// Simpler equivalent can be found in hello_world example.

	// Now we get an iterator for the path and optimize it.
	// The second return is if it was optimized, but we don't care for now.
	it, _ := p.BuildIterator().Optimize()

	// Optimize iterator on quad store level.
	// After this step iterators will be replaced with backend-specific ones.
	it, _ = store.OptimizeIterator(it)

	// remember to cleanup after yourself
	defer it.Close()

	// While we have items
	for it.Next() {
		token := it.Result()                // get a ref to a node (backend-specific)
		value := store.NameOf(token)        // get the value in the node (RDF)
		nativeValue := quad.NativeOf(value) // convert value to normal Go type

		fmt.Println(nativeValue) // print it!
	}
	if err := it.Err(); err != nil {
		log.Fatalln(err)
	}
}
Exemple #4
0
func (qs *store) valueAt(i int) quad.Value {
	if !qs.parse {
		return quad.Raw(qs.data[i])
	}
	iv, err := strconv.Atoi(qs.data[i])
	if err == nil {
		return quad.Int(iv)
	}
	return quad.String(qs.data[i])
}
Exemple #5
0
// ToNative converts protobuf Value to quad.Value.
func (m *Value) ToNative() (qv quad.Value) {
	if m == nil {
		return nil
	}
	switch v := m.Value.(type) {
	case *Value_Raw:
		return quad.Raw(v.Raw)
	case *Value_Str:
		return quad.String(v.Str)
	case *Value_Iri:
		return quad.IRI(v.Iri)
	case *Value_Bnode:
		return quad.BNode(v.Bnode)
	case *Value_TypedStr:
		return quad.TypedString{
			Value: quad.String(v.TypedStr.Value),
			Type:  quad.IRI(v.TypedStr.Type),
		}
	case *Value_LangStr:
		return quad.LangString{
			Value: quad.String(v.LangStr.Value),
			Lang:  v.LangStr.Lang,
		}
	case *Value_Int:
		return quad.Int(v.Int)
	case *Value_Float_:
		return quad.Float(v.Float_)
	case *Value_Boolean:
		return quad.Bool(v.Boolean)
	case *Value_Time:
		var t time.Time
		if v.Time == nil {
			t = time.Unix(0, 0).UTC()
		} else {
			t = time.Unix(v.Time.Seconds, int64(v.Time.Nanos)).UTC()
		}
		return quad.Time(t)
	default:
		panic(fmt.Errorf("unsupported type: %T", m.Value))
	}
}
Exemple #6
0
func main() {
	// Create a brand new graph
	store, err := cayley.NewMemoryGraph()
	if err != nil {
		log.Fatalln(err)
	}

	store.AddQuad(quad.Make("phrase of the day", "is of course", "Hello World!", nil))

	// Now we create the path, to get to our data
	p := cayley.StartPath(store, quad.String("phrase of the day")).Out(quad.String("is of course"))

	// Now we iterate over results. Arguments:
	// 1. Optional context used for cancellation.
	// 2. Quad store, but we can omit it because we have already built path with it.
	err = p.Iterate(nil).EachValue(nil, func(value quad.Value) {
		nativeValue := quad.NativeOf(value) // this converts RDF values to normal Go types
		fmt.Println(nativeValue)
	})
	if err != nil {
		log.Fatalln(err)
	}
}
Exemple #7
0
func TestCompareTypedValues(t testing.TB, gen DatabaseFunc, conf *Config) {
	qs, opts, closer := gen(t)
	defer closer()

	w := MakeWriter(t, qs, opts)

	t1 := tzero
	t2 := t1.Add(time.Hour)
	t3 := t2.Add(time.Hour * 48)
	t4 := t1.Add(time.Hour * 24 * 365)

	err := w.AddQuadSet([]quad.Quad{
		{quad.BNode("alice"), quad.BNode("bob"), quad.BNode("charlie"), quad.BNode("dani")},
		{quad.IRI("alice"), quad.IRI("bob"), quad.IRI("charlie"), quad.IRI("dani")},
		{quad.String("alice"), quad.String("bob"), quad.String("charlie"), quad.String("dani")},
		{quad.Int(100), quad.Int(112), quad.Int(110), quad.Int(20)},
		{quad.Time(t1), quad.Time(t2), quad.Time(t3), quad.Time(t4)},
	})
	require.Nil(t, err)

	for _, c := range casesCompare {
		it := iterator.NewComparison(qs.NodesAllIterator(), c.op, c.val, qs)
		ExpectIteratedValues(t, qs, it, c.expect)
	}

	for _, c := range casesCompare {
		it := iterator.NewComparison(qs.NodesAllIterator(), c.op, c.val, qs)
		nit, ok := qs.OptimizeIterator(it)
		require.Equal(t, conf.OptimizesComparison, ok)
		if conf.OptimizesComparison {
			require.NotEqual(t, it, nit)
		} else {
			require.Equal(t, it, nit)
		}
		ExpectIteratedValues(t, qs, nit, c.expect)
	}
}
Exemple #8
0
func (qs *store) NameOf(v graph.Value) quad.Value {
	switch v.(type) {
	case Int64Node:
		i := int(v.(Int64Node))
		if i < 0 || i >= len(qs.data) {
			return nil
		}
		return qs.valueAt(i)
	case stringNode:
		if qs.parse {
			return quad.String(v.(stringNode))
		}
		return quad.Raw(v.(stringNode))
	default:
		return nil
	}
}
Exemple #9
0
func TestZeroRune(t *testing.T) {
	qs, opts, closer := makePostgres(t)
	defer closer()

	w := graphtest.MakeWriter(t, qs, opts)

	obj := quad.String("AB\u0000CD")
	if !utf8.ValidString(string(obj)) {
		t.Fatal("invalid utf8")
	}

	err := w.AddQuad(quad.Quad{
		Subject:   quad.IRI("bob"),
		Predicate: quad.IRI("pred"),
		Object:    obj,
	})
	require.Nil(t, err)
	require.Equal(t, obj, qs.NameOf(qs.ValueOf(quad.Raw(obj.String()))))
}
Exemple #10
0
// TestUpsertItem tests the insert and update of an item.
func TestUpsertItem(t *testing.T) {
	store := setup(t)
	defer teardown(t, store)

	t.Log("Given the need to insert and then update an item.")
	{
		//----------------------------------------------------------------------
		// Get the fixture.

		items, err := itemfix.Get()
		if err != nil {
			t.Fatalf("\t%s\tShould be able to retrieve the fixture : %v", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to retrieve the fixture.", tests.Success)

		itemStrData, err := json.Marshal(&items[0])
		if err != nil {
			t.Fatalf("\t%s\tShould be able to marshal the fixture : %v", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to marshal the fixture.", tests.Success)

		//----------------------------------------------------------------------
		// Insert the Item.

		url := "/v1/item"
		r := httptest.NewRequest("PUT", url, bytes.NewBuffer(itemStrData))
		w := httptest.NewRecorder()

		a.ServeHTTP(w, r)

		t.Logf("\tWhen calling url to insert : %s", url)
		{
			if w.Code != http.StatusOK {
				t.Fatalf("\t%s\tShould be able to insert the item : %v", tests.Failed, w.Code)
			}
			t.Logf("\t%s\tShould be able to insert the item.", tests.Success)
		}

		//----------------------------------------------------------------------
		// Check the inferred relationship.

		p := cayley.StartPath(store, quad.String("ITEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("authored"))
		it, _ := p.BuildIterator().Optimize()
		defer it.Close()
		for it.Next() {
			token := it.Result()
			value := store.NameOf(token)
			if quad.NativeOf(value) != "ITEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82" {
				t.Fatalf("\t%s\tShould be able to get the inferred relationships from the graph", tests.Failed)
			}
		}
		if err := it.Err(); err != nil {
			t.Fatalf("\t%s\tShould be able to get the inferred relationships from the graph : %s", tests.Failed, err)
		}
		it.Close()
		t.Logf("\t%s\tShould be able to get the inferred relationships from the graph.", tests.Success)

		//----------------------------------------------------------------------
		// Retrieve the item.

		url = "/v1/item/" + items[0].ID
		r = httptest.NewRequest("GET", url, nil)
		w = httptest.NewRecorder()

		a.ServeHTTP(w, r)

		t.Logf("\tWhen calling url to get : %s", url)
		{
			if w.Code != http.StatusOK {
				t.Fatalf("\t%s\tShould be able to retrieve the item : %v", tests.Failed, w.Code)
			}
			t.Logf("\t%s\tShould be able to retrieve the item.", tests.Success)

			var itemsBack []item.Item
			if err := json.Unmarshal(w.Body.Bytes(), &itemsBack); err != nil {
				t.Fatalf("\t%s\tShould be able to unmarshal the results : %v", tests.Failed, err)
			}
			t.Logf("\t%s\tShould be able to unmarshal the results.", tests.Success)

			if itemsBack[0].ID != items[0].ID || itemsBack[0].Type != items[0].Type {
				t.Logf("\t%+v", items[0])
				t.Logf("\t%+v", itemsBack[0])
				t.Fatalf("\t%s\tShould be able to get back the same item.", tests.Failed)
			}
			t.Logf("\t%s\tShould be able to get back the same item.", tests.Success)
		}

		//----------------------------------------------------------------------
		// Update the Item.

		items[0].Version = 2

		itemStrData, err = json.Marshal(items[0])
		if err != nil {
			t.Fatalf("\t%s\tShould be able to marshal the changed fixture : %v", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to marshal the changed fixture.", tests.Success)

		url = "/v1/item"
		r = httptest.NewRequest("PUT", url, bytes.NewBuffer(itemStrData))
		w = httptest.NewRecorder()

		a.ServeHTTP(w, r)

		t.Logf("\tWhen calling url to update : %s", url)
		{
			if w.Code != http.StatusOK {
				t.Fatalf("\t%s\tShould be able to update the item : %v", tests.Failed, w.Code)
			}
			t.Logf("\t%s\tShould be able to update the item.", tests.Success)
		}

		//----------------------------------------------------------------------
		// Retrieve the Item.

		url = "/v1/item/" + items[0].ID
		r = httptest.NewRequest("GET", url, nil)
		w = httptest.NewRecorder()

		a.ServeHTTP(w, r)

		t.Logf("\tWhen calling url to get : %s", url)
		{
			if w.Code != http.StatusOK {
				t.Fatalf("\t%s\tShould be able to retrieve the item : %v", tests.Failed, w.Code)
			}
			t.Logf("\t%s\tShould be able to retrieve the item.", tests.Success)

			var itUpdated []item.Item
			if err := json.Unmarshal(w.Body.Bytes(), &itUpdated); err != nil {
				t.Fatalf("\t%s\tShould be able to unmarshal the results : %v", tests.Failed, err)
			}
			t.Logf("\t%s\tShould be able to unmarshal the results.", tests.Success)

			if itUpdated[0].Version != 2 {
				t.Log(w.Body.String())
				t.Fatalf("\t%s\tShould get the expected result.", tests.Failed)
			}
			t.Logf("\t%s\tShould get the expected result.", tests.Success)
		}
	}
}
Exemple #11
0
// TestDeleteItem tests the insert and deletion of a item.
func TestDeleteItem(t *testing.T) {
	store := setup(t)
	defer teardown(t, store)

	t.Log("Given the need to delete an item.")
	{
		//----------------------------------------------------------------------
		// Delete the Item.

		url := "/v1/item/ITEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82"
		r := httptest.NewRequest("DELETE", url, nil)
		w := httptest.NewRecorder()

		a.ServeHTTP(w, r)

		t.Logf("\tWhen calling url to delete : %s", url)
		{
			if w.Code != http.StatusNoContent {
				t.Fatalf("\t%s\tShould be able to delete the item : %v", tests.Failed, w.Code)
			}
			t.Logf("\t%s\tShould be able to delete the item.", tests.Success)
		}

		//----------------------------------------------------------------------
		// Retrieve the Item.

		url = "/v1/view/ITEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82"
		r = httptest.NewRequest("GET", url, nil)
		w = httptest.NewRecorder()

		a.ServeHTTP(w, r)

		t.Logf("\tWhen calling url to get : %s", url)
		{
			if w.Code != 404 {
				t.Fatalf("\t%s\tShould not be able to retrieve the item : %v", tests.Failed, w.Code)
			}
			t.Logf("\t%s\tShould not be able to retrieve the item.", tests.Success)
		}

		//----------------------------------------------------------------------
		// Check the inferred relationships.

		p := cayley.StartPath(store, quad.String("ITEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("authored"))
		it, _ := p.BuildIterator().Optimize()
		defer it.Close()

		var count int
		for it.Next() {
			count++
		}
		if err := it.Err(); err != nil {
			t.Fatalf("\t%s\tShould be able to confirm removed relationships : %s", tests.Failed, err)
		}

		if count > 0 {
			t.Fatalf("\t%s\tShould be able to confirm removed relationships.", tests.Failed)
		}
		t.Logf("\t%s\tShould be able to confirm removed relationships.", tests.Success)

	}
}
Exemple #12
0
// Decorate decorates the given graph node with a predicate with the given string value.
func (gn ModifiableGraphNode) Decorate(predicate Predicate, value string) {
	gn.DecorateWithValue(predicate, GraphValue{quad.String(value)})
}
Exemple #13
0
func unEscape(r []rune, spec int, isQuoted, isEscaped bool) quad.Value {
	raw := r
	var sp []rune
	if spec > 0 {
		r, sp = r[:spec], r[spec:]
		isQuoted = true
	}
	if isQuoted {
		r = r[1 : len(r)-1]
	} else {
		if len(r) >= 2 && r[0] == '<' && r[len(r)-1] == '>' {
			return quad.IRI(r[1 : len(r)-1])
		}
		if len(r) >= 2 && r[0] == '_' && r[1] == ':' {
			return quad.BNode(string(r[2:]))
		}
	}
	var val string
	if isEscaped {
		buf := bytes.NewBuffer(make([]byte, 0, len(r)))

		for i := 0; i < len(r); {
			switch r[i] {
			case '\\':
				i++
				var c byte
				switch r[i] {
				case 't':
					c = '\t'
				case 'b':
					c = '\b'
				case 'n':
					c = '\n'
				case 'r':
					c = '\r'
				case 'f':
					c = '\f'
				case '"':
					c = '"'
				case '\'':
					c = '\''
				case '\\':
					c = '\\'
				case 'u':
					rc, err := strconv.ParseInt(string(r[i+1:i+5]), 16, 32)
					if err != nil {
						panic(fmt.Errorf("internal parser error: %v", err))
					}
					buf.WriteRune(rune(rc))
					i += 5
					continue
				case 'U':
					rc, err := strconv.ParseInt(string(r[i+1:i+9]), 16, 32)
					if err != nil {
						panic(fmt.Errorf("internal parser error: %v", err))
					}
					buf.WriteRune(rune(rc))
					i += 9
					continue
				}
				buf.WriteByte(c)
			default:
				buf.WriteRune(r[i])
			}
			i++
		}
		val = buf.String()
	} else {
		val = string(r)
	}
	if len(sp) == 0 {
		if isQuoted {
			return quad.String(val)
		}
		return quad.Raw(val)
	}
	if sp[0] == '@' {
		return quad.LangString{
			Value: quad.String(val),
			Lang:  string(sp[1:]),
		}
	} else if len(sp) >= 4 && sp[0] == '^' && sp[1] == '^' && sp[2] == '<' && sp[len(sp)-1] == '>' {
		v := quad.TypedString{
			Value: quad.String(val),
			Type:  quad.IRI(sp[3 : len(sp)-1]),
		}
		if AutoConvertTypedString {
			nv, err := v.ParseValue()
			if err == nil {
				return nv
			}
		}
		return v
	}
	return quad.Raw(raw)
}
Exemple #14
0
			return otto.NullValue()
		}
		return outObj(call, cmpOperator{op: op, val: qv})
	}
}

type cmpOperator struct {
	op  iterator.Operator
	val quad.Value
}

var defaultEnv = map[string]func(call otto.FunctionCall) otto.Value{
	"iri":   oneStringType(func(s string) quad.Value { return quad.IRI(s) }),
	"bnode": oneStringType(func(s string) quad.Value { return quad.BNode(s) }),
	"raw":   oneStringType(func(s string) quad.Value { return quad.Raw(s) }),
	"str":   oneStringType(func(s string) quad.Value { return quad.String(s) }),

	"lang": twoStringType(func(s, lang string) quad.Value {
		return quad.LangString{Value: quad.String(s), Lang: lang}
	}),
	"typed": twoStringType(func(s, typ string) quad.Value {
		return quad.TypedString{Value: quad.String(s), Type: quad.IRI(typ)}
	}),

	"lt":  cmpOpType(iterator.CompareLT),
	"lte": cmpOpType(iterator.CompareLTE),
	"gt":  cmpOpType(iterator.CompareGT),
	"gte": cmpOpType(iterator.CompareGTE),
}

func newWorker(qs graph.QuadStore) *worker {
// TestAddRemoveGraph tests if we can add/remove relationship quads to/from cayley.
func TestAddRemoveGraph(t *testing.T) {
	db, store, items := setupGraph(t)
	defer tests.DisplayLog()

	t.Log("Given the need to add/remove relationship quads from the Cayley graph.")
	{
		t.Log("\tWhen starting from an empty graph")
		{

			//----------------------------------------------------------------------
			// Infer and add the relationships to the graph.

			if err := wire.AddToGraph(tests.Context, db, store, items[0]); err != nil {
				t.Fatalf("\t%s\tShould be able to add relationships to the graph : %s", tests.Failed, err)
			}
			t.Logf("\t%s\tShould be able to add relationships to the graph.", tests.Success)

			//----------------------------------------------------------------------
			// Get the relationship quads from the graph.

			p := cayley.StartPath(store, quad.String("WTEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("WTEST_flagged"))
			it, _ := p.BuildIterator().Optimize()
			defer it.Close()

			var count int
			for it.Next() {
				count++
				token := it.Result()
				value := store.NameOf(token)
				if quad.NativeOf(value) != "WTEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82" {
					t.Fatalf("\t%s\tShould be able to get the relationships from the graph", tests.Failed)
				}
			}
			if err := it.Err(); err != nil {
				t.Fatalf("\t%s\tShould be able to get the relationships from the graph : %s", tests.Failed, err)
			}
			it.Close()

			p = cayley.StartPath(store, quad.String("WTEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82")).Out(quad.String("WTEST_on"))
			it, _ = p.BuildIterator().Optimize()
			defer it.Close()
			for it.Next() {
				count++
				token := it.Result()
				value := store.NameOf(token)
				if quad.NativeOf(value) != "WTEST_c1b2bbfe-af9f-4903-8777-bd47c4d5b20a" {
					t.Fatalf("\t%s\tShould be able to get the relationships from the graph", tests.Failed)
				}
			}
			if err := it.Err(); err != nil {
				t.Fatalf("\t%s\tShould be able to get the relationships from the graph : %s", tests.Failed, err)
			}
			it.Close()

			if count != 2 {
				t.Fatalf("\t%s\tShould be able to get relationships from the graph", tests.Failed)
			}
			t.Logf("\t%s\tShould be able to get relationships from the graph.", tests.Success)

			//----------------------------------------------------------------------
			// Try to infer and add the relationships again.

			if err := wire.AddToGraph(tests.Context, db, store, items[0]); err != nil {
				t.Fatalf("\t%s\tShould be able to add an item again and maintain relationships : %s", tests.Failed, err)
			}
			t.Logf("\t%s\tShould be able to add an item again and maintain relationships.", tests.Success)

			//----------------------------------------------------------------------
			// Remove the relationships from the graph.

			if err := wire.RemoveFromGraph(tests.Context, db, store, items[0]); err != nil {
				t.Fatalf("\t%s\tShould be able to remove relationships from the graph : %s", tests.Failed, err)
			}
			t.Logf("\t%s\tShould be able to remove relationships from the graph.", tests.Success)

			//----------------------------------------------------------------------
			// Try to get the relationships.

			count = 0
			p = cayley.StartPath(store, quad.String("WTEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("WTEST_authored"))
			it, _ = p.BuildIterator().Optimize()
			defer it.Close()
			for it.Next() {
				count++
			}
			if err := it.Err(); err != nil {
				t.Fatalf("\t%s\tShould be able to verify the empty graph : %s", tests.Failed, err)
			}
			it.Close()

			p = cayley.StartPath(store, quad.String("WTEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82")).Out(quad.String("WTEST_on"))
			it, _ = p.BuildIterator().Optimize()
			defer it.Close()
			for it.Next() {
				count++
			}
			if err := it.Err(); err != nil {
				t.Fatalf("\t%s\tShould be able to verify the empty graph : %s", tests.Failed, err)
			}
			it.Close()

			if count != 0 {
				t.Fatalf("\t%s\tShould be able to verify the empty graph", tests.Failed)
			}
			t.Logf("\t%s\tShould be able to verify the empty graph.", tests.Success)
		}
	}
}
Exemple #16
0
const lt, lte, gt, gte = iterator.CompareLT, iterator.CompareLTE, iterator.CompareGT, iterator.CompareGTE

var tzero = time.Unix(time.Now().Unix(), 0)

var casesCompare = []struct {
	op     iterator.Operator
	val    quad.Value
	expect []quad.Value
}{
	{lt, quad.BNode("b"), []quad.Value{
		quad.BNode("alice"),
	}},
	{lte, quad.BNode("bob"), []quad.Value{
		quad.BNode("alice"), quad.BNode("bob"),
	}},
	{lt, quad.String("b"), []quad.Value{
		quad.String("alice"),
	}},
	{lte, quad.String("bob"), []quad.Value{
		quad.String("alice"), quad.String("bob"),
	}},
	{gte, quad.String("b"), []quad.Value{
		quad.String("bob"), quad.String("charlie"), quad.String("dani"),
	}},
	{lt, quad.IRI("b"), []quad.Value{
		quad.IRI("alice"),
	}},
	{lte, quad.IRI("bob"), []quad.Value{
		quad.IRI("alice"), quad.IRI("bob"),
	}},
	{lte, quad.IRI("bob"), []quad.Value{
Exemple #17
0
func TestLoadTypedQuads(t testing.TB, gen DatabaseFunc, conf *Config) {
	qs, opts, closer := gen(t)
	defer closer()

	w := MakeWriter(t, qs, opts)

	values := []quad.Value{
		quad.BNode("A"), quad.IRI("name"), quad.String("B"), quad.IRI("graph"),
		quad.IRI("B"), quad.Raw("<type>"),
		quad.TypedString{Value: "10", Type: "int"},
		quad.LangString{Value: "value", Lang: "en"},
		quad.Int(-123456789),
		quad.Float(-12345e-6),
		quad.Bool(true),
		quad.Time(time.Now()),
	}

	err := w.AddQuadSet([]quad.Quad{
		{values[0], values[1], values[2], values[3]},
		{values[4], values[5], values[6], nil},
		{values[4], values[5], values[7], nil},
		{values[0], values[1], values[8], nil},
		{values[0], values[1], values[9], nil},
		{values[0], values[1], values[10], nil},
		{values[0], values[1], values[11], nil},
	})
	require.Nil(t, err)
	for _, pq := range values {
		got := qs.NameOf(qs.ValueOf(pq))
		if !conf.UnTyped {
			if pt, ok := pq.(quad.Time); ok {
				var trim int64
				if conf.TimeInMcs {
					trim = 1000
				} else if conf.TimeInMs {
					trim = 1000000
				}
				if trim > 0 {
					tm := time.Time(pt)
					seconds := tm.Unix()
					nanos := int64(tm.Sub(time.Unix(seconds, 0)))
					if conf.TimeRound {
						nanos = (nanos/trim + ((nanos/(trim/10))%10)/5) * trim
					} else {
						nanos = (nanos / trim) * trim
					}
					pq = quad.Time(time.Unix(seconds, nanos).UTC())
				}
			}
			if eq, ok := pq.(quad.Equaler); ok {
				assert.True(t, eq.Equal(got), "Failed to roundtrip %q (%T), got %q (%T)", pq, pq, got, got)
			} else {
				assert.Equal(t, pq, got, "Failed to roundtrip %q (%T)", pq, pq)
				if !conf.NoHashes {
					assert.Equal(t, pq, qs.NameOf(qs.ValueOf(quad.Raw(pq.String()))), "Failed to exchange raw value %q (%T)", pq, pq)
				}
			}
		} else {
			assert.Equal(t, quad.StringOf(pq), quad.StringOf(got), "Failed to roundtrip raw %q (%T)", pq, pq)
		}
	}
	require.Equal(t, int64(7), qs.Size(), "Unexpected quadstore size")
}
Exemple #18
0
func (qs *QuadStore) NameOf(v graph.Value) quad.Value {
	if v == nil {
		if clog.V(2) {
			clog.Infof("NameOf was nil")
		}
		return nil
	}
	hash := v.(NodeHash)
	if !hash.Valid() {
		if clog.V(2) {
			clog.Infof("NameOf was nil")
		}
		return nil
	}
	if val, ok := qs.ids.Get(hash.String()); ok {
		return val.(quad.Value)
	}
	query := `SELECT
		value,
		value_string,
		datatype,
		language,
		iri,
		bnode,
		value_int,
		value_bool,
		value_float,
		value_time
	FROM nodes WHERE hash = $1 LIMIT 1;`
	c := qs.db.QueryRow(query, hash.toSQL())
	var (
		data   []byte
		str    sql.NullString
		typ    sql.NullString
		lang   sql.NullString
		iri    sql.NullBool
		bnode  sql.NullBool
		vint   sql.NullInt64
		vbool  sql.NullBool
		vfloat sql.NullFloat64
		vtime  pq.NullTime
	)
	if err := c.Scan(
		&data,
		&str,
		&typ,
		&lang,
		&iri,
		&bnode,
		&vint,
		&vbool,
		&vfloat,
		&vtime,
	); err != nil {
		clog.Errorf("Couldn't execute value lookup: %v", err)
		return nil
	}
	var val quad.Value
	if str.Valid {
		if iri.Bool {
			val = quad.IRI(str.String)
		} else if bnode.Bool {
			val = quad.BNode(str.String)
		} else if lang.Valid {
			val = quad.LangString{
				Value: quad.String(unescapeNullByte(str.String)),
				Lang:  lang.String,
			}
		} else if typ.Valid {
			val = quad.TypedString{
				Value: quad.String(unescapeNullByte(str.String)),
				Type:  quad.IRI(typ.String),
			}
		} else {
			val = quad.String(unescapeNullByte(str.String))
		}
	} else if vint.Valid {
		val = quad.Int(vint.Int64)
	} else if vbool.Valid {
		val = quad.Bool(vbool.Bool)
	} else if vfloat.Valid {
		val = quad.Float(vfloat.Float64)
	} else if vtime.Valid {
		val = quad.Time(vtime.Time)
	} else {
		qv, err := proto.UnmarshalValue(data)
		if err != nil {
			clog.Errorf("Couldn't unmarshal value: %v", err)
			return nil
		}
		val = qv
	}
	if val != nil {
		qs.ids.Put(hash.String(), val)
	}
	return val
}
		operator: CompareGTE,
		expect:   []quad.Value{quad.Int(2), quad.Int(3), quad.Int(4)},
		qs:       simpleStore,
		iterator: simpleFixedIterator,
	},
	{
		message:  "successful int64 greater than or equal comparison (mixed)",
		operand:  quad.Int(2),
		operator: CompareGTE,
		expect:   []quad.Value{quad.Int(2), quad.Int(3), quad.Int(4), quad.Int(5)},
		qs:       mixedStore,
		iterator: mixedFixedIterator,
	},
	{
		message:  "successful string less than comparison",
		operand:  quad.String("echo"),
		operator: CompareLT,
		expect:   []quad.Value{quad.String("bar"), quad.String("baz")},
		qs:       stringStore,
		iterator: stringFixedIterator,
	},
	{
		message:  "empty string less than comparison",
		operand:  quad.String(""),
		operator: CompareLT,
		expect:   nil,
		qs:       stringStore,
		iterator: stringFixedIterator,
	},
	{
		message:  "successful string greater than comparison",
Exemple #20
0
		message: "parse simple triples",
		input:   "this is valid .",
		expect: quad.Quad{
			Subject:   quad.Raw("this"),
			Predicate: quad.Raw("is"),
			Object:    quad.Raw("valid"),
			Label:     nil,
		},
	},
	{
		message: "parse quoted triples",
		input:   `this is "valid too" .`,
		expect: quad.Quad{
			Subject:   quad.Raw("this"),
			Predicate: quad.Raw("is"),
			Object:    quad.String("valid too"),
			Label:     nil,
		},
	},
	{
		message: "parse escaped quoted triples",
		input:   `he said "\"That's all folks\"" .`,
		expect: quad.Quad{
			Subject:   quad.Raw("he"),
			Predicate: quad.Raw("said"),
			Object:    quad.String(`"That's all folks"`),
			Label:     nil,
		},
	},
	{
		message: "parse an example real triple",
Exemple #21
0
type test struct {
	message string
	path    *Path
	expect  []quad.Value
	tag     string
}

// Define morphisms without a QuadStore

const (
	vFollows   = quad.IRI("follows")
	vAre       = quad.IRI("are")
	vStatus    = quad.IRI("status")
	vPredicate = quad.IRI("predicates")

	vCool       = quad.String("cool_person")
	vSmart      = quad.String("smart_person")
	vSmartGraph = quad.IRI("smart_graph")

	vAlice   = quad.IRI("alice")
	vBob     = quad.IRI("bob")
	vCharlie = quad.IRI("charlie")
	vDani    = quad.IRI("dani")
	vFred    = quad.IRI("fred")
	vGreg    = quad.IRI("greg")
	vEmily   = quad.IRI("emily")
)

var (
	grandfollows = StartMorphism().Out(vFollows).Out(vFollows)
)
Exemple #22
0
// viewPathToGraphPath translates the path in a view into a "path"
// utilized in graph queries.
func viewPathToGraphPath(v *view.View, key string, graphDB *cayley.Handle) (*path.Path, error) {

	// outputPath is the final tranlated graph path.
	var outputPath *path.Path

	// Loop over the paths in the view translating the metadata.
	for idx, pth := range v.Paths {

		// We create an alias prefix for tags, so we can track which
		// path a tag is in.
		alias := strconv.Itoa(idx+1) + "_"

		// Sort the view Path value.
		sort.Sort(pth.Segments)

		// graphPath will contain the entire strict graph path.
		var graphPath *path.Path

		// subPaths will contain each sub path of the full graph path,
		// as a separate graph path.
		var subPaths []path.Path

		// Loop over the path segments translating the path.
		level := 1
		for _, segment := range pth.Segments {

			// Check that the level is the level we expect (i.e., that the levels
			// are in order)
			if level != segment.Level {
				err := fmt.Errorf("Invalid view path level, expected %d but seeing %d", level, segment.Level)
				return graphPath, err
			}

			// Initialize the path, if we are on level 1.
			if level == 1 {

				// Add the first level relationship.
				switch segment.Direction {
				case inString:
					graphPath = cayley.StartPath(graphDB, quad.String(key)).In(quad.String(segment.Predicate))
				case outString:
					graphPath = cayley.StartPath(graphDB, quad.String(key)).Out(quad.String(segment.Predicate))
				}

				// Add the tag, if present.
				if segment.Tag != "" {
					graphPath = graphPath.Clone().Tag(alias + segment.Tag)
				}

				// Track this as a subpath.
				subPaths = append(subPaths, *graphPath.Clone())

				level++
				continue
			}

			// Add the relationship.
			switch segment.Direction {
			case inString:
				graphPath = graphPath.Clone().In(quad.String(segment.Predicate))
			case outString:
				graphPath = graphPath.Clone().Out(quad.String(segment.Predicate))
			}

			// Add the tag, if present.
			if segment.Tag != "" {
				graphPath = graphPath.Clone().Tag(alias + segment.Tag)
			}

			// Add this as a subpath.
			subPaths = append(subPaths, *graphPath.Clone())

			level++
		}

		// If we are forcing a strict path, return only the resulting or
		// tagged items along the full path.
		if pth.StrictPath {
			if outputPath == nil {
				outputPath = graphPath
				continue
			}
			outputPath = outputPath.Clone().Or(graphPath)
			continue
		}

		// Otherwise add all the subpaths to the output path.
		for _, subPath := range subPaths {
			if outputPath == nil {
				addedPath := &subPath
				outputPath = addedPath.Clone()
				continue
			}
			outputPath = outputPath.Clone().Or(&subPath)
		}
	}

	return outputPath, nil
}
Exemple #23
0
// TestImportRemoveItem tests the insert and update of an item.
func TestImportRemoveItem(t *testing.T) {
	db, store := setup(t)
	defer teardown(t, db, store)

	t.Log("Given the need to import an item.")
	{
		//----------------------------------------------------------------------
		// Get the fixture.

		items, err := itemfix.Get()
		if err != nil {
			t.Fatalf("\t%s\tShould be able to retrieve the fixture : %v", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to retrieve the fixture.", tests.Success)

		//----------------------------------------------------------------------
		// Import the Item.

		if err := sponge.Import(tests.Context, db, store, &items[0]); err != nil {
			t.Fatalf("\t%s\tShould be able to import an item : %s", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to import an item", tests.Success)

		//----------------------------------------------------------------------
		// Check the inferred relationship.

		p := cayley.StartPath(store, quad.String("ITEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("authored"))
		it, _ := p.BuildIterator().Optimize()
		defer it.Close()
		for it.Next() {
			token := it.Result()
			value := store.NameOf(token)
			if quad.NativeOf(value) != "ITEST_d1dfa366-d2f7-4a4a-a64f-af89d4c97d82" {
				t.Fatalf("\t%s\tShould be able to get the inferred relationships from the graph", tests.Failed)
			}
		}
		if err := it.Err(); err != nil {
			t.Fatalf("\t%s\tShould be able to get the inferred relationships from the graph : %s", tests.Failed, err)
		}
		it.Close()
		t.Logf("\t%s\tShould be able to get the inferred relationships from the graph.", tests.Success)

		//----------------------------------------------------------------------
		// Import the Item again to test for duplicate imports.

		if err := sponge.Import(tests.Context, db, store, &items[0]); err != nil {
			t.Fatalf("\t%s\tShould be able to import a duplicate item : %s", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to import a duplicate item", tests.Success)

		//----------------------------------------------------------------------
		// Remove the item.

		if err := sponge.Remove(tests.Context, db, store, items[0].ID); err != nil {
			t.Fatalf("\t%s\tShould be able to remove the item : %s", tests.Failed, err)
		}
		t.Logf("\t%s\tShould be able to remove the item", tests.Success)

		//----------------------------------------------------------------------
		// Check the inferred relationships.

		p = cayley.StartPath(store, quad.String("ITEST_80aa936a-f618-4234-a7be-df59a14cf8de")).Out(quad.String("authored"))
		it, _ = p.BuildIterator().Optimize()
		defer it.Close()

		var count int
		for it.Next() {
			count++
		}
		if err := it.Err(); err != nil {
			t.Fatalf("\t%s\tShould be able to confirm removed relationships : %s", tests.Failed, err)
		}

		if count > 0 {
			t.Fatalf("\t%s\tShould be able to confirm removed relationships.", tests.Failed)
		}
		t.Logf("\t%s\tShould be able to confirm removed relationships.", tests.Success)
	}
}