upper / db

Data Access Layer (DAL) for PostgreSQL, CockroachDB, MySQL, SQLite and MongoDB with ORM-like features.
https://upper.io/
MIT License
3.53k stars 235 forks source link

Support conflicting column names when using joins #533

Open tonyhb opened 4 years ago

tonyhb commented 4 years ago

Given two structs User and Profile linked with a foreign key:

type User struct {
    ID        uuid.UUID
    Name      string
    CreatedAt time.Time
    UpdatedAt time.Time
}

type Profile struct {
    ID        uuid.UUID
    UserID    uuid.UUID
    CreatedAt time.Time
    UpdatedAt time.Time
}

It would be good to be able to query as follows:

type UserWithProfile struct {
    User    User    `db:",inline"`
    Profile Profile `db:",inline"`
}

res := []*UserWithProfile{}
err := db.
        SelectFrom("users").
        Join("profiles AS p").On("users.id = p.user_id").
        All(res)

Right now, this is impossible due to conflicting field names with multiple inline structs. The user's ID, CreatedAt and UpdatedAt columns are all unset, while only the joined Profile's fields are set.

This could be solvable via:

  1. When iterating through column names, record the number of times that you've seen each column name (https://github.com/upper/db/blob/fad80cdab4f761cb26416675df120f5d8c3f0db7/lib/sqlbuilder/fetch.go#L162)
  2. If we've seen a column name > 1 time, iterate through the embedded structs in order and set the N'th struct's field with the given value.

This assumes that the struct field's ordering is the same as the order in the database query.

We could also dynamically rename fields on the fly so that we can match regardless of order, though this is much more work.

lenuse commented 3 years ago

@xiam Is there any plan to resolve this issue