pgx
pgx copied to clipboard
RowToStructByName does not scan into embedded structures
Describe the bug
I get "struct doesn't have corresponding row field id" error when I try to do RowToStructByName because I have another field in nested structure with db:"id"
tag
To Reproduce
type Subscription struct {
ID int `db:"id"`
TariffAlias string `db:"tariff_alias"`
Tariff
}
type Tariff struct {
ID int `db:"id"`
Alias string `db:"alias"`
}
pgx.CollectOneRow(rows, pgx.RowToStructByName[Subscription])
select * from subscription as s join tariff t on t.alias = s.tariff_alias;
Expected behavior I get the completed structure Subscription Actual behavior struct doesn't have corresponding row field id
Version
- Go: go version go1.21 darwin/amd64
- pgx: github.com/jackc/pgx/v5.3.1
Additional context
The problem can be corrected by adding zeroing of the field name in the fieldPosByName function, as a mark that it has already found a match in the structure fldDescs[i].Name = ""
Perhaps we should have a better error message, but I don't think that your example should work. The *StructByName*
helpers are supposed to work independently of column order. There is no way to safely scan multiple columns with the same name.
The problem can be corrected by adding zeroing of the field name in the fieldPosByName function, as a mark that it has already found a match in the structure fldDescs[i].Name = ""
That might happen to work for your particular example query:
select * from subscription as s join tariff t on t.alias = s.tariff_alias;
But it could silently fail with data corruption if the column order was changed.
select * from tariff t join subscription as s on t.alias = s.tariff_alias;
Tell me, are there any changes on this topic? Is it possible to assemble this structure with one database query?
type Role struct {
ID int64 `db:"role_id"`
Name string `db:"role_name"`
}
type Permission struct {
ID int64 `db:"permission_id"`
Name string `db:"permission_name"`
}
type User struct {
ID int64 `db:"user_id"`
Email string
Password string
Role
Permissions []Permission
}
Now, using pgx.CollectOneRow(rows, pgx.RowToStructByName[User]), I can join the user with the role, but not the permissions. I think this is because permissions is a slice.
Error: There is no corresponding permission_id string field in the structure.
+1
+1
Now, using pgx.CollectOneRow(rows, pgx.RowToStructByName[User]), I can join the user with the role
Is that so? I have an embedded struct into which I scan, and it doesn't see any embedded fields.