Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions mdl/executor/cmd_microflows_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import (
"github.com/mendixlabs/mxcli/sdk/mpr"
)

// isBuiltinModuleEntity returns true for modules whose entities are defined
// internally by the Mendix runtime and are therefore not present in the MPR's
// domain models. These types are serialized using the qualified name reference
// ("System.Workflow", "System.User", etc.) and resolved at runtime.
func isBuiltinModuleEntity(moduleName string) bool {
return moduleName == "System"
}

// execCreateMicroflow handles CREATE MICROFLOW statements.
func (e *Executor) execCreateMicroflow(s *ast.CreateMicroflowStmt) error {
if e.writer == nil {
Expand Down Expand Up @@ -105,8 +113,10 @@ func (e *Executor) execCreateMicroflow(s *ast.CreateMicroflowStmt) error {

// Validate and add parameters
for _, p := range s.Parameters {
// Validate entity references for List and Entity types
if p.Type.EntityRef != nil {
// Validate entity references for List and Entity types.
// Built-in modules (e.g. System) are not stored in the MPR domain models;
// their types are serialized by qualified name and resolved at runtime.
if p.Type.EntityRef != nil && !isBuiltinModuleEntity(p.Type.EntityRef.Module) {
entityID := entityResolver(*p.Type.EntityRef)
if entityID == "" {
return fmt.Errorf("entity '%s.%s' not found for parameter '%s'",
Expand All @@ -133,8 +143,10 @@ func (e *Executor) execCreateMicroflow(s *ast.CreateMicroflowStmt) error {

// Validate and set return type
if s.ReturnType != nil {
// Validate entity references for return type
if s.ReturnType.Type.EntityRef != nil {
// Validate entity references for return type.
// Built-in modules (e.g. System) are not stored in the MPR domain models;
// their types are serialized by qualified name and resolved at runtime.
if s.ReturnType.Type.EntityRef != nil && !isBuiltinModuleEntity(s.ReturnType.Type.EntityRef.Module) {
entityID := entityResolver(*s.ReturnType.Type.EntityRef)
if entityID == "" {
return fmt.Errorf("entity '%s.%s' not found for return type",
Expand Down
14 changes: 12 additions & 2 deletions mdl/executor/cmd_microflows_format_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func (e *Executor) formatActivity(

case *microflows.EndEvent:
if activity.ReturnValue != "" {
returnVal := activity.ReturnValue
if !strings.HasPrefix(returnVal, "$") {
returnVal := strings.TrimSuffix(activity.ReturnValue, "\n")
if !strings.HasPrefix(returnVal, "$") && !isMendixKeyword(returnVal) {
returnVal = "$" + returnVal
}
return fmt.Sprintf("RETURN %s;", returnVal)
Expand Down Expand Up @@ -846,3 +846,13 @@ func (e *Executor) formatExecuteDatabaseQueryAction(a *microflows.ExecuteDatabas
sb.WriteString(";")
return sb.String()
}

// isMendixKeyword returns true for Mendix expression keywords that must not be
// prefixed with "$" when serialized as a RETURN value.
func isMendixKeyword(s string) bool {
switch s {
case "empty", "true", "false", "null":
return true
}
return false
}
26 changes: 26 additions & 0 deletions mdl/executor/roundtrip_microflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,32 @@ END;`
)
}

// TestRoundtripMicroflow_SystemEntityParameter tests that microflows with
// System.* built-in entity parameter types can be created (issue #29).
// System entities (System.Workflow, System.User, etc.) are not stored in the
// MPR domain models — they are serialized by qualified name at runtime.
func TestRoundtripMicroflow_SystemEntityParameter(t *testing.T) {
env := setupTestEnv(t)
defer env.teardown()

mfName := testModule + ".RT_SystemEntityParam"
env.registerCleanup("microflow", mfName)

createMDL := `CREATE MICROFLOW ` + mfName + ` (
$Workflow: System.Workflow,
$Count: Integer
) RETURNS List of System.User
BEGIN
RETURN empty;
END;`

assertMicroflowContains(t, env, mfName, createMDL,
// "empty" is a reserved keyword — must round-trip as "RETURN empty", not "$empty"
[]string{"System.Workflow", "System.User", "RETURN empty"},
[]string{"RETURN $empty"},
)
}

// TestRoundtripMicroflow_Position tests @position is emitted in DESCRIBE output.
func TestRoundtripMicroflow_Position(t *testing.T) {
env := setupTestEnv(t)
Expand Down
10 changes: 4 additions & 6 deletions sdk/mpr/writer_microflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,9 @@ func (w *Writer) serializeMicroflow(mf *microflows.Microflow) ([]byte, error) {
}

// Add remaining optional fields
returnVarName := mf.ReturnVariableName
if returnVarName == "" {
returnVarName = "Variable" // Default value used by Mendix
}
doc = append(doc, bson.E{Key: "ReturnVariableName", Value: returnVarName})
// ReturnVariableName is "" by default (Studio Pro convention).
// Only set a custom name when explicitly specified via "RETURNS xxx AS $VarName".
doc = append(doc, bson.E{Key: "ReturnVariableName", Value: mf.ReturnVariableName})
doc = append(doc, bson.E{Key: "StableId", Value: idToBsonBinary(generateUUID())})
doc = append(doc, bson.E{Key: "Url", Value: ""})
doc = append(doc, bson.E{Key: "UrlSearchParameters", Value: bson.A{int32(1)}})
Expand Down Expand Up @@ -223,7 +221,7 @@ func serializeMicroflowParameter(p *microflows.MicroflowParameter, posX int) bso
{Key: "$Type", Value: "Microflows$MicroflowParameter"},
{Key: "DefaultValue", Value: ""},
{Key: "Documentation", Value: p.Documentation},
{Key: "HasVariableNameBeenChanged", Value: true},
{Key: "HasVariableNameBeenChanged", Value: false},
{Key: "IsRequired", Value: true},
{Key: "Name", Value: p.Name},
{Key: "RelativeMiddlePoint", Value: relativeMiddlePoint},
Expand Down
Loading