1 package pgtype_test
2
3 import (
4 "context"
5 "fmt"
6 "testing"
7
8 pgx "github.com/jackc/pgx/v5"
9 "github.com/jackc/pgx/v5/pgtype"
10 "github.com/stretchr/testify/require"
11 )
12
13 func TestCompositeCodecTranscode(t *testing.T) {
14 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
15
16 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
17
18 _, err := conn.Exec(ctx, `drop type if exists ct_test;
19
20 create type ct_test as (
21 a text,
22 b int4
23 );`)
24 require.NoError(t, err)
25 defer conn.Exec(ctx, "drop type ct_test")
26
27 dt, err := conn.LoadType(ctx, "ct_test")
28 require.NoError(t, err)
29 conn.TypeMap().RegisterType(dt)
30
31 formats := []struct {
32 name string
33 code int16
34 }{
35 {name: "TextFormat", code: pgx.TextFormatCode},
36 {name: "BinaryFormat", code: pgx.BinaryFormatCode},
37 }
38
39 for _, format := range formats {
40 var a string
41 var b int32
42
43 err := conn.QueryRow(ctx, "select $1::ct_test", pgx.QueryResultFormats{format.code},
44 pgtype.CompositeFields{"hi", int32(42)},
45 ).Scan(
46 pgtype.CompositeFields{&a, &b},
47 )
48 require.NoErrorf(t, err, "%v", format.name)
49 require.EqualValuesf(t, "hi", a, "%v", format.name)
50 require.EqualValuesf(t, 42, b, "%v", format.name)
51 }
52 })
53 }
54
55 type point3d struct {
56 X, Y, Z float64
57 }
58
59 func (p point3d) IsNull() bool {
60 return false
61 }
62
63 func (p point3d) Index(i int) any {
64 switch i {
65 case 0:
66 return p.X
67 case 1:
68 return p.Y
69 case 2:
70 return p.Z
71 default:
72 panic("invalid index")
73 }
74 }
75
76 func (p *point3d) ScanNull() error {
77 return fmt.Errorf("cannot scan NULL into point3d")
78 }
79
80 func (p *point3d) ScanIndex(i int) any {
81 switch i {
82 case 0:
83 return &p.X
84 case 1:
85 return &p.Y
86 case 2:
87 return &p.Z
88 default:
89 panic("invalid index")
90 }
91 }
92
93 func TestCompositeCodecTranscodeStruct(t *testing.T) {
94 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
95
96 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
97
98 _, err := conn.Exec(ctx, `drop type if exists point3d;
99
100 create type point3d as (
101 x float8,
102 y float8,
103 z float8
104 );`)
105 require.NoError(t, err)
106 defer conn.Exec(ctx, "drop type point3d")
107
108 dt, err := conn.LoadType(ctx, "point3d")
109 require.NoError(t, err)
110 conn.TypeMap().RegisterType(dt)
111
112 formats := []struct {
113 name string
114 code int16
115 }{
116 {name: "TextFormat", code: pgx.TextFormatCode},
117 {name: "BinaryFormat", code: pgx.BinaryFormatCode},
118 }
119
120 for _, format := range formats {
121 input := point3d{X: 1, Y: 2, Z: 3}
122 var output point3d
123 err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
124 require.NoErrorf(t, err, "%v", format.name)
125 require.Equalf(t, input, output, "%v", format.name)
126 }
127 })
128 }
129
130 func TestCompositeCodecTranscodeStructWrapper(t *testing.T) {
131 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
132
133 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
134
135 _, err := conn.Exec(ctx, `drop type if exists point3d;
136
137 create type point3d as (
138 x float8,
139 y float8,
140 z float8
141 );`)
142 require.NoError(t, err)
143 defer conn.Exec(ctx, "drop type point3d")
144
145 dt, err := conn.LoadType(ctx, "point3d")
146 require.NoError(t, err)
147 conn.TypeMap().RegisterType(dt)
148
149 formats := []struct {
150 name string
151 code int16
152 }{
153 {name: "TextFormat", code: pgx.TextFormatCode},
154 {name: "BinaryFormat", code: pgx.BinaryFormatCode},
155 }
156
157 type anotherPoint struct {
158 X, Y, Z float64
159 }
160
161 for _, format := range formats {
162 input := anotherPoint{X: 1, Y: 2, Z: 3}
163 var output anotherPoint
164 err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
165 require.NoErrorf(t, err, "%v", format.name)
166 require.Equalf(t, input, output, "%v", format.name)
167 }
168 })
169 }
170
171 func TestCompositeCodecDecodeValue(t *testing.T) {
172 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
173
174 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
175
176 _, err := conn.Exec(ctx, `drop type if exists point3d;
177
178 create type point3d as (
179 x float8,
180 y float8,
181 z float8
182 );`)
183 require.NoError(t, err)
184 defer conn.Exec(ctx, "drop type point3d")
185
186 dt, err := conn.LoadType(ctx, "point3d")
187 require.NoError(t, err)
188 conn.TypeMap().RegisterType(dt)
189
190 formats := []struct {
191 name string
192 code int16
193 }{
194 {name: "TextFormat", code: pgx.TextFormatCode},
195 {name: "BinaryFormat", code: pgx.BinaryFormatCode},
196 }
197
198 for _, format := range formats {
199 rows, err := conn.Query(ctx, "select '(1,2,3)'::point3d", pgx.QueryResultFormats{format.code})
200 require.NoErrorf(t, err, "%v", format.name)
201 require.True(t, rows.Next())
202 values, err := rows.Values()
203 require.NoErrorf(t, err, "%v", format.name)
204 require.Lenf(t, values, 1, "%v", format.name)
205 require.Equalf(t, map[string]any{"x": 1.0, "y": 2.0, "z": 3.0}, values[0], "%v", format.name)
206 require.False(t, rows.Next())
207 require.NoErrorf(t, rows.Err(), "%v", format.name)
208 }
209 })
210 }
211
212
213
214
215
216 func TestCompositeCodecTranscodeStructWrapperForTable(t *testing.T) {
217 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)")
218
219 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) {
220
221 _, err := conn.Exec(ctx, `drop table if exists point3d;
222
223 create table point3d (
224 x float8,
225 y float8,
226 z float8
227 );`)
228 require.NoError(t, err)
229 defer conn.Exec(ctx, "drop table point3d")
230
231 dt, err := conn.LoadType(ctx, "point3d")
232 require.NoError(t, err)
233 conn.TypeMap().RegisterType(dt)
234
235 formats := []struct {
236 name string
237 code int16
238 }{
239 {name: "TextFormat", code: pgx.TextFormatCode},
240 {name: "BinaryFormat", code: pgx.BinaryFormatCode},
241 }
242
243 type anotherPoint struct {
244 X, Y, Z float64
245 }
246
247 for _, format := range formats {
248 input := anotherPoint{X: 1, Y: 2, Z: 3}
249 var output anotherPoint
250 err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output)
251 require.NoErrorf(t, err, "%v", format.name)
252 require.Equalf(t, input, output, "%v", format.name)
253 }
254 })
255 }
256
View as plain text