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 }