diff --git a/client/go/main.go b/client/go/main.go index 4d8ac26752e494f6e0c28ba60c16a2ebcaa734dc..3912bb9dcf94ba4c6d3bcc7a3622c59273b061f4 100644 --- a/client/go/main.go +++ b/client/go/main.go @@ -23,7 +23,7 @@ import ( "golang.org/x/net/context" "google.golang.org/grpc" - "github.com/dgraph-io/dgraph/query/pb" + "github.com/dgraph-io/dgraph/query/graph" "github.com/dgraph-io/dgraph/x" ) @@ -40,9 +40,9 @@ func main() { } defer conn.Close() - c := pb.NewDGraphClient(conn) + c := graph.NewDGraphClient(conn) - r, err := c.Query(context.Background(), &pb.GraphRequest{Query: *q}) + r, err := c.Query(context.Background(), &graph.Request{Query: *q}) if err != nil { x.Err(glog, err).Fatal("Error in getting response from server") } diff --git a/query/graph/graphresponse.pb.go b/query/graph/graphresponse.pb.go new file mode 100644 index 0000000000000000000000000000000000000000..1acdc3048db1c51e82215ba48fa1eb14fcac2a7c --- /dev/null +++ b/query/graph/graphresponse.pb.go @@ -0,0 +1,176 @@ +// Code generated by protoc-gen-go. +// source: graphresponse.proto +// DO NOT EDIT! + +/* +Package graph is a generated protocol buffer package. + +It is generated from these files: + graphresponse.proto + +It has these top-level messages: + Request + Value + Node +*/ +package graph + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +const _ = proto.ProtoPackageIsVersion1 + +type Request struct { + Query string `protobuf:"bytes,1,opt,name=query" json:"query,omitempty"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} +func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type Value struct { + Binary []byte `protobuf:"bytes,1,opt,name=binary,proto3" json:"binary,omitempty"` +} + +func (m *Value) Reset() { *m = Value{} } +func (m *Value) String() string { return proto.CompactTextString(m) } +func (*Value) ProtoMessage() {} +func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type Node struct { + Uid uint64 `protobuf:"varint,1,opt,name=uid" json:"uid,omitempty"` + Attribute string `protobuf:"bytes,2,opt,name=attribute" json:"attribute,omitempty"` + Properties map[string]*Value `protobuf:"bytes,3,rep,name=properties" json:"properties,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Children []*Node `protobuf:"bytes,4,rep,name=children" json:"children,omitempty"` +} + +func (m *Node) Reset() { *m = Node{} } +func (m *Node) String() string { return proto.CompactTextString(m) } +func (*Node) ProtoMessage() {} +func (*Node) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Node) GetProperties() map[string]*Value { + if m != nil { + return m.Properties + } + return nil +} + +func (m *Node) GetChildren() []*Node { + if m != nil { + return m.Children + } + return nil +} + +func init() { + proto.RegisterType((*Request)(nil), "graph.Request") + proto.RegisterType((*Value)(nil), "graph.Value") + proto.RegisterType((*Node)(nil), "graph.Node") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion2 + +// Client API for DGraph service + +type DGraphClient interface { + Query(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Node, error) +} + +type dGraphClient struct { + cc *grpc.ClientConn +} + +func NewDGraphClient(cc *grpc.ClientConn) DGraphClient { + return &dGraphClient{cc} +} + +func (c *dGraphClient) Query(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Node, error) { + out := new(Node) + err := grpc.Invoke(ctx, "/graph.DGraph/Query", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for DGraph service + +type DGraphServer interface { + Query(context.Context, *Request) (*Node, error) +} + +func RegisterDGraphServer(s *grpc.Server, srv DGraphServer) { + s.RegisterService(&_DGraph_serviceDesc, srv) +} + +func _DGraph_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Request) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DGraphServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/graph.DGraph/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DGraphServer).Query(ctx, req.(*Request)) + } + return interceptor(ctx, in, info, handler) +} + +var _DGraph_serviceDesc = grpc.ServiceDesc{ + ServiceName: "graph.DGraph", + HandlerType: (*DGraphServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Query", + Handler: _DGraph_Query_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, +} + +var fileDescriptor0 = []byte{ + // 266 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x5c, 0x90, 0x41, 0x4b, 0xc3, 0x40, + 0x10, 0x85, 0x4d, 0x93, 0x8d, 0x76, 0x52, 0x54, 0x46, 0x91, 0x50, 0x05, 0x4b, 0x0e, 0xda, 0x53, + 0x90, 0x78, 0x11, 0xbd, 0x2a, 0x1e, 0x04, 0xd1, 0x3d, 0x78, 0x4f, 0xcc, 0x60, 0x17, 0x4b, 0x12, + 0x37, 0x1b, 0xa1, 0x3f, 0xd9, 0x7f, 0x61, 0x76, 0xba, 0xd6, 0xd0, 0xdb, 0xcc, 0x7c, 0x33, 0x8f, + 0x37, 0x0f, 0x8e, 0x3e, 0x74, 0xde, 0x2c, 0x34, 0xb5, 0x4d, 0x5d, 0xb5, 0x94, 0x36, 0xba, 0x36, + 0x35, 0x0a, 0x1e, 0x26, 0xe7, 0xb0, 0x2b, 0xe9, 0xab, 0xa3, 0xd6, 0xe0, 0x31, 0x88, 0xbe, 0xd0, + 0xab, 0xd8, 0x9b, 0x79, 0xf3, 0xb1, 0x5c, 0x37, 0xfd, 0x82, 0x78, 0xcb, 0x97, 0x1d, 0xe1, 0x09, + 0x84, 0x85, 0xaa, 0x72, 0xc7, 0x27, 0xd2, 0x75, 0xc9, 0x8f, 0x07, 0xc1, 0x73, 0x5d, 0x12, 0x1e, + 0x82, 0xdf, 0xa9, 0x92, 0x69, 0x20, 0x6d, 0x89, 0x67, 0x30, 0xce, 0x8d, 0xd1, 0xaa, 0xe8, 0x0c, + 0xc5, 0x23, 0x56, 0xfd, 0x1f, 0xe0, 0x1d, 0x40, 0x6f, 0xa5, 0x21, 0x6d, 0x14, 0xb5, 0xb1, 0x3f, + 0xf3, 0xe7, 0x51, 0x76, 0x9a, 0xb2, 0xad, 0xd4, 0x0a, 0xa6, 0x2f, 0x1b, 0xfa, 0x50, 0x19, 0xbd, + 0x92, 0x83, 0x75, 0xbc, 0x84, 0xbd, 0xf7, 0x85, 0x5a, 0x96, 0x9a, 0xaa, 0x38, 0xe0, 0xd3, 0x68, + 0x70, 0x2a, 0x37, 0x70, 0xfa, 0x04, 0x07, 0x5b, 0x3a, 0xd6, 0xe8, 0x27, 0xfd, 0xbd, 0x69, 0x4b, + 0x4c, 0x40, 0x7c, 0xdb, 0x27, 0xd9, 0x64, 0x94, 0x4d, 0x9c, 0x14, 0x3f, 0x2e, 0xd7, 0xe8, 0x76, + 0x74, 0xe3, 0x65, 0x57, 0x10, 0xde, 0x3f, 0x5a, 0x84, 0x17, 0x20, 0x5e, 0x6d, 0x3e, 0xb8, 0xef, + 0x76, 0x5d, 0x8a, 0xd3, 0xa1, 0x8d, 0x64, 0xa7, 0x08, 0x39, 0xed, 0xeb, 0xdf, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x2c, 0xc9, 0x79, 0xe9, 0x84, 0x01, 0x00, 0x00, +} diff --git a/query/graph/graphresponse.proto b/query/graph/graphresponse.proto new file mode 100644 index 0000000000000000000000000000000000000000..aeaebc54b5f035c45c05ff1888286a1784dd84ca --- /dev/null +++ b/query/graph/graphresponse.proto @@ -0,0 +1,24 @@ +// To compile this file run the command below from inside the graph directory +// protoc --go_out=plugins=grpc:. *.proto + +syntax="proto3"; +package graph; + +service DGraph { + rpc Query (Request) returns (Node) {} +} + +message Request { + string query = 1; +} + +message Value { + bytes binary = 1; +} + +message Node { + uint64 uid = 1; + string attribute = 2; + map<string, Value> properties = 3; + repeated Node children = 4; // Each node can have multiple children +} diff --git a/query/pb/graphresponse.pb.go b/query/pb/graphresponse.pb.go deleted file mode 100644 index b76e1525c2c6b0d9a93a238d7061c57495e269c7..0000000000000000000000000000000000000000 --- a/query/pb/graphresponse.pb.go +++ /dev/null @@ -1,174 +0,0 @@ -// Code generated by protoc-gen-go. -// source: graphresponse.proto -// DO NOT EDIT! - -/* -Package pb is a generated protocol buffer package. - -It is generated from these files: - graphresponse.proto - -It has these top-level messages: - GraphRequest - Value - GraphResponse -*/ -package pb - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -import ( - context "golang.org/x/net/context" - grpc "google.golang.org/grpc" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -const _ = proto.ProtoPackageIsVersion1 - -type GraphRequest struct { - Query string `protobuf:"bytes,1,opt,name=query" json:"query,omitempty"` -} - -func (m *GraphRequest) Reset() { *m = GraphRequest{} } -func (m *GraphRequest) String() string { return proto.CompactTextString(m) } -func (*GraphRequest) ProtoMessage() {} -func (*GraphRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -type Value struct { - Byte []byte `protobuf:"bytes,1,opt,name=byte,proto3" json:"byte,omitempty"` -} - -func (m *Value) Reset() { *m = Value{} } -func (m *Value) String() string { return proto.CompactTextString(m) } -func (*Value) ProtoMessage() {} -func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -type GraphResponse struct { - Attribute string `protobuf:"bytes,1,opt,name=attribute" json:"attribute,omitempty"` - Values map[string]*Value `protobuf:"bytes,2,rep,name=values" json:"values,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Children []*GraphResponse `protobuf:"bytes,3,rep,name=children" json:"children,omitempty"` -} - -func (m *GraphResponse) Reset() { *m = GraphResponse{} } -func (m *GraphResponse) String() string { return proto.CompactTextString(m) } -func (*GraphResponse) ProtoMessage() {} -func (*GraphResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -func (m *GraphResponse) GetValues() map[string]*Value { - if m != nil { - return m.Values - } - return nil -} - -func (m *GraphResponse) GetChildren() []*GraphResponse { - if m != nil { - return m.Children - } - return nil -} - -func init() { - proto.RegisterType((*GraphRequest)(nil), "pb.GraphRequest") - proto.RegisterType((*Value)(nil), "pb.Value") - proto.RegisterType((*GraphResponse)(nil), "pb.GraphResponse") -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion2 - -// Client API for DGraph service - -type DGraphClient interface { - Query(ctx context.Context, in *GraphRequest, opts ...grpc.CallOption) (*GraphResponse, error) -} - -type dGraphClient struct { - cc *grpc.ClientConn -} - -func NewDGraphClient(cc *grpc.ClientConn) DGraphClient { - return &dGraphClient{cc} -} - -func (c *dGraphClient) Query(ctx context.Context, in *GraphRequest, opts ...grpc.CallOption) (*GraphResponse, error) { - out := new(GraphResponse) - err := grpc.Invoke(ctx, "/pb.DGraph/Query", in, out, c.cc, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// Server API for DGraph service - -type DGraphServer interface { - Query(context.Context, *GraphRequest) (*GraphResponse, error) -} - -func RegisterDGraphServer(s *grpc.Server, srv DGraphServer) { - s.RegisterService(&_DGraph_serviceDesc, srv) -} - -func _DGraph_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GraphRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(DGraphServer).Query(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.DGraph/Query", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(DGraphServer).Query(ctx, req.(*GraphRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _DGraph_serviceDesc = grpc.ServiceDesc{ - ServiceName: "pb.DGraph", - HandlerType: (*DGraphServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Query", - Handler: _DGraph_Query_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, -} - -var fileDescriptor0 = []byte{ - // 253 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x64, 0x90, 0x31, 0x4f, 0xc3, 0x30, - 0x10, 0x85, 0x71, 0x42, 0x22, 0x72, 0x2d, 0x52, 0x39, 0x18, 0xa2, 0x02, 0xa2, 0x8a, 0x18, 0xba, - 0xe0, 0xa1, 0x08, 0xa9, 0x62, 0x2e, 0x62, 0xc6, 0x03, 0x7b, 0x0c, 0x27, 0x5a, 0x51, 0x25, 0xc6, - 0x76, 0x90, 0xf2, 0x53, 0xf9, 0x37, 0xc4, 0x97, 0x00, 0x45, 0xdd, 0xce, 0x77, 0xf7, 0xbe, 0x77, - 0x7e, 0x70, 0xfa, 0x66, 0x4b, 0xb3, 0xb6, 0xe4, 0x4c, 0x5d, 0x39, 0x92, 0xc6, 0xd6, 0xbe, 0xc6, - 0xc8, 0xe8, 0xe2, 0x1a, 0xc6, 0x8f, 0x61, 0xa4, 0xe8, 0xa3, 0x21, 0xe7, 0xf1, 0x0c, 0x92, 0xae, - 0xb0, 0x6d, 0x2e, 0x66, 0x62, 0x9e, 0xa9, 0xfe, 0x51, 0x9c, 0x43, 0xf2, 0x5c, 0x6e, 0x1b, 0x42, - 0x84, 0x43, 0xdd, 0x7a, 0xe2, 0xe9, 0x58, 0x71, 0x5d, 0x7c, 0x09, 0x38, 0x1e, 0x18, 0x3d, 0x1e, - 0x2f, 0x20, 0x2b, 0xbd, 0xb7, 0x1b, 0xdd, 0x0c, 0xab, 0x99, 0xfa, 0x6b, 0xe0, 0x1d, 0xa4, 0x9f, - 0x01, 0xe6, 0xf2, 0x68, 0x16, 0xcf, 0x47, 0x8b, 0x4b, 0x69, 0xb4, 0xfc, 0x07, 0x90, 0x6c, 0xe6, - 0x1e, 0x2a, 0x6f, 0x5b, 0x35, 0x2c, 0xe3, 0x0d, 0x1c, 0xbd, 0xac, 0x37, 0xdb, 0x57, 0x4b, 0x55, - 0x1e, 0xb3, 0xf0, 0x64, 0x4f, 0xa8, 0x7e, 0x57, 0xa6, 0x2b, 0x18, 0xed, 0x50, 0x70, 0x02, 0xf1, - 0x3b, 0xfd, 0xfc, 0x2a, 0x94, 0x78, 0x05, 0x09, 0x93, 0xbb, 0x2b, 0x44, 0x07, 0xcb, 0x02, 0x8c, - 0x15, 0xaa, 0xef, 0xdf, 0x47, 0x4b, 0xb1, 0x58, 0x42, 0xba, 0x62, 0x07, 0x94, 0x90, 0x3c, 0x85, - 0x2c, 0x70, 0xb2, 0xe3, 0xca, 0x99, 0x4d, 0xf7, 0xef, 0x28, 0x0e, 0x74, 0xca, 0x19, 0xdf, 0x7e, - 0x07, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x05, 0xc8, 0x3f, 0x7a, 0x01, 0x00, 0x00, -} diff --git a/query/pb/graphresponse.proto b/query/pb/graphresponse.proto deleted file mode 100644 index e85286e2dc3c7b75e1dbb470080e1c1f7876968c..0000000000000000000000000000000000000000 --- a/query/pb/graphresponse.proto +++ /dev/null @@ -1,23 +0,0 @@ -// To compile this file run the command below from inside the pb directory -// protoc --go_out=plugins=grpc:. *.proto - -syntax="proto3"; -package pb; - -service DGraph { - rpc Query (GraphRequest) returns (GraphResponse) {} -} - -message GraphRequest { - string query = 1; -} - -message Value { - bytes byte = 1; -} - -message GraphResponse { - string attribute = 1; - map<string, Value> values = 2; - repeated GraphResponse children = 3; // Each node can have multiple children -} diff --git a/query/query.go b/query/query.go index 368e4c61ec159a4a20fcb7738a61ace2646cb37b..ff607a19069ddccf220d1a9587e638ecf46b4ba8 100644 --- a/query/query.go +++ b/query/query.go @@ -26,7 +26,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/dgraph-io/dgraph/gql" "github.com/dgraph-io/dgraph/posting" - "github.com/dgraph-io/dgraph/query/pb" + "github.com/dgraph-io/dgraph/query/graph" "github.com/dgraph-io/dgraph/task" "github.com/dgraph-io/dgraph/worker" "github.com/dgraph-io/dgraph/x" @@ -253,111 +253,15 @@ func (g *SubGraph) ToJson(l *Latency) (js []byte, rerr error) { return json.Marshal(r) } -// Struct to retrieve values from flatbuffers, so that they can later be used -// to control the entity based protocol buffer subgraph. -type result struct { - values [][]byte - uidmatrix [][]uint64 -} - -// This method takes in a flatbuffer query and result extracts values. -func extract(q *task.Query, r *task.Result) ([]uint64, *result, error) { - re := new(result) - var qu []uint64 - var ul task.UidList - - for i := 0; i < q.UidsLength(); i++ { - uid := q.Uids(i) - qu = append(qu, uid) - } - - for i := 0; i < r.UidmatrixLength(); i++ { - if ok := r.Uidmatrix(&ul, i); !ok { - return qu, re, fmt.Errorf("While parsing UidList") - } - - var uidList []uint64 - for j := 0; j < ul.UidsLength(); j++ { - uid := ul.Uids(j) - uidList = append(uidList, uid) - } - re.uidmatrix = append(re.uidmatrix, uidList) - } - - var tv task.Value - for i := 0; i < r.ValuesLength(); i++ { - if ok := r.Values(&tv, i); !ok { - return qu, re, fmt.Errorf("While parsing value") - } - - var ival interface{} - if err := posting.ParseValue(&ival, tv.ValBytes()); err != nil { - return qu, re, err - } - - if ival == nil { - ival = "" - } - re.values = append(re.values, []byte(ival.(string))) - } - return qu, re, nil -} - -// Struct to store reference to the subgraph associated with a protocol buffer -// graph response -type sgReference struct { - uid uint64 - sg *SubGraph -} - -// This method converts a subgraph to a protocol buffer response. It transforms -// the predicate based subgraph to an entity based protocol buffer subgraph. -func (g *SubGraph) ToProtocolBuffer(l *Latency) (gr *pb.GraphResponse, - rerr error) { - gr = &pb.GraphResponse{} - gr.Attribute = g.Attr - if len(g.query) == 0 { - return gr, nil - } - - ro := flatbuffers.GetUOffsetT(g.result) - r := new(task.Result) - r.Init(g.result, ro) - - uo := flatbuffers.GetUOffsetT(g.query) - q := new(task.Query) - q.Init(g.query, uo) - - _, result, err := extract(q, r) - if err != nil { - x.Err(glog, err).Error("Error while extracting query, result") - return gr, err - } - - re := &sgReference{} - // Storing reference to root node. - re.sg = g - // Stores the uid for the root node in the reference struct. - re.uid = result.uidmatrix[0][0] - gr.Values, gr.Children, rerr = re.preTraverse() - if rerr != nil { - x.Err(glog, rerr).Error("Error while traversal") - return gr, rerr - } - - l.ProtocolBuffer = time.Since(l.Start) - l.Parsing - l.Processing - return gr, nil -} - // This function performs a binary search on the uids slice and returns the // index at which it finds the uid, else returns -1 -func indexOf(uid uint64, uids []uint64) int { - low, mid, high := 0, 0, len(uids)-1 +func indexOf(uid uint64, q *task.Query) int { + low, mid, high := 0, 0, q.UidsLength()-1 for low <= high { mid = (low + high) / 2 - if uids[mid] == uid { + if q.Uids(mid) == uid { return mid - } else if uids[mid] > uid { + } else if q.Uids(mid) > uid { high = mid - 1 } else { low = mid + 1 @@ -366,67 +270,104 @@ func indexOf(uid uint64, uids []uint64) int { return -1 } -// This method gets the values and children for a GraphResponse. -func (re *sgReference) preTraverse() (map[string]*pb.Value, - []*pb.GraphResponse, error) { - values := make(map[string]*pb.Value) - var children []*pb.GraphResponse +// This method gets the values and children for a subgraph. +func preTraverse(uid uint64, g *SubGraph) (map[string]*graph.Value, []*graph.Node, error) { + values := make(map[string]*graph.Value) + var children []*graph.Node - for _, child := range re.sg.Children { - ro := flatbuffers.GetUOffsetT(child.result) + for _, predChild := range g.Children { + ro := flatbuffers.GetUOffsetT(predChild.result) r := new(task.Result) - r.Init(child.result, ro) + r.Init(predChild.result, ro) - uo := flatbuffers.GetUOffsetT(child.query) + uo := flatbuffers.GetUOffsetT(predChild.query) q := new(task.Query) - q.Init(child.query, uo) + q.Init(predChild.query, uo) - query, result, err := extract(q, r) - if err != nil { - x.Err(glog, err).Error("Error while extracting query, result") - return values, children, fmt.Errorf("While extracting query, result") - } + idx := indexOf(uid, q) - idx := indexOf(re.uid, query) if idx == -1 { glog.WithFields(logrus.Fields{ - "uid": re.uid, - "attribute": re.sg.Attr, - "childAttribute": child.Attr, + "uid": uid, + "attribute": g.Attr, + "childAttribute": predChild.Attr, }).Fatal("Attribute with uid not found in child Query uids") return values, children, fmt.Errorf("Attribute with uid not found") } - // This means the child is a leaf node hence we just extract its value. - if len(child.Children) == 0 { - v := new(pb.Value) - v.Byte = result.values[idx] - values[child.Attr] = v - } else { - uids := result.uidmatrix[idx] - // We create as many predicate children as the number of uids. - for _, uid := range uids { - predChild := new(pb.GraphResponse) - predChild.Attribute = child.Attr + var ul task.UidList + var tv task.Value + if ok := r.Uidmatrix(&ul, idx); !ok { + return values, children, fmt.Errorf("While parsing UidList") + } - ref := new(sgReference) - ref.sg = child - ref.uid = uid + if ul.UidsLength() > 0 { + // We create as many predicate entity children as the length of uids for + // this predicate. + for i := 0; i < ul.UidsLength(); i++ { + uid := ul.Uids(i) + uidChild := new(graph.Node) + uidChild.Attribute = predChild.Attr + uidChild.Uid = uid - vals, ch, rerr := ref.preTraverse() + vals, ch, rerr := preTraverse(uid, predChild) if rerr != nil { x.Err(glog, rerr).Error("Error while traversal") return values, children, rerr } - predChild.Values, predChild.Children = vals, ch - children = append(children, predChild) + uidChild.Properties, uidChild.Children = vals, ch + children = append(children, uidChild) + } + } else { + v := new(graph.Value) + if ok := r.Values(&tv, idx); !ok { + return values, children, fmt.Errorf("While parsing value") + } + + var ival interface{} + if err := posting.ParseValue(&ival, tv.ValBytes()); err != nil { + return values, children, err } + + if ival == nil { + ival = "" + } + + v.Binary = []byte(ival.(string)) + values[predChild.Attr] = v } } return values, children, nil } +// This method transforms the predicate based subgraph to an +// predicate-entity based protocol buffer subgraph. +func (g *SubGraph) ToProtocolBuffer(l *Latency) (n *graph.Node, rerr error) { + n = &graph.Node{} + n.Attribute = g.Attr + if len(g.query) == 0 { + return n, nil + } + + ro := flatbuffers.GetUOffsetT(g.result) + r := new(task.Result) + r.Init(g.result, ro) + + var ul task.UidList + r.Uidmatrix(&ul, 0) + n.Uid = ul.Uids(0) + + n.Properties, n.Children, rerr = preTraverse(n.Uid, g) + if rerr != nil { + x.Err(glog, rerr).Error("Error while traversal") + return n, rerr + } + + l.ProtocolBuffer = time.Since(l.Start) - l.Parsing - l.Processing + return n, nil +} + func treeCopy(gq *gql.GraphQuery, sg *SubGraph) { for _, gchild := range gq.Children { dst := new(SubGraph) diff --git a/query/query_test.go b/query/query_test.go index 2e2396d983b6e19e45ae552544c2761abdb4c9f8..22364ca7b3499b93e917cb1b506ee252335db945 100644 --- a/query/query_test.go +++ b/query/query_test.go @@ -333,6 +333,8 @@ func TestToProtocolBuffer(t *testing.T) { friend { name } + friend { + } } } ` @@ -362,29 +364,50 @@ func TestToProtocolBuffer(t *testing.T) { if gr.Attribute != "_root_" { t.Errorf("Expected attribute _root_, Got: %v", gr.Attribute) } - if len(gr.Values) != 3 { + if gr.Uid != 1 { + t.Errorf("Expected uid 1, Got: %v", gr.Uid) + } + if len(gr.Properties) != 3 { t.Errorf("Expected values map to contain 3 properties, Got: %v", - len(gr.Values)) + len(gr.Properties)) } - if string(gr.Values["name"].Byte) != "Michonne" { + if string(gr.Properties["name"].Binary) != "Michonne" { t.Errorf("Expected property name to have value Michonne, Got: %v", - string(gr.Values["name"].Byte)) + string(gr.Properties["name"].Binary)) } - if len(gr.Children) != 5 { - t.Errorf("Expected 5 children, Got: %v", len(gr.Children)) + if len(gr.Children) != 10 { + t.Errorf("Expected 10 children, Got: %v", len(gr.Children)) } child := gr.Children[0] + if child.Uid != 23 { + t.Errorf("Expected uid 23, Got: %v", gr.Uid) + } if child.Attribute != "friend" { t.Errorf("Expected attribute friend, Got: %v", child.Attribute) } - if len(child.Values) != 1 { + if len(child.Properties) != 1 { t.Errorf("Expected values map to contain 1 property, Got: %v", - len(child.Values)) + len(child.Properties)) } - if string(child.Values["name"].Byte) != "Rick Grimes" { + if string(child.Properties["name"].Binary) != "Rick Grimes" { t.Errorf("Expected property name to have value Rick Grimes, Got: %v", - string(child.Values["name"].Byte)) + string(child.Properties["name"].Binary)) + } + if len(child.Children) != 0 { + t.Errorf("Expected 0 children, Got: %v", len(child.Children)) + } + + child = gr.Children[5] + if child.Uid != 23 { + t.Errorf("Expected uid 23, Got: %v", gr.Uid) + } + if child.Attribute != "friend" { + t.Errorf("Expected attribute friend, Got: %v", child.Attribute) + } + if len(child.Properties) != 0 { + t.Errorf("Expected values map to contain 0 properties, Got: %v", + len(child.Properties)) } if len(child.Children) != 0 { t.Errorf("Expected 0 children, Got: %v", len(child.Children)) diff --git a/server/main.go b/server/main.go index 0bd9712beecd025a731467afaf4d768bac358568..29cd30744a63084a917b6d4d051cb3f40bd80715 100644 --- a/server/main.go +++ b/server/main.go @@ -36,7 +36,7 @@ import ( "github.com/dgraph-io/dgraph/gql" "github.com/dgraph-io/dgraph/posting" "github.com/dgraph-io/dgraph/query" - "github.com/dgraph-io/dgraph/query/pb" + "github.com/dgraph-io/dgraph/query/graph" "github.com/dgraph-io/dgraph/rdf" "github.com/dgraph-io/dgraph/store" "github.com/dgraph-io/dgraph/uid" @@ -203,14 +203,14 @@ func queryHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, string(js)) } -// server is used to implement pb.DGraphServer +// server is used to implement graph.DGraphServer type server struct{} // This method is used to execute the query and return the response to the // client as a protocol buffer message. func (s *server) Query(ctx context.Context, - req *pb.GraphRequest) (*pb.GraphResponse, error) { - resp := new(pb.GraphResponse) + req *graph.Request) (*graph.Node, error) { + resp := new(graph.Node) if len(req.Query) == 0 { glog.Error("While reading query") return resp, fmt.Errorf("Empty query") @@ -265,7 +265,7 @@ func runGrpcServer(address string) error { glog.WithField("address", ln.Addr()).Info("Client Worker listening") s := grpc.NewServer() - pb.RegisterDGraphServer(s, &server{}) + graph.RegisterDGraphServer(s, &server{}) if err = s.Serve(ln); err != nil { glog.Fatalf("While serving gRpc requests", err) }