mxaccesscli: support bulk array writes via <arrayAttr>[]
WriteCommand now accepts multiple positional values when the tag reference ends with '[]', bundling them into a strongly-typed array (string[], int[], bool[], etc.) before passing to MxAccess.Write. The CLR marshals the array to a COM SAFEARRAY of the matching VARTYPE, which is the shape MxAccess expects for an array attribute. Verified live on a 50-slot String[] (MESReceiver_001.MoveInPartNumbers): write 50 distinct strings A1..A50 -> ok, MxCategoryOk read [] -> ['A1','A2', ..., 'A50'] Plus a guardrail: passing multiple values without the '[]' suffix exits 2 with a clear error so a typo can't accidentally write only the first element of an indexed reference. Critical finding documented in docs/usage.md: **a bulk write resizes the array to the count provided.** Writing 25 values into a 50-slot array leaves the array at 25 elements; the trailing 25 are deallocated, not zero-filled. Verified by 50 -> 25 -> 50 round-trip on the same attribute. Discover the runtime length via 'mxa read <attr>[]' or the configured length via grdb's attributes.sql array_dimension column. Type matrix in docs/usage.md updated: - Bulk array via '[]' - read ✅ + write ✅ - Bare reference (no brackets) - read ❌ + write ❌ - Element via '[N]' - unchanged ValueCoercion.cs: adds CoerceArray(IReadOnlyList<string>, typeHint) that produces strongly-typed arrays. Default element type is inferred from the first value when --type is unspecified. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -131,8 +131,8 @@ Verified end-to-end against the live `ZB` galaxy (System Platform 2017 Express,
|
||||
| `MxQualifiedStruct` (14) | – | – | – | Access via dotted member names: `<obj>.<struct>.<field>`. |
|
||||
| `MxInternationalizedString` (15) | ❓ | ❓ | (likely string) | No accessible instance. |
|
||||
| `MxBigString` (16) | ❓ | ❓ | JSON string | No accessible instance. |
|
||||
| **Array (any type), bulk read** | ✅ | – | JSON array of element type | Reference syntax `<obj>.<arrayAttr>[]` — **empty square brackets**. Verified on `MESReceiver_001.MoveInPartNumbers[]` (String[50]) and `MoveOutWorkOrderNumbers[]`. Returns the entire array as a single value with `MxCategoryOk`. |
|
||||
| **Array (bare reference)** | ❌ | – | — | The plain `<obj>.<arrayAttr>` (no brackets) returns `MxCategoryCommunicationError, Detail=1003`. Use `[]` instead. |
|
||||
| **Array (any type), bulk read/write via `[]`** | ✅ | ✅ | JSON array of element type | Reference syntax `<obj>.<arrayAttr>[]` — **empty square brackets**. Read returns the entire array as a single value. Write takes one positional value per element (`mxa write '<obj>.<arr>[]' v1 v2 v3 ...`). **A bulk write resizes the array to the count provided** (verified: 50 → 25 → 50 round-trip on `MoveInPartNumbers`). |
|
||||
| **Array (bare reference)** | ❌ | ❌ | — | The plain `<obj>.<arrayAttr>` (no brackets) returns `MxCategoryCommunicationError, Detail=1003`. Always use `[]` for bulk operations. |
|
||||
| **Array element by index** | ✅ | ✅ | scalar of element type | Reference syntax `<obj>.<arrayAttr>[<n>]`. **1-based**, runs from `[1]` to `[NumElements]`. `[0]` is invalid. |
|
||||
|
||||
Legend: ✅ verified live, ⚠️ wiring present but no live instance to write, ❓ wiring present but no live instance found, ❌ not supported by MxAccess at this layer, – not applicable.
|
||||
@@ -191,6 +191,27 @@ mxa read 'MESReceiver_001.MoveInPartNumbers[2]' --llm-json
|
||||
|
||||
Indices are **1-based**: `[1]` is the first element, `[NumElements]` is the last. `[0]` is invalid. Single-element reads are also writeable: `mxa write '<obj>.<attr>[N]' <value>`.
|
||||
|
||||
### Whole array write — also via `[]`
|
||||
|
||||
Pass one positional value per element after the tag. The CLI bundles them into a strongly-typed array (`string[]`, `int[]`, `bool[]`, …) before writing.
|
||||
|
||||
```powershell
|
||||
# Write a 50-element string array
|
||||
mxa write 'MESReceiver_001.MoveInPartNumbers[]' \
|
||||
"" "11111" "" "" "" "" "" "" "" "" \
|
||||
"" "" "" "" "" "15" "" "" "" "" \
|
||||
"" "" "" "" "" "" "" "" "" "" \
|
||||
"" "" "" "" "" "" "" "" "" "" \
|
||||
"" "" "" "" "" "" "" "" "" ""
|
||||
|
||||
# Write a typed array
|
||||
mxa write 'SomeObj.SomeFloats[]' 1.0 2.5 3.14 --type float
|
||||
```
|
||||
|
||||
> ⚠️ **A bulk write resizes the array to the count provided.** If the configured `array_dimension` is 50 and you supply 25 values, after the write `mxa read '...[]'` returns **25** elements, not 50. The trailing slots are deallocated, not zero-filled. Always supply the full element count when you want to preserve the array's logical size — fetch the current count via `mxa read '...[]' --llm-json` first, or read it from `array_dimension` in [`../../grdb/queries/attributes.sql`](../../grdb/queries/attributes.sql).
|
||||
>
|
||||
> Mixing scalar / array forms is guarded: passing multiple values without `[]` exits 2 with a clear error message.
|
||||
|
||||
### What does *not* work
|
||||
|
||||
```powershell
|
||||
@@ -198,14 +219,14 @@ mxa read 'MESReceiver_001.MoveInPartNumbers' # bare ref, no brackets
|
||||
# → MxCategoryCommunicationError, Detail=1003
|
||||
```
|
||||
|
||||
The plain reference (no `[]`, no `[N]`) is rejected by the proxy. Always include the brackets — empty for whole-array, indexed for element.
|
||||
The plain reference (no `[]`, no `[N]`) is rejected by the proxy on both read and write. Always include the brackets — empty for whole-array, indexed for element.
|
||||
|
||||
### Discovering array length
|
||||
|
||||
The CLI doesn't (yet) auto-discover element count. Two ways to find it:
|
||||
|
||||
1. Read with `[]` and count the returned values.
|
||||
2. Query the Galaxy Repository's [`../../grdb/queries/attributes.sql`](../../grdb/queries/attributes.sql) — the `array_dimension` column reports the configured size from the template.
|
||||
1. Read with `[]` and count the returned values (this is the **runtime** length, which may have been resized by a previous bulk write).
|
||||
2. Query the Galaxy Repository's [`../../grdb/queries/attributes.sql`](../../grdb/queries/attributes.sql) — the `array_dimension` column reports the **configured** size from the template at deploy time.
|
||||
|
||||
## Picking a tag for a smoke test
|
||||
|
||||
|
||||
Reference in New Issue
Block a user