Skip to content

Commit 851efda

Browse files
authored
Merge pull request #74 from upfluence/florentcarrez/thrift-sql-serializer
SQL Thrift type as binary
2 parents 5ba5058 + 4ff2231 commit 851efda

File tree

4 files changed

+159
-3
lines changed

4 files changed

+159
-3
lines changed

go.mod

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ require (
3434
github.com/upfluence/errors v0.2.9
3535
github.com/upfluence/log v0.0.5
3636
github.com/upfluence/stats v0.1.4
37-
github.com/upfluence/thrift v2.4.4+incompatible
37+
github.com/upfluence/thrift v2.6.8+incompatible
3838
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
3939
golang.org/x/oauth2 v0.19.0
4040
golang.org/x/sync v0.9.0
@@ -43,6 +43,8 @@ require (
4343
golang.org/x/time v0.3.0
4444
)
4545

46+
require github.com/upfluence/base v0.1.138
47+
4648
require (
4749
github.com/beorn7/perks v1.0.1 // indirect
4850
github.com/cespare/xxhash/v2 v2.2.0 // indirect

go.sum

+4-2
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
451451
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
452452
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
453453
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
454+
github.com/upfluence/base v0.1.138 h1:QvYPq0fhSE54AVCr5rsB+pACAP2vVdpr+Yn0r2Ud7yo=
455+
github.com/upfluence/base v0.1.138/go.mod h1:jjVPOP0HtL6weh6xrqSIo2Mzt+30LIjjr4yK8npiiTM=
454456
github.com/upfluence/cfg v0.3.5 h1:NoA7vrzPM2gOso58x0H8kEDdDd9TnBJtds6zXCaieI0=
455457
github.com/upfluence/cfg v0.3.5/go.mod h1:0TzWsboPheOr4WtyZ370j6KuFAkXAS2IqpdVnTYSBSc=
456458
github.com/upfluence/errors v0.0.0-20210413181856-d161314a8a8c/go.mod h1:WWK5iZiYpEHoLYZV+MZSFsHrnYueCUMwsaEEko7aiTU=
@@ -461,8 +463,8 @@ github.com/upfluence/log v0.0.5 h1:OR7KY6NKfrqvWfXz1nWHEGLtwP+tw1a5x/6hfPBatHU=
461463
github.com/upfluence/log v0.0.5/go.mod h1:1uMfWKPiN8wDCUtENVcYC0bRrTqMeSyAP5R3P5yWXsc=
462464
github.com/upfluence/stats v0.1.4 h1:youBJzTz7H2xgXY7okdBauu321Aa/W4SeYQC6g8HHHU=
463465
github.com/upfluence/stats v0.1.4/go.mod h1:kzquL6D8zXPCcjFgPqq6e/+6lzzglTJZzJ3V7UWf/as=
464-
github.com/upfluence/thrift v2.4.4+incompatible h1:xmhLcu9nmMcMjZOVzDl95E+Q9NmMQLDQ/gQ3V54tq4Q=
465-
github.com/upfluence/thrift v2.4.4+incompatible/go.mod h1:3uGdmLrgG2WjEd1pvDN5Rnxlui3lAE1cZHtv+7O337E=
466+
github.com/upfluence/thrift v2.6.8+incompatible h1:y8wb0oxdKgPfWW+p62lYZkbks3rIvh/IWGS73RwAQ8Y=
467+
github.com/upfluence/thrift v2.6.8+incompatible/go.mod h1:3uGdmLrgG2WjEd1pvDN5Rnxlui3lAE1cZHtv+7O337E=
466468
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
467469
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
468470
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=

thrift/sql/serializing.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package sql
2+
3+
import (
4+
"database/sql/driver"
5+
6+
"github.com/upfluence/errors"
7+
"github.com/upfluence/thrift/lib/go/thrift"
8+
9+
"github.com/upfluence/pkg/thrift/serializer"
10+
"github.com/upfluence/pkg/thrift/thriftutil"
11+
)
12+
13+
var defaultSerializerFactory = serializer.NewTSerializerFactory(
14+
thriftutil.BinaryProtocolFactory,
15+
)
16+
17+
type TStructPtr[T any] interface {
18+
thrift.TStruct
19+
*T
20+
}
21+
22+
type NullThrift[T any, PT TStructPtr[T]] struct {
23+
Data PT
24+
SerializerFactory *serializer.TSerializerFactory
25+
}
26+
27+
func (t NullThrift[T, PT]) serializerFactory() *serializer.TSerializerFactory {
28+
if t.SerializerFactory == nil {
29+
return defaultSerializerFactory
30+
}
31+
32+
return t.SerializerFactory
33+
}
34+
35+
func (t *NullThrift[T, PT]) Scan(value any) error {
36+
if value == nil {
37+
t.Data = nil
38+
39+
return nil
40+
}
41+
42+
data, ok := value.([]byte)
43+
44+
if !ok {
45+
return errors.New("invalid type: expected []byte")
46+
}
47+
48+
if t.Data == nil {
49+
t.Data = new(T)
50+
}
51+
52+
return errors.WithStack(
53+
t.serializerFactory().GetDeserializer().Read(t.Data, data),
54+
)
55+
}
56+
57+
func (t NullThrift[T, PT]) Value() (driver.Value, error) {
58+
if t.Data == nil {
59+
return nil, nil // nolint:nilnil
60+
}
61+
62+
data, err := t.serializerFactory().GetSerializer().Write(t.Data)
63+
64+
return data, errors.WithStack(err)
65+
}

thrift/sql/serializing_test.go

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package sql
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
"github.com/upfluence/errors"
10+
"github.com/upfluence/thrift/lib/go/thrift"
11+
12+
"github.com/upfluence/pkg/thrift/serializer"
13+
"github.com/upfluence/pkg/thrift/thriftutil"
14+
)
15+
16+
type fakeTStruct struct {
17+
value int64
18+
}
19+
20+
func (t fakeTStruct) Write(p thrift.TProtocol) error {
21+
return errors.WithStack(p.WriteI64(t.value))
22+
}
23+
24+
func (t *fakeTStruct) Read(p thrift.TProtocol) error {
25+
val, err := p.ReadI64()
26+
27+
if err != nil {
28+
return errors.WithStack(err)
29+
}
30+
31+
t.value = val
32+
33+
return nil
34+
}
35+
36+
func (t *fakeTStruct) String() string {
37+
return fmt.Sprint(t.value)
38+
}
39+
40+
func TestNullableThrift_Scan(t *testing.T) {
41+
for _, tt := range []struct {
42+
name string
43+
fakeValue *fakeTStruct
44+
serializerFactory *serializer.TSerializerFactory
45+
}{
46+
{
47+
name: "nil value",
48+
fakeValue: nil,
49+
},
50+
{
51+
name: "with value",
52+
fakeValue: &fakeTStruct{
53+
value: 42,
54+
},
55+
},
56+
{
57+
name: "with custom serializer factory",
58+
fakeValue: &fakeTStruct{
59+
value: 42,
60+
},
61+
serializerFactory: serializer.NewTSerializerFactory(
62+
thriftutil.JSONProtocolFactory,
63+
),
64+
},
65+
} {
66+
t.Run(tt.name, func(t *testing.T) {
67+
var (
68+
s = NullThrift[
69+
fakeTStruct,
70+
*fakeTStruct,
71+
]{
72+
Data: tt.fakeValue,
73+
SerializerFactory: tt.serializerFactory,
74+
}
75+
76+
data, err = s.Value()
77+
)
78+
79+
require.NoError(t, err)
80+
81+
s.Data = nil
82+
83+
require.NoError(t, s.Scan(data))
84+
assert.Equal(t, tt.fakeValue, s.Data)
85+
})
86+
}
87+
}

0 commit comments

Comments
 (0)