Skip to content

helpers.js oql() turns column-keyed JSON into positional rows: a null column shifts every later value left, and oqlScalar over a view reads the ID #154

Closed

Description

@MendixMau

What happens

project-tests/e2e/helpers.js oql() (~l.617) normalises mxcli oql --direct --json output to {rows:[[v…]]}. For the bare-array shape it does Object.values(r). oqlScalar() (~l.647) then returns rows[0][0].

On mxcli v0.24.0 the answer is an array of objects whose keys come back in alphabetical order, with null columns left out. So:

  1. Positional rows are wrong.
    • Column order is alphabetical by alias, not the SELECT order.
    • Every column after a null is shifted one place left.
    • A check that reads row[2] reads a different column, with no error.
  2. oqlScalar over a view entity reads the ID. A query such as SELECT b.AttentionCount AS n FROM <Module>.<ViewEntity> AS b answers with the view's ID key as well. rows[0][0] is then the ID, not the count.
  3. Brace-depth slicing is not string-aware. A string value containing ] or } truncates the JSON before JSON.parse, and the helper returns null.

Evidence (card-disbursement requirements-driven build, 2026-09-26/27)

  • A workflow-proof script's early runs read wrong values. The raw mxcli oql --json answer listed each row's keys alphabetically and omitted the null ones. The project moved that script to reading rows as objects keyed by alias.
  • Drafting a view-entity check, oqlScalar returned the view row's ID.
    • Workaround: compare inside a scalar subquery so the only column is n — SELECT COUNT(c.ID) AS n FROM … WHERE … AND (SELECT b.X FROM <View> AS b) = (SELECT COUNT(x.ID) …), expect 1.
  • Separately, an unaliased column fails with "All OQL select columns must have a name". The helper's comment already says so.

Suggested fix

  • Parse the SELECT list's aliases (AS <alias>, in order) and build each row as aliases.map(a => obj[a] ?? null). Positional rows are then in SELECT order, with explicit nulls.
  • Add oqlRows(sql) → array of alias-keyed objects, and make oqlScalar read the first alias, not rows[0][0].
  • Replace the brace counter with a string-aware scan, or parse the line that starts with [/{ through to the matching end.
  • Callers in journey-runner.js (count(), data rungs) use oqlScalar with a single AS n. For them the alias rule is the fix for the view case.

Filed rather than fixed because the golden capture (verbatim mxcli oql --direct --json output with nulls, and over a view entity) needs a running app's admin API. The field project's app could not be queried from this session.

Files

  • project-tests/e2e/helpers.js: oql, oqlScalar
  • project-tests/e2e/journey-runner.js: callers
  • skills/learned-db-assertions.md

Activity

  1. added a commit that references this issue on Oct 13, 2026
    a5235d6
  2. MendixMau commented on Oct 14, 2026

    @MendixMau
    OwnerAuthor

    Fixed by #310, which landed on master in the integration squash #329 (commit 31e90ae) after independent review. Closing; reopen if it still reproduces on master.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions