Skip to content

Align contains query with utopia-php/database semantics#28

Merged
lohanidamodar merged 2 commits into
mainfrom
claude/usage-audit-contains-query-yeyydm
Jul 21, 2026
Merged

Align contains query with utopia-php/database semantics#28
lohanidamodar merged 2 commits into
mainfrom
claude/usage-audit-contains-query-yeyydm

Conversation

@lohanidamodar

Copy link
Copy Markdown
Contributor

What

The ClickHouse adapter translated Query::contains / Query::notContains into SQL IN (...) / NOT IN (...) — exact-value set matching. utopia-php/database treats contains on scalar attributes as a substring match instead. This aligns the adapter with that behavior:

  • contains('attr', [v1, v2])(attr LIKE '%v1%' OR attr LIKE '%v2%')
  • notContains('attr', [v1, v2])(attr NOT LIKE '%v1%' AND attr NOT LIKE '%v2%')
  • LIKE wildcards (%, _, \) in needles are escaped so they match literally, mirroring the database library's escapeWildcards
  • Non-string values are rejected, matching existing startsWith / endsWith handling

The Database adapter already delegates contains / notContains to utopia-php/database and needed no change.

Behavior note

contains is now a genuine superset match: contains('metric', ['requests']) also matches a hypothetical sub-requests metric. This is the database library's documented behavior; callers wanting exact set membership should use Query::equal with an array.

Tests

  • testContainsQuery extended with substring assertions ('band' matches bandwidth)
  • New testNotContainsQuery covering negated substring matching
  • Both run against the ClickHouse and Database adapters via UsageBase
  • Ran against live ClickHouse 25.8 and MariaDB: ClickHouse e2e 74/74, Database 37/37, service-free suites 56/56; pint passes

🤖 Generated with Claude Code

https://claude.ai/code/session_01MkhSkCMPSXuJ4aY3T7XMbg


Generated by Claude Code

The ClickHouse adapter translated Query::contains/notContains into
IN/NOT IN lists — exact-value set matching. utopia-php/database treats
contains on scalar attributes as a substring match: each value becomes
LIKE '%value%' (OR'd together), and notContains becomes NOT LIKE
(AND'd). Generate the same SQL here, escaping LIKE wildcards in the
needles so '%' and '_' match literally. The Database adapter already
delegates to utopia-php/database and needs no change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MkhSkCMPSXuJ4aY3T7XMbg
@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR aligns ClickHouse usage queries with substring matching semantics. The main changes are:

  • contains now builds LIKE predicates instead of exact IN checks.
  • notContains now builds combined NOT LIKE predicates.
  • LIKE wildcard characters in search values are escaped before binding.
  • Usage tests now cover substring matches and literal wildcard needles.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
src/Usage/Adapter/ClickHouse.php Updates ClickHouse query generation for contains and notContains to use escaped substring matching.
tests/Usage/UsageBase.php Adds shared usage tests for substring matching and literal wildcard handling.

Reviews (2): Last reviewed commit: "Add e2e coverage for LIKE wildcard escap..." | Re-trigger Greptile

Comment thread src/Usage/Adapter/ClickHouse.php
Verifies against a real server that '%' and '_' in contains needles
match literally through the bound-parameter path: a '%' needle matches
only the metric containing a literal percent sign, and 'cache_hit'
does not match 'cache%hit'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MkhSkCMPSXuJ4aY3T7XMbg
@lohanidamodar
lohanidamodar merged commit 7c3fbf1 into main Jul 21, 2026
4 checks passed
@lohanidamodar
lohanidamodar deleted the claude/usage-audit-contains-query-yeyydm branch July 21, 2026 05:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants