bun
bun copied to clipboard
fix: handle invalid value on fieldByIndex
When using deep Relation()
with Scan(ctx)
, if the value we're scanning is invalid (usually zero), then bun currently panics when attempting v.Field(idx)
Let's handle that correctly before trying to apply it.
Thanks! Any chance you can add a test or demonstrate how to reproduce this?
Shall do that next week on my midsummer break! Things have been busy; sorry for the delayed reply
@tinyfluffs thank you in advance!
Hello! Is it possible to hope that this PR will get into the release?
We are waiting for a test that demonstrates why we need this PR. @lakkinzimusic perhaps you have one?
We are waiting for a test that demonstrates why we need this PR. @lakkinzimusic perhaps you have one?
"context"
"database/sql"
"encoding/json"
"fmt"
"log"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/sqlitedialect"
"github.com/uptrace/bun/driver/sqliteshim"
"github.com/uptrace/bun/extra/bundebug"
)
func main() {
ctx := context.Background()
// Open an in-memory SQLite database.
sqlite, err := sql.Open(sqliteshim.ShimName, "file::memory:?cache=shared")
if err != nil {
panic(err)
}
// Create a Bun db on top of it.
db := bun.NewDB(sqlite, sqlitedialect.New())
// Print all queries to stdout.
db.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
// create and insert data
db.NewCreateTable().Model((*SampleTable)(nil)).Exec(ctx)
db.NewInsert().Model(&Data).Exec(ctx)
var st []SampleTable
err = db.NewSelect().Model(&st).
Relation("FirstChild").
Relation("FirstChild.FirstChild").
Scan(ctx)
if err != nil {
log.Println(err)
}
res, _ := json.MarshalIndent(st, "", " ")
fmt.Println(string(res))
}
type SampleTable struct {
bun.BaseModel `bun:"table:sample_table"`
ID int `bun:",autoincrement,pk"`
FirstChildID int
FirstChild *SampleTable `bun:"rel:has-one,join:first_child_id=id"`
}
var Data = []SampleTable{
{FirstChildID: 0},
}
Hi @vmihailenco , above I have pasted the reproducible program.
I'm facing the similar problem.
I think it's better to check for m.struct.IsValid()
in m.scanColumn()
along with m.isNil()
, before calling field.ScanValue()
.
Something like this:
if !m.strct.IsValid() || (src == nil && m.isNil()) {
return true, nil
}
Thank you.
@nilsocket this is what I get when I run your program
[bun] 10:51:32.521 CREATE TABLE 1.07ms CREATE TABLE "sample_table" ("id" INTEGER NOT NULL, "first_child_id" INTEGER, PRIMARY KEY ("id"))
[bun] 10:51:32.521 INSERT 143µs INSERT INTO "sample_table" ("first_child_id") VALUES (0) RETURNING "id"
[bun] 10:51:32.521 SELECT 132µs SELECT "sample_table"."id", "sample_table"."first_child_id", "first_child"."id" AS "first_child__id", "first_child"."first_child_id" AS "first_child__first_child_id", "first_child__first_child"."id" AS "first_child__first_child__id", "first_child__first_child"."first_child_id" AS "first_child__first_child__first_child_id" FROM "sample_table" LEFT JOIN "sample_table" AS "first_child" ON ("first_child"."id" = "sample_table"."first_child_id") LEFT JOIN "sample_table" AS "first_child__first_child" ON ("first_child__first_child"."id" = "first_child"."first_child_id")
[
{
"ID": 1,
"FirstChildID": 0,
"FirstChild": null
}
]
Is there anything worng?