feat(eap): Add wildcard search support for array string attributes#7770
feat(eap): Add wildcard search support for array string attributes#7770
Conversation
Support LIKE/NOT_LIKE operations on TYPE_ARRAY attribute keys in the EAP RPC filter layer. This enables searching for rows where any element in an array attribute matches a wildcard pattern (e.g. `%error%`). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/MPMg6cd5C44sTcO2w7G21dFgr2ROlgzLl2IsE6tXT_M
snuba/protos/common.py
Outdated
| alias, | ||
| ) | ||
|
|
||
| if attr_key.type == AttributeKey.Type.TYPE_ARRAY: |
There was a problem hiding this comment.
There should be no need for this
There was a problem hiding this comment.
Good call — moved the array expression building out of attribute_key_to_expression and into a local helper _build_array_attr_expression in the filter code. The k_expression for TYPE_ARRAY is now resolved directly at the filter site without touching the shared proto function.
volokluev
left a comment
There was a problem hiding this comment.
There should be a test of the API actually doing stuff, not just the query generation
…ession Address review feedback: instead of adding TYPE_ARRAY handling to the shared attribute_key_to_expression function, build the array extraction expression directly in the filter code where it's needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/pjQ2FphvcZ1pKVc4nPolPe74-FfTxXiVaeKc5q4XyME
Handle TYPE_ARRAY as an early return in comparison filter processing so unsupported operations (EQUALS, IN, etc.) raise immediately instead of producing invalid SQL. Add test for this error path. Co-Authored-By: Claude <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/hhni4eW0BB_sX1hx1k3ocFkKDVAR5tFkoNu10Z-uERw
Add check that the comparison value is a string before using val_str for TYPE_ARRAY LIKE/NOT_LIKE operations. Without this, a non-string value silently defaults to an empty string pattern. Co-Authored-By: Claude <noreply@anthropic.com> Agent transcript: https://claudescope.sentry.dev/share/H-XBt-koklI88xXMMmB8rnyAuP-g8fRDyDXx9KD7YI4
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| def _build_array_attr_expression(attr_name: str) -> DangerousRawSQL: | ||
| """Build a DangerousRawSQL expression that extracts string values from | ||
| the attributes_array JSON column for a given attribute name.""" | ||
| safe_name = attr_name.replace("`", "``") |
There was a problem hiding this comment.
Incorrect identifier escaping in raw SQL construction
High Severity
The _build_array_attr_expression escapes backticks by doubling (replace("", "")`), but the codebase's own `escape_identifier` in `snuba/clickhouse/escaping.py` uses backslash-prefix escaping for both backticks and backslashes ( `` → `` \ , `\` → `\\`). This inconsistency means backslashes in `attr_name` are not escaped at all. An attribute name containing a backslash followed by content could cause ClickHouse to misparse the backtick-quoted identifier boundary, since `\ would be interpreted as an escaped backtick rather than the closing delimiter. Since this flows through DangerousRawSQL which bypasses all safety checks, this could lead to SQL parsing errors or injection.


Summary
TYPE_ARRAYhandling inattribute_key_to_expressionusingDangerousRawSQLto extract string values from the JSONattributes_arraycolumnOP_LIKE/OP_NOT_LIKEfilter translation to supportTYPE_ARRAYkeys viaarrayExistswith a lambdaLIKEon arrays:arrayExists(x -> like(x, pattern), array)— true if any element matchesNOT_LIKEon arrays:NOT(arrayExists(x -> like(x, pattern), array))— true if no element matchesignore_caseflag (switcheslike→ilike)Test plan
attribute_key_to_expressionwithTYPE_ARRAY(expression shape, alias, backtick escaping)🤖 Generated with Claude Code
Agent transcript: https://claudescope.sentry.dev/share/CSlg1g-5P5OFoOJQo-B83K2SA1OibDF7tSh1ralLTgs