lib/pq — pull request #86 by chrisfarms (2013-03-08 19:59:19+00:00)
Title: Proposal for an extensible "codec" system for managing composite/array/custom types.

Proposal for an extensible "codec" system for managing custom pg_types by oid.

* Ability to register Decoder or Encoder funcs globally for all
connections or build a set (Codec) of funcs that can be
referenced in the connection string to Open()
* **go1.1 only (relies on fix to goissue3640)!** (lib/pq will need a go1.1 branch)
* Existing (pre-registered) types cannot be overriden by design
for consistancy - might change this though.

Example:

```Go
// func that takes postgres bytes and turns into a []int
func int4SliceDecoder(b []byte) (driver.Value, error) {
ca := make([]int, 0)
for _, s := range strings.Split(string(b), ",") {
ca = append(ca, s)
}
return ca, nil
}

// func that takes []int and returns raw []byte for postgres
func int4SliceEncoder(v interface{}) (driver.Value, error) {
switch x := v.(type) {
case []int:
s := make([]string, len(x))
for i, n := range x {
s[i] = strconv.Itoa(n)
}
return []byte(fmt.Sprintf(`{%s}`, strings.Join(s, ","))), nil
}
panic("unexpected type")
}

// create and register a new set of codecs
c := pq.NewCodec()
c.RegisterDecoder(1007, int4SliceDecoder) // 1007 is type oid
c.RegisterEncoder(1007, int4SliceEncoder)
pq.RegisterCodec("mydec", c)

// get a DB that will use the codec
db := sql.Open("postgres", "codec=mydec")

// use our new array type
arg := make([]int,1)
arg[0] = 1
rs,_ := db.Query(`SELECT ARRAY[10,20,30]
WHERE ARRAY[1] = $1`, arg)
for rs.Next() {
var res []int
rs.Scan(&res)
// res[0] = 10
// res[1] = 20
// res[2] = 30
}

```

You don't _have_ to create a whole codec. And you don't _have_ to write both an encoder and decoder for your type. You may just add to the default global codec.

```Go
pq.RegisterDecoder(oid, func(b []byte) (driver.Value,error){
return b, nil
})
```