Skip to content

Commit b516184

Browse files
committed
schema loading
1 parent e680762 commit b516184

File tree

4 files changed

+307
-1
lines changed

4 files changed

+307
-1
lines changed

config.lua

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,37 @@ box.cfg{
33
wal_dir='xlog',
44
snap_dir='snap',
55
}
6+
67
local s = box.schema.space.create('test', {if_not_exists = true})
7-
local i = s:create_index('primary', {type = 'hash', parts = {1, 'NUM'}, if_not_exists = true})
8+
s:create_index('primary', {type = 'hash', parts = {1, 'NUM'}, if_not_exists = true})
89
s:truncate()
910

11+
local st = box.schema.space.create('schematest', {
12+
id = 9991,
13+
temporary = true,
14+
if_not_exists = true,
15+
field_count = 7,
16+
format = {
17+
[2] = {name = "name1"},
18+
[3] = {type = "type2"},
19+
[6] = {name = "name5", type = "str", more = "extra"},
20+
},
21+
})
22+
st:create_index('primary', {
23+
type = 'hash',
24+
parts = {1, 'NUM'},
25+
unique = true,
26+
if_not_exists = true,
27+
})
28+
st:create_index('secondary', {
29+
id = 3,
30+
type = 'tree',
31+
unique = false,
32+
parts = { 2, 'num', 3, 'STR' },
33+
if_not_exists = true,
34+
})
35+
36+
s:truncate()
1037
--box.schema.user.grant('guest', 'read,write,execute', 'universe')
1138

1239
-- auth testing: access control

connection.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Connection struct {
1818
r *bufio.Reader
1919
w *bufio.Writer
2020
mutex *sync.Mutex
21+
Schema *Schema
2122
requestId uint32
2223
Greeting *Greeting
2324
requests map[uint32]*Future
@@ -65,6 +66,11 @@ func Connect(addr string, opts Opts) (conn *Connection, err error) {
6566
go conn.writer()
6667
go conn.reader()
6768

69+
if err = conn.loadSchema(); err != nil {
70+
conn.closeConnection(err)
71+
return nil, err
72+
}
73+
6874
return conn, err
6975
}
7076

schema.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package tarantool
2+
3+
import (
4+
_ "fmt"
5+
)
6+
7+
type Schema struct {
8+
Version uint
9+
Spaces map[uint32]*Space
10+
SpacesN map[string]*Space
11+
}
12+
13+
type Space struct {
14+
Id uint32
15+
Name string
16+
Engine string
17+
Temporary bool
18+
FieldsCount uint32
19+
Fields map[uint32]*Field
20+
FieldsN map[string]*Field
21+
Indexes map[uint32]*Index
22+
IndexesN map[string]*Index
23+
}
24+
25+
type Field struct {
26+
Id uint32
27+
Name string
28+
Type string
29+
}
30+
31+
type Index struct {
32+
Id uint32
33+
Name string
34+
Type string
35+
Unique bool
36+
Fields []*IndexField
37+
}
38+
39+
type IndexField struct {
40+
Id uint32
41+
Type string
42+
}
43+
44+
const (
45+
maxSchemas = 10000
46+
spaceSpId = 280
47+
vspaceSpId = 281
48+
indexSpId = 288
49+
vindexSpId = 289
50+
)
51+
52+
func (conn *Connection) loadSchema() (err error) {
53+
var req *Request
54+
var resp *Response
55+
56+
schema := new(Schema)
57+
schema.Spaces = make(map[uint32]*Space)
58+
schema.SpacesN = make(map[string]*Space)
59+
60+
// reload spaces
61+
req = conn.NewRequest(SelectRequest)
62+
req.fillSearch(spaceSpId, 0, []interface{}{})
63+
req.fillIterator(0, maxSchemas, IterAll)
64+
resp, err = req.perform()
65+
if err != nil {
66+
return err
67+
}
68+
for _, row := range resp.Data {
69+
row := row.([]interface{})
70+
space := new(Space)
71+
space.Id = uint32(row[0].(uint64))
72+
space.Name = row[2].(string)
73+
space.Engine = row[3].(string)
74+
space.FieldsCount = uint32(row[4].(uint64))
75+
space.Temporary = bool(row[5].(string) == "temporary")
76+
space.Fields = make(map[uint32]*Field)
77+
space.FieldsN = make(map[string]*Field)
78+
space.Indexes = make(map[uint32]*Index)
79+
space.IndexesN = make(map[string]*Index)
80+
for i, f := range row[6].([]interface{}) {
81+
if f == nil {
82+
continue
83+
}
84+
f := f.(map[interface{}]interface{})
85+
field := new(Field)
86+
field.Id = uint32(i)
87+
if name, ok := f["name"]; ok && name != nil {
88+
field.Name = name.(string)
89+
}
90+
if type_, ok := f["type"]; ok && type_ != nil {
91+
field.Type = type_.(string)
92+
}
93+
space.Fields[field.Id] = field
94+
if field.Name != "" {
95+
space.FieldsN[field.Name] = field
96+
}
97+
}
98+
99+
schema.Spaces[space.Id] = space
100+
schema.SpacesN[space.Name] = space
101+
}
102+
103+
// reload indexes
104+
req = conn.NewRequest(SelectRequest)
105+
req.fillSearch(indexSpId, 0, []interface{}{})
106+
req.fillIterator(0, maxSchemas, IterAll)
107+
resp, err = req.perform()
108+
if err != nil {
109+
return err
110+
}
111+
for _, row := range resp.Data {
112+
row := row.([]interface{})
113+
index := new(Index)
114+
index.Id = uint32(row[1].(uint64))
115+
index.Name = row[2].(string)
116+
index.Type = row[3].(string)
117+
opts := row[4].(map[interface{}]interface{})
118+
index.Unique = opts["unique"].(bool)
119+
for _, f := range row[5].([]interface{}) {
120+
f := f.([]interface{})
121+
field := new(IndexField)
122+
field.Id = uint32(f[0].(uint64))
123+
field.Type = f[1].(string)
124+
index.Fields = append(index.Fields, field)
125+
}
126+
spaceId := uint32(row[0].(uint64))
127+
schema.Spaces[spaceId].Indexes[index.Id] = index
128+
schema.Spaces[spaceId].IndexesN[index.Name] = index
129+
}
130+
conn.Schema = schema
131+
return nil
132+
}

tarantool_test.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,4 +492,145 @@ func TestClient(t *testing.T) {
492492
if val != 11 {
493493
t.Errorf("5 + 6 == 11, but got %v", val)
494494
}
495+
496+
// Schema
497+
schema := conn.Schema
498+
if schema.Spaces == nil {
499+
t.Errorf("schema.Spaces is nil")
500+
}
501+
if schema.SpacesN == nil {
502+
t.Errorf("schema.SpacesN is nil")
503+
}
504+
var space, space2 *Space
505+
var ok bool
506+
if space, ok = schema.Spaces[9991]; !ok {
507+
t.Errorf("space with id = 9991 was not found in schema.Spaces")
508+
}
509+
if space2, ok = schema.SpacesN["schematest"]; !ok {
510+
t.Errorf("space with name 'schematest' was not found in schema.Spaces")
511+
}
512+
if space != space2 {
513+
t.Errorf("space with id = 9991 and space with name schematest are different")
514+
}
515+
if space.Id != 9991 {
516+
t.Errorf("space 9991 has incorrect Id")
517+
}
518+
if space.Name != "schematest" {
519+
t.Errorf("space 9991 has incorrect Name")
520+
}
521+
if !space.Temporary {
522+
t.Errorf("space 9991 should be temporary")
523+
}
524+
if space.Engine != "memtx" {
525+
t.Errorf("space 9991 engine should be memtx")
526+
}
527+
if space.FieldsCount != 7 {
528+
t.Errorf("space 9991 has incorrect fields count")
529+
}
530+
531+
if space.Fields == nil {
532+
t.Errorf("space.Fields is nill")
533+
}
534+
if space.FieldsN == nil {
535+
t.Errorf("space.FieldsN is nill")
536+
}
537+
if len(space.Fields) != 3 {
538+
t.Errorf("space.Fields len is incorrect")
539+
}
540+
if len(space.FieldsN) != 2 {
541+
t.Errorf("space.FieldsN len is incorrect")
542+
}
543+
544+
var field1, field2, field5, field1_, field5_ *Field
545+
if field1, ok = space.Fields[1]; !ok {
546+
t.Errorf("field id = 1 was not found")
547+
}
548+
if field2, ok = space.Fields[2]; !ok {
549+
t.Errorf("field id = 2 was not found")
550+
}
551+
if field5, ok = space.Fields[5]; !ok {
552+
t.Errorf("field id = 5 was not found")
553+
}
554+
555+
if field1_, ok = space.FieldsN["name1"]; !ok {
556+
t.Errorf("field name = name1 was not found")
557+
}
558+
if field5_, ok = space.FieldsN["name5"]; !ok {
559+
t.Errorf("field name = name5 was not found")
560+
}
561+
if field1 != field1_ || field5 != field5_ {
562+
t.Errorf("field with id = 1 and field with name 'name1' are different")
563+
}
564+
if field1.Name != "name1" {
565+
t.Errorf("field 1 has incorrect Name")
566+
}
567+
if field1.Type != "" {
568+
t.Errorf("field 1 has incorrect Type")
569+
}
570+
if field2.Name != "" {
571+
t.Errorf("field 2 has incorrect Name")
572+
}
573+
if field2.Type != "type2" {
574+
t.Errorf("field 2 has incorrect Type")
575+
}
576+
577+
if space.Indexes == nil {
578+
t.Errorf("space.Indexes is nill")
579+
}
580+
if space.IndexesN == nil {
581+
t.Errorf("space.IndexesN is nill")
582+
}
583+
if len(space.Indexes) != 2 {
584+
t.Errorf("space.Indexes len is incorrect")
585+
}
586+
if len(space.IndexesN) != 2 {
587+
t.Errorf("space.IndexesN len is incorrect")
588+
}
589+
590+
var index0, index3, index0_, index3_ *Index
591+
if index0, ok = space.Indexes[0]; !ok {
592+
t.Errorf("index id = 0 was not found")
593+
}
594+
if index3, ok = space.Indexes[3]; !ok {
595+
t.Errorf("index id = 3 was not found")
596+
}
597+
if index0_, ok = space.IndexesN["primary"]; !ok {
598+
t.Errorf("index name = primary was not found")
599+
}
600+
if index3_, ok = space.IndexesN["secondary"]; !ok {
601+
t.Errorf("index name = secondary was not found")
602+
}
603+
if index0 != index0_ || index3 != index3_ {
604+
t.Errorf("index with id = 3 and index with name 'secondary' are different")
605+
}
606+
if index3.Id != 3 {
607+
t.Errorf("index has incorrect Id")
608+
}
609+
if index0.Name != "primary" {
610+
t.Errorf("index has incorrect Name")
611+
}
612+
if index0.Type != "hash" || index3.Type != "tree" {
613+
t.Errorf("index has incorrect Type")
614+
}
615+
if !index0.Unique || index3.Unique {
616+
t.Errorf("index has incorrect Unique")
617+
}
618+
if index3.Fields == nil {
619+
t.Errorf("index.Fields is nil")
620+
}
621+
if len(index3.Fields) != 2 {
622+
t.Errorf("index.Fields len is incorrect")
623+
}
624+
625+
ifield1 := index3.Fields[0]
626+
ifield2 := index3.Fields[1]
627+
if ifield1 == nil || ifield2 == nil {
628+
t.Errorf("index field is nil")
629+
}
630+
if ifield1.Id != 1 || ifield2.Id != 2 {
631+
t.Errorf("index field has incorrect Id")
632+
}
633+
if ifield1.Type != "num" || ifield2.Type != "STR" {
634+
t.Errorf("index field has incorrect Type[")
635+
}
495636
}

0 commit comments

Comments
 (0)