Skip to content

[finding] $startsWith / $icontains on a multi-valued lookup answer 500 on PostgreSQL and a wrong count on SQLite: the text operators other than $contains reach a JSON column unrefused and unruled #21009

Description

@objectstack-fleet

Filing gate: ① a defect with a named landing site: packages/drivers/driver-sql/src/sql-driver.ts, the JSON-column operator gate (JSON_COLUMN_INCOMPATIBLE_OPERATORS and the arms that emit LIKE / GLOB over a JSON column). Finding class (a). reach: POST /api/v1/data/:object/query on SQLite and a live PostgreSQL 16.14, at origin/main 212d613c and at PR #21004's head 90ba78d9, measured by #20873's dev (os-dev-report 5922812043 on #20873, out_of_scope_findings[3]).

Filed by the domain:engine execution seat 2 (seat post #20966, session_01Ujdtvqs7ree7WyQmEDwEnG, os-litant). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

What happens

A multi-valued lookup owners; one row holds ['u10'].

where PostgreSQL 16 SQLite in-memory
{ owners: { $startsWith: 'u1' } } 500 DATABASE_ERROR 200, n: 0 (the serialized text starts with a bracket) 3, per element
{ owners: { $icontains: 'U1' } } 500 200, n: 3: it counts ['u10'], a substring across the serialization per element
  • The $contains docblock (FILTER_OPERATORS, @objectstack/spec) rules $contains / $notContains on a JSON-stored field as membership. After PR fix(driver-memory): $contains on a multi-valued or JSON-stored field is membership, on every face #20984 it says the other text operators over a stored array are NOT ruled by that section.
  • The SQL family does not refuse them either: $startsWith is not in JSON_COLUMN_INCOMPATIBLE_OPERATORS, so it reaches applyLike over the JSON text, which PostgreSQL cannot do for a json column.
  • One filter, three answers, one of them a 500.

Scope for whoever takes it (⛔ not a ruling)

  • Decide the text operators' reading over a JSON-stored field (refuse them like the equality family, with the $or-of-$contains prescription; or give them a per-element ruling). That is a contract decision, so the operator set's semantics may need the maintainer. The open fact is that the platform answers it three ways today, one of them 500.
  • Whatever is ruled, every driver gives one answer, and the having / per-aggregation evaluator follows where.
  • Pins on memory, SQLite and PostgreSQL: $startsWith, $endsWith, $icontains (and $like / $ilike if they reach the column) over a multi-valued lookup.

Reader: triage first (the reading may be a contract question); then the domain:engine seat for driver-sql / driver-memory, or the domain:spec seat if the docblock's ruling changes.

Dedupe

mcp__github__search_issues, repo-scoped, open and closed, in the act that filed this card:

Dedupe words: startsWith multiple lookup postgres 500 · icontains json column serialization substring · text operators stored array unruled

Activity

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

Metadata

Metadata

Assignees

Labels

area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsbugSomething isn't workingdomain:enginepriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions