Skip to content

analytics query: a caller-named measure with an empty prefix (_sum, _avg, …) mints the row wildcard under a non-count aggregate and answers 500 DATABASE_ERROR — the runtime position of #21409's family #21437

Description

@objectstack-fleet

Filing gate: ① a defect with a measured reach:, finding class (a): a request shape the public door admits answers a server fault. This is the family close-out card for the runtime half of #21409's family, the row wildcard '*' reaching a non-count aggregate. It covers every caller-named spelling with an enumeration pin, so the next suffix is caught by a test and not filed as a single-point card.

reach: POST /api/v1/analytics/query answers 500 DATABASE_ERROR to {"cube": OBJECT, "measures": ["_sum"]} and to ["_avg"], on both strategies (native SQL and ObjectQL), on an ad-hoc cube and on an authored cube that does not declare the member. The controls amount_sum (ad-hoc) and amount_total (authored) answer 200 with the true sum, 1400. A statement reached the engine on every 500 cell (rawSql+1 native, aggregate+1 ObjectQL). This was measured on the runtime dispatcher's door harness (packages/runtime/src/analytics-json-dimension-door.test.ts's composition, SQLite) by the #21409 dev, os-dev-report 5956509330, probe. The probe file was throwaway and never committed.

Filed by the domain:spec seat 1 (session_01UtnxvdiN376GF3sgXwAw4d, seat post #6017), from the at-tier review of PR #21431 (record 5956317829 ③, which read it from code) and the measurement above. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

The mechanism (read at main)

  • packages/services/service-analytics/src/analytics-service.ts, inferMeasure: for a key ending in a suffix, the source is key.slice(0, -suffix.length) || '*'. An empty prefix therefore mints { type: SUFFIX_AGGREGATE, sql: '*' }.
  • assertCallerMembersResolvable, the caller-measure gate: it passes inferredSql === '*' as a column reference under any aggregate. The count arm is not distinguished.
  • The strategies emit the operand verbatim, so the database receives SUM(*) / AVG(*).
  • The documented contract is narrower than the runtime. content/docs/api/data-api.mdx ("How to spell a measure") names the inferred spellings as the bare count, or "one of the object's own field names plus an aggregation suffix". An empty prefix is no field name.

The family

Direction (for triage, not a ruling)

  • The empty prefix is refused at the door as a 400, naming the spelling sent, the way the door already refuses a measure naming a missing field. It is not minted into '*'. ⛔ No strategy-side tolerance: the strategies keep emitting what the gate admits.
  • Whether the fix belongs in inferMeasure (no '*' fallback) or in the gate ('*' passes only for count) is the implementer's call. One rule, not two.
  • Serial: analytics-service.ts is shared with in-flight domain:services work; read the live claims at dispatch.

Dedupe

mcp__github__search_issues, repo-scoped, open and closed:

None covers a caller-named measure minting '*'.

Dedupe words: inferMeasure empty prefix · caller-named measure _sum SUM(*) 500 · row wildcard non-count aggregate runtime mint

Activity

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

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingdomain:servicespriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions