georgysavva / scany

Library for scanning data from a database into Go structs and more
MIT License
1.29k stars 68 forks source link

Custom enums #59

Closed dclipca closed 3 years ago

dclipca commented 3 years ago

DBeaver type representation


type Film struct {
    ID           string
    Name         string
    ReleaseYear  int
    Genres       []string
    CoverImageId string
}

func GetFilms() ([]*Film, error) {
    ctx := context.Background()
    var films []*Film
    err := pgxscan.Select(ctx, DBConn, &films, `SELECT * FROM film;`)
    if err != nil {
        return films, err
    }
    return films, nil
}

Error:

{
    "error": "scany: scan row into struct fields: can't scan into dest[2]: unknown oid 16397 cannot be scanned into *[]string"
}

The problem is clearly that scany doesn't work with custom enums. How to make it work like in https://github.com/jackc/pgx/blob/master/example_custom_type_test.go?

georgysavva commented 3 years ago

Hello! scany just passes your field to the pgx library, it does by taking a reference: &Genres, so pgx receives *[]string type. It's your responsibility to use a type that pgx library can handle. See https://pkg.go.dev/github.com/georgysavva/scany@v0.2.9/dbscan#hdr-NULLs_and_custom_types and https://pkg.go.dev/github.com/georgysavva/scany@v0.2.9/pgxscan#hdr-Note_about_pgx_custom_types

Basically you need to use a type that implements sql.Scanner interface or special pgx Decoder interface as in the example you mentioned. Something like that:

type CustomEnum []string

func (ce *CustomEnum) Scan(b []byte) error {
     ...
}

type Film struct {
    ID           string
    Name         string
    ReleaseYear  int
    Genres       CustomEnum
    CoverImageId string
}
dclipca commented 3 years ago

Thank you for replying! Will try this.

dclipca commented 3 years ago

I forgot to add that it worked like a charm. Thanks again!