Skip to content

Commit ff83f19

Browse files
wip
1 parent 26d9e9f commit ff83f19

File tree

6 files changed

+141
-102
lines changed

6 files changed

+141
-102
lines changed

box_error.go

Lines changed: 101 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package tarantool
22

3+
import (
4+
"reflect"
5+
)
6+
37
const error_extId = 3
48

59
// BoxError is a type representing Tarantool `box.error` object: a single
@@ -27,7 +31,7 @@ func (err BoxError) Depth() (depth int) {
2731
return depth
2832
}
2933

30-
func decodeBoxErrorStack(d *decoder) (*BoxError, error) {
34+
func decodeBoxError(d *decoder) (*BoxError, error) {
3135
var l, larr, l1, l2 int
3236
var errorStack []BoxError
3337
var err error
@@ -124,99 +128,99 @@ func decodeBoxErrorStack(d *decoder) (*BoxError, error) {
124128
return nil, nil
125129
}
126130

127-
// func encodeBoxError(enc *encoder, err BoxError) (*BoxError, error) {
128-
// var l, larr, l1, l2 int
129-
// var errorStack []BoxError
130-
// var err error
131-
// var mapk, mapv interface{}
132-
133-
// if l, err = d.DecodeMapLen(); err != nil {
134-
// return nil, err
135-
// }
136-
137-
// for ; l > 0; l-- {
138-
// var cd int
139-
// if cd, err = d.DecodeInt(); err != nil {
140-
// return nil, err
141-
// }
142-
// switch cd {
143-
// case KeyErrorStack:
144-
// if larr, err = d.DecodeArrayLen(); err != nil {
145-
// return nil, err
146-
// }
147-
148-
// errorStack = make([]BoxError, larr)
149-
150-
// for i := 0; i < larr; i++ {
151-
// if l1, err = d.DecodeMapLen(); err != nil {
152-
// return nil, err
153-
// }
154-
155-
// for ; l1 > 0; l1-- {
156-
// var cd1 int
157-
// if cd1, err = d.DecodeInt(); err != nil {
158-
// return nil, err
159-
// }
160-
// switch cd1 {
161-
// case KeyErrorType:
162-
// if errorStack[i].Type, err = d.DecodeString(); err != nil {
163-
// return nil, err
164-
// }
165-
// case KeyErrorFile:
166-
// if errorStack[i].File, err = d.DecodeString(); err != nil {
167-
// return nil, err
168-
// }
169-
// case KeyErrorLine:
170-
// if errorStack[i].Line, err = d.DecodeInt64(); err != nil {
171-
// return nil, err
172-
// }
173-
// case KeyErrorMessage:
174-
// if errorStack[i].Message, err = d.DecodeString(); err != nil {
175-
// return nil, err
176-
// }
177-
// case KeyErrorErrno:
178-
// if errorStack[i].Errno, err = d.DecodeInt64(); err != nil {
179-
// return nil, err
180-
// }
181-
// case KeyErrorErrcode:
182-
// if errorStack[i].Errcode, err = d.DecodeInt64(); err != nil {
183-
// return nil, err
184-
// }
185-
// case KeyErrorFields:
186-
// errorStack[i].Fields = make(map[interface{}]interface{})
187-
// if l2, err = d.DecodeMapLen(); err != nil {
188-
// return nil, err
189-
// }
190-
// for ; l2 > 0; l2-- {
191-
// if mapk, err = d.DecodeInterface(); err != nil {
192-
// return nil, err
193-
// }
194-
// if mapv, err = d.DecodeInterface(); err != nil {
195-
// return nil, err
196-
// }
197-
// errorStack[i].Fields[mapk] = mapv
198-
// }
199-
// default:
200-
// if err = d.Skip(); err != nil {
201-
// return nil, err
202-
// }
203-
// }
204-
// }
205-
206-
// if i > 0 {
207-
// errorStack[i-1].Prev = &errorStack[i]
208-
// }
209-
// }
210-
// default:
211-
// if err = d.Skip(); err != nil {
212-
// return nil, err
213-
// }
214-
// }
215-
// }
216-
217-
// if len(errorStack) > 0 {
218-
// return &errorStack[0], nil
219-
// }
220-
221-
// return nil, nil
222-
// }
131+
func msgpackDecodeBoxError(d *decoder, v reflect.Value) (err error) {
132+
boxError, err := decodeBoxError(d)
133+
if err != nil {
134+
return err
135+
}
136+
137+
v.Set(reflect.ValueOf(boxError))
138+
return nil
139+
}
140+
141+
func encodeBoxError(enc *encoder, boxError BoxError) (err error) {
142+
if err = enc.EncodeArrayLen(1); err != nil {
143+
return err
144+
}
145+
if err = encodeUint(enc, KeyErrorStack); err != nil {
146+
return err
147+
}
148+
149+
var stackDepth = boxError.Depth()
150+
if err = enc.EncodeArrayLen(stackDepth); err != nil {
151+
return err
152+
}
153+
154+
for ; stackDepth > 0; stackDepth-- {
155+
if err = encodeUint(enc, KeyErrorType); err != nil {
156+
return err
157+
}
158+
if err = enc.EncodeString(boxError.Type); err != nil {
159+
return err
160+
}
161+
162+
if err = encodeUint(enc, KeyErrorFile); err != nil {
163+
return err
164+
}
165+
if err = enc.EncodeString(boxError.File); err != nil {
166+
return err
167+
}
168+
169+
if err = encodeUint(enc, KeyErrorLine); err != nil {
170+
return err
171+
}
172+
if err = enc.EncodeInt64(boxError.Line); err != nil {
173+
return err
174+
}
175+
176+
if err = encodeUint(enc, KeyErrorFile); err != nil {
177+
return err
178+
}
179+
if err = enc.EncodeString(boxError.File); err != nil {
180+
return err
181+
}
182+
183+
if err = encodeUint(enc, KeyErrorMessage); err != nil {
184+
return err
185+
}
186+
if err = enc.EncodeString(boxError.Message); err != nil {
187+
return err
188+
}
189+
190+
if err = encodeUint(enc, KeyErrorErrno); err != nil {
191+
return err
192+
}
193+
if err = enc.EncodeInt64(boxError.Errno); err != nil {
194+
return err
195+
}
196+
197+
if err = encodeUint(enc, KeyErrorErrcode); err != nil {
198+
return err
199+
}
200+
if err = enc.EncodeInt64(boxError.Errcode); err != nil {
201+
return err
202+
}
203+
204+
if len(boxError.Fields) > 0 {
205+
if err = encodeUint(enc, KeyErrorFields); err != nil {
206+
return err
207+
}
208+
209+
for k, v := range boxError.Fields {
210+
if err = enc.Encode(k); err != nil {
211+
return err
212+
}
213+
if err = enc.Encode(v); err != nil {
214+
return err
215+
}
216+
}
217+
}
218+
}
219+
220+
return nil
221+
}
222+
223+
func msgpackEncodeBoxError(e *encoder, v reflect.Value) (err error) {
224+
val := v.Interface().(BoxError)
225+
return encodeBoxError(e, val)
226+
}

msgpack.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package tarantool
55

66
import (
77
"io"
8+
"reflect"
89

910
"gopkg.in/vmihailenco/msgpack.v2"
1011
msgpcode "gopkg.in/vmihailenco/msgpack.v2/codes"
@@ -50,5 +51,6 @@ func msgpackIsString(code byte) bool {
5051
}
5152

5253
func init() {
53-
msgpack.RegisterExt(error_extId, &BoxError{})
54+
msgpack.Register(reflect.TypeOf((*BoxError)(nil)).Elem(), msgpackEncodeBoxError, msgpackDecodeBoxError)
55+
msgpack.RegisterExt(error_extId, (*BoxError)(nil))
5456
}

msgpack_v5.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package tarantool
55

66
import (
77
"io"
8+
"reflect"
89

910
"github.com/vmihailenco/msgpack/v5"
1011
"github.com/vmihailenco/msgpack/v5/msgpcode"
@@ -55,4 +56,19 @@ func msgpackIsString(code byte) bool {
5556

5657
func init() {
5758
msgpack.RegisterExt(error_extId, (*BoxError)(nil))
59+
msgpack.RegisterExtEncoder(error_extId, BoxError{},
60+
func(e *msgpack.Encoder, v reflect.Value) (ret []byte, err error) {
61+
var b bytes.Buffer
62+
63+
enc := msgpack.NewEncoder(&b)
64+
if err = msgpackEncodeBoxError(enc, v); err == nil {
65+
ret = b.Bytes()
66+
}
67+
68+
return
69+
})
70+
msgpack.RegisterExtDecoder(error_extId, BoxError{},
71+
func(d *msgpack.Decoder, v reflect.Value, extLen int) error {
72+
return msgpackDecodeBoxError(d, v)
73+
})
5874
}

protocol.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const (
3333
// (supported by connector).
3434
TransactionsFeature ProtocolFeature = 1
3535
// ErrorExtensionFeature represents support of MP_ERROR objects over MessagePack
36-
// (unsupported by connector).
36+
// (supported by connector).
3737
ErrorExtensionFeature ProtocolFeature = 2
3838
// WatchersFeature represents support of watchers
3939
// (unsupported by connector).
@@ -68,10 +68,12 @@ var clientProtocolInfo ProtocolInfo = ProtocolInfo{
6868
// 1.10.0.
6969
Version: ProtocolVersion(4),
7070
// Streams and transactions were introduced in protocol version 1
71-
// (Tarantool 2.10.0), in connector since 1.7.0.
71+
// (Tarantool 2.10.0), in connector since 1.7.0. Error extension type
72+
// is supported in Tarantool 2.10.0, in connector since 1.10.0.
7273
Features: []ProtocolFeature{
7374
StreamsFeature,
7475
TransactionsFeature,
76+
ErrorExtensionFeature,
7577
},
7678
}
7779

response.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (resp *Response) decodeBody() (err error) {
178178
return err
179179
}
180180
case KeyError:
181-
if extraErrorInfo, err = decodeBoxErrorStack(d); err != nil {
181+
if extraErrorInfo, err = decodeBoxError(d); err != nil {
182182
return err
183183
}
184184
case KeySQLInfo:
@@ -274,7 +274,7 @@ func (resp *Response) decodeBodyTyped(res interface{}) (err error) {
274274
return err
275275
}
276276
case KeyError:
277-
if extraErrorInfo, err = decodeBoxErrorStack(d); err != nil {
277+
if extraErrorInfo, err = decodeBoxError(d); err != nil {
278278
return err
279279
}
280280
case KeySQLInfo:

test_helpers/utils.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,18 @@ func SkipIfErrorExtraInfoUnsupported(t *testing.T) {
126126
t.Skip("Skipping test for Tarantool without extra error info")
127127
}
128128
}
129+
130+
func SkipIfErrorExtentionTypeUnsupported(t *testing.T) {
131+
t.Helper()
132+
133+
// Tarantool supports error extension type only since 2.4.1 version,
134+
// yet encoding was introduced only in 2.10.0.
135+
isLess, err := IsTarantoolVersionLess(2, 10, 0)
136+
if err != nil {
137+
t.Fatalf("Could not check the Tarantool version")
138+
}
139+
140+
if isLess {
141+
t.Skip("Skipping test for Tarantool without error type encoding support")
142+
}
143+
}

0 commit comments

Comments
 (0)