4
4
"errors"
5
5
"fmt"
6
6
7
- "github.com/tarantool/go-iproto"
8
7
"github.com/vmihailenco/msgpack/v5"
9
8
"github.com/vmihailenco/msgpack/v5/msgpcode"
10
9
)
@@ -58,9 +57,22 @@ type SchemaResolver interface {
58
57
type Schema struct {
59
58
Version uint
60
59
// Spaces is map from space names to spaces.
61
- Spaces map [string ]* Space
60
+ Spaces map [string ]Space
62
61
// SpacesById is map from space numbers to spaces.
63
- SpacesById map [uint32 ]* Space
62
+ SpacesById map [uint32 ]Space
63
+ }
64
+
65
+ func (schema * Schema ) copy () Schema {
66
+ schemaCopy := * schema
67
+ schemaCopy .Spaces = make (map [string ]Space , len (schema .Spaces ))
68
+ for name , space := range schema .Spaces {
69
+ schemaCopy .Spaces [name ] = space .copy ()
70
+ }
71
+ schemaCopy .SpacesById = make (map [uint32 ]Space , len (schema .SpacesById ))
72
+ for id , space := range schema .SpacesById {
73
+ schemaCopy .SpacesById [id ] = space .copy ()
74
+ }
75
+ return schemaCopy
64
76
}
65
77
66
78
// Space contains information about Tarantool's space.
@@ -72,12 +84,33 @@ type Space struct {
72
84
Temporary bool // Is this space temporary?
73
85
// Field configuration is not mandatory and not checked by Tarantool.
74
86
FieldsCount uint32
75
- Fields map [string ]* Field
76
- FieldsById map [uint32 ]* Field
87
+ Fields map [string ]Field
88
+ FieldsById map [uint32 ]Field
77
89
// Indexes is map from index names to indexes.
78
- Indexes map [string ]* Index
90
+ Indexes map [string ]Index
79
91
// IndexesById is map from index numbers to indexes.
80
- IndexesById map [uint32 ]* Index
92
+ IndexesById map [uint32 ]Index
93
+ }
94
+
95
+ func (space * Space ) copy () Space {
96
+ spaceCopy := * space
97
+ spaceCopy .Fields = make (map [string ]Field , len (space .Fields ))
98
+ for name , field := range space .Fields {
99
+ spaceCopy .Fields [name ] = field
100
+ }
101
+ spaceCopy .FieldsById = make (map [uint32 ]Field , len (space .FieldsById ))
102
+ for id , field := range space .FieldsById {
103
+ spaceCopy .FieldsById [id ] = field
104
+ }
105
+ spaceCopy .Indexes = make (map [string ]Index , len (space .Indexes ))
106
+ for name , index := range space .Indexes {
107
+ spaceCopy .Indexes [name ] = index .copy ()
108
+ }
109
+ spaceCopy .IndexesById = make (map [uint32 ]Index , len (space .IndexesById ))
110
+ for id , index := range space .IndexesById {
111
+ spaceCopy .IndexesById [id ] = index .copy ()
112
+ }
113
+ return spaceCopy
81
114
}
82
115
83
116
func (space * Space ) DecodeMsgpack (d * msgpack.Decoder ) error {
@@ -135,17 +168,17 @@ func (space *Space) DecodeMsgpack(d *msgpack.Decoder) error {
135
168
return errors .New ("unexpected schema format (space flags)" )
136
169
}
137
170
}
138
- space .FieldsById = make (map [uint32 ]* Field )
139
- space .Fields = make (map [string ]* Field )
140
- space .IndexesById = make (map [uint32 ]* Index )
141
- space .Indexes = make (map [string ]* Index )
171
+ space .FieldsById = make (map [uint32 ]Field )
172
+ space .Fields = make (map [string ]Field )
173
+ space .IndexesById = make (map [uint32 ]Index )
174
+ space .Indexes = make (map [string ]Index )
142
175
if arrayLen >= vspaceSpFormatFieldNum {
143
176
fieldCount , err := d .DecodeArrayLen ()
144
177
if err != nil {
145
178
return err
146
179
}
147
180
for i := 0 ; i < fieldCount ; i ++ {
148
- field := & Field {}
181
+ field := Field {}
149
182
if err := field .DecodeMsgpack (d ); err != nil {
150
183
return err
151
184
}
@@ -206,7 +239,14 @@ type Index struct {
206
239
Name string
207
240
Type string
208
241
Unique bool
209
- Fields []* IndexField
242
+ Fields []IndexField
243
+ }
244
+
245
+ func (index * Index ) copy () Index {
246
+ indexCopy := * index
247
+ indexCopy .Fields = make ([]IndexField , len (index .Fields ))
248
+ copy (indexCopy .Fields , index .Fields )
249
+ return indexCopy
210
250
}
211
251
212
252
func (index * Index ) DecodeMsgpack (d * msgpack.Decoder ) error {
@@ -261,9 +301,9 @@ func (index *Index) DecodeMsgpack(d *msgpack.Decoder) error {
261
301
if err != nil {
262
302
return err
263
303
}
264
- index .Fields = make ([]* IndexField , fieldCount )
304
+ index .Fields = make ([]IndexField , fieldCount )
265
305
for i := 0 ; i < int (fieldCount ); i ++ {
266
- index .Fields [i ] = new ( IndexField )
306
+ index .Fields [i ] = IndexField {}
267
307
if index .Fields [i ].Id , err = d .DecodeUint32 (); err != nil {
268
308
return err
269
309
}
@@ -340,51 +380,40 @@ func (indexField *IndexField) DecodeMsgpack(d *msgpack.Decoder) error {
340
380
return errors .New ("unexpected schema format (index fields)" )
341
381
}
342
382
343
- func (conn * Connection ) loadSchema () (err error ) {
344
- schema := new (Schema )
345
- schema .SpacesById = make (map [uint32 ]* Space )
346
- schema .Spaces = make (map [string ]* Space )
383
+ // GetSchema returns the actual schema for the connection.
384
+ func GetSchema (conn Connector ) (Schema , error ) {
385
+ schema := Schema {}
386
+ schema .SpacesById = make (map [uint32 ]Space )
387
+ schema .Spaces = make (map [string ]Space )
347
388
348
389
// Reload spaces.
349
- var spaces []* Space
350
- err = conn .SelectTyped (vspaceSpId , 0 , 0 , maxSchemas , IterAll , []interface {}{}, & spaces )
390
+ var spaces []Space
391
+ err : = conn .SelectTyped (vspaceSpId , 0 , 0 , maxSchemas , IterAll , []interface {}{}, & spaces )
351
392
if err != nil {
352
- return err
393
+ return Schema {}, err
353
394
}
354
395
for _ , space := range spaces {
355
396
schema .SpacesById [space .Id ] = space
356
397
schema .Spaces [space .Name ] = space
357
398
}
358
399
359
400
// Reload indexes.
360
- var indexes []* Index
401
+ var indexes []Index
361
402
err = conn .SelectTyped (vindexSpId , 0 , 0 , maxSchemas , IterAll , []interface {}{}, & indexes )
362
403
if err != nil {
363
- return err
404
+ return Schema {}, err
364
405
}
365
406
for _ , index := range indexes {
366
407
spaceId := index .SpaceId
367
408
if _ , ok := schema .SpacesById [spaceId ]; ok {
368
409
schema .SpacesById [spaceId ].IndexesById [index .Id ] = index
369
410
schema .SpacesById [spaceId ].Indexes [index .Name ] = index
370
411
} else {
371
- return errors .New ("concurrent schema update" )
412
+ return Schema {}, errors .New ("concurrent schema update" )
372
413
}
373
414
}
374
415
375
- spaceAndIndexNamesSupported :=
376
- isFeatureInSlice (iproto .IPROTO_FEATURE_SPACE_AND_INDEX_NAMES ,
377
- conn .serverProtocolInfo .Features )
378
-
379
- conn .lockShards ()
380
- conn .Schema = schema
381
- conn .schemaResolver = & loadedSchemaResolver {
382
- Schema : schema ,
383
- SpaceAndIndexNamesSupported : spaceAndIndexNamesSupported ,
384
- }
385
- conn .unlockShards ()
386
-
387
- return nil
416
+ return schema , nil
388
417
}
389
418
390
419
// resolveSpaceNumber tries to resolve a space number.
@@ -462,7 +491,7 @@ func resolveIndexNumber(i interface{}) (uint32, error) {
462
491
}
463
492
464
493
type loadedSchemaResolver struct {
465
- Schema * Schema
494
+ Schema Schema
466
495
// SpaceAndIndexNamesSupported shows if a current Tarantool version supports
467
496
// iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES.
468
497
SpaceAndIndexNamesSupported bool
0 commit comments