forked from jackc/pgtype
-
Notifications
You must be signed in to change notification settings - Fork 0
/
custom_composite_test.go
87 lines (68 loc) · 2.07 KB
/
custom_composite_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package pgtype_test
import (
"context"
"fmt"
"os"
"github.com/jackc/pgtype"
pgx "github.com/jackc/pgx/v4"
errors "golang.org/x/xerrors"
)
type MyType struct {
a int32 // NULL will cause decoding error
b *string // there can be NULL in this position in SQL
}
func (dst *MyType) DecodeBinary(ci *pgtype.ConnInfo, src []byte) error {
if src == nil {
return errors.New("NULL values can't be decoded. Scan into a &*MyType to handle NULLs")
}
if err := (pgtype.CompositeFields{&dst.a, &dst.b}).DecodeBinary(ci, src); err != nil {
return err
}
return nil
}
func (src MyType) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) (newBuf []byte, err error) {
a := pgtype.Int4{src.a, pgtype.Present}
var b pgtype.Text
if src.b != nil {
b = pgtype.Text{*src.b, pgtype.Present}
} else {
b = pgtype.Text{Status: pgtype.Null}
}
return (pgtype.CompositeFields{&a, &b}).EncodeBinary(ci, buf)
}
func ptrS(s string) *string {
return &s
}
func E(err error) {
if err != nil {
panic(err)
}
}
// ExampleCustomCompositeTypes demonstrates how support for custom types mappable to SQL
// composites can be added.
func Example_customCompositeTypes() {
conn, err := pgx.Connect(context.Background(), os.Getenv("PGX_TEST_DATABASE"))
E(err)
defer conn.Close(context.Background())
_, err = conn.Exec(context.Background(), `drop type if exists mytype;
create type mytype as (
a int4,
b text
);`)
E(err)
defer conn.Exec(context.Background(), "drop type mytype")
var result *MyType
// Demonstrates both passing and reading back composite values
err = conn.QueryRow(context.Background(), "select $1::mytype",
pgx.QueryResultFormats{pgx.BinaryFormatCode}, MyType{1, ptrS("foo")}).
Scan(&result)
E(err)
fmt.Printf("First row: a=%d b=%s\n", result.a, *result.b)
// Because we scan into &*MyType, NULLs are handled generically by assigning nil to result
err = conn.QueryRow(context.Background(), "select NULL::mytype", pgx.QueryResultFormats{pgx.BinaryFormatCode}).Scan(&result)
E(err)
fmt.Printf("Second row: %v\n", result)
// Output:
// First row: a=1 b=foo
// Second row: <nil>
}