Skip to content

Commit 89bd082

Browse files
authored
Fix bugs with namespaces and add back tests (#9505)
1 parent 36a9b70 commit 89bd082

File tree

6 files changed

+340
-5
lines changed

6 files changed

+340
-5
lines changed

edgraph/alter_test.go

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
//go:build integration
2+
3+
/*
4+
* SPDX-FileCopyrightText: © Hypermode Inc. <[email protected]>
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
package edgraph
9+
10+
import (
11+
"context"
12+
"testing"
13+
14+
"github.com/dgraph-io/dgo/v250/protos/api"
15+
"github.com/hypermodeinc/dgraph/v25/dgraphapi"
16+
"github.com/hypermodeinc/dgraph/v25/dgraphtest"
17+
18+
"github.com/stretchr/testify/require"
19+
)
20+
21+
// TODO: add a test that talks to different alphas in the same cluster
22+
func TestDropAll(t *testing.T) {
23+
dc := dgraphtest.NewComposeCluster()
24+
client, cleanup, err := dc.Client()
25+
require.NoError(t, err)
26+
defer cleanup()
27+
28+
// Drop all data
29+
require.NoError(t, client.Login(context.Background(),
30+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
31+
require.NoError(t, client.Dgraph.DropAll(context.Background()))
32+
33+
// Create two namespaces
34+
ctx := context.Background()
35+
ns1, err := client.CreateNamespace(ctx)
36+
require.NoError(t, err)
37+
ns2, err := client.CreateNamespace(ctx)
38+
require.NoError(t, err)
39+
40+
nsMaps, err := client.ListNamespaces(ctx)
41+
require.NoError(t, err)
42+
ns1ID := nsMaps[ns1].Id
43+
require.NotZero(t, ns1ID)
44+
ns2ID := nsMaps[ns2].Id
45+
require.NotZero(t, ns2ID)
46+
47+
// namespace 1
48+
require.NoError(t, client.LoginIntoNamespace(ctx,
49+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns1))
50+
require.NoError(t, client.SetSchema(ctx, `name: string @index(exact) .`))
51+
_, err = client.Mutate(&api.Mutation{
52+
SetNquads: []byte(`_:a <name> "Alice" .`),
53+
CommitNow: true,
54+
})
55+
require.NoError(t, err)
56+
resp, err := client.Query(`{ q(func: has(name)) { name } }`)
57+
require.NoError(t, err)
58+
require.JSONEq(t, `{"q":[{"name":"Alice"}]}`, string(resp.GetJson()))
59+
60+
// namespace 2
61+
require.NoError(t, client.LoginIntoNamespace(ctx,
62+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns2))
63+
require.NoError(t, client.SetSchema(ctx, `name: string @index(exact) .`))
64+
_, err = client.Mutate(&api.Mutation{
65+
SetNquads: []byte(`_:a <name> "Bob" .`),
66+
CommitNow: true,
67+
})
68+
require.NoError(t, err)
69+
resp, err = client.Query(`{ q(func: has(name)) { name } }`)
70+
require.NoError(t, err)
71+
require.JSONEq(t, `{"q":[{"name":"Bob"}]}`, string(resp.GetJson()))
72+
73+
// Drop all data
74+
require.NoError(t, client.Login(context.Background(),
75+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
76+
require.NoError(t, client.Dgraph.DropAll(context.Background()))
77+
78+
resp, err = client.Query(`{ q(func: has(name)) { name } }`)
79+
require.NoError(t, err)
80+
require.JSONEq(t, `{"q":[]}`, string(resp.GetJson()))
81+
82+
require.ErrorContains(t, client.LoginIntoNamespace(context.Background(),
83+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns1ID),
84+
"invalid username or password")
85+
}
86+
87+
func TestDropData(t *testing.T) {
88+
dc := dgraphtest.NewComposeCluster()
89+
client, cleanup, err := dc.Client()
90+
require.NoError(t, err)
91+
defer cleanup()
92+
93+
// Drop all data
94+
require.NoError(t, client.Login(context.Background(),
95+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
96+
require.NoError(t, client.Dgraph.DropAll(context.Background()))
97+
98+
// Create two namespaces
99+
ctx := context.Background()
100+
ns1, err := client.CreateNamespace(ctx)
101+
require.NoError(t, err)
102+
ns2, err := client.CreateNamespace(ctx)
103+
require.NoError(t, err)
104+
105+
nsMaps, err := client.ListNamespaces(ctx)
106+
require.NoError(t, err)
107+
ns1ID := nsMaps[ns1].Id
108+
require.NotZero(t, ns1ID)
109+
ns2ID := nsMaps[ns2].Id
110+
require.NotZero(t, ns2ID)
111+
112+
// namespace 1
113+
require.NoError(t, client.LoginIntoNamespace(ctx,
114+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns1))
115+
require.NoError(t, client.SetSchema(ctx, `name: string @index(exact) .`))
116+
_, err = client.Mutate(&api.Mutation{
117+
SetNquads: []byte(`_:a <name> "Alice" .`),
118+
CommitNow: true,
119+
})
120+
require.NoError(t, err)
121+
resp, err := client.Query(`{ q(func: has(name)) { name } }`)
122+
require.NoError(t, err)
123+
require.JSONEq(t, `{"q":[{"name":"Alice"}]}`, string(resp.GetJson()))
124+
125+
require.NoError(t, client.DropData(context.Background()))
126+
127+
resp, err = client.Query(`{ q(func: has(name)) { name } }`)
128+
require.NoError(t, err)
129+
require.JSONEq(t, `{"q":[]}`, string(resp.GetJson()))
130+
131+
resp, err = client.Query(`schema{}`)
132+
require.NoError(t, err)
133+
require.Contains(t, string(resp.GetJson()), `"predicate":"name"`)
134+
}
135+
136+
func TestDropPredicate(t *testing.T) {
137+
dc := dgraphtest.NewComposeCluster()
138+
client, cleanup, err := dc.Client()
139+
require.NoError(t, err)
140+
defer cleanup()
141+
142+
// Drop all data
143+
require.NoError(t, client.Login(context.Background(),
144+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
145+
require.NoError(t, client.DropAll())
146+
147+
// Create two namespaces
148+
ctx := context.Background()
149+
ns1, err := client.CreateNamespace(ctx)
150+
require.NoError(t, err)
151+
ns2, err := client.CreateNamespace(ctx)
152+
require.NoError(t, err)
153+
154+
nsMaps, err := client.ListNamespaces(ctx)
155+
require.NoError(t, err)
156+
ns1ID := nsMaps[ns1].Id
157+
require.NotZero(t, ns1ID)
158+
ns2ID := nsMaps[ns2].Id
159+
require.NotZero(t, ns2ID)
160+
161+
// namespace 1
162+
require.NoError(t, client.LoginIntoNamespace(ctx,
163+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns1))
164+
require.NoError(t, client.SetSchema(ctx, `name: string @index(exact) .`))
165+
_, err = client.Mutate(&api.Mutation{
166+
SetNquads: []byte(`_:a <name> "Alice" .`),
167+
CommitNow: true,
168+
})
169+
require.NoError(t, err)
170+
resp, err := client.Query(`{ q(func: has(name)) { name } }`)
171+
require.NoError(t, err)
172+
require.JSONEq(t, `{"q":[{"name":"Alice"}]}`, string(resp.GetJson()))
173+
174+
require.NoError(t, client.Dgraph.DropPredicate(context.Background(), "name"))
175+
176+
resp, err = client.Query(`{ q(func: has(name)) { name } }`)
177+
require.NoError(t, err)
178+
require.JSONEq(t, `{"q":[]}`, string(resp.GetJson()))
179+
180+
resp, err = client.Query(`schema{}`)
181+
require.NoError(t, err)
182+
require.NotContains(t, string(resp.GetJson()), `"predicate":"name"`)
183+
}
184+
185+
func TestDropType(t *testing.T) {
186+
dc := dgraphtest.NewComposeCluster()
187+
client, cleanup, err := dc.Client()
188+
require.NoError(t, err)
189+
defer cleanup()
190+
191+
// Drop all data
192+
require.NoError(t, client.Login(context.Background(),
193+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
194+
require.NoError(t, client.DropAll())
195+
196+
// Create two namespaces
197+
ctx := context.Background()
198+
ns1, err := client.CreateNamespace(ctx)
199+
require.NoError(t, err)
200+
ns2, err := client.CreateNamespace(ctx)
201+
require.NoError(t, err)
202+
203+
nsMaps, err := client.ListNamespaces(ctx)
204+
require.NoError(t, err)
205+
ns1ID := nsMaps[ns1].Id
206+
require.NotZero(t, ns1ID)
207+
ns2ID := nsMaps[ns2].Id
208+
require.NotZero(t, ns2ID)
209+
210+
// namespace 1
211+
require.NoError(t, client.LoginIntoNamespace(ctx,
212+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns1))
213+
require.NoError(t, client.SetSchema(context.Background(),
214+
`name: string .
215+
age: int .
216+
type Person {
217+
name
218+
age
219+
}`))
220+
resp, err := client.Query(`schema{}`)
221+
require.NoError(t, err)
222+
require.Contains(t, string(resp.GetJson()), `"predicate":"name"`)
223+
resp, err = client.Query(`schema(type: Person) { }`)
224+
require.NoError(t, err)
225+
require.Contains(t, string(resp.GetJson()), `"name":"name"`)
226+
227+
require.NoError(t, client.DropType(context.Background(), "Person"))
228+
resp, err = client.Query(`schema{}`)
229+
require.NoError(t, err)
230+
require.NotContains(t, string(resp.GetJson()), `"name":"Person"`)
231+
resp, err = client.Query(`schema(type: Person) { }`)
232+
require.NoError(t, err)
233+
require.NotContains(t, string(resp.GetJson()), `"name":"name"`)
234+
}

edgraph/namespace.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (s *Server) CreateNamespace(ctx context.Context, in *api.CreateNamespaceReq
3333
}
3434

3535
glog.Infof("Created namespace with id [%d]", ns)
36-
return &api.CreateNamespaceResponse{}, nil
36+
return &api.CreateNamespaceResponse{Namespace: ns}, nil
3737
}
3838

3939
func (s *Server) DropNamespace(ctx context.Context, in *api.DropNamespaceRequest) (

edgraph/namespace_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//go:build integration
2+
3+
/*
4+
* SPDX-FileCopyrightText: © Hypermode Inc. <[email protected]>
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
package edgraph
9+
10+
import (
11+
"context"
12+
"testing"
13+
14+
"github.com/stretchr/testify/require"
15+
16+
"github.com/hypermodeinc/dgraph/v25/dgraphapi"
17+
"github.com/hypermodeinc/dgraph/v25/dgraphtest"
18+
)
19+
20+
func TestNamespaces(t *testing.T) {
21+
dc := dgraphtest.NewComposeCluster()
22+
client, cleanup, err := dc.Client()
23+
require.NoError(t, err)
24+
defer cleanup()
25+
26+
// Drop all data
27+
require.NoError(t, client.Login(context.Background(),
28+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
29+
require.NoError(t, client.Dgraph.DropAll(context.Background()))
30+
31+
// Create two namespaces
32+
ctx := context.Background()
33+
ns1, err := client.CreateNamespace(ctx)
34+
require.NoError(t, err)
35+
ns2, err := client.CreateNamespace(ctx)
36+
require.NoError(t, err)
37+
38+
// namespace 1
39+
require.NoError(t, client.LoginIntoNamespace(ctx,
40+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns1))
41+
require.NoError(t, client.SetSchema(ctx, `name: string @index(exact) .`))
42+
resp, err := client.RunDQL(ctx, `{ set {_:a <name> "Alice" .}}`)
43+
require.NoError(t, err)
44+
require.Equal(t, 1, len(resp.Uids))
45+
resp, err = client.RunDQL(ctx, `{ q(func: has(name)) { name } }`)
46+
require.NoError(t, err)
47+
require.JSONEq(t, `{"q":[{"name":"Alice"}]}`, string(resp.GetJson()))
48+
49+
// namespace 2
50+
require.NoError(t, client.LoginIntoNamespace(ctx,
51+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns2))
52+
require.NoError(t, client.SetSchema(ctx, `name: string @index(exact) .`))
53+
_, err = client.RunDQL(ctx, `{ set {_:a <name> "Bob" .}}`)
54+
require.NoError(t, err)
55+
resp, err = client.RunDQL(ctx, `{ q(func: has(name)) { name } }`)
56+
require.NoError(t, err)
57+
require.JSONEq(t, `{"q":[{"name":"Bob"}]}`, string(resp.GetJson()))
58+
59+
// List Namespaces
60+
require.NoError(t, client.Login(context.Background(),
61+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
62+
nsMaps, err := client.ListNamespaces(ctx)
63+
require.NoError(t, err)
64+
require.Len(t, nsMaps, 3)
65+
66+
// drop ns2-new namespace
67+
require.NoError(t, client.DropNamespace(ctx, ns2))
68+
require.ErrorContains(t, client.LoginIntoNamespace(ctx,
69+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword, ns2),
70+
"invalid username or password")
71+
72+
nsMaps, err = client.ListNamespaces(ctx)
73+
require.NoError(t, err)
74+
require.Len(t, nsMaps, 2)
75+
}
76+
77+
func TestDropNamespaceErr(t *testing.T) {
78+
dc := dgraphtest.NewComposeCluster()
79+
client, cleanup, err := dc.Client()
80+
require.NoError(t, err)
81+
defer cleanup()
82+
83+
// Drop all data
84+
require.NoError(t, client.Login(context.Background(),
85+
dgraphapi.DefaultUser, dgraphapi.DefaultPassword))
86+
require.NoError(t, client.DropAll())
87+
88+
// create ns1
89+
ctx := context.Background()
90+
ns1, err := client.CreateNamespace(ctx)
91+
require.NoError(t, err)
92+
93+
// Dropping a non-existent namespace should not be an error
94+
require.NoError(t, client.DropNamespace(ctx, ns1))
95+
require.NoError(t, client.DropNamespace(ctx, uint64(10000000)))
96+
97+
nsMaps, err := client.ListNamespaces(ctx)
98+
require.NoError(t, err)
99+
require.Len(t, nsMaps, 1)
100+
}

edgraph/query.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import (
1111

1212
"github.com/dgraph-io/dgo/v250/protos/api"
1313
"github.com/hypermodeinc/dgraph/v25/dql"
14+
"github.com/hypermodeinc/dgraph/v25/x"
1415
)
1516

1617
// Alter handles requests to change the schema or remove parts or all of the data.
1718
func (s *Server) RunDQL(ctx context.Context, req *api.RunDQLRequest) (*api.Response, error) {
18-
1919
apiReq, err := dql.ParseDQL(req.DqlQuery)
2020
if err != nil {
2121
return nil, fmt.Errorf("error parsing DQL query: %w", err)
@@ -29,5 +29,6 @@ func (s *Server) RunDQL(ctx context.Context, req *api.RunDQLRequest) (*api.Respo
2929
apiReq.CommitNow = true
3030
}
3131

32+
ctx = x.AttachJWTNamespace(ctx)
3233
return (&Server{}).doQuery(ctx, &Request{req: apiReq})
3334
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/Masterminds/semver/v3 v3.4.0
1010
github.com/blevesearch/bleve/v2 v2.5.3
1111
github.com/dgraph-io/badger/v4 v4.8.0
12-
github.com/dgraph-io/dgo/v250 v250.0.0-preview4.0.20250903065320-fda084b621ca
12+
github.com/dgraph-io/dgo/v250 v250.0.0-preview4.0.20250920053640-1e130664dcf9
1313
github.com/dgraph-io/gqlgen v0.13.2
1414
github.com/dgraph-io/gqlparser/v2 v2.2.2
1515
github.com/dgraph-io/graphql-transport-ws v0.0.0-20210511143556-2cef522f1f15

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
132132
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
133133
github.com/dgraph-io/badger/v4 v4.8.0 h1:JYph1ChBijCw8SLeybvPINizbDKWZ5n/GYbz2yhN/bs=
134134
github.com/dgraph-io/badger/v4 v4.8.0/go.mod h1:U6on6e8k/RTbUWxqKR0MvugJuVmkxSNc79ap4917h4w=
135-
github.com/dgraph-io/dgo/v250 v250.0.0-preview4.0.20250903065320-fda084b621ca h1:Xn/aRxYMy47NVc3WjM5mfVuJ+Inktd5Tze2wW7bqxF4=
136-
github.com/dgraph-io/dgo/v250 v250.0.0-preview4.0.20250903065320-fda084b621ca/go.mod h1:H3PcQuhmfzSC/1I7FLJYOxntpk3UG6lmZAyv0QxRm+o=
135+
github.com/dgraph-io/dgo/v250 v250.0.0-preview4.0.20250920053640-1e130664dcf9 h1:oaoEY03LQnp4MxMWgvRRvOfX//Lhn8E+utSnn8+Fujk=
136+
github.com/dgraph-io/dgo/v250 v250.0.0-preview4.0.20250920053640-1e130664dcf9/go.mod h1:H3PcQuhmfzSC/1I7FLJYOxntpk3UG6lmZAyv0QxRm+o=
137137
github.com/dgraph-io/gqlgen v0.13.2 h1:TNhndk+eHKj5qE7BenKKSYdSIdOGhLqxR1rCiMso9KM=
138138
github.com/dgraph-io/gqlgen v0.13.2/go.mod h1:iCOrOv9lngN7KAo+jMgvUPVDlYHdf7qDwsTkQby2Sis=
139139
github.com/dgraph-io/gqlparser/v2 v2.1.1/go.mod h1:MYS4jppjyx8b9tuUtjV7jU1UFZK6P9fvO8TsIsQtRKU=

0 commit comments

Comments
 (0)