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

Support loading association using Join query #302

Merged
merged 4 commits into from Jul 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 28 additions & 3 deletions join_query.go
Expand Up @@ -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.
Expand Down
45 changes: 30 additions & 15 deletions join_query_test.go
Expand Up @@ -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) {
Expand All @@ -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",
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions query.go
Expand Up @@ -11,7 +11,7 @@ type Querier interface {
}

type QueryPopulator interface {
Populate(DocumentMeta)
Populate(*Query, DocumentMeta)
}

// Build for given table using given queriers.
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion query_test.go
Expand Up @@ -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",
Expand Down