mirror of https://github.com/jackc/pgx.git
91 lines
2.0 KiB
Go
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
|
|
}
|