lib / pq

Pure Go Postgres driver for database/sql
https://pkg.go.dev/github.com/lib/pq
MIT License
9.02k stars 910 forks source link

export ParseArray #898

Open bleakley opened 4 years ago

bleakley commented 4 years ago

Fixes https://github.com/lib/pq/issues/602

This function is needed for writing custom Scan functions to parse a JSONB[] column.

cbandy commented 4 years ago

Can you give an example of what you're trying to scan into? pq.Array() can be used if you are scanning into an array or slice.

bleakley commented 4 years ago

What I'm trying to do is scan an array of arbitrary types. I'm representing it in the DB as JSONB[] column because it might be strings or floats or another type, so each element is a JSON scalar in an array.

cbandy commented 4 years ago

When array support was added in #466, the parseArray implementation was the least desired aspect. I don't expect we should commit to it further by exporting it as-is.

The unexported parseArray function returns a slice of byte slices. You can achieve a similar result with the exported Array function and a small Scanner implementation. For example,

type Bytes []byte
func (b *Bytes) Scan(src interface{}) error {
  *b = append(*b, src.([]byte)...)
  return nil
}

var result []Bytes
err := db.QueryRow(`SELECT ARRAY['{}', '"a"', '9']::jsonb[]`).Scan(pq.Array(&result))

In your case, something like json.RawMessage might be more appropriate?

type JSONB json.RawMessage
func (j *JSONB) Scan(src interface{}) error {
  *j = append(*j, src.([]byte)...)
  return nil
}

var result []JSONB
err := db.QueryRow(`SELECT ARRAY['{}', '"a"', '9']::jsonb[]`).Scan(pq.Array(&result))

Keep in mind that all PostgreSQL arrays can contain nulls... You might be happiest with the built-in types:

var result []sql.NullString
err := db.QueryRow(`SELECT ARRAY['{}', '"a"', '9', NULL]::jsonb[]`).Scan(pq.Array(&result))