Skip to content

Commit 0f35801

Browse files
authored
Merge pull request #381 from hjotha/submit/retrieve-reverse-reference-owner-both-list
fix: emit list retrieve for owner-both reverse references
2 parents 632c9e4 + d775f18 commit 0f35801

2 files changed

Lines changed: 42 additions & 13 deletions

File tree

mdl/executor/cmd_microflows_builder_actions.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func (fb *flowBuilder) addRetrieveAction(s *ast.RetrieveStmt) model.ID {
303303
}
304304

305305
if assocInfo != nil && assocInfo.Type == domainmodel.AssociationTypeReference &&
306-
assocInfo.Owner != domainmodel.AssociationOwnerBoth &&
306+
assocInfo.Owner != "" &&
307307
assocInfo.parentPersistable &&
308308
assocInfo.childEntityQN != "" && startVarType == assocInfo.childEntityQN {
309309
// Reverse traversal on Reference: child → parent (one-to-many)
@@ -326,12 +326,18 @@ func (fb *flowBuilder) addRetrieveAction(s *ast.RetrieveStmt) model.ID {
326326
}
327327
if fb.varTypes != nil {
328328
if assocInfo != nil && assocInfo.Type == domainmodel.AssociationTypeReference {
329-
// Reference forward traversal: returns single object
329+
// Forward Reference traversal returns a single object. Legacy or
330+
// non-persistable reverse traversal can still use association
331+
// source syntax, but keeps list typing for downstream actions.
330332
otherEntity := assocInfo.childEntityQN
331333
if startVarType == assocInfo.childEntityQN {
332334
otherEntity = assocInfo.parentEntityQN
333335
}
334-
fb.varTypes[s.Variable] = otherEntity
336+
if startVarType == assocInfo.childEntityQN {
337+
fb.varTypes[s.Variable] = "List of " + otherEntity
338+
} else {
339+
fb.varTypes[s.Variable] = otherEntity
340+
}
335341
} else if assocInfo != nil && assocInfo.Type == domainmodel.AssociationTypeReferenceSet {
336342
// ReferenceSet traversal returns a list of the entity on the other side,
337343
// not a list typed as the association itself.

mdl/executor/cmd_microflows_builder_retrieve_reverse_test.go

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ import (
1212
"github.com/mendixlabs/mxcli/sdk/microflows"
1313
)
1414

15-
func TestAddRetrieveAction_ReverseReferenceOwnerBothUsesAssociationSource(t *testing.T) {
15+
func TestAddRetrieveAction_ReverseReferenceOwnerBothUsesDatabaseSource(t *testing.T) {
1616
fb := newRetrieveAssociationFlowBuilder(domainmodel.AssociationOwnerBoth)
1717
fb.varTypes["Child"] = "Sample.Child"
1818

1919
fb.addRetrieveAction(&ast.RetrieveStmt{
20-
Variable: "Parent",
20+
Variable: "Parents",
2121
StartVariable: "Child",
2222
Source: ast.QualifiedName{Module: "Sample", Name: "Parent_Child"},
2323
})
2424

2525
action := onlyRetrieveAction(t, fb)
26-
source, ok := action.Source.(*microflows.AssociationRetrieveSource)
26+
source, ok := action.Source.(*microflows.DatabaseRetrieveSource)
2727
if !ok {
28-
t.Fatalf("owner-both reverse retrieve source = %T, want AssociationRetrieveSource", action.Source)
28+
t.Fatalf("owner-both reverse retrieve source = %T, want DatabaseRetrieveSource", action.Source)
2929
}
30-
if source.StartVariable != "Child" || source.AssociationQualifiedName != "Sample.Parent_Child" {
31-
t.Fatalf("association source = %#v", source)
30+
if source.EntityQualifiedName != "Sample.Parent" || source.XPathConstraint != "[Sample.Parent_Child = $Child]" {
31+
t.Fatalf("database source = %#v", source)
3232
}
33-
if got := fb.varTypes["Parent"]; got != "Sample.Parent" {
34-
t.Fatalf("result var type = %q, want Sample.Parent", got)
33+
if got := fb.varTypes["Parents"]; got != "List of Sample.Parent" {
34+
t.Fatalf("result var type = %q, want List of Sample.Parent", got)
3535
}
3636
}
3737

@@ -76,8 +76,31 @@ func TestAddRetrieveAction_ReverseReferenceNonPersistableParentUsesAssociationSo
7676
if source.StartVariable != "Child" || source.AssociationQualifiedName != "Sample.Parent_Child" {
7777
t.Fatalf("association source = %#v", source)
7878
}
79-
if got := fb.varTypes["Parents"]; got != "Sample.Parent" {
80-
t.Fatalf("result var type = %q, want Sample.Parent", got)
79+
if got := fb.varTypes["Parents"]; got != "List of Sample.Parent" {
80+
t.Fatalf("result var type = %q, want List of Sample.Parent", got)
81+
}
82+
}
83+
84+
func TestAddRetrieveAction_ReverseReferenceUnknownOwnerPreservesAssociationSource(t *testing.T) {
85+
fb := newRetrieveAssociationFlowBuilder("")
86+
fb.varTypes["Child"] = "Sample.Child"
87+
88+
fb.addRetrieveAction(&ast.RetrieveStmt{
89+
Variable: "Parents",
90+
StartVariable: "Child",
91+
Source: ast.QualifiedName{Module: "Sample", Name: "Parent_Child"},
92+
})
93+
94+
action := onlyRetrieveAction(t, fb)
95+
source, ok := action.Source.(*microflows.AssociationRetrieveSource)
96+
if !ok {
97+
t.Fatalf("unknown-owner reverse retrieve source = %T, want AssociationRetrieveSource", action.Source)
98+
}
99+
if source.StartVariable != "Child" || source.AssociationQualifiedName != "Sample.Parent_Child" {
100+
t.Fatalf("association source = %#v", source)
101+
}
102+
if got := fb.varTypes["Parents"]; got != "List of Sample.Parent" {
103+
t.Fatalf("result var type = %q, want List of Sample.Parent", got)
81104
}
82105
}
83106

0 commit comments

Comments
 (0)