pgx/example_value_transcoder_te...

91 lines
2.0 KiB
Go

package pgx_test
import (
"fmt"
"github.com/jackc/pgx"
"regexp"
"strconv"
)
const (
pointOid = 600
)
var pointRegexp *regexp.Regexp = regexp.MustCompile(`^\((.*),(.*)\)$`)
type Point struct {
x float64
y float64
}
func (p Point) String() string {
return fmt.Sprintf("%v, %v", p.x, p.y)
}
func Example_customValueTranscoder() {
pgx.ValueTranscoders[pointOid] = &pgx.ValueTranscoder{
Decode: func(qr *pgx.QueryResult, fd *pgx.FieldDescription, size int32) interface{} {
return decodePoint(qr, fd, size)
},
EncodeTo: encodePoint}
conn, err := pgx.Connect(*defaultConnConfig)
if err != nil {
fmt.Printf("Unable to establish connection: %v", err)
return
}
v, _ := conn.SelectValue("select point(1.5,2.5)")
fmt.Println(v)
// Output:
// 1.5, 2.5
}
func decodePoint(qr *pgx.QueryResult, fd *pgx.FieldDescription, size int32) Point {
var p Point
if fd.DataType != pointOid {
qr.Fatal(pgx.ProtocolError(fmt.Sprintf("Tried to read point but received: %v", fd.DataType)))
return p
}
switch fd.FormatCode {
case pgx.TextFormatCode:
s := qr.MsgReader().ReadString(size)
match := pointRegexp.FindStringSubmatch(s)
if match == nil {
qr.Fatal(pgx.ProtocolError(fmt.Sprintf("Received invalid point: %v", s)))
return p
}
var err error
p.x, err = strconv.ParseFloat(match[1], 64)
if err != nil {
qr.Fatal(pgx.ProtocolError(fmt.Sprintf("Received invalid point: %v", s)))
return p
}
p.y, err = strconv.ParseFloat(match[2], 64)
if err != nil {
qr.Fatal(pgx.ProtocolError(fmt.Sprintf("Received invalid point: %v", s)))
return p
}
return p
default:
qr.Fatal(pgx.ProtocolError(fmt.Sprintf("Unknown field description format code: %v", fd.FormatCode)))
return p
}
}
func encodePoint(w *pgx.WriteBuf, value interface{}) error {
p, ok := value.(Point)
if !ok {
return fmt.Errorf("Expected Point, received %T", value)
}
s := fmt.Sprintf("point(%v,%v)", p.x, p.y)
w.WriteInt32(int32(len(s)))
w.WriteBytes([]byte(s))
return nil
}