uptrace / bun

SQL-first Golang ORM
https://bun.uptrace.dev
BSD 2-Clause "Simplified" License
3.65k stars 223 forks source link

Libary crashes on resolving nested relations #886

Open ys3d opened 1 year ago

ys3d commented 1 year ago

I defined the following structs:

type Job struct {
    Id           int       `bun:",pk"` // uniq job ID
    Data       []*JobData `bun:"rel:has-many,join:id=job_id"`
}
type JobData struct {
    Id               int64  `bun:",pk,autoincrement"`
    JobId            int    `bun:",unique:unique_data"`
    ConfigGuid string `bun:",unique:unique_data"`
    Config           config.Config `bun:"rel:has-one,join:config_guid=guid"`
    Points     []Point       `bun:"rel:has-many,join:id=data_id"`
}
type Point struct {
    Id     int64 `bun:",pk,autoincrement"`
    DataId int64
    Time   time.Time
}

I tried to pull an element of JobData with:

err =s.db.NewSelect().
                          Model(&job).
                          WherePK().
                          Relation("Data", func(q *bun.SelectQuery) *bun.SelectQuery {
                              return q.Relation("Config").Relation("Points")
                          }).
                          Scan(context.Background())

In case I only try to resolve the relation "Config" everything works fine. The relation "Points" causes the following error. The error is caused with and without additionally requesting the "Config" relation:

panic: reflect: call of reflect.Value.Field on zero Value
goroutine 1 [running]:
reflect.Value.Field({0x0?, 0x0?, 0xc0004a2f28?}, 0x7f47703f9d40?)
        /usr/local/go/src/reflect/value.go:1268 +0xe5
github.com/uptrace/bun/schema.fieldByIndexAlloc({0x0?, 0x0?, 0x4311d6?}, {0xc00002ae70?, 0x4c8966?, 0xde0700?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/schema/reflect.go:52 +0x45
github.com/uptrace/bun/schema.(*Field).Value(...)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/schema/field.go:53
github.com/uptrace/bun.modelKey({0xc0003652e0?, 0x41866d?, 0xe0a4b0?}, {0x0?, 0x0?, 0xc0004a3048?}, {0xc00050c1f0, 0x1, 0x422807?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/model_table_has_many.go:146 +0xed
github.com/uptrace/bun.baseValues.func1({0x0?, 0x0?, 0xc000382210?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/model_table_has_many.go:137 +0xaa
github.com/uptrace/bun.visitField({0x0?, 0x0?, 0x7f4770e66fb8?}, {0xc0000a9478, 0x0, 0x1}, 0xc0004a31d8)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/util.go:38 +0xf2
github.com/uptrace/bun.walk({0x0?, 0x0?, 0xa76c0?}, {0xc0000a9478, 0x0, 0x1}, 0x10?)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/util.go:25 +0xa9
github.com/uptrace/bun.baseValues({0xaae438, 0xc0000264b0}, {0xc00050c1f0, 0x1, 0x1})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/model_table_has_many.go:136 +0x1d6
github.com/uptrace/bun.newHasManyModel(0xc000260550)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/model_table_has_many.go:27 +0x7a
github.com/uptrace/bun.(*relationJoin).manyQuery(0x0?, 0xc0005bf4a0)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/relation_join.go:57 +0x27
github.com/uptrace/bun.(*relationJoin).selectMany(0xc0005bf2c0?, {0xaab518, 0xc0000a8000}, 0x0?)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/relation_join.go:49 +0x26
github.com/uptrace/bun.(*SelectQuery).selectJoins(0xc0005bf2c0, {0xaab518, 0xc0000a8000}, {0xc000260500, 0x2, 0xc0005bf2c0?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/query_select.go:473 +0x3d5
github.com/uptrace/bun.(*SelectQuery).Scan(0xc0005bf2c0, {0xaab518, 0xc0000a8000}, {0x0?, 0x996800?, 0xaaa201?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/query_select.go:888 +0x1db
github.com/uptrace/bun.(*relationJoin).selectMany(0x0?, {0xaab518, 0xc0000a8000}, 0xc000287000?)
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/relation_join.go:53 +0x45
github.com/uptrace/bun.(*SelectQuery).selectJoins(0xc0005bed20, {0xaab518, 0xc0000a8000}, {0xc00028e500, 0x3, 0xc0005bed20?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/query_select.go:473 +0x3d5
github.com/uptrace/bun.(*SelectQuery).Scan(0xc0005bed20, {0xaab518, 0xc0000a8000}, {0x0?, 0x1?, 0x0?})
        /go/pkg/mod/github.com/uptrace/bun@v1.1.14/query_select.go:888 +0x1db
jobmon/store.(*PostgresStore).GetJob(_, _)
        /app/store/postgres_store.go:291 +0x185
main.main()
        /app/jobmon.go:62 +0x50c

Does anybody have an idea what is causing this behaviour? Is that an bug or is it an mistake on my side?

ys3d commented 1 year ago

Update: Directly fetching an element of type JobData works perfectly fine using both relations

yohimik commented 9 months ago

up I get the same error using such syntax when Data is null

Model(&job).
WherePK().
Relation("Data.Config").
Relation("Data.Points").
Scan(context.Background())
hsequeda commented 7 months ago

I'm getting the same error. My model is:

type User struct {
    bun.BaseModel `bun:"table:user,alias:u"`
    ID       int64
    Name     string
    Password string

    SuperUser       *SuperUser              `bun:"su,rel:has-one,join:id=user_id"`
    ClientUser      *ClientUser             `bun:"cu,rel:has-one,join:id=user_id"`
}

type SuperUser struct {
    bun.BaseModel `bun:"table:super_user,alias:su"`
    ID     int64
    Email  string
    UserID int64

    User   *User `bun:"rel:belongs-to,join:user_id=id"`
}

type ClientUser struct {
    bun.BaseModel `bun:"table:client_user,alias:cu"`
    ID     int64
    Email  string
    UserID int64

    User   *User `bun:"rel:belongs-to,join:user_id=id"`
}

type Order struct {
    bun.BaseModel `bun:"table:order,alias:o"`
    ID int64

    OwnerID int64

    Owner   *User `bun:"rel:belongs-to,join:owner_id=id"`
}

And I try the request:

Model(&order).
Relation("Owner").
Scan(context.Background())

It fails when I've values in both user tables (ClientUser and SuperUser)

hsequeda commented 7 months ago

This issue is duplicating => https://github.com/uptrace/bun/issues/872