georgysavva / scany

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

Add scanning for a single row #28

Closed nickelghost closed 3 years ago

nickelghost commented 3 years ago

Hi, thanks for creating this library, it's very useful!

However, I think it'd be great to add a function (or change behaviour of ScanOne) so we can pass the row type. Right now, when implementing scany, all code that uses QueryRow has to switch to using Query because none of the functions support scanning sql's row, only rows.

georgysavva commented 3 years ago

Hi. Thanks for opening this issue. Could you please provide an example of what are you trying to achieve?

nickelghost commented 3 years ago

Sure. Basically, I had this code:

err = n.DB.QueryRow(context.Background(), sql, args...).Scan(
    &news.ID,
    &news.Title,
    &news.Subtitle,
    &news.Content,
    &news.Category,
    &news.Slug,
    &news.PublishedAt,
    &news.CreatedAt,
    &news.UpdatedAt,
)

And I'd like to be able to implement scany for it to look like this:

row := n.DB.QueryRow(context.Background(), sql, args...)
var news entity.News
err = pgxscan.ScanOneRow(&news, row)

But, since all scany's methods require rows, and don't support row, I had to implement it like this:

rows, err := n.DB.Query(context.Background(), sql, args...)
if err != nil {
    return nil, err
}
var news entity.News
err = pgxscan.ScanOne(&news, rows)

Which requires more code and isn't as clear (because we query for multiple rows, but only use one).

georgysavva commented 3 years ago

You can do it even simpler, using the pgxscan.Get() function:

var news entity.News
err := pgxscan.Get(context.Background(), n.DB, &news, sql, args...)
...

For more detail see docs for the .Get() function.

Scany doesn't work with Row type intentionally, because it doesn't expose enough information to do the mapping. And generally, there should be no need to pass a Row type to scany, since it provides all helper functions that you would need. I hope it helps!

nickelghost commented 3 years ago

I won't be able to use pgxscan.Get() in every situation, but fair enough! Thanks!