fix: keep parsed-JSON "Add to Filters" keys as valid SQL#2561
Conversation
"Add to Filters" on a value inside parsed JSON from a String column (for example Body) builds a JSONExtractString(...) expression as the filter key. toClickHouseKeyExpression only short-circuited bracket access, backtick paths, and toString(...), so the JSONExtract expression fell through to parseMapFieldName, whose dot pattern split on the dot inside the quoted JSON path argument. mergePath then rewrote it into the invalid JSONExtractString(Body, 'app['user.currency')'], which ClickHouse rejects. Generalize the pass-through guard to any raw SQL function-call expression so JSONExtractString/Float/Bool (and toString) keys reach filtersToQuery unchanged and serialize to valid SQL. Add unit, pipeline, and component coverage asserting the JSON add-to-filter path emits valid, round-trippable SQL. HDX-4427 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Seed a log whose Body is a JSON string with a flat dotted key into the
default logs table, add a SidePanelComponent helper that adds a nested
JSON value to filters from the parsed tab, and assert the resulting
search runs against ClickHouse without error and returns the matching
row.
Verified by driving the real app: the action builds
JSONExtractString(Body, 'app.user.currency') IN ('USD') and the query
succeeds instead of the previously mangled, rejected expression.
HDX-4427
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: c055770 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🔵 Tier 2 — Low RiskSmall, isolated change with no API route or data model modifications. Why this tier:
Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns. Stats
|
Greptile SummaryThis PR fixes a SQL-generation bug where "Add to Filters" on a value inside a parsed-JSON String column (e.g.
Confidence Score: 5/5Safe to merge — the change is a one-line regex guard in a single utility function with no broader side effects on existing key shapes. The fix is minimal: one new predicate and one replaced condition in No files require special attention. Important Files Changed
Reviews (4): Last reviewed commit: "Merge branch 'main' into alex/fix-json-a..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 224 passed • 3 skipped • 1345s
Tests ran across 4 shards in parallel. |
…t id
The e2e failed in CI because ServiceName:"json-body-filter-svc" (hyphens)
tokenizes in Lucene and did not isolate to the seeded row (48 rows matched).
Use an underscore ServiceName so the quoted Lucene term matches exactly,
matching the pattern in total-count-matches-table.
Address the review note on the fragile CSS-module class selector: add
data-testid="json-viewer-line" to the JSON viewer line and locate lines by
that test id instead of an xpath class-substring match.
Verified end to end in a real browser: the search isolates to one row and
"Add to Filters" builds JSONExtractString(Body, 'app.user.currency') IN ('USD').
HDX-4427
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Selecting the source resets the search bar, so the ServiceName query never
applied and the results stayed unfiltered (48 rows in CI, failing the
toHaveCount(1) setup). The default source is already the logs source, the
same assumption total-count-matches relies on, so goto -> selectRelativeTime
-> performSearch isolates correctly. Verified end to end in a real browser
against ClickHouse: search isolates, "Add to Filters" builds
JSONExtractString(Body, 'app.user.currency') IN ('USD'), no error.
HDX-4427
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deep ReviewFocused SQL-serialization bug fix: 🔴 P0/P1 — must fix
🟡 P2 — recommended
🔵 P3 nitpicks (2)
Reviewers (7): ce-correctness-reviewer, ce-testing-reviewer, ce-maintainability-reviewer, ce-project-standards-reviewer, ce-kieran-typescript-reviewer, ce-security-reviewer, ce-adversarial-reviewer. Testing gaps: No coverage for adversarial JSON keys (embedded quote/paren/backslash) through the widened pass-through guard, nor a producer-level test asserting |
"Add to Filters" on a value inside parsed JSON from a String column (for example
Body) builds a query ClickHouse rejects. Expand a log whoseBodyis a JSON string, then filter on a nested value such asapp.user.currency = USD, and the generated condition is:which fails to parse. This fixes the filter-key serialization so the generated SQL is valid.
Resolves HDX-4427.
Summary
The JSON viewer builds a correct ClickHouse expression for the filter key,
JSONExtractString(Body, 'app.user.currency'). That key then flows throughescapeFilterStateKeysintotoClickHouseKeyExpression, which only short-circuited bracket access, backtick paths, andtoString(...). AJSONExtract*(...)expression fell through toparseMapFieldName, whose dot pattern split on the dot inside the quoted JSON path argument, andmergePaththen rewrote it into the invalidJSONExtractString(Body, 'app['user.currency')'].The pass-through guard now treats any raw SQL function-call expression (
toString(...),JSONExtractString/Float/Bool(...)) as an already-valid ClickHouse expression and returns it unchanged, so it reachesfiltersToQueryintact and serializes toJSONExtractString(Body, 'app.user.currency') IN ('USD'). Dot-form Map sub-keys likeLogAttributes.host.namecontain no parentheses, so they still rewrite to bracket form as before.Changes
packages/app/src/components/DBSearchPageFilters/utils.ts: generalize thetoClickHouseKeyExpressionpass-through guard fromtoString(to any function-call expression.escapeFilterStateKeys->filtersToQuery->parseQuerypipeline and asserts every emitted condition is valid, round-trippable SQL across a range of JSON and Map key shapes; and a component test locking the "Add to Filters" contract for a parsed-JSON String column.Bodyvalue from the row side panel and confirms the search runs without a ClickHouse error and returns the matching row.Test plan
nx run-many -t ci:lint(eslint + tsc)nx run-many -t ci:unitBodyvalue buildsJSONExtractString(Body, 'app.user.currency') IN ('USD'), the query runs, and the row is returnedpackages/app/tests/e2e/features/search/json-add-to-filter.spec.ts[ui-check: allow] No visual surface; the change is filter-key SQL serialization, verified via unit, integration, and end-to-end tests.
[viewport: allow] Layout-neutral logic fix.
[ui-states: allow] No empty/loading/error UI states in scope.