Problem
Both SDKs emulate the like/not_like filter operators client-side (for live-stream and other client-side filtering paths) using case-insensitive regexes, while the server compiles the same operator to ClickHouse's LIKE, which is case-sensitive, for historical queries. A LiveQuery that combines a historical backfill with a live stream can therefore apply two different match semantics to the same filter within a single query: the backfill (server-side LIKE) excludes rows the live stream (client-side, case-insensitive) would include — or, for not_like, the reverse.
Evidence
- Go:
clients/go/stream.go, compileLike compiles the SQL LIKE pattern to a regex with the (?i) case-insensitive flag; its doc comment explicitly says "matching the TS SDK."
- TS:
clients/ts/src/query-builder.ts:341-353 — both the like and not_like cases build new RegExp(pattern, "i"), the case-insensitive flag.
- Server:
internal/query/builder.go:365-366 — the like case compiles directly to ClickHouse col + " LIKE ?", which is case-sensitive by default in ClickHouse (there's no ILIKE here).
- The client-side behavior is documented, not accidental:
docs/src/content/docs/sdk/go/streaming.md:198-201 states client-side like/not_like matching is case-insensitive, and the Go implementation's own comment calls this deliberate TS parity.
Proposed fix
This is a design-alignment decision, not a straightforward bug fix — three options, each with different tradeoffs:
- Make both SDKs case-sensitive to match ClickHouse's
LIKE. Removes the split, but is a breaking behavior change for any TS SDK user currently relying on case-insensitive client-side matching (the TS SDK is where this behavior originated).
- Switch the server to
ILIKE for the like/not_like operators. Aligns the server with the SDKs' existing behavior, but changes historical-query semantics for any existing caller relying on ClickHouse's default case-sensitive LIKE.
- Keep the divergence and document it more prominently in both SDKs' reference/streaming pages, calling out specifically that a
LiveQuery's backfill and live-stream portions can disagree on like/not_like matches.
No option is obviously correct without knowing whether any current caller depends on either semantic; this issue is to make the decision explicitly rather than let the split remain implicit.
Scope
clients/go/stream.go
clients/ts/src/query-builder.ts
internal/query/builder.go
docs/src/content/docs/sdk/go/streaming.md
docs/src/content/docs/sdk/streaming.md
Surfaced by an external Codex review of PR #434; verified pre-existing since the TS SDK (the Go SDK's case-insensitive behavior is an intentional match to the earlier TS behavior, not a new regression).
Problem
Both SDKs emulate the
like/not_likefilter operators client-side (for live-stream and other client-side filtering paths) using case-insensitive regexes, while the server compiles the same operator to ClickHouse'sLIKE, which is case-sensitive, for historical queries. ALiveQuerythat combines a historical backfill with a live stream can therefore apply two different match semantics to the same filter within a single query: the backfill (server-sideLIKE) excludes rows the live stream (client-side, case-insensitive) would include — or, fornot_like, the reverse.Evidence
clients/go/stream.go,compileLikecompiles the SQL LIKE pattern to a regex with the(?i)case-insensitive flag; its doc comment explicitly says "matching the TS SDK."clients/ts/src/query-builder.ts:341-353— both thelikeandnot_likecases buildnew RegExp(pattern, "i"), the case-insensitive flag.internal/query/builder.go:365-366— thelikecase compiles directly to ClickHousecol + " LIKE ?", which is case-sensitive by default in ClickHouse (there's noILIKEhere).docs/src/content/docs/sdk/go/streaming.md:198-201states client-sidelike/not_likematching is case-insensitive, and the Go implementation's own comment calls this deliberate TS parity.Proposed fix
This is a design-alignment decision, not a straightforward bug fix — three options, each with different tradeoffs:
LIKE. Removes the split, but is a breaking behavior change for any TS SDK user currently relying on case-insensitive client-side matching (the TS SDK is where this behavior originated).ILIKEfor thelike/not_likeoperators. Aligns the server with the SDKs' existing behavior, but changes historical-query semantics for any existing caller relying on ClickHouse's default case-sensitiveLIKE.LiveQuery's backfill and live-stream portions can disagree onlike/not_likematches.No option is obviously correct without knowing whether any current caller depends on either semantic; this issue is to make the decision explicitly rather than let the split remain implicit.
Scope
clients/go/stream.goclients/ts/src/query-builder.tsinternal/query/builder.godocs/src/content/docs/sdk/go/streaming.mddocs/src/content/docs/sdk/streaming.mdSurfaced by an external Codex review of PR #434; verified pre-existing since the TS SDK (the Go SDK's case-insensitive behavior is an intentional match to the earlier TS behavior, not a new regression).