Proposal for selecting multiple things as alternative for the initial proposal
The prisma types could be generated with all relations a type can have. For example, when a User can have Posts and a Post has an Author, the respective types define the relation in the struct.
// generated code by prisma
type User struct {
Name string
Posts []Post
}
type Post struct {
Title string
Likes []User
}
// ...
Now, we can easily query for a user with their posts.
user, err := client.User(
prisma.user.WithPosts()
)
log.Printf("user: %+v", user) // { Name: John }
// user.Posts is filled:
log.Printf("user posts: %+v", user.Posts) // []{{ Title: First post, Likes: <nil> }}
We could even go deeper:
user, err := client.User(
prisma.user.WithPosts(
prisma.post.WithLikes()
)
)
log.Printf("user: %+v", user) // { Name: John }
// user.Posts is filled with likes:
log.Printf("user posts: %+v", user.Posts) // []{{ Title: First post, Likes: []Likes{{ Name: Luca }} }}
However, this means that you would have to make sure you're not using the fields if you didn't query for them:
user, err := client.User()
log.Printf("user: %+v", user) // { Name: John }
log.Printf("user posts: %+v", user.Posts) // <nil>
// user.posts is now nil because we didn't ask for it, so we are not allowed to access it.
user.Posts[0].Title // ERROR: runtime error: index out of range
In theory, it could be possible to generate types for it when chaining function calls, instead of using functional options:
user1, err := client.User().Exec()
// user1 is User{ Name: "John" }
user2, err := client.User().UserWithPosts().PostWithLikes().Exec()
// user2 is User{ Name: "John", Posts: []Post{}{ Title: "First Post", Likes: []User{ Name: "Jane" } } }
// assuming a user has more relations than posts, i.e. posts and emails
user3, err := client.User().UserWithEmailsAndPosts().PostWithLikes().Exec()
// user3 is User{ Name: "John", Emails: []Email, Posts: []Post{}{ Title: "First Post", Likes: []User{ Name: "Jane" } } }
Each of those methods could return another struct to generate all possible chainings.
However, when using more and more relations, this would generate an abnormal amount of structs, growing exponentially with more relations. It's probably possible, but I'm not sure if it's a good idea.