Skip to content

Commit 9143c87

Browse files
committed
Schema lookups for spaces and indexes
1 parent e680762 commit 9143c87

File tree

1 file changed

+260
-0
lines changed

1 file changed

+260
-0
lines changed

Diff for: schema.go

+260
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
package tarantool
2+
3+
import "errors"
4+
5+
const (
6+
SpaceSchema = 272
7+
SpaceSpace = 280
8+
SpaceIndex = 288
9+
SpaceFunc = 296
10+
SpaceVSpace = 281
11+
SpaceVIndex = 289
12+
SpaceVFunc = 297
13+
SpaceUser = 304
14+
SpacePriv = 312
15+
SpaceCluster = 320
16+
)
17+
18+
const (
19+
IndexSpacePrimary = 0
20+
IndexSpaceName = 2
21+
IndexIndexPrimary = 0
22+
IndexIndexName = 2
23+
)
24+
25+
// Space implements lookups on a box.space
26+
type Space struct {
27+
No uint32
28+
Name string
29+
Type string
30+
schema *Schema
31+
index map[string]*Index
32+
indexNo map[uint32]*Index
33+
}
34+
35+
func newSpace(schema *Schema, no uint32, name, kind string) *Space {
36+
return &Space{
37+
No: no,
38+
Name: name,
39+
Type: kind,
40+
schema: schema,
41+
index: make(map[string]*Index),
42+
indexNo: make(map[uint32]*Index),
43+
}
44+
}
45+
46+
// Index resolves an index by name
47+
func (space *Space) Index(name string) (index *Index, err error) {
48+
var ok bool
49+
if index, ok = space.index[name]; ok {
50+
return
51+
}
52+
53+
var res *Response
54+
if res, err = space.schema.conn.Select(SpaceVIndex, IndexIndexName, 0, 1, 0, []interface{}{space.No, name}); err != nil {
55+
return
56+
}
57+
if res.Data == nil || len(res.Data) == 0 {
58+
if res, err = space.schema.conn.Select(SpaceIndex, IndexIndexName, 0, 1, 0, []interface{}{space.No, name}); err != nil {
59+
return
60+
}
61+
}
62+
63+
var row []interface{}
64+
if res.Data == nil || len(res.Data) == 0 {
65+
return nil, errors.New(`no such space`)
66+
}
67+
if row, ok = res.Data[0].([]interface{}); !ok {
68+
return nil, errors.New(`unexpected result`)
69+
}
70+
71+
return space.add(row)
72+
}
73+
74+
func (space *Space) IndexNo(no uint32) (index *Index, err error) {
75+
var ok bool
76+
if index, ok = space.indexNo[no]; ok {
77+
return
78+
}
79+
80+
var res *Response
81+
if res, err = space.schema.conn.Select(SpaceVIndex, IndexIndexPrimary, 0, 1, 0, []interface{}{space.No, no}); err != nil {
82+
return
83+
}
84+
if res.Data == nil || len(res.Data) == 0 {
85+
if res, err = space.schema.conn.Select(SpaceIndex, IndexIndexPrimary, 0, 1, 0, []interface{}{space.No, no}); err != nil {
86+
return
87+
}
88+
}
89+
90+
var row []interface{}
91+
if res.Data == nil || len(res.Data) == 0 {
92+
return nil, errors.New(`no such index`)
93+
}
94+
if row, ok = res.Data[0].([]interface{}); !ok {
95+
return nil, errors.New(`unexpected result`)
96+
}
97+
98+
return space.add(row)
99+
}
100+
101+
func (space *Space) Indexes() ([]*Index, error) {
102+
var (
103+
res *Response
104+
row []interface{}
105+
index *Index
106+
err error
107+
ok bool
108+
)
109+
110+
if res, err = space.schema.conn.Select(SpaceIndex, IndexIndexPrimary, 0, 0xffffffff, 0, []interface{}{space.No}); err != nil {
111+
return nil, err
112+
}
113+
114+
indexes := make([]*Index, len(res.Data))
115+
for i, raw := range res.Data {
116+
if row, ok = raw.([]interface{}); !ok {
117+
return nil, errors.New("unexpected result")
118+
}
119+
120+
if index, err = space.add(row); err != nil {
121+
return nil, err
122+
}
123+
124+
indexes[i] = index
125+
}
126+
127+
return indexes, nil
128+
}
129+
130+
func (space *Space) add(row []interface{}) (index *Index, err error) {
131+
if row == nil || len(row) == 0 {
132+
return nil, errors.New(`no such index`)
133+
}
134+
135+
index = &Index{Space: space, No: uint32(row[1].(uint64)), Name: row[2].(string)}
136+
space.index[index.Name] = index
137+
space.indexNo[index.No] = index
138+
139+
return
140+
}
141+
142+
type Index struct {
143+
Space *Space
144+
No uint32
145+
Name string
146+
}
147+
148+
// Schema gives access to the schema definition, such as indexes and spaces.
149+
type Schema struct {
150+
conn *Connection
151+
space map[string]*Space
152+
spaceNo map[uint32]*Space
153+
}
154+
155+
func (conn *Connection) NewSchema() *Schema {
156+
return &Schema{
157+
conn: conn,
158+
space: make(map[string]*Space),
159+
spaceNo: make(map[uint32]*Space),
160+
}
161+
}
162+
163+
// Space resolves a space by name
164+
func (schema *Schema) Space(name string) (space *Space, err error) {
165+
var ok bool
166+
if space, ok = schema.space[name]; ok {
167+
return
168+
}
169+
170+
var res *Response
171+
if res, err = schema.conn.Select(SpaceVSpace, IndexSpaceName, 0, 1, 0, []interface{}{name}); err != nil {
172+
return
173+
}
174+
if res.Data == nil || len(res.Data) == 0 {
175+
if res, err = schema.conn.Select(SpaceSpace, IndexSpaceName, 0, 1, 0, []interface{}{name}); err != nil {
176+
return
177+
}
178+
}
179+
180+
var row []interface{}
181+
if res.Data == nil || len(res.Data) == 0 {
182+
return nil, errors.New(`no such space`)
183+
}
184+
if row, ok = res.Data[0].([]interface{}); !ok {
185+
return nil, errors.New(`unexpected result`)
186+
}
187+
188+
return schema.add(row)
189+
}
190+
191+
// SpaceNo resolves a space by number
192+
func (schema *Schema) SpaceNo(no uint32) (space *Space, err error) {
193+
var ok bool
194+
195+
if space, ok = schema.spaceNo[no]; ok {
196+
return
197+
}
198+
199+
var res *Response
200+
if res, err = schema.conn.Select(SpaceVSpace, IndexSpacePrimary, 0, 1, 0, []interface{}{no}); err != nil {
201+
return
202+
}
203+
if res.Data == nil || len(res.Data) == 0 {
204+
if res, err = schema.conn.Select(SpaceSpace, IndexSpacePrimary, 0, 1, 0, []interface{}{no}); err != nil {
205+
return
206+
}
207+
}
208+
209+
var row []interface{}
210+
if res.Data == nil || len(res.Data) == 0 {
211+
return nil, errors.New(`no such space`)
212+
}
213+
if row, ok = res.Data[0].([]interface{}); !ok {
214+
return nil, errors.New(`unexpected result`)
215+
}
216+
217+
return schema.add(row)
218+
}
219+
220+
// Spaces retrieves all spaces for a schema
221+
func (schema *Schema) Spaces() ([]*Space, error) {
222+
var (
223+
res *Response
224+
row []interface{}
225+
space *Space
226+
err error
227+
ok bool
228+
)
229+
230+
if res, err = schema.conn.Select(SpaceSpace, 0, 0, 0xffffffff, 0, []interface{}{}); err != nil {
231+
return nil, err
232+
}
233+
234+
spaces := make([]*Space, len(res.Data))
235+
for i, raw := range res.Data {
236+
if row, ok = raw.([]interface{}); !ok {
237+
return nil, errors.New("unexpected result")
238+
}
239+
240+
if space, err = schema.add(row); err != nil {
241+
return nil, err
242+
}
243+
244+
spaces[i] = space
245+
}
246+
247+
return spaces, nil
248+
}
249+
250+
func (schema *Schema) add(row []interface{}) (space *Space, err error) {
251+
if row == nil || len(row) == 0 {
252+
return nil, errors.New(`no such space`)
253+
}
254+
255+
space = newSpace(schema, uint32(row[0].(uint64)), row[2].(string), row[3].(string))
256+
schema.space[space.Name] = space
257+
schema.spaceNo[space.No] = space
258+
259+
return
260+
}

0 commit comments

Comments
 (0)