44 "errors"
55 "fmt"
66
7- "github.com/tarantool/go-iproto"
87 "github.com/vmihailenco/msgpack/v5"
98 "github.com/vmihailenco/msgpack/v5/msgpcode"
109)
@@ -58,9 +57,22 @@ type SchemaResolver interface {
5857type Schema struct {
5958 Version uint
6059 // Spaces is map from space names to spaces.
61- Spaces map [string ]* Space
60+ Spaces map [string ]Space
6261 // 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
6476}
6577
6678// Space contains information about Tarantool's space.
@@ -72,12 +84,33 @@ type Space struct {
7284 Temporary bool // Is this space temporary?
7385 // Field configuration is not mandatory and not checked by Tarantool.
7486 FieldsCount uint32
75- Fields map [string ]* Field
76- FieldsById map [uint32 ]* Field
87+ Fields map [string ]Field
88+ FieldsById map [uint32 ]Field
7789 // Indexes is map from index names to indexes.
78- Indexes map [string ]* Index
90+ Indexes map [string ]Index
7991 // 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
81114}
82115
83116func (space * Space ) DecodeMsgpack (d * msgpack.Decoder ) error {
@@ -135,17 +168,17 @@ func (space *Space) DecodeMsgpack(d *msgpack.Decoder) error {
135168 return errors .New ("unexpected schema format (space flags)" )
136169 }
137170 }
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 )
142175 if arrayLen >= vspaceSpFormatFieldNum {
143176 fieldCount , err := d .DecodeArrayLen ()
144177 if err != nil {
145178 return err
146179 }
147180 for i := 0 ; i < fieldCount ; i ++ {
148- field := & Field {}
181+ field := Field {}
149182 if err := field .DecodeMsgpack (d ); err != nil {
150183 return err
151184 }
@@ -206,7 +239,14 @@ type Index struct {
206239 Name string
207240 Type string
208241 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
210250}
211251
212252func (index * Index ) DecodeMsgpack (d * msgpack.Decoder ) error {
@@ -261,9 +301,9 @@ func (index *Index) DecodeMsgpack(d *msgpack.Decoder) error {
261301 if err != nil {
262302 return err
263303 }
264- index .Fields = make ([]* IndexField , fieldCount )
304+ index .Fields = make ([]IndexField , fieldCount )
265305 for i := 0 ; i < int (fieldCount ); i ++ {
266- index .Fields [i ] = new ( IndexField )
306+ index .Fields [i ] = IndexField {}
267307 if index .Fields [i ].Id , err = d .DecodeUint32 (); err != nil {
268308 return err
269309 }
@@ -340,51 +380,40 @@ func (indexField *IndexField) DecodeMsgpack(d *msgpack.Decoder) error {
340380 return errors .New ("unexpected schema format (index fields)" )
341381}
342382
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 )
347388
348389 // 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 )
351392 if err != nil {
352- return err
393+ return Schema {}, err
353394 }
354395 for _ , space := range spaces {
355396 schema .SpacesById [space .Id ] = space
356397 schema .Spaces [space .Name ] = space
357398 }
358399
359400 // Reload indexes.
360- var indexes []* Index
401+ var indexes []Index
361402 err = conn .SelectTyped (vindexSpId , 0 , 0 , maxSchemas , IterAll , []interface {}{}, & indexes )
362403 if err != nil {
363- return err
404+ return Schema {}, err
364405 }
365406 for _ , index := range indexes {
366407 spaceId := index .SpaceId
367408 if _ , ok := schema .SpacesById [spaceId ]; ok {
368409 schema .SpacesById [spaceId ].IndexesById [index .Id ] = index
369410 schema .SpacesById [spaceId ].Indexes [index .Name ] = index
370411 } else {
371- return errors .New ("concurrent schema update" )
412+ return Schema {}, errors .New ("concurrent schema update" )
372413 }
373414 }
374415
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
388417}
389418
390419// resolveSpaceNumber tries to resolve a space number.
@@ -462,7 +491,7 @@ func resolveIndexNumber(i interface{}) (uint32, error) {
462491}
463492
464493type loadedSchemaResolver struct {
465- Schema * Schema
494+ Schema Schema
466495 // SpaceAndIndexNamesSupported shows if a current Tarantool version supports
467496 // iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES.
468497 SpaceAndIndexNamesSupported bool
0 commit comments