Skip to content

Fix queryChange dropping quotes from plain phrases containing reserved characters - #138

Open
paperboyo wants to merge 1 commit into
mainfrom
mk-claude-fix-cqlstr-quoting
Open

Fix queryChange dropping quotes from plain phrases containing reserved characters#138
paperboyo wants to merge 1 commit into
mainfrom
mk-claude-fix-cqlstr-quoting

Conversation

@paperboyo

@paperboyo paperboyo commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Co-authored by Claude; description written by me. The top bit. The smaller one.

I noticed that "hello:world" a) does not survive a page reload quoted and subsequently b) is turned into a chip in Kupua, but not Kahuna. Upon (robot) investigation, it turned out Kahuna contains a workaround for something that (robot “says”) should probably be provided by CQL itself. This has practical implications for these boring fileMetadata searches in Grid (they can contain colon in keys).

We now have a workaround in Kupua too. So if this here code is unwelcomed for whatever reason, please feel free to 🔪 it (although I am interested in what is correct here!).

All tests pass successfully.

🤖 narrative:

strFromExpr's CqlStr case (in interpreter.ts) only re-quotes a plain phrase when it contains whitespace. Chip keys/values (strFromField) already check the fuller shouldQuoteFieldValue (whitespace or a reserved char: :, (, ), "). This PR makes both cases use the same predicate.

Symptom: a quoted phrase like "hello:world" loses its quotes the moment queryChange reports it (detail.queryStr), then gets mis-parsed as a hello:world chip the next time that text is read — reproducible with a bare <cql-input> element and zero application code, on the very first value set.

Some context that might be useful: the scanner treats a bare colon as chip syntax everywhere, not just after a recognised key, so an unquoted colon in free text is ambiguous on the next parse — the same reasoning chip values already handle. I don't know if the current whitespace-only check for plain phrases was a deliberate call or an oversight, so I'll leave that judgement to you — happy to close/rework this if there's a reason for the current behaviour I'm missing.

Context: found while building a feature in kupua that surfaced this via arbitrary ES field paths used as quoted CQL phrases (e.g. "fileMetadata.xmp.dc:subject"). kupua has a local workaround (a corrected reimplementation of this same serialiser) that can be deleted once this ships and kupua upgrades — happy to link that if useful for review context.

A second consumer of this library hit the same gap and worked around it independently: kahuna never uses queryStr/searchExpr for its persisted query at all — it reads the string token's raw .lexeme instead, specifically to avoid this. From gr-cql-input/syntax.ts (structuredQueryFromStr):

value: str.token.lexeme,
// Take the lexeme, rather than the literal, as if the string
// is quoted we must preserve the quotes: this what Grid expects

Changes:

  • lib/cql/src/lang/interpreter.ts — one-line fix, drops now-unused hasWhitespace import.
  • lib/cql/src/lang/interpreter.spec.ts — 4 new tests (colon, parens, no-reserved-char passthrough, alongside the existing quote-escaping test).
  • Changeset (patch bump).

How has this change been tested?

Tested by deploying to Sandbox.

How can we measure success?

Less workarounds in apps. Chips are chips only when we really want. Colons in their keys do not trip us up (as often).

Have we considered potential risks?

The risk is that chip-like present may eventually conflict with chip-less future (?).

Images

Before:

before2

After:

after1

interpreter.ts's strFromExpr serialised a CqlStr (plain phrase) back to
a string using hasWhitespace() alone to decide whether to re-quote it.
Chip keys/values (strFromField) already used the more complete
shouldQuoteFieldValue() (whitespace OR reserved char: `:`, `(`, `)`,
`"`). The two should agree — an unquoted colon is exactly as ambiguous
in a plain phrase as in a chip value, since the scanner treats a bare
colon as chip syntax everywhere.

Symptom: a quoted phrase like "hello:world" loses its quotes the
moment queryChange reports it, then gets mis-parsed as a hello:world
chip the next time that text is read (e.g. the next keystroke, or just
focusing the input again after the value was set once).
@paperboyo paperboyo added the fix Departmental tracking: fix label Aug 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@paperboyo
paperboyo requested a lite review from Copilot August 10, 2026 23:57
@github-actions

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes CQL query string serialization so that plain phrases containing reserved characters (e.g. : or parentheses) remain quoted when re-serialized from the AST. This prevents round-trip corruption where a quoted phrase like "hello:world" becomes hello:world and then gets re-parsed as a chip (hello:world) on subsequent reads (notably via the <cql-input> queryChange.detail.queryStr flow).

Changes:

  • Update the CqlStr serialization logic to use the same quoting predicate as chip keys/values (shouldQuoteFieldValue), rather than only quoting on whitespace.
  • Add unit tests covering reserved-character phrases (colon, parens) and a non-quoting passthrough case.
  • Add a patch changeset documenting the behavioral fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
lib/cql/src/lang/interpreter.ts Aligns plain-string quoting with chip key/value quoting to preserve reserved characters across serialization.
lib/cql/src/lang/interpreter.spec.ts Adds tests to prevent regressions for reserved-character plain phrases and simple unquoted strings.
.changeset/gentle-moles-jump.md Declares a patch bump and documents the quote-preservation fix and its motivation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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

Labels

fix Departmental tracking: fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants