diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc7576f0..ddbfef219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Fixed + +- `GetRawUnit` on v1 MPR files (Mendix < 10.18) — UUID string was passed directly to SQLite instead of being converted to a GUID blob, causing every lookup to fail with "no rows in result set" (#705) + ## [0.14.0] - 2026-06-21 Headline: **JavaScript actions, clickable containers, and the v0.13.0 enum-visibility regression fixed.** This release adds `CREATE JAVASCRIPT ACTION` authoring and clickable-container support, a new `check` heuristic for `System.owner` XPath constraints, and fixes a v0.13.0 regression that mangled enum literals in conditional-visibility expressions (a release blocker for status-pill authoring). diff --git a/sdk/mpr/get_raw_unit_v1_test.go b/sdk/mpr/get_raw_unit_v1_test.go new file mode 100644 index 000000000..4e83d4557 --- /dev/null +++ b/sdk/mpr/get_raw_unit_v1_test.go @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: Apache-2.0 + +package mpr + +import ( + "testing" + + "github.com/mendixlabs/mxcli/model" +) + +// TestGetRawUnit_V1 verifies that GetRawUnit works on v1 MPR files (Mendix < 10.18) +// where UnitID is stored as a 16-byte GUID blob in SQLite. +// Regression test for https://github.com/mendixlabs/mxcli/issues/705 +func TestGetRawUnit_V1(t *testing.T) { + mprPath := "testdata/v1-project/App.mpr" + + reader, err := Open(mprPath) + if err != nil { + t.Fatalf("failed to open v1 MPR: %v", err) + } + defer reader.Close() + + if reader.Version() != MPRVersionV1 { + t.Fatalf("expected MPR v1, got v%d", reader.Version()) + } + + // ListAllUnitIDs works correctly (uses blobToUUID internally) + ids, err := reader.ListAllUnitIDs() + if err != nil { + t.Fatalf("ListAllUnitIDs: %v", err) + } + if len(ids) == 0 { + t.Fatal("expected at least one unit ID") + } + + // GetRawUnit must be able to retrieve any unit by the ID that ListAllUnitIDs returns. + // Before the fix, this always returned "no rows in result set" on v1 MPRs. + for _, id := range ids { + raw, err := reader.GetRawUnit(model.ID(id)) + if err != nil { + t.Errorf("GetRawUnit(%s): %v", id, err) + continue + } + if raw == nil { + t.Errorf("GetRawUnit(%s): returned nil map", id) + continue + } + if _, ok := raw["$Type"]; !ok { + t.Errorf("GetRawUnit(%s): BSON missing $Type field", id) + } + } +} diff --git a/sdk/mpr/reader_documents.go b/sdk/mpr/reader_documents.go index a64cc18eb..a8b735bb4 100644 --- a/sdk/mpr/reader_documents.go +++ b/sdk/mpr/reader_documents.go @@ -462,8 +462,9 @@ func (r *Reader) GetRawUnit(id model.ID) (map[string]any, error) { return nil, fmt.Errorf("failed to read unit contents: %w", err) } } else { - // V1: Read from database - row := r.db.QueryRow("SELECT Contents FROM Unit WHERE UnitID = ?", string(id)) + // V1: Read from database — convert UUID to GUID blob for the query + unitIDBlob := types.UUIDToBlob(string(id)) + row := r.db.QueryRow("SELECT Contents FROM Unit WHERE UnitID = ?", unitIDBlob) err = row.Scan(&contents) if err != nil { return nil, fmt.Errorf("failed to read unit from database: %w", err) diff --git a/sdk/mpr/testdata/v1-project/App.mpr b/sdk/mpr/testdata/v1-project/App.mpr new file mode 100644 index 000000000..c86692854 Binary files /dev/null and b/sdk/mpr/testdata/v1-project/App.mpr differ