-
Notifications
You must be signed in to change notification settings - Fork 120
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
Infinite loop on types that reference eachother #107
Comments
Hi. Assuming you want to scan into Scanner should be able to catch up circular dependency and return an error, so this can be implemented in the future. Allowing pointer might make sense in some scenarios(something to think about). But recommendation would be to not to use circular dependencies: type TableOne struct {
model.TableOnes
TableTwos []model.TableTwos
} |
It's part of a typical schema, I believe GORM even has an example in their docs. If you have a HasMany/HasOne relationship, at the other end you have a BelongsTo, if you need to access the parent table from the child (very common) you have to have the child reference the parent's type. |
The data is different, you basically have one path of data being loaded. Table 4 -> Table 3 -> Table 2 -> []Table 1 (I'm table 2, grab all my children) and In the first path I have to access table 2 through table 3 as the reference for table 3 is in table 4 and table 3 has no table 1 reference This is common when having two foreign keys (parents) on the same table. |
@go-jet Any ideas on this? It shouldn't return an error as it wouldn't be instances pointing to eachother, the objects can simply have eachother's type as a type of a field (or as a slice of said type). The current workaround for this requires another library and is a bit hacky in terms of implementation. |
Don't see many problems with supporting a pointer to shared scan data. The only issue would be, because all database tables are related in one way or the other, scan destination would be always a complex struct containing all the db models. This might slowdown the scan, because the scan would need to introspect every model in that destination. But eventually this would be developer decision, so it isn't a big issue. |
A pointer to shared scan data? The issue lies when two structs use eachother as a type.
If I'm working from TableOne and wanted all its TableTwo children If I'm working from TableTwo in a completely different area and wanted to use its parent for something Typically the first scenario, you're doing an everyday say
Hence why you'd need TicketReplies on Ticket and Ticket on TicketReply |
@go-jet Is there any target date for 2.7? I'm refactoring our entire codebase to use go-jet and this is currently the only issue we're having and to get around it theres a lot of boilerplate, err != nil checking, and inefficient data-usage. (looping and copying data) |
You're awesome! This worked when I tried a test struct I made which failed on the initial branch it seemed to work perfectly!
Heres the stacktrace
|
Got it to work by adding table.JoinedTable.ID to the select (not just inner join), going to look at why this is but branch seems to work :)! Thanks a million @go-jet |
Went from 13-20ms to 5-6ms! On a production sized table this difference would be massive. |
Refactored all our current jet code to use this detection, everything working smoothly, functions are now specific yet lean and many less points of failure, this is the reason I wanted to use this library, glad I can finally use it as intended. Working great! |
Cool! Glad to hear that. |
@go-jet Getting type A struct {
model.As
B *B
C *C
}
type B struct {
model.Bs
D *D
}
type C struct {
model.Cs
D *D
} When doing a select a.inner_join(b).inner_join(c).inner_join(d) |
Hi @CmpHDL, |
|
Running version |
Your destination type looks similar to the type from this discussion. |
Thank you @houten11 This is how I fixed it in the meantime. Although, is there a way we could put an alias on a struct field? Eg: type A struct {
model.As
B *B
C *C
}
type B struct {
model.Bs
D *D `alias:b_ds`
}
type C struct {
model.Cs
D *D `alias:"c_ds"`
}
type D struct {
model.Ds
} That way we would could maintain all of the methods on D without having to duplicate them in another model or have to do some sort of casting? |
Also is there no way to distinguish which should nested struct should go on which automatically? |
Yeah, you're right. Discussion type is not that similar to your destination type. Your alias example should work, except maybe |
@houten11 Problem is we would lose all methods on type D |
No, you can still add methods on the renamed type. type D model.Ds
func (d D) SomeMethod() {} |
@CmpHDL Could you share the query you used in your first attempt. I can't reproduce the bug. Just by looking at stacktrace it doesn't' seems to be related to types circular reference. Also, what driver are you using? |
Postgres, I'll create a reproduction for this so you can reproduce. But I essentially just did inner joins. |
However, then, additional properties cannot be added. |
This would be great. |
Forgot about this, always juggling 100 things. I'll make one today if not then this week. |
This seems like a scan grouping bug, so for your test sample you can ignore all the columns except the primary key columns. |
Preforming a stmt.Query with either of these structs (or anything that has either of these structs) will load infinitely.
No error is returned, it was incredibly long and time consuming to find the source of the issue.
I have tried making the types pointers to no avail. (idea being they would become nullable)
This pattern is common when you have a Has(One/Many)BelongsTo relationship.
The text was updated successfully, but these errors were encountered: