Skip to content

$search is case-sensitive on textual fields, contrary to three declarations that say case-insensitive #7641

Description

@huangyiirene

Symptom

$search is case-sensitive on textual fields, contrary to three declarations that all say case-insensitive: the cross-field-object-search checklist item title, the search-filter.ts docblock ("Matching: case-insensitive"), and the search-conformance ledger row.

POST /api/v1/data/showcase_account/query {"search":"Retail","searchFields":["name"]} returns 1 record ("Acme Retail"); the same query with "retail" returns [], total 0. Also reproduces for stark/Stark, wonka/Wonka, NORTHWIND. Reproduced on two fresh boots.

Cross-field OR scanning and multi-term AND semantics are correct; only the case-fold clause fails. Enum/select terms are unaffected because optionValuesMatching lowercases both sides in JS before emitting $in.

Root cause

packages/objectql/src/search-filter.tsfieldClausesForTerm emits {field:{$contains:term}} for textual types, and $contains is contractually case-sensitive (#4706 Q2=A). The #6518 SQLite LIKEGLOB change removed SQLite's incidental ASCII fold, exposing this. The case-insensitive operator is $icontains: {name:{$icontains:'retail'}}does return "Acme Retail".

Confirmed still present on origin/main (76d74ecb): the docblock (line 18) still declares "Matching: case-insensitive", and fieldClausesForTerm still emits $contains (lines 91/93).

Decision dimension

The fix has a direction that is the maintainer's call:

  • (A) make $search emit $icontains for textual fields, so behaviour matches the three declarations; or
  • (B) change the three declarations to say case-sensitive.

Recommend (A): search is near-universally expected to be case-insensitive, and three places already declare it so. Whichever way #4706 Q2 finally lands, the three declarations (item title, search-filter.ts docblock, search-conformance ledger row) must be made consistent with the behaviour. Filed as a bug per maintainer instruction.

Reproduction

POST /api/v1/data/showcase_account/query {"search":"Retail","searchFields":["name"]}
→ 200, 1 record "Acme Retail"
POST /api/v1/data/showcase_account/query {"search":"retail","searchFields":["name"]}
→ 200, records [] total 0

{name:{$icontains:'retail'}} matches; {name:{$contains:'retail'}} does not. The dogfood pin stayed green because its only case assertion is a select label — a single lowercase-name assertion would catch this.

Source

Extracted from the QA run #7629 (framework 92f26f7, console 6314e87f).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions