diff --git a/join_query.go b/join_query.go index 95af9754..61c6e43b 100644 --- a/join_query.go +++ b/join_query.go @@ -20,15 +20,40 @@ func (jq JoinQuery) Build(query *Query) { } } -func (jq *JoinQuery) Populate(docMeta DocumentMeta) { +func (jq *JoinQuery) Populate(query *Query, docMeta DocumentMeta) { var ( assocMeta = docMeta.Association(jq.Assoc) assocDocMeta = assocMeta.DocumentMeta() ) - jq.Table = assocDocMeta.Table() - jq.To = jq.Table + "." + assocMeta.ForeignField() + jq.Table = assocDocMeta.Table() + " as " + jq.Assoc + jq.To = jq.Assoc + "." + assocMeta.ForeignField() jq.From = docMeta.Table() + "." + assocMeta.ReferenceField() + + // load association if defined and supported + if assocMeta.Type() == HasOne || assocMeta.Type() == BelongsTo { + var ( + load = false + selectField = jq.Assoc + ".*" + ) + + for i := range query.SelectQuery.Fields { + if load && i > 0 { + query.SelectQuery.Fields[i-1] = query.SelectQuery.Fields[i] + } + if query.SelectQuery.Fields[i] == selectField { + load = true + } + } + + if load { + fields := make([]string, len(assocDocMeta.Fields())) + for i, f := range assocDocMeta.Fields() { + fields[i] = jq.Assoc + "." + f + " as " + jq.Assoc + "." + f + } + query.SelectQuery.Fields = append(query.SelectQuery.Fields[:(len(query.SelectQuery.Fields)-1)], fields...) + } + } } // NewJoinWith query with custom join mode, table, field and additional filters with AND condition. diff --git a/join_query_test.go b/join_query_test.go index b87ab6c9..7a6e748c 100644 --- a/join_query_test.go +++ b/join_query_test.go @@ -73,34 +73,49 @@ func TestJoin(t *testing.T) { func TestJoinAssoc_hasOne(t *testing.T) { var ( - populated = rel.Build("", rel.NewJoinAssoc("address")). - Populate(rel.NewDocument(&rel.User{}, false).Meta()). - JoinQuery[0] + populated = rel.Build("", rel.Select("*", "address.*"), rel.NewJoinAssoc("address")). + Populate(rel.NewDocument(&rel.User{}, false).Meta()) ) assert.Equal(t, rel.JoinQuery{ Mode: "JOIN", - Table: "user_addresses", - To: "user_addresses.user_id", + Table: "user_addresses as address", + To: "address.user_id", From: "users.id", Assoc: "address", - }, populated) + }, populated.JoinQuery[0]) + assert.Equal(t, []string{ + "*", + "address.id as address.id", + "address.user_id as address.user_id", + "address.street as address.street", + "address.notes as address.notes", + "address.deleted_at as address.deleted_at", + }, populated.SelectQuery.Fields) } func TestJoinPopulate_hasOnePtr(t *testing.T) { var ( - populated = rel.Build("", rel.NewJoinAssoc("work_address")). - Populate(rel.NewDocument(&rel.User{}, false).Meta()). - JoinQuery[0] + populated = rel.Build("", rel.Select("id", "work_address.*", "name"), rel.NewJoinAssoc("work_address")). + Populate(rel.NewDocument(&rel.User{}, false).Meta()) ) assert.Equal(t, rel.JoinQuery{ Mode: "JOIN", - Table: "user_addresses", - To: "user_addresses.user_id", + Table: "user_addresses as work_address", + To: "work_address.user_id", From: "users.id", Assoc: "work_address", - }, populated) + }, populated.JoinQuery[0]) + assert.Equal(t, []string{ + "id", + "name", + "work_address.id as work_address.id", + "work_address.user_id as work_address.user_id", + "work_address.street as work_address.street", + "work_address.notes as work_address.notes", + "work_address.deleted_at as work_address.deleted_at", + }, populated.SelectQuery.Fields) } func TestJoinPopulate_hasMany(t *testing.T) { @@ -112,7 +127,7 @@ func TestJoinPopulate_hasMany(t *testing.T) { assert.Equal(t, rel.JoinQuery{ Mode: "JOIN", - Table: "transactions", + Table: "transactions as transactions", To: "transactions.user_id", From: "users.id", Assoc: "transactions", @@ -128,8 +143,8 @@ func TestJoinAssoc_belongsTo(t *testing.T) { assert.Equal(t, rel.JoinQuery{ Mode: "JOIN", - Table: "users", - To: "users.id", + Table: "users as user", + To: "user.id", From: "user_addresses.user_id", Assoc: "user", }, populated) diff --git a/query.go b/query.go index 4de73fe2..23a40b73 100644 --- a/query.go +++ b/query.go @@ -11,7 +11,7 @@ type Querier interface { } type QueryPopulator interface { - Populate(DocumentMeta) + Populate(*Query, DocumentMeta) } // Build for given table using given queriers. @@ -130,7 +130,7 @@ func (q Query) Build(query *Query) { func (q Query) Populate(documentMeta DocumentMeta) Query { for i := range q.queryPopulators { - q.queryPopulators[i].Populate(documentMeta) + q.queryPopulators[i].Populate(&q, documentMeta) } return q diff --git a/query_test.go b/query_test.go index 3164780e..d95d3e76 100644 --- a/query_test.go +++ b/query_test.go @@ -383,7 +383,7 @@ func TestQuery_JoinAssoc(t *testing.T) { JoinQuery: []rel.JoinQuery{ { Mode: "JOIN", - Table: "transactions", + Table: "transactions as transactions", To: "transactions.user_id", From: "users.id", Assoc: "transactions",