mirror of
https://github.com/jackc/pgx.git
synced 2025-05-31 11:42:24 +00:00
Add example custom type
This commit is contained in:
parent
88d5a25fc4
commit
5dace165f5
@ -145,7 +145,7 @@ added for additional types like point, hstore, numeric, etc. that do not have
|
|||||||
direct mappings in Go by the types implementing Scanner, TextEncoder, and
|
direct mappings in Go by the types implementing Scanner, TextEncoder, and
|
||||||
optionally BinaryEncoder. To enable binary format for custom types, a prepared
|
optionally BinaryEncoder. To enable binary format for custom types, a prepared
|
||||||
statement must be used and the field description of the returned field must have
|
statement must be used and the field description of the returned field must have
|
||||||
FormatCode set to BinaryFormatCode. See example_value_transcoder_test.go for an
|
FormatCode set to BinaryFormatCode. See example_custom_type_test.go for an
|
||||||
example of a custom type for the PostgreSQL point type.
|
example of a custom type for the PostgreSQL point type.
|
||||||
|
|
||||||
### Null Mapping
|
### Null Mapping
|
||||||
|
99
example_custom_type_test.go
Normal file
99
example_custom_type_test.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package pgx_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jackc/pgx"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pointRegexp *regexp.Regexp = regexp.MustCompile(`^\((.*),(.*)\)$`)
|
||||||
|
|
||||||
|
// NullPoint represents a point that may be null.
|
||||||
|
//
|
||||||
|
// If Valid is false then the value is NULL.
|
||||||
|
type NullPoint struct {
|
||||||
|
X, Y float64 // Coordinates of point
|
||||||
|
Valid bool // Valid is true if not NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointOid = 600
|
||||||
|
|
||||||
|
func (p *NullPoint) Scan(vr *pgx.ValueReader) error {
|
||||||
|
if vr.Type().DataType != pointOid {
|
||||||
|
return pgx.SerializationError(fmt.Sprintf("NullPoint.Scan cannot decode OID %d", vr.Type().DataType))
|
||||||
|
}
|
||||||
|
|
||||||
|
if vr.Len() == -1 {
|
||||||
|
p.X, p.Y, p.Valid = 0, 0, false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch vr.Type().FormatCode {
|
||||||
|
case pgx.TextFormatCode:
|
||||||
|
s := vr.ReadString(vr.Len())
|
||||||
|
match := pointRegexp.FindStringSubmatch(s)
|
||||||
|
if match == nil {
|
||||||
|
return pgx.SerializationError(fmt.Sprintf("Received invalid point: %v", s))
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
p.X, err = strconv.ParseFloat(match[1], 64)
|
||||||
|
if err != nil {
|
||||||
|
return pgx.SerializationError(fmt.Sprintf("Received invalid point: %v", s))
|
||||||
|
}
|
||||||
|
p.Y, err = strconv.ParseFloat(match[2], 64)
|
||||||
|
if err != nil {
|
||||||
|
return pgx.SerializationError(fmt.Sprintf("Received invalid point: %v", s))
|
||||||
|
}
|
||||||
|
case pgx.BinaryFormatCode:
|
||||||
|
return errors.New("binary format not implemented")
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown format %v", vr.Type().FormatCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Valid = true
|
||||||
|
return vr.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p NullPoint) EncodeText() (string, byte, error) {
|
||||||
|
if p.Valid {
|
||||||
|
return fmt.Sprintf("point(%v,%v)", p.X, p.Y), pgx.SafeText, nil
|
||||||
|
} else {
|
||||||
|
return "", pgx.NullText, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p NullPoint) String() string {
|
||||||
|
if p.Valid {
|
||||||
|
return fmt.Sprintf("%v, %v", p.X, p.Y)
|
||||||
|
}
|
||||||
|
return "null point"
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_CustomType() {
|
||||||
|
conn, err := pgx.Connect(*defaultConnConfig)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to establish connection: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var p NullPoint
|
||||||
|
err = conn.QueryRow("select null::point").Scan(&p)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(p)
|
||||||
|
|
||||||
|
err = conn.QueryRow("select point(1.5,2.5)").Scan(&p)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(p)
|
||||||
|
// Output:
|
||||||
|
// null point
|
||||||
|
// 1.5, 2.5
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user