georgysavva / scany

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

Inconsistent behavior between Get and Select #126

Closed steeling closed 6 months ago

steeling commented 9 months ago

Select requires that the database schema does not have extra rows that are not present in the struct, whereas Get is more lenient.

Note: I'm a fan of the leniency provided by get, or there could be some global option to enable/disable the behavior.

To repro:

CREATE TABLE my_table (
  id STRING PRIMARY KEY,
  data string
);
INSERT INTO my_table (id, data) VALUES('id1', 'hello world');
type MyStruct struct {
   ID string `db:"id"`
}

func main() {
  ...
  err := pgxscan.Get(ctx, db, &MyStruct{}, `SELECT * FROM my_table WHERE id = 'id1'`)
  fmt.Println(err) // no error
  vals := []*MyStruct{}
  err = pgxscan.Select(ctx, db, &vals, `SELECT * FROM my_table`)
  fmt.Println(err) // this has an error
}

Disclaimer: I didn't run the above code, so it may need some tweaks.

I'm using scany v2.1.0

georgysavva commented 9 months ago

Hi, both methods should return an error. Unfortunately, I wasn't able to reproduce the error on the latest scary version. Here is the code I used:

func TestIssue(t *testing.T) {
    t.Parallel()

    type MyStruct struct {
        ID string `db:"id"`
    }

    if _, err := testDB.Exec(ctx, `
CREATE TABLE my_table (
    id STRING PRIMARY KEY,
    data string
);
INSERT INTO my_table (id, data) VALUES('id1', 'hello world');
`); err != nil {
        t.Fatal(err)
    }

    err := pgxscan.Get(ctx, testDB, &MyStruct{}, `
SELECT * FROM my_table WHERE id = 'id1'
`)
    fmt.Println(err) // this has an error

    vals := []*MyStruct{}
    err = pgxscan.Select(ctx, testDB, &vals, `
SELECT * FROM my_table
`)
    fmt.Println(err) // this has an error
}

It outputs:

scanning one: scanning: doing scan: scanFn: scany: column: 'data': no corresponding field found, or it's unexported in pgxscan_test.MyStruct
scanning all: scanning: scanning: doing scan: scanFn: scany: column: 'data': no corresponding field found, or it's unexported in pgxscan_test.MyStruct
steeling commented 9 months ago

I’ll try to get a working snippet soon.

What are your thoughts on adding an option to disable the strict marshaling rule?

Would prefer to use SELECT * in simple use cases and raising an error in this case would break compatibility

georgysavva commented 9 months ago

Scany already has this feature. You just need to instantiate a custom API object using this option: https://pkg.go.dev/github.com/georgysavva/scany/v2@v2.1.0/dbscan#WithAllowUnknownColumns

georgysavva commented 6 months ago

Closing due to inactivity. Feel free to reopen