diff --git a/posting/list.go b/posting/list.go index 8fec9f188bd09aa003326f2a84e8048ef9f76a4f..17450f2452c48165a9d4238b7080abfb1a0956bc 100644 --- a/posting/list.go +++ b/posting/list.go @@ -19,8 +19,6 @@ package posting import ( "bytes" "encoding/binary" - "encoding/json" - "errors" "fmt" "math" "sync" @@ -116,16 +114,11 @@ func Key(uid uint64, attr string) []byte { func newPosting(t x.DirectedEdge, op byte) []byte { b := flatbuffers.NewBuilder(0) var bo flatbuffers.UOffsetT - if t.Value != nil { + if !bytes.Equal(t.Value, nil) { if t.ValueId != math.MaxUint64 { glog.Fatal("This should have already been set by the caller.") } - bytes, err := json.Marshal(t.Value) - if err != nil { - glog.WithError(err).Fatal("Unable to marshal value") - return []byte{} - } - bo = b.CreateByteVector(bytes) + bo = b.CreateByteVector(t.Value) } so := b.CreateString(t.Source) types.PostingStart(b) @@ -146,16 +139,11 @@ func addEdgeToPosting(b *flatbuffers.Builder, t x.DirectedEdge, op byte) flatbuffers.UOffsetT { var bo flatbuffers.UOffsetT - if t.Value != nil { + if !bytes.Equal(t.Value, nil) { if t.ValueId != math.MaxUint64 { glog.Fatal("This should have already been set by the caller.") } - bytes, err := json.Marshal(t.Value) - if err != nil { - glog.WithError(err).Fatal("Unable to marshal value") - return 0 - } - bo = b.CreateByteVector(bytes) + bo = b.CreateByteVector(t.Value) } so := b.CreateString(t.Source) // Do this before posting start. @@ -214,19 +202,6 @@ func init() { len(empty), len(emptyPosting)) } -func ParseValue(i *interface{}, value []byte) error { - if len(value) == 0 { - return errors.New("No value found in posting") - } - - if len(value) == 1 && value[0] == 0x00 { - i = nil - return nil - } - - return json.Unmarshal(value, i) -} - func (l *List) init(key []byte, pstore *store.Store, clog *commit.Logger) { l.Lock() defer l.Unlock() @@ -624,8 +599,8 @@ func (l *List) AddMutation(t x.DirectedEdge, op byte) error { // - If no, disregard this mutation. // All edges with a value set, have the same uid. In other words, - // an (entity, attribute) can only have one interface{} value. - if t.Value != nil { + // an (entity, attribute) can only have one value. + if !bytes.Equal(t.Value, nil) { t.ValueId = math.MaxUint64 } if t.ValueId == 0 { diff --git a/posting/list_test.go b/posting/list_test.go index 79cde4bcbef35fe0dcb99f5287c5e975a3963034..d17837663feade955bf98f711ee942b276b29be0 100644 --- a/posting/list_test.go +++ b/posting/list_test.go @@ -17,11 +17,13 @@ package posting import ( + "bytes" "fmt" "io/ioutil" "math" "math/rand" "os" + "strconv" "testing" "time" @@ -238,7 +240,7 @@ func TestAddMutation_Value(t *testing.T) { glog.Debug("Init successful.") edge := x.DirectedEdge{ - Value: "oh hey there", + Value: []byte("oh hey there"), Source: "new-testing", Timestamp: time.Now(), } @@ -250,13 +252,8 @@ func TestAddMutation_Value(t *testing.T) { if p.Uid() != math.MaxUint64 { t.Errorf("All value uids should go to MaxUint64. Got: %v", p.Uid()) } - var iout interface{} - if err := ParseValue(&iout, p.ValueBytes()); err != nil { - t.Error(err) - } - out := iout.(string) - if out != "oh hey there" { - t.Errorf("Expected a value. Got: [%q]", out) + if !bytes.Equal(p.ValueBytes(), []byte("oh hey there")) { + t.Errorf("Expected a value. Got: [%q]", string(p.ValueBytes())) } // Run the same check after committing. @@ -268,17 +265,13 @@ func TestAddMutation_Value(t *testing.T) { if ok := ol.Get(&tp, 0); !ok { t.Error("While retrieving posting") } - if err := ParseValue(&iout, tp.ValueBytes()); err != nil { - t.Error(err) - } - out := iout.(string) - if out != "oh hey there" { - t.Errorf("Expected a value. Got: [%q]", out) + if !bytes.Equal(tp.ValueBytes(), []byte("oh hey there")) { + t.Errorf("Expected a value. Got: [%q]", string(tp.ValueBytes())) } } // The value made it to the posting list. Changing it now. - edge.Value = 119 + edge.Value = []byte(strconv.Itoa(119)) if err := ol.AddMutation(edge, Set); err != nil { t.Error(err) } @@ -288,10 +281,10 @@ func TestAddMutation_Value(t *testing.T) { if ok := ol.Get(&p, 0); !ok { t.Error("While retrieving posting") } - if err := ParseValue(&iout, p.ValueBytes()); err != nil { + var intout int + if intout, err = strconv.Atoi(string(p.ValueBytes())); err != nil { t.Error(err) } - intout := iout.(float64) if intout != 119 { t.Errorf("Expected 119. Got: %v", intout) } diff --git a/query/query.go b/query/query.go index 83a869726119751bdcb35c4f9f3a7dfaff1855ba..351378ba2e12465ad75d58dbd5927ea11d855391 100644 --- a/query/query.go +++ b/query/query.go @@ -17,6 +17,7 @@ package query import ( + "bytes" "container/heap" "encoding/json" "fmt" @@ -25,7 +26,6 @@ import ( "github.com/Sirupsen/logrus" "github.com/dgraph-io/dgraph/gql" - "github.com/dgraph-io/dgraph/posting" "github.com/dgraph-io/dgraph/query/graph" "github.com/dgraph-io/dgraph/task" "github.com/dgraph-io/dgraph/worker" @@ -208,27 +208,24 @@ func postTraverse(g *SubGraph) (result map[uint64]interface{}, rerr error) { if ok := r.Values(&tv, i); !ok { return result, fmt.Errorf("While parsing value") } - var ival interface{} - if err := posting.ParseValue(&ival, tv.ValBytes()); err != nil { - return result, err - } - if ival == nil { + val := tv.ValBytes() + if bytes.Equal(val, nil) { continue } if pval, present := result[q.Uids(i)]; present { glog.WithField("prev", pval). WithField("_uid_", q.Uids(i)). - WithField("new", ival). + WithField("new", val). Fatal("Previous value detected.") } m := make(map[string]interface{}) m["_uid_"] = fmt.Sprintf("%#x", q.Uids(i)) glog.WithFields(logrus.Fields{ "_uid_": q.Uids(i), - "val": ival, + "val": val, }).Debug("Got value") - m[g.Attr] = ival + m[g.Attr] = val result[q.Uids(i)] = m } return result, nil @@ -335,7 +332,6 @@ func (g *SubGraph) preTraverse(uid uint64, dst *graph.Node) error { p := &graph.Property{Prop: pc.Attr, Val: v} properties = append(properties, p) } - } } dst.Properties, dst.Children = properties, children diff --git a/query/query_test.go b/query/query_test.go index bf8663ac419b14102a776670ce332ed36771b346..8276c52ba36b69048917a89d10471c238e086457 100644 --- a/query/query_test.go +++ b/query/query_test.go @@ -54,13 +54,9 @@ func checkName(t *testing.T, r *task.Result, idx int, expected string) { if ok := r.Values(&tv, idx); !ok { t.Error("Unable to retrieve value") } - var iname interface{} - if err := posting.ParseValue(&iname, tv.ValBytes()); err != nil { - t.Error(err) - } - name := iname.(string) - if name != expected { - t.Errorf("Expected: %v. Got: %v", expected, name) + name := tv.ValBytes() + if string(name) != expected { + t.Errorf("Expected: %v. Got: %v", expected, string(name)) } } @@ -165,29 +161,29 @@ func populateGraph(t *testing.T) (string, *store.Store) { addEdge(t, edge, posting.GetOrCreate(posting.Key(1, "friend"), ps)) // Now let's add a few properties for the main user. - edge.Value = "Michonne" + edge.Value = []byte("Michonne") addEdge(t, edge, posting.GetOrCreate(posting.Key(1, "name"), ps)) - edge.Value = "female" + edge.Value = []byte("female") addEdge(t, edge, posting.GetOrCreate(posting.Key(1, "gender"), ps)) - edge.Value = "alive" + edge.Value = []byte("alive") addEdge(t, edge, posting.GetOrCreate(posting.Key(1, "status"), ps)) // Now let's add a name for each of the friends, except 101. - edge.Value = "Rick Grimes" + edge.Value = []byte("Rick Grimes") addEdge(t, edge, posting.GetOrCreate(posting.Key(23, "name"), ps)) - edge.Value = "Glenn Rhee" + edge.Value = []byte("Glenn Rhee") addEdge(t, edge, posting.GetOrCreate(posting.Key(24, "name"), ps)) - edge.Value = "Daryl Dixon" + edge.Value = []byte("Daryl Dixon") addEdge(t, edge, posting.GetOrCreate(posting.Key(25, "name"), ps)) - edge.Value = "Andrea" + edge.Value = []byte("Andrea") addEdge(t, edge, posting.GetOrCreate(posting.Key(31, "name"), ps)) - edge.Value = "mich" + edge.Value = []byte("mich") addEdge(t, edge, posting.GetOrCreate(posting.Key(1, "_xid_"), ps)) return dir, ps @@ -274,8 +270,8 @@ func TestProcessGraph(t *testing.T) { if ok := r.Values(&tv, 4); !ok { t.Error("Unable to retrieve value") } - if tv.ValLength() != 1 || tv.ValBytes()[0] != 0x00 { - t.Error("Expected a null byte") + if !bytes.Equal(tv.ValBytes(), []byte{}) { + t.Error("Expected a null byte slice") } } @@ -383,15 +379,14 @@ func TestToPB(t *testing.T) { if gr.Uid != 1 { t.Errorf("Expected uid 1, Got: %v", gr.Uid) } - // TODO(pawan) - Fix "" being stored in the the flatbuffer val. - if gr.Xid != `"mich"` { + if gr.Xid != "mich" { t.Errorf("Expected xid mich, Got: %v", gr.Xid) } if len(gr.Properties) != 3 { t.Errorf("Expected values map to contain 3 properties, Got: %v", len(gr.Properties)) } - if string(getProperty(gr.Properties, "name")) != `"Michonne"` { + if string(getProperty(gr.Properties, "name")) != "Michonne" { t.Errorf("Expected property name to have value Michonne, Got: %v", string(getProperty(gr.Properties, "name"))) } @@ -410,7 +405,7 @@ func TestToPB(t *testing.T) { t.Errorf("Expected values map to contain 1 property, Got: %v", len(child.Properties)) } - if string(getProperty(child.Properties, "name")) != `"Rick Grimes"` { + if string(getProperty(child.Properties, "name")) != "Rick Grimes" { t.Errorf("Expected property name to have value Rick Grimes, Got: %v", string(getProperty(child.Properties, "name"))) } diff --git a/rdf/parse.go b/rdf/parse.go index be0d5611b63d14816379a4a67bbd758a19643a83..402025a6227c0877f262064b13d52e5590052191 100644 --- a/rdf/parse.go +++ b/rdf/parse.go @@ -31,7 +31,7 @@ type NQuad struct { Subject string Predicate string ObjectId string - ObjectValue interface{} + ObjectValue []byte Label string } @@ -158,7 +158,7 @@ func Parse(line string) (rnq NQuad, rerr error) { return rnq, fmt.Errorf("Invalid end of input. Input: [%s]", line) } if len(oval) > 0 { - rnq.ObjectValue = oval + rnq.ObjectValue = []byte(oval) } if len(rnq.Subject) == 0 || len(rnq.Predicate) == 0 { return rnq, fmt.Errorf("Empty required fields in NQuad. Input: [%s]", line) diff --git a/rdf/parse_test.go b/rdf/parse_test.go index 77e18c5bdb2cea9917b36489cfb7bf640e8a5f67..2c69775c9953d7f247b99cb8df536b08746e342d 100644 --- a/rdf/parse_test.go +++ b/rdf/parse_test.go @@ -32,7 +32,7 @@ var testNQuads = []struct { Subject: "some_subject_id", Predicate: "predicate", ObjectId: "object_id", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -41,7 +41,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "predicate", ObjectId: "object_id", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -50,7 +50,7 @@ var testNQuads = []struct { Subject: "_uid_:0x01", Predicate: "predicate", ObjectId: "object_id", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -59,7 +59,7 @@ var testNQuads = []struct { Subject: "some_subject_id", Predicate: "predicate", ObjectId: "_uid_:0x01", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -68,7 +68,7 @@ var testNQuads = []struct { Subject: "_uid_:0x01", Predicate: "predicate", ObjectId: "_uid_:0x02", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -77,7 +77,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "follows", ObjectId: "_:bob0", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -86,7 +86,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "name", ObjectId: "", - ObjectValue: "Alice In Wonderland", + ObjectValue: []byte("Alice In Wonderland"), }, }, { @@ -95,7 +95,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "name.en-0", ObjectId: "", - ObjectValue: "Alice In Wonderland", + ObjectValue: []byte("Alice In Wonderland"), }, }, { @@ -104,7 +104,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "age", ObjectId: "", - ObjectValue: "013@@integer", + ObjectValue: []byte("013@@integer"), }, }, { @@ -113,7 +113,7 @@ var testNQuads = []struct { Subject: "http://www.w3.org/2001/sw/RDFCore/nedges/", Predicate: "http://purl.org/dc/terms/title.en-US", ObjectId: "", - ObjectValue: "N-Edges", + ObjectValue: []byte("N-Edges"), }, }, { @@ -122,7 +122,7 @@ var testNQuads = []struct { Subject: "_:art", Predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", ObjectId: "http://xmlns.com/foaf/0.1/Person", - ObjectValue: nil, + ObjectValue: []byte(nil), }, }, { @@ -179,7 +179,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "knows", ObjectId: "", - ObjectValue: "stuff@@xs:string", + ObjectValue: []byte("stuff@@xs:string"), }, hasErr: false, }, @@ -189,7 +189,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "knows", ObjectId: "", - ObjectValue: "stuff@@xs:string", + ObjectValue: []byte("stuff@@xs:string"), Label: "label", }, hasErr: false, @@ -200,7 +200,7 @@ var testNQuads = []struct { Subject: "_:alice", Predicate: "knows", ObjectId: "", - ObjectValue: "stuff@@xs:string", + ObjectValue: []byte("stuff@@xs:string"), Label: "_:label", }, hasErr: false, @@ -222,7 +222,7 @@ var testNQuads = []struct { nq: NQuad{ Subject: "_:alice", Predicate: "likes", - ObjectValue: `mov\"enpick`, + ObjectValue: []byte(`mov\"enpick`), }, }, } diff --git a/uid/assigner.go b/uid/assigner.go index 5e06d871643044f3a94fc4561aeda8ffab83edbd..8bcb4cc90f8bfedf405613e48de061824a2a6c5e 100644 --- a/uid/assigner.go +++ b/uid/assigner.go @@ -130,16 +130,13 @@ func allocateUniqueUid(xid string, instanceIdx uint64, // Something already present here. var p types.Posting pl.Get(&p, 0) - - var tmp interface{} - posting.ParseValue(&tmp, p.ValueBytes()) - glog.Debug("Found existing xid: [%q]. Continuing...", tmp.(string)) + glog.Debug("Found existing xid: [%q]. Continuing...", string(p.ValueBytes())) continue } // Uid hasn't been assigned yet. t := x.DirectedEdge{ - Value: xid, // not txid + Value: []byte(xid), // not txid Source: "_assigner_", Timestamp: time.Now(), } @@ -251,8 +248,5 @@ func ExternalId(uid uint64) (xid string, rerr error) { if p.Uid() != math.MaxUint64 { glog.WithField("uid", uid).Fatal("Value uid must be MaxUint64.") } - var t interface{} - rerr = posting.ParseValue(&t, p.ValueBytes()) - xid = t.(string) - return xid, rerr + return string(p.ValueBytes()), rerr } diff --git a/worker/worker_test.go b/worker/worker_test.go index f879efac7e3274be107918654072201170392b2b..763dfc89e19bcfbec7a9f2cbca6f733ad0703761 100644 --- a/worker/worker_test.go +++ b/worker/worker_test.go @@ -17,6 +17,7 @@ package worker import ( + "bytes" "fmt" "io/ioutil" "os" @@ -95,7 +96,7 @@ func TestProcessTask(t *testing.T) { addEdge(t, edge, posting.GetOrCreate(posting.Key(10, "friend"), ps)) addEdge(t, edge, posting.GetOrCreate(posting.Key(12, "friend"), ps)) - edge.Value = "photon" + edge.Value = []byte("photon") addEdge(t, edge, posting.GetOrCreate(posting.Key(12, "friend"), ps)) query := NewQuery("friend", []uint64{10, 11, 12}) @@ -128,27 +129,21 @@ func TestProcessTask(t *testing.T) { if ok := r.Values(&tval, 0); !ok { t.Errorf("Unable to retrieve value") } - if tval.ValLength() != 1 || - tval.ValBytes()[0] != 0x00 { - t.Errorf("Invalid byte value at index 0") + if !bytes.Equal(tval.ValBytes(), []byte{}) { + t.Errorf("Invalid value") } + if ok := r.Values(&tval, 1); !ok { t.Errorf("Unable to retrieve value") } - if tval.ValLength() != 1 || - tval.ValBytes()[0] != 0x00 { - t.Errorf("Invalid byte value at index 0") + if !bytes.Equal(tval.ValBytes(), []byte{}) { + t.Errorf("Invalid value") } if ok := r.Values(&tval, 2); !ok { t.Errorf("Unable to retrieve value") } - var iout interface{} - if err := posting.ParseValue(&iout, tval.ValBytes()); err != nil { - t.Error(err) - } - v := iout.(string) - if v != "photon" { - t.Errorf("Expected photon. Got: %q", v) + if string(tval.ValBytes()) != "photon" { + t.Errorf("Expected photon. Got: %q", string(tval.ValBytes())) } } diff --git a/x/x.go b/x/x.go index c9213f07a29d4f2daf469c08d043689fa831ae9b..0a428be789cda788d2c99a089f2b9e6f94879766 100644 --- a/x/x.go +++ b/x/x.go @@ -49,7 +49,7 @@ type Status struct { type DirectedEdge struct { Entity uint64 Attribute string - Value interface{} + Value []byte ValueId uint64 Source string Timestamp time.Time @@ -114,8 +114,3 @@ func UidlistOffset(b *flatbuffers.Builder, } var Nilbyte []byte - -func init() { - Nilbyte = make([]byte, 1) - Nilbyte[0] = 0x00 -}