Skip to content

Instantly share code, notes, and snippets.

@andyollylarkin
Created April 15, 2023 21:41
Show Gist options
  • Save andyollylarkin/ef868da6d4c3b1b0d8f46a864972c539 to your computer and use it in GitHub Desktop.
Save andyollylarkin/ef868da6d4c3b1b0d8f46a864972c539 to your computer and use it in GitHub Desktop.
jackx pgx composite db type
package main
import (
"context"
"database/sql/driver"
"fmt"
"log"
"strconv"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
)
type City struct {
Id int
Coordinates Coord
}
type Coord struct {
xpos int
ypos int
}
type encodePlanCoord struct{}
func (p *encodePlanCoord) Encode(value any, buf []byte) (newBuf []byte, err error) {
var val string
if v, ok := value.(Coord); ok {
val = fmt.Sprintf(`(%d, %d)`, v.xpos, v.ypos)
} else {
val = `(300,300)`
}
return []byte(val), nil
}
// FormatSupported returns true if the format is supported.
func (c *Coord) FormatSupported(_ int16) bool {
return true
}
// PreferredFormat returns the preferred format.
func (c *Coord) PreferredFormat() int16 {
return 0
}
// PlanEncode returns an EncodePlan for encoding value into PostgreSQL format for oid and format. If no plan can be
// found then nil is returned.
func (c *Coord) PlanEncode(m *pgtype.Map, oid uint32, format int16, value any) pgtype.EncodePlan {
return &encodePlanCoord{}
}
// PlanScan returns a ScanPlan for scanning a PostgreSQL value into a destination with the same type as target. If
// no plan can be found then nil is returned.
func (c *Coord) PlanScan(m *pgtype.Map, oid uint32, format int16, target any) pgtype.ScanPlan {
panic("not implemented") // TODO: Implement
}
// DecodeDatabaseSQLValue returns src decoded into a value compatible with the sql.Scanner interface.
func (c *Coord) DecodeDatabaseSQLValue(m *pgtype.Map, oid uint32, format int16, src []byte) (driver.Value, error) {
panic("not implemented") // TODO: Implement
}
// DecodeValue returns src decoded into its default format.
func (c *Coord) DecodeValue(m *pgtype.Map, oid uint32, format int16, src []byte) (any, error) {
panic("not implemented") // TODO: Implement
}
func (c *Coord) Scan(value interface{}) error {
if v, ok := value.(string); ok {
v1, _ := strconv.Atoi(string(v[1]))
v2, _ := strconv.Atoi(string(v[3]))
c.xpos = v1
c.ypos = v2
}
return nil
}
func main() {
conn, err := pgx.Connect(context.Background(), "postgresql://postgres:[email protected]:5432/postgres?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer conn.Close(context.Background())
err = conn.Ping(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Println("Connection successfull")
var c City
err = conn.QueryRow(context.Background(), `SELECT id,location FROM cities;`).Scan(&c.Id, &c.Coordinates)
if err != nil {
log.Fatal(err)
}
c.Coordinates.xpos = 10
c.Coordinates.ypos = 20
conn.TypeMap().RegisterType(&pgtype.Type{Name: "coord", OID: 16649, Codec: &Coord{}})
_, err = conn.Exec(context.Background(), `INSERT INTO cities(id,location) VALUES(60,$1)`, c.Coordinates)
if err != nil {
log.Fatal(err)
}
}
@andyollylarkin
Copy link
Author

DB

CREATE TYPE coord AS (
	xpos int,
	ypos int
);


CREATE TABLE cities (
	id serial PRIMARY KEY,
	LOCATION coord
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment