Skip to content

fix(queryBuilder): support JSON column filters and JSON-typed trace tags#1792

Open
adamyeats wants to merge 2 commits intomainfrom
feat/json-type-filter-support
Open

fix(queryBuilder): support JSON column filters and JSON-typed trace tags#1792
adamyeats wants to merge 2 commits intomainfrom
feat/json-type-filter-support

Conversation

@adamyeats
Copy link
Copy Markdown
Contributor

@adamyeats adamyeats commented Apr 19, 2026

Summary

  • Adds isJsonType() type guard so JSON columns can be detected alongside Map/String/etc. rather than falling through to the string catch-all.
  • Fixes filter SQL generation for JSON sub-columns (closes "filter for value" do not support json type #1281): after JSON path navigation in getFilters(), the column is now cast to Nullable(String) and type set to 'String', so IN / NOT IN / IsEmpty / IsNotEmpty route through the correct filter-part builders instead of stringifying arrays or skipping the value branch.
  • Restricts the operator list for JSON columns in FilterEditor to the set that actually works on JSON paths (excludes IsEmpty / IsNotEmpty, which are unreliable on JSON sub-columns).
  • Handles JSON-typed traceTags / traceServiceTags in generateTraceIdQuery() — previously the generator unconditionally emitted Map mapKeys(...) syntax, which crashes on JSON columns (closes Cannot query single trace when using JSON column for ResourceAttributes and ScopeAttributes #1321). Partial fix for JSON type support for Logs and Traces #1424.
  • New E2E regression guard validates the generated SQL shape against a real ClickHouse instance (fixture table with a JSON column + jsonFilter.spec.ts covering Equals / IN / nested path / LIKE).

Why ::Nullable(String) and not plain ::String?

Writing the E2E tests surfaced a runtime bug that the unit tests couldn't have caught: ClickHouse JSON path extraction returns Dynamic, and IN / NOT IN reject Dynamic with ILLEGAL_TYPE_OF_ARGUMENT. The obvious fix is a ::String cast — but that quietly breaks IS NULL, because ::String maps a missing JSON key to an empty string rather than null. ::Nullable(String) satisfies both constraints and is a no-op for Equals / NotEquals / LIKE.

Scope

  • Does NOT enable fetchPathsForJSONColumns() (still disabled for perf reasons).
  • Does NOT broaden the catch-all isStringType in utils.ts.
  • No new filter types — JSON piggybacks on the existing StringFilter / MultiFilter shapes since path values are strings.

…me bug

The E2E fixture now includes a table with a ClickHouse JSON column so the
exact SQL our query builder emits for JSON sub-column filters can be
validated end-to-end against a real ClickHouse instance.

Writing the tests surfaced a real bug: path extraction from a JSON column
returns Dynamic, which ClickHouse's `IN` / `NOT IN` reject with
ILLEGAL_TYPE_OF_ARGUMENT. Unit tests only asserted the string shape and
couldn't catch this.

Fix: cast JSON path accesses to `Nullable(String)`. A plain `::String`
cast would silently break `IS NULL` (missing keys become empty strings);
`Nullable(String)` keeps the null signal intact while satisfying `IN`'s
type requirements. Equals / NotEquals / LIKE are unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Incoming

Development

Successfully merging this pull request may close these issues.

Cannot query single trace when using JSON column for ResourceAttributes and ScopeAttributes "filter for value" do not support json type

1 participant