jackc / jackc/pgx

pgtype: driver.Valuer support for Array or Map

Open
#1,662 12 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
14.3k
Forks
1.1k
Avg merge
6d 9h
Merged PRs (30d)
11

Description

**Is your feature request related to a problem? Please describe.**

We use `stdlib` pgx in our project. For unit tests we use [sqlmock](https://github.com/DATA-DOG/go-sqlmock) for unit tests. We want to migrate to `v5` and the related `v5/pgtype` sub-package from the stand-alone `pgtype` package.

sqlmock doesn't like slice types such as `[]int`, `[]string` etc. As a solution we have some wrapper types like:

```
type StringArray []string

// Scan implements the [database/sql.Scanner] interface.
func (s *StringArray) Scan(src any) error {
array := new(pgtype.TextArray)
if err := array.Scan(src); err != nil {
return err
}
if err := array.AssignTo(s); err != nil {
return err
}
return nil
}

// Value implements the [database/sql/driver.Valuer] interface.
func (s StringArray) Value() (driver.Value, error) {
if len(s) == 0 {
return nil, nil
}

array := pgtype.TextArray{}
if err := array.Set(s); err != nil {
return nil, err
}

return array.Value()
}
```

I'm aware that `pgx/stdlib` support direct passing of a slice as parameter value, but `sqlmock` does not. Hence we need to implement the `driver.Valuer` interface like above. The new [`pgtype.Array`](https://pkg.go.dev/github.com/jackc/pgx/v5@v5.4.1/pgtype#Array) does not implement `driver.Valuer` anymore.

I've read the conversation in https://github.com/jackc/pgx/issues/1458. It pointed out, the `Map` type can be used for scanning into arrays, which is fine for that case.

**Describe the solution you'd like**
It would be awesome if one of the following were to be implemented:

1. `pgtype.Array` gets a `Value()` method.
2. `pgtype.Map` gets a `SQLValuer()` or similar method.

**Describe alternatives you've considered**

I'm aware this is not a `pgx` issue necessarily, as we are the ones swapping to another (mock) driver. `sqlmock` provides the possibility to use a [`driver.ValueConverter`](https://pkg.go.dev/github.com/DATA-DOG/go-sqlmock#ValueConverterOption) instead. As some discussions over there suggest, the driver might already export a `ValueConverter` which then can be used. However, I was not able to find anything in the pgx project.

1. If there is a `ValueConverter` somewhere and I missed it, I will gladly use it.
2 Implement my own `ValueConverter` as a last resort.

**Additional context**
none

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No source file or test is named. Start by reading the pgtype.Array and pgtype.Map APIs, then compare them with database/sql/driver.Valuer and the stdlib conversion path. Done means a supported way to pass array or map values through sqlmock, with tests covering the relevant parameter conversions.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, postgresql, sql
Domain
backend, databases
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.