jackc / pgx

PostgreSQL driver and toolkit for Go
MIT License
10.38k stars 820 forks source link

RowToStructByName does not abide by `db:"-"` ignore field tag. #1712

Open tamis-laan opened 1 year ago

tamis-laan commented 1 year ago

Describe the bug When using RowToStructByName (https://pkg.go.dev/github.com/jackc/pgx/v5#RowToStructByName) and the struct tag db:"-" on a field according to the documentation the field should be ignored. Instead pgx produces the error:

struct doesn't have corresponding row field <field to ignore>

To Reproduce

type MyStruct struct {
        Description string `db:"description"`
    Secret string `db:"-"`
}
rows, _ := pool.Query(context.Background(), `SELECT * FROM mytable`)
responses, _ := pgx.CollectRows(rows, pgx.RowToStructByName[MyStruct])

Expected behavior I would expect the Secret field to be ignored.

Actual behavior The secret field is not ignored and instead an error is produced saying: struct doesn't have corresponding row field secret

Version

jackc commented 1 year ago

Try latest version of pgx. Works for me.

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/jackc/pgx/v5"
)

type MyStruct struct {
    Description string `db:"description"`
    Secret      string `db:"-"`
}

func main() {
    ctx := context.Background()

    conn, err := pgx.Connect(ctx, os.Getenv("DATABASE_URL"))
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close(ctx)

    rows, _ := conn.Query(context.Background(), `SELECT 'foo' as description`)
    responses, err := pgx.CollectRows(rows, pgx.RowToStructByName[MyStruct])
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(responses)
}
jack@glados ~/dev/pgx_issues/pgx-1712 ±master⚡ » go run .
[{foo }]
tamis-laan commented 1 year ago

hm... strange, I still have this problem after upgrading: go: upgraded github.com/jackc/pgx/v5 v5.3.1 => v5.4.3

Does it still work with SELECT *? Here you are explicitly querying only foo.

urjitbhatia commented 1 month ago

hm... strange, I still have this problem after upgrading: go: upgraded github.com/jackc/pgx/v5 v5.3.1 => v5.4.3

Does it still work with SELECT *? Here you are explicitly querying only foo.

Running into the same thing: I'd expect it work for the select * case

jackc commented 1 month ago

I just reread this thread and I think I know what is happening. There is an ambiguity regarding what ignore means. Normally, there must be an exact match between the fields in the struct and the columns in the result set. If there is an extra column in the result set that is not in the struct, then that is an error. Using db:"-" marks the struct field to be ignored. But it does nothing to the result set. So the ignored field is actually causing the error. In essence, the struct doesn't have that field because it is ignored, so there is no place for the result column to go.