1 package pgtype_test
2
3 import (
4 "math"
5 "math/big"
6 "math/rand"
7 "reflect"
8 "testing"
9
10 "github.com/jackc/pgtype"
11 "github.com/jackc/pgtype/testutil"
12 )
13
14
15 func numericEqual(left, right *pgtype.Numeric) bool {
16 return left.Status == right.Status &&
17 left.Exp == right.Exp &&
18 ((left.Int == nil && right.Int == nil) || (left.Int != nil && right.Int != nil && left.Int.Cmp(right.Int) == 0)) &&
19 left.NaN == right.NaN
20 }
21
22
23 func numericNormalizedEqual(left, right *pgtype.Numeric) bool {
24 if left.Status != right.Status {
25 return false
26 }
27
28 normLeft := &pgtype.Numeric{Int: (&big.Int{}).Set(left.Int), Status: left.Status}
29 normRight := &pgtype.Numeric{Int: (&big.Int{}).Set(right.Int), Status: right.Status}
30
31 if left.Exp < right.Exp {
32 mul := (&big.Int{}).Exp(big.NewInt(10), big.NewInt(int64(right.Exp-left.Exp)), nil)
33 normRight.Int.Mul(normRight.Int, mul)
34 } else if left.Exp > right.Exp {
35 mul := (&big.Int{}).Exp(big.NewInt(10), big.NewInt(int64(left.Exp-right.Exp)), nil)
36 normLeft.Int.Mul(normLeft.Int, mul)
37 }
38
39 return normLeft.Int.Cmp(normRight.Int) == 0
40 }
41
42 func mustParseBigInt(t *testing.T, src string) *big.Int {
43 i := &big.Int{}
44 if _, ok := i.SetString(src, 10); !ok {
45 t.Fatalf("could not parse big.Int: %s", src)
46 }
47 return i
48 }
49
50 func TestNumericNormalize(t *testing.T) {
51 testutil.TestSuccessfulNormalize(t, []testutil.NormalizeTest{
52 {
53 SQL: "select '0'::numeric",
54 Value: &pgtype.Numeric{Int: big.NewInt(0), Exp: 0, Status: pgtype.Present},
55 },
56 {
57 SQL: "select '1'::numeric",
58 Value: &pgtype.Numeric{Int: big.NewInt(1), Exp: 0, Status: pgtype.Present},
59 },
60 {
61 SQL: "select '10.00'::numeric",
62 Value: &pgtype.Numeric{Int: big.NewInt(1000), Exp: -2, Status: pgtype.Present},
63 },
64 {
65 SQL: "select '1e-3'::numeric",
66 Value: &pgtype.Numeric{Int: big.NewInt(1), Exp: -3, Status: pgtype.Present},
67 },
68 {
69 SQL: "select '-1'::numeric",
70 Value: &pgtype.Numeric{Int: big.NewInt(-1), Exp: 0, Status: pgtype.Present},
71 },
72 {
73 SQL: "select '10000'::numeric",
74 Value: &pgtype.Numeric{Int: big.NewInt(1), Exp: 4, Status: pgtype.Present},
75 },
76 {
77 SQL: "select '3.14'::numeric",
78 Value: &pgtype.Numeric{Int: big.NewInt(314), Exp: -2, Status: pgtype.Present},
79 },
80 {
81 SQL: "select '1.1'::numeric",
82 Value: &pgtype.Numeric{Int: big.NewInt(11), Exp: -1, Status: pgtype.Present},
83 },
84 {
85 SQL: "select '100010001'::numeric",
86 Value: &pgtype.Numeric{Int: big.NewInt(100010001), Exp: 0, Status: pgtype.Present},
87 },
88 {
89 SQL: "select '100010001.0001'::numeric",
90 Value: &pgtype.Numeric{Int: big.NewInt(1000100010001), Exp: -4, Status: pgtype.Present},
91 },
92 {
93 SQL: "select '4237234789234789289347892374324872138321894178943189043890124832108934.43219085471578891547854892438945012347981'::numeric",
94 Value: &pgtype.Numeric{
95 Int: mustParseBigInt(t, "423723478923478928934789237432487213832189417894318904389012483210893443219085471578891547854892438945012347981"),
96 Exp: -41,
97 Status: pgtype.Present,
98 },
99 },
100 {
101 SQL: "select '0.8925092023480223478923478978978937897879595901237890234789243679037419057877231734823098432903527585734549035904590854890345905434578345789347890402348952348905890489054234237489234987723894789234'::numeric",
102 Value: &pgtype.Numeric{
103 Int: mustParseBigInt(t, "8925092023480223478923478978978937897879595901237890234789243679037419057877231734823098432903527585734549035904590854890345905434578345789347890402348952348905890489054234237489234987723894789234"),
104 Exp: -196,
105 Status: pgtype.Present,
106 },
107 },
108 {
109 SQL: "select '0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123'::numeric",
110 Value: &pgtype.Numeric{
111 Int: mustParseBigInt(t, "123"),
112 Exp: -186,
113 Status: pgtype.Present,
114 },
115 },
116 })
117 }
118
119 func TestNumericTranscode(t *testing.T) {
120 max := new(big.Int).Exp(big.NewInt(10), big.NewInt(147454), nil)
121 max.Add(max, big.NewInt(1))
122 longestNumeric := &pgtype.Numeric{Int: max, Exp: -16383, Status: pgtype.Present}
123
124 testutil.TestSuccessfulTranscodeEqFunc(t, "numeric", []interface{}{
125 &pgtype.Numeric{NaN: true, Status: pgtype.Present},
126 &pgtype.Numeric{InfinityModifier: pgtype.Infinity, Status: pgtype.Present},
127 &pgtype.Numeric{InfinityModifier: pgtype.NegativeInfinity, Status: pgtype.Present},
128
129 &pgtype.Numeric{Int: big.NewInt(0), Exp: 0, Status: pgtype.Present},
130 &pgtype.Numeric{Int: big.NewInt(1), Exp: 0, Status: pgtype.Present},
131 &pgtype.Numeric{Int: big.NewInt(-1), Exp: 0, Status: pgtype.Present},
132 &pgtype.Numeric{Int: big.NewInt(1), Exp: 6, Status: pgtype.Present},
133
134
135 &pgtype.Numeric{Int: big.NewInt(10000000), Exp: -1, Status: pgtype.Present},
136 &pgtype.Numeric{Int: big.NewInt(10000000), Exp: -2, Status: pgtype.Present},
137 &pgtype.Numeric{Int: big.NewInt(10000000), Exp: -3, Status: pgtype.Present},
138 &pgtype.Numeric{Int: big.NewInt(10000000), Exp: -4, Status: pgtype.Present},
139 &pgtype.Numeric{Int: big.NewInt(10000000), Exp: -5, Status: pgtype.Present},
140 &pgtype.Numeric{Int: big.NewInt(10000000), Exp: -6, Status: pgtype.Present},
141
142 &pgtype.Numeric{Int: big.NewInt(314), Exp: -2, Status: pgtype.Present},
143 &pgtype.Numeric{Int: big.NewInt(123), Exp: -7, Status: pgtype.Present},
144 &pgtype.Numeric{Int: big.NewInt(123), Exp: -8, Status: pgtype.Present},
145 &pgtype.Numeric{Int: big.NewInt(123), Exp: -9, Status: pgtype.Present},
146 &pgtype.Numeric{Int: big.NewInt(123), Exp: -1500, Status: pgtype.Present},
147 &pgtype.Numeric{Int: mustParseBigInt(t, "2437"), Exp: 23790, Status: pgtype.Present},
148 &pgtype.Numeric{Int: mustParseBigInt(t, "243723409723490243842378942378901237502734019231380123"), Exp: 23790, Status: pgtype.Present},
149 &pgtype.Numeric{Int: mustParseBigInt(t, "43723409723490243842378942378901237502734019231380123"), Exp: 80, Status: pgtype.Present},
150 &pgtype.Numeric{Int: mustParseBigInt(t, "3723409723490243842378942378901237502734019231380123"), Exp: 81, Status: pgtype.Present},
151 &pgtype.Numeric{Int: mustParseBigInt(t, "723409723490243842378942378901237502734019231380123"), Exp: 82, Status: pgtype.Present},
152 &pgtype.Numeric{Int: mustParseBigInt(t, "23409723490243842378942378901237502734019231380123"), Exp: 83, Status: pgtype.Present},
153 &pgtype.Numeric{Int: mustParseBigInt(t, "3409723490243842378942378901237502734019231380123"), Exp: 84, Status: pgtype.Present},
154 &pgtype.Numeric{Int: mustParseBigInt(t, "913423409823409243892349028349023482934092340892390101"), Exp: -14021, Status: pgtype.Present},
155 &pgtype.Numeric{Int: mustParseBigInt(t, "13423409823409243892349028349023482934092340892390101"), Exp: -90, Status: pgtype.Present},
156 &pgtype.Numeric{Int: mustParseBigInt(t, "3423409823409243892349028349023482934092340892390101"), Exp: -91, Status: pgtype.Present},
157 &pgtype.Numeric{Int: mustParseBigInt(t, "423409823409243892349028349023482934092340892390101"), Exp: -92, Status: pgtype.Present},
158 &pgtype.Numeric{Int: mustParseBigInt(t, "23409823409243892349028349023482934092340892390101"), Exp: -93, Status: pgtype.Present},
159 &pgtype.Numeric{Int: mustParseBigInt(t, "3409823409243892349028349023482934092340892390101"), Exp: -94, Status: pgtype.Present},
160
161 longestNumeric,
162
163 &pgtype.Numeric{Status: pgtype.Null},
164 }, func(aa, bb interface{}) bool {
165 a := aa.(pgtype.Numeric)
166 b := bb.(pgtype.Numeric)
167
168 return numericEqual(&a, &b)
169 })
170
171 }
172
173 func TestNumericTranscodeFuzz(t *testing.T) {
174 r := rand.New(rand.NewSource(0))
175 max := &big.Int{}
176 max.SetString("9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 10)
177
178 values := make([]interface{}, 0, 2000)
179 for i := 0; i < 10; i++ {
180 for j := -50; j < 50; j++ {
181 num := (&big.Int{}).Rand(r, max)
182 negNum := &big.Int{}
183 negNum.Neg(num)
184 values = append(values, &pgtype.Numeric{Int: num, Exp: int32(j), Status: pgtype.Present})
185 values = append(values, &pgtype.Numeric{Int: negNum, Exp: int32(j), Status: pgtype.Present})
186 }
187 }
188
189 testutil.TestSuccessfulTranscodeEqFunc(t, "numeric", values,
190 func(aa, bb interface{}) bool {
191 a := aa.(pgtype.Numeric)
192 b := bb.(pgtype.Numeric)
193
194 return numericNormalizedEqual(&a, &b)
195 })
196 }
197
198 func TestNumericSet(t *testing.T) {
199 successfulTests := []struct {
200 source interface{}
201 result *pgtype.Numeric
202 }{
203 {source: float32(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
204 {source: float32(math.Copysign(0, -1)), result: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present}},
205 {source: float64(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
206 {source: float64(math.Copysign(0, -1)), result: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present}},
207 {source: int8(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
208 {source: int16(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
209 {source: int32(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
210 {source: int64(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
211 {source: int8(-1), result: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}},
212 {source: int16(-1), result: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}},
213 {source: int32(-1), result: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}},
214 {source: int64(-1), result: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}},
215 {source: uint8(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
216 {source: uint16(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
217 {source: uint32(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
218 {source: uint64(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
219 {source: "1", result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
220 {source: _int8(1), result: &pgtype.Numeric{Int: big.NewInt(1), Status: pgtype.Present}},
221 {source: float64(1000), result: &pgtype.Numeric{Int: big.NewInt(1), Exp: 3, Status: pgtype.Present}},
222 {source: float64(1234), result: &pgtype.Numeric{Int: big.NewInt(1234), Exp: 0, Status: pgtype.Present}},
223 {source: float64(12345678900), result: &pgtype.Numeric{Int: big.NewInt(123456789), Exp: 2, Status: pgtype.Present}},
224 {source: float64(12345.678901), result: &pgtype.Numeric{Int: big.NewInt(12345678901), Exp: -6, Status: pgtype.Present}},
225 {source: math.NaN(), result: &pgtype.Numeric{Int: nil, Exp: 0, Status: pgtype.Present, NaN: true}},
226 {source: float32(math.NaN()), result: &pgtype.Numeric{Int: nil, Exp: 0, Status: pgtype.Present, NaN: true}},
227 {source: pgtype.Infinity, result: &pgtype.Numeric{InfinityModifier: pgtype.Infinity, Status: pgtype.Present}},
228 {source: math.Inf(1), result: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}},
229 {source: float32(math.Inf(1)), result: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}},
230 {source: pgtype.NegativeInfinity, result: &pgtype.Numeric{InfinityModifier: pgtype.NegativeInfinity, Status: pgtype.Present}},
231 {source: math.Inf(-1), result: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}},
232 {source: float32(math.Inf(1)), result: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}},
233 }
234
235 for i, tt := range successfulTests {
236 r := &pgtype.Numeric{}
237 err := r.Set(tt.source)
238 if err != nil {
239 t.Errorf("%d: %v", i, err)
240 }
241
242 if !numericEqual(r, tt.result) {
243 t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r)
244 }
245 }
246 }
247
248 func TestNumericAssignTo(t *testing.T) {
249 var i8 int8
250 var i16 int16
251 var i32 int32
252 var i64 int64
253 var i int
254 var ui8 uint8
255 var ui16 uint16
256 var ui32 uint32
257 var ui64 uint64
258 var ui uint
259 var pi8 *int8
260 var _i8 _int8
261 var _pi8 *_int8
262 var f32 float32
263 var f64 float64
264 var pf32 *float32
265 var pf64 *float64
266 var br = new(big.Rat)
267
268 simpleTests := []struct {
269 src *pgtype.Numeric
270 dst interface{}
271 expected interface{}
272 }{
273 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &f32, expected: float32(42)},
274 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &f64, expected: float64(42)},
275 {src: &pgtype.Numeric{Int: big.NewInt(42), Exp: -1, Status: pgtype.Present}, dst: &f32, expected: float32(4.2)},
276 {src: &pgtype.Numeric{Int: big.NewInt(42), Exp: -1, Status: pgtype.Present}, dst: &f64, expected: float64(4.2)},
277 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i16, expected: int16(42)},
278 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i32, expected: int32(42)},
279 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i64, expected: int64(42)},
280 {src: &pgtype.Numeric{Int: big.NewInt(42), Exp: 3, Status: pgtype.Present}, dst: &i64, expected: int64(42000)},
281 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &i, expected: int(42)},
282 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui8, expected: uint8(42)},
283 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui16, expected: uint16(42)},
284 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui32, expected: uint32(42)},
285 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui64, expected: uint64(42)},
286 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &ui, expected: uint(42)},
287 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &_i8, expected: _int8(42)},
288 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: &pi8, expected: ((*int8)(nil))},
289 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: &_pi8, expected: ((*_int8)(nil))},
290 {src: &pgtype.Numeric{Int: big.NewInt(1006), Exp: -2, Status: pgtype.Present}, dst: &f64, expected: float64(10.06)},
291 {src: &pgtype.Numeric{Status: pgtype.Present, NaN: true}, dst: &f64, expected: math.NaN()},
292 {src: &pgtype.Numeric{Status: pgtype.Present, NaN: true}, dst: &f32, expected: float32(math.NaN())},
293 {src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: &f64, expected: math.Inf(1)},
294 {src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: &f32, expected: float32(math.Inf(1))},
295 {src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f64, expected: math.Inf(-1)},
296 {src: &pgtype.Numeric{Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: &f32, expected: float32(math.Inf(-1))},
297 {src: &pgtype.Numeric{Int: big.NewInt(-1023), Exp: -2, Status: pgtype.Present}, dst: br, expected: big.NewRat(-1023, 100)},
298 {src: &pgtype.Numeric{Int: big.NewInt(-1023), Exp: 2, Status: pgtype.Present}, dst: br, expected: big.NewRat(-102300, 1)},
299 {src: &pgtype.Numeric{Int: big.NewInt(23), Exp: 0, Status: pgtype.Present}, dst: br, expected: big.NewRat(23, 1)},
300 }
301
302 for i, tt := range simpleTests {
303 err := tt.src.AssignTo(tt.dst)
304 if err != nil {
305 t.Errorf("%d: %v", i, err)
306 }
307
308 dst := reflect.ValueOf(tt.dst).Elem().Interface()
309 switch dstTyped := dst.(type) {
310 case float32:
311 nanExpected := math.IsNaN(float64(tt.expected.(float32)))
312 if nanExpected && !math.IsNaN(float64(dstTyped)) {
313 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
314 } else if !nanExpected && dst != tt.expected {
315 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
316 }
317 case float64:
318 nanExpected := math.IsNaN(tt.expected.(float64))
319 if nanExpected && !math.IsNaN(dstTyped) {
320 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
321 } else if !nanExpected && dst != tt.expected {
322 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
323 }
324 case big.Rat:
325 if (&dstTyped).Cmp(tt.expected.(*big.Rat)) != 0 {
326 t.Errorf("%d: expected %v to assign %v, but result was %v",
327 i, tt.src, tt.expected, dst)
328 }
329 default:
330 if dst != tt.expected {
331 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
332 }
333 }
334 }
335
336 pointerAllocTests := []struct {
337 src *pgtype.Numeric
338 dst interface{}
339 expected interface{}
340 }{
341 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &pf32, expected: float32(42)},
342 {src: &pgtype.Numeric{Int: big.NewInt(42), Status: pgtype.Present}, dst: &pf64, expected: float64(42)},
343 }
344
345 for i, tt := range pointerAllocTests {
346 err := tt.src.AssignTo(tt.dst)
347 if err != nil {
348 t.Errorf("%d: %v", i, err)
349 }
350
351 if dst := reflect.ValueOf(tt.dst).Elem().Elem().Interface(); dst != tt.expected {
352 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst)
353 }
354 }
355
356 errorTests := []struct {
357 src *pgtype.Numeric
358 dst interface{}
359 }{
360 {src: &pgtype.Numeric{Int: big.NewInt(150), Status: pgtype.Present}, dst: &i8},
361 {src: &pgtype.Numeric{Int: big.NewInt(40000), Status: pgtype.Present}, dst: &i16},
362 {src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui8},
363 {src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui16},
364 {src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui32},
365 {src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui64},
366 {src: &pgtype.Numeric{Int: big.NewInt(-1), Status: pgtype.Present}, dst: &ui},
367 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: &i32},
368 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Null}, dst: br},
369 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, NaN: true}, dst: br},
370 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, InfinityModifier: pgtype.Infinity}, dst: br},
371 {src: &pgtype.Numeric{Int: big.NewInt(0), Status: pgtype.Present, InfinityModifier: pgtype.NegativeInfinity}, dst: br},
372 }
373
374 for i, tt := range errorTests {
375 err := tt.src.AssignTo(tt.dst)
376 if err == nil {
377 t.Errorf("%d: expected error but none was returned (%v -> %v)", i, tt.src, tt.dst)
378 }
379 }
380 }
381
382 func TestNumericEncodeDecodeBinary(t *testing.T) {
383 ci := pgtype.NewConnInfo()
384 tests := []interface{}{
385 123,
386 0.000012345,
387 1.00002345,
388 math.NaN(),
389 float32(math.NaN()),
390 math.Inf(1),
391 float32(math.Inf(1)),
392 math.Inf(-1),
393 float32(math.Inf(-1)),
394 }
395
396 for i, tt := range tests {
397 toString := func(n *pgtype.Numeric) string {
398 ci := pgtype.NewConnInfo()
399 text, err := n.EncodeText(ci, nil)
400 if err != nil {
401 t.Errorf("%d (EncodeText): %v", i, err)
402 }
403 return string(text)
404 }
405 numeric := &pgtype.Numeric{}
406 numeric.Set(tt)
407
408 encoded, err := numeric.EncodeBinary(ci, nil)
409 if err != nil {
410 t.Errorf("%d (EncodeBinary): %v", i, err)
411 }
412 decoded := &pgtype.Numeric{}
413 err = decoded.DecodeBinary(ci, encoded)
414 if err != nil {
415 t.Errorf("%d (DecodeBinary): %v", i, err)
416 }
417
418 text0 := toString(numeric)
419 text1 := toString(decoded)
420
421 if text0 != text1 {
422 t.Errorf("%d: expected %v to equal to %v, but doesn't", i, text0, text1)
423 }
424 }
425 }
426
View as plain text