Skip to content

Commit 209a8dc

Browse files
author
Pawan Rawal
committed
Add DeleteEdges function to client and fix small issues on server.
1 parent f27fed9 commit 209a8dc

File tree

13 files changed

+420
-468
lines changed

13 files changed

+420
-468
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project will adhere to [Semantic Versioning](http://semver.org/spec/v2.
1010

1111
* Support for removing dead node from quorum.
1212
* Support for alias in groupby queries.
13+
* Add DeleteEdges helper function for Go client.
1314

1415
### Changed
1516

client/client.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,18 @@ func (d *Dgraph) Alter(ctx context.Context, op *protos.Operation) error {
7878
func (d *Dgraph) anyClient() protos.DgraphClient {
7979
return d.dc[rand.Intn(len(d.dc))]
8080
}
81+
82+
// DeleteEdges sets the edges corresponding to predicates on the node with the given uid
83+
// for deletion.
84+
// This helper function doesn't run the mutation on the server. It must be done by the user
85+
// after the function returns.
86+
func DeleteEdges(mu *protos.Mutation, uid string, predicates ...string) {
87+
for _, predicate := range predicates {
88+
mu.Del = append(mu.Del, &protos.NQuad{
89+
Subject: uid,
90+
Predicate: predicate,
91+
// _STAR_ALL is defined as x.Star in x package.
92+
ObjectValue: &protos.Value{&protos.Value_DefaultVal{"_STAR_ALL"}},
93+
})
94+
}
95+
}

client/example_set_object_test.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"log"
8+
"time"
89

910
"github.com/dgraph-io/dgraph/client"
1011
"github.com/dgraph-io/dgraph/protos"
@@ -24,14 +25,15 @@ type loc struct {
2425
// for bool) would be created for values not specified explicitly.
2526

2627
type Person struct {
27-
Uid string `json:"uid,omitempty"`
28-
Name string `json:"name,omitempty"`
29-
Age int `json:"age,omitempty"`
30-
Married bool `json:"married,omitempty"`
31-
Raw []byte `json:"raw_bytes",omitempty`
32-
Friends []Person `json:"friend,omitempty"`
33-
Location loc `json:"loc,omitempty"`
34-
School []School `json:"school,omitempty"`
28+
Uid string `json:"uid,omitempty"`
29+
Name string `json:"name,omitempty"`
30+
Age int `json:"age,omitempty"`
31+
Dob *time.Time `json:"dob,omitempty"`
32+
Married bool `json:"married,omitempty"`
33+
Raw []byte `json:"raw_bytes",omitempty`
34+
Friends []Person `json:"friend,omitempty"`
35+
Location loc `json:"loc,omitempty"`
36+
School []School `json:"school,omitempty"`
3537
}
3638

3739
func Example_setObject() {
@@ -50,6 +52,7 @@ func Example_setObject() {
5052
// have a Uid). Alice is also connected via the friend edge to an existing node with Uid
5153
// 1000(Bob). We also set Name and Age values for this node with Uid 1000.
5254

55+
dob := time.Date(1980, 01, 01, 23, 0, 0, 0, time.UTC)
5356
p := Person{
5457
Name: "Alice",
5558
Age: 26,
@@ -58,6 +61,7 @@ func Example_setObject() {
5861
Type: "Point",
5962
Coords: []float64{1.1, 2},
6063
},
64+
Dob: &dob,
6165
Raw: []byte("raw_bytes"),
6266
Friends: []Person{{
6367
Uid: "1000",
@@ -77,6 +81,7 @@ func Example_setObject() {
7781
age: int .
7882
married: bool .
7983
loc: geo .
84+
dob: datetime .
8085
`
8186

8287
ctx := context.Background()
@@ -105,6 +110,7 @@ func Example_setObject() {
105110
me(func: uid(%s)) {
106111
uid
107112
name
113+
dob
108114
age
109115
loc
110116
raw_bytes

client/examples_test.go

Lines changed: 9 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ func ExampleTxn_Mutate_list(t *testing.T) {
604604
fmt.Printf("Me: %+v\n", r.Me)
605605
}
606606

607-
func ExampleTxn_Mutate_delete() {
607+
func ExampleDeleteEdges() {
608608
conn, err := grpc.Dial("127.0.0.1:9080", grpc.WithInsecure())
609609
if err != nil {
610610
log.Fatal("While trying to dial gRPC")
@@ -631,22 +631,18 @@ func ExampleTxn_Mutate_delete() {
631631

632632
// Lets add some data first.
633633
p := Person{
634-
Uid: "1000",
635634
Name: "Alice",
636635
Age: 26,
637636
Married: true,
638637
Location: "Riley Street",
639638
Friends: []Person{{
640-
Uid: "1001",
641639
Name: "Bob",
642640
Age: 24,
643641
}, {
644-
Uid: "1002",
645642
Name: "Charlie",
646643
Age: 29,
647644
}},
648645
School: []*School{&School{
649-
Uid: "1003",
650646
Name: "Crown Public School",
651647
}},
652648
}
@@ -671,13 +667,14 @@ func ExampleTxn_Mutate_delete() {
671667

672668
mu.SetJson = pb
673669
mu.CommitNow = true
674-
_, err = dg.NewTxn().Mutate(ctx, mu)
670+
assigned, err := dg.NewTxn().Mutate(ctx, mu)
675671
if err != nil {
676672
log.Fatal(err)
677673
}
678674

675+
uid := assigned.Uids["blank-0"]
679676
q := fmt.Sprintf(`{
680-
me(func: uid(1000)) {
677+
me(func: uid(%s)) {
681678
uid
682679
name
683680
age
@@ -693,45 +690,19 @@ func ExampleTxn_Mutate_delete() {
693690
name@en
694691
}
695692
}
696-
697-
me2(func: uid(1001)) {
698-
uid
699-
name
700-
age
701-
}
702-
703-
me3(func: uid(1003)) {
704-
uid
705-
name@en
706-
}
707-
708-
me4(func: uid(1002)) {
709-
uid
710-
name
711-
age
712-
}
713-
}`)
693+
}`, uid)
714694

715695
resp, err := dg.NewTxn().Query(ctx, q)
716696
if err != nil {
717697
log.Fatal(err)
718698
}
719699

720-
// Now lets delete the edge between Alice and Bob.
721-
// Also lets delete the location for Alice.
722-
p2 := Person{
723-
Uid: "1000",
724-
Location: "",
725-
Friends: []Person{Person{Uid: "1001"}},
726-
}
700+
fmt.Println(string(resp.Json))
727701

702+
// Now lets delete the friend and location edge from Alice
728703
mu = &protos.Mutation{}
729-
pb, err = json.Marshal(p2)
730-
if err != nil {
731-
log.Fatal(err)
732-
}
704+
client.DeleteEdges(mu, uid, "friend", "loc")
733705

734-
mu.DeleteJson = pb
735706
mu.CommitNow = true
736707
_, err = dg.NewTxn().Mutate(ctx, mu)
737708
if err != nil {
@@ -744,10 +715,7 @@ func ExampleTxn_Mutate_delete() {
744715
}
745716

746717
type Root struct {
747-
Me []Person `json:"me"`
748-
Me2 []Person `json:"me2"`
749-
Me3 []School `json:"me3"`
750-
Me4 []Person `json:"me4"`
718+
Me []Person `json:"me"`
751719
}
752720

753721
var r Root

dgraph/cmd/live/run.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@ func setupConnection(host string, insecure bool) (*grpc.ClientConn, error) {
212212
grpc.WithDefaultCallOptions(
213213
grpc.MaxCallRecvMsgSize(x.GrpcMaxSize),
214214
grpc.MaxCallSendMsgSize(x.GrpcMaxSize)),
215-
grpc.WithInsecure())
215+
grpc.WithInsecure(),
216+
grpc.WithBlock(),
217+
grpc.WithTimeout(10*time.Second))
216218
}
217219

218220
tlsConf.ConfigType = x.TLSClientConfig
@@ -228,7 +230,7 @@ func setupConnection(host string, insecure bool) (*grpc.ClientConn, error) {
228230
grpc.MaxCallSendMsgSize(x.GrpcMaxSize)),
229231
grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg)),
230232
grpc.WithBlock(),
231-
grpc.WithTimeout(5*time.Second))
233+
grpc.WithTimeout(10*time.Second))
232234
}
233235

234236
func fileList(files string) []string {
@@ -250,7 +252,7 @@ func setup(opts batchMutationOptions, dc *client.Dgraph) *loader {
250252
x.Checkf(err, "Error while creating badger KV posting store")
251253

252254
connzero, err := setupConnection(opt.zero, true)
253-
x.Checkf(err, "While trying to dial gRPC")
255+
x.Checkf(err, "While trying to setup connection to Zero")
254256

255257
alloc := xidmap.New(kv,
256258
&uidProvider{
@@ -308,7 +310,7 @@ func run() {
308310
var clients []protos.DgraphClient
309311
for _, d := range ds {
310312
conn, err := setupConnection(d, !tlsConf.CertRequired)
311-
x.Checkf(err, "While trying to dial gRPC")
313+
x.Checkf(err, "While trying to setup connection to Dgraph server.")
312314
defer conn.Close()
313315

314316
dc := protos.NewDgraphClient(conn)

dgraph/cmd/server/run_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,11 @@ func TestMain(m *testing.M) {
13621362
}
13631363
time.Sleep(10 * time.Millisecond)
13641364

1365+
// Increment lease, so that mutations work.
1366+
_, err = worker.AssignUidsOverNetwork(context.Background(), &protos.Num{Val: 10e6})
1367+
if err != nil {
1368+
log.Fatal(err)
1369+
}
13651370
// Parse GQL into internal query representation.
13661371
r := m.Run()
13671372
closeAll(dir1, dir2)

edgraph/server.go

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ func (s *ServerState) getTimestamp() uint64 {
193193

194194
func (s *Server) Alter(ctx context.Context, op *protos.Operation) (*protos.Payload, error) {
195195
empty := &protos.Payload{}
196+
if err := x.HealthCheck(); err != nil {
197+
if tr, ok := trace.FromContext(ctx); ok {
198+
tr.LazyPrintf("Request rejected %v", err)
199+
}
200+
return empty, err
201+
}
202+
196203
if op.DropAll {
197204
m := protos.Mutations{DropAll: true}
198205
_, err := query.ApplyMutations(ctx, &m)
@@ -233,6 +240,13 @@ func (s *Server) Alter(ctx context.Context, op *protos.Operation) (*protos.Paylo
233240

234241
func (s *Server) Mutate(ctx context.Context, mu *protos.Mutation) (resp *protos.Assigned, err error) {
235242
resp = &protos.Assigned{}
243+
if err := x.HealthCheck(); err != nil {
244+
if tr, ok := trace.FromContext(ctx); ok {
245+
tr.LazyPrintf("Request rejected %v", err)
246+
}
247+
return resp, err
248+
}
249+
236250
if !isMutationAllowed(ctx) {
237251
return nil, x.Errorf("No mutations allowed.")
238252
}
@@ -296,7 +310,6 @@ func (s *Server) Mutate(ctx context.Context, mu *protos.Mutation) (resp *protos.
296310
// This method is used to execute the query and return the response to the
297311
// client as a protocol buffer message.
298312
func (s *Server) Query(ctx context.Context, req *protos.Request) (resp *protos.Response, err error) {
299-
// we need membership information
300313
if err := x.HealthCheck(); err != nil {
301314
if tr, ok := trace.FromContext(ctx); ok {
302315
tr.LazyPrintf("Request rejected %v", err)
@@ -388,6 +401,13 @@ func (s *Server) Query(ctx context.Context, req *protos.Request) (resp *protos.R
388401

389402
func (s *Server) CommitOrAbort(ctx context.Context, tc *protos.TxnContext) (*protos.TxnContext,
390403
error) {
404+
if err := x.HealthCheck(); err != nil {
405+
if tr, ok := trace.FromContext(ctx); ok {
406+
tr.LazyPrintf("Request rejected %v", err)
407+
}
408+
return &protos.TxnContext{}, err
409+
}
410+
391411
commitTs, err := worker.CommitOverNetwork(ctx, tc)
392412
return &protos.TxnContext{
393413
CommitTs: commitTs,
@@ -564,12 +584,19 @@ func mapToNquads(m map[string]interface{}, idx *int, op int, parentPred string)
564584
uid = uint64(u)
565585
}
566586
}
587+
567588
if uid > 0 {
568589
mr.uid = fmt.Sprintf("%d", uid)
569590
}
591+
570592
}
571593

572-
if len(mr.uid) == 0 && op != delete {
594+
if len(mr.uid) == 0 {
595+
if op == delete {
596+
// Delete operations with a non-nil value must have a uid specified.
597+
return mr, x.Errorf("uid must be present and non-zero while deleting edges.")
598+
}
599+
573600
mr.uid = fmt.Sprintf("_:blank-%d", *idx)
574601
*idx++
575602
}
@@ -584,17 +611,14 @@ func mapToNquads(m map[string]interface{}, idx *int, op int, parentPred string)
584611
}
585612

586613
if op == delete {
587-
// This corresponds to predicate deletion.
614+
// This corresponds to edge deletion.
588615
if v == nil {
589616
mr.nquads = append(mr.nquads, &protos.NQuad{
590-
Subject: x.Star,
617+
Subject: mr.uid,
591618
Predicate: pred,
592619
ObjectValue: &protos.Value{&protos.Value_DefaultVal{x.Star}},
593620
})
594621
continue
595-
} else if len(mr.uid) == 0 {
596-
// Delete operations with a non-nil value must have a uid specified.
597-
return mr, x.Errorf("uid must be present and non-zero. Got: %+v", m)
598622
}
599623
}
600624

edgraph/server_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ func TestNquadsFromJson4(t *testing.T) {
158158
require.Contains(t, nq, makeNquad("_:blank-0", "name", oval))
159159
}
160160

161+
func TestNquadsDeleteEdges(t *testing.T) {
162+
json := `[{"uid": "0x1","name":null,"mobile":null,"car":null}]`
163+
nq, err := nquadsFromJson([]byte(json), delete)
164+
require.NoError(t, err)
165+
require.Equal(t, 3, len(nq))
166+
}
167+
161168
func checkCount(t *testing.T, nq []*protos.NQuad, pred string, count int) {
162169
for _, n := range nq {
163170
if n.Predicate == pred {
@@ -200,7 +207,7 @@ func TestNquadsFromJsonError1(t *testing.T) {
200207

201208
_, err = nquadsFromJson(b, delete)
202209
require.Error(t, err)
203-
require.Contains(t, err.Error(), "uid must be present and non-zero.")
210+
require.Contains(t, err.Error(), "uid must be present and non-zero while deleting edges.")
204211
}
205212

206213
func TestNquadsFromJsonList(t *testing.T) {

0 commit comments

Comments
 (0)