Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joins and Preload Regression with gorm version 1.25.7 #6834

Closed
ldjebran opened this issue Feb 9, 2024 · 7 comments · Fixed by #6877
Closed

Joins and Preload Regression with gorm version 1.25.7 #6834

ldjebran opened this issue Feb 9, 2024 · 7 comments · Fixed by #6877
Assignees
Labels
type:with reproduction steps with reproduction steps

Comments

@ldjebran
Copy link

ldjebran commented Feb 9, 2024

GORM Playground Link

go-gorm/playground#688

Description

suppose we have the following data structures

type Repo struct {
	ID     uint   `gorm:"primarykey"`
	URL    string `json:"RepoURL"`
	Status string `json:"RepoStatus"`
}

type DispatchRecord struct {
	ID                   uint `gorm:"primarykey"`
	PlaybookURL          string
	PlaybookDispatcherID string
}

type UpdateTransaction struct {
	ID              uint `gorm:"primarykey"`
	RepoID          *uint
	Repo            *Repo
	DispatchRecords []DispatchRecord `gorm:"many2many:updatetransaction_dispatchrecords"`
}

type DeviceUpdate struct {
	ID       uint `gorm:"primarykey"`
	Name     string
	UpdateID *uint
	Update   *UpdateTransaction
}

Panic Occurs when Mixing Joins and Preload with the same field
eg query like

DB.Joins("Update.Repo").Joins("Update").Preload("Update.DispatchRecords").Find(&deviceUpdates)

will panic with

panic: reflect: call of reflect.Value.Field on slice Value [recovered]
        panic: reflect: call of reflect.Value.Field on slice Value

goroutine 15 [running]:
testing.tRunner.func1.2({0xc50dc0, 0xc000013e78})
        /home/djlezzou/bin/go/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
        /home/djlezzou/bin/go/src/testing/testing.go:1529 +0x39f
panic({0xc50dc0, 0xc000013e78})
        /home/djlezzou/bin/go/src/runtime/panic.go:884 +0x213
reflect.Value.Field({0xc1db00?, 0xc000012798?, 0xc0004e81a8?}, 0xc00001f970?)
        /home/djlezzou/bin/go/src/reflect/value.go:1268 +0xe5
gorm.io/gorm/schema.(*Field).setupValuerAndSetter.func4({0xd3e90f?, 0x6?}, {0xc1db00?, 0xc000012798?, 0x10?})
        /home/djlezzou/projects/gorm/playground/gorm/schema/field.go:503 +0x65
gorm.io/gorm/callbacks.preloadEntryPoint(0xc0001845d0, {0xc00001f970, 0x1, 0x1}, 0xc0004b7748, 0xc000012798?, {0x0, 0x0, 0x0})
        /home/djlezzou/projects/gorm/playground/gorm/callbacks/preload.go:124 +0x429
gorm.io/gorm/callbacks.Preload(0xc000023b90)
        /home/djlezzou/projects/gorm/playground/gorm/callbacks/query.go:283 +0x2e5
gorm.io/gorm.(*processor).Execute(0xc0002508c0, 0xc00025c360?)
        /home/djlezzou/projects/gorm/playground/gorm/callbacks.go:130 +0x3ce
gorm.io/gorm.(*DB).Find(0x1221520?, {0xc04c60?, 0xc000012798}, {0x0, 0x0, 0x0})
        /home/djlezzou/projects/gorm/playground/gorm/finisher_api.go:170 +0x137
gorm.io/playground.TestGORM1(0x0?)
        /home/djlezzou/projects/gorm/playground/main_test.go:72 +0x4ad
testing.tRunner(0xc000583380, 0xd97258)
        /home/djlezzou/bin/go/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
        /home/djlezzou/bin/go/src/testing/testing.go:1629 +0x3ea

with version v1.25.6 all the tests passed

this has been discovered with dependency PR in our project RedHatInsights/edge-api#2406

@ldjebran
Copy link
Author

ldjebran commented Feb 9, 2024

I think I found the problem

Used the same test used in unit tests in PR #6771
The unit tests are only using First with var find1 Value

But when using Find with type var find1 []Value it will panic
eg :

type (
	Preload struct {
		ID       uint
		Value    string
		NestedID uint
	}
	Join struct {
		ID       uint
		Value    string
		NestedID uint
	}
	Nested struct {
		ID       uint
		Preloads []*Preload
		Join     Join
		ValueID  uint
	}
	Value struct {
		ID     uint
		Name   string
		Nested Nested
	}
)

func TestJoinsPreloads(t *testing.T) {
	_ = DB.AutoMigrate(&Preload{}, &Join{}, &Nested{}, &Value{})

	value := Value{
		Name: "value",
		Nested: Nested{
			Preloads: []*Preload{
				{Value: "p1"}, {Value: "p2"},
			},
			Join: Join{Value: "j1"},
		},
	}
	if err := DB.Create(&value).Error; err != nil {
		t.Errorf("failed to create value, got err: %v", err)
	}

	var err error

	// this will succeed
	var find Value
	err = DB.Joins("Nested").Joins("Nested.Join").Preload("Nested.Preloads").First(&find).Error
	if err != nil {
		t.Errorf("Failed, got error: %v", err)
	}

	// this will panic
	var values []Value
	err = DB.Joins("Nested").Joins("Nested.Join").Preload("Nested.Preloads").Find(&values).Error
	if err != nil {
		t.Errorf("Failed, got error: %v", err)
	}
}

the second query will panic

var values []Value
	err = DB.Joins("Nested").Joins("Nested.Join").Preload("Nested.Preloads").Find(&values).Error
	if err != nil {
		t.Errorf("Failed, got error: %v", err)
	}

The unit tests in that PR was not using Find with slice , but only First with pointer to a struct

@System-Glitch
Copy link

System-Glitch commented Feb 23, 2024

Experiencing the same issue. Debugging revealed that the db.Statement.ReflectValue here appears to be of Kind reflect.Slice despite my relationship being a simple struct pointer.

System-Glitch added a commit to go-goyave/goyave that referenced this issue Feb 23, 2024
go-gorm/gorm#6834
Gorm will be updated again when this is fixed
@VetSoftKeith
Copy link

I have this exact same issue. Upgrading to 1.25.7 completely breaks my entire application consisting of a dozen+ microservices all using gorm.

@a631807682
Copy link
Member

I haven't investigated it, but it seems from the description that it may have something to do with #6771. Do you have time to take a look? @black-06

@black-06
Copy link
Contributor

I haven't investigated it, but it seems from the description that it may have something to do with #6771. Do you have time to take a look? @black-06

Okay...

@DAcodedBEAT
Copy link

DAcodedBEAT commented Mar 11, 2024

Hello @go-gorm maintainers 👋 do you know when this fix will be released?

I cannot test this with https://github.com/go-gorm/postgres/releases/tag/v1.5.7 because m.GuessConstraintInterfaceAndTable undefined in <= v1.25.6

@VetSoftKeith
Copy link

@DAcodedBEAT looks like it was released in 1.25.8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:with reproduction steps with reproduction steps
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants