Skip to content

fix(cubesql): Correctly escape/unescape LIKE patterns#10862

Open
MazterQyou wants to merge 1 commit into
masterfrom
cubesql/like-escaped-fix
Open

fix(cubesql): Correctly escape/unescape LIKE patterns#10862
MazterQyou wants to merge 1 commit into
masterfrom
cubesql/like-escaped-fix

Conversation

@MazterQyou
Copy link
Copy Markdown
Member

Check List

  • Tests have been run in packages where changes have been made if available
  • Linter has been run for changed code
  • Tests for the changes have been added if not covered yet
  • Docs have been added / updated if required

Description of Changes Made

This PR fixes an issue with special characters in LIKE pattern generating incorrect SQL by fixes two issues in CubeSQL and one in BaseQuery:

  • Fixed CubeSQL passing LIKE filters to CubeScan by unescaping the escape sequences
  • Fixed an issue where BaseQuery would not autoescape query params when using startsWith/endsWith filter operators
  • Fixed CubeSQL push down not generating an implicit ESCAPE clause for LIKE for data warehouses that have no default escape

Related tests are included.

@MazterQyou MazterQyou requested review from a team as code owners May 11, 2026 18:08
@github-actions github-actions Bot added rust Pull requests that update Rust code driver:dremio javascript Pull requests that update Javascript code data source driver driver:duckdb labels May 11, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 11, 2026

Claude finished @MazterQyou's task in 5m 42s —— View job


Code Review: fix(cubesql): Correctly escape/unescape LIKE patterns

  • Gather context and read all changed files
  • Review Rust changes (filters, wrapper, transport)
  • Review TypeScript changes (BaseFilter, drivers)
  • Review test coverage
  • Post comprehensive review

Summary

This is a well-structured fix addressing three related LIKE-pattern escaping issues. The changes are correct and the approach is sound. I have a few observations and minor suggestions below.

What This PR Does

  1. CubeSQL filter parsing (filters.rs): New parse_like_pattern function properly tokenizes LIKE patterns, resolving escape sequences (\%%, \__, \\\) before converting to Cube filter operators. This replaces the previous naive starts_with/ends_with logic that treated \% as a wildcard %.

  2. CubeSQL push-down (wrapper.rs, service.rs): BinaryExpr nodes with LIKE operators now route through like_expr() instead of binary_expr(), enabling the default_escape template variable. This allows drivers to emit an ESCAPE '\' clause for databases that don't have a default escape character.

  3. BaseFilter wildcard escaping (BaseFilter.ts): isWildcardOperator() now includes startsWith/notStartsWith/endsWith/notEndsWith, ensuring user-supplied values like 100% or fem_ale get their % and _ escaped before being interpolated into LIKE patterns.

  4. Driver templates (Dremio, DuckDB, MSSQL, Presto, Snowflake): Updated to conditionally emit ESCAPE '\' when default_escape is true. Snowflake correctly uses double-escaped '\\\\' due to its string literal processing.

Correctness

  • parse_like_pattern is well-designed: handles escape sequences correctly, returns None for patterns with internal wildcards (preventing silent misrepresentation), and cleanly separates tokenization from shape classification.
  • Escape char handling in wrapper.rs: Operator::Like in BinaryExpr always has escape_char = None, which is correct — the rewrite engine only converts Expr::Like to BinaryExpr when there is no explicit ESCAPE clause (members.rs:2620).
  • Driver coverage looks complete: MySQL and BigQuery don't get template changes because MySQL has \ as default escape, and BigQuery deletes like_escape entirely (no escape mechanism).

Suggestions & Observations

  1. Edge case — single % pattern: LIKE '%' now produces endsWith("") instead of the previous contains(""). Both match everything, but it's a subtle behavior change due to the tokens.len() > 1 guard on ends_with_percent. See inline comment.

  2. Push-down test assertion: test_sql_push_down_like_with_escape only checks sql.contains(" LIKE ") and sql.contains(" ESCAPE "). A more specific assertion (e.g., checking the actual pattern) would make the test more robust. See inline comment.

  3. Missing TypeScript tests for isWildcardOperator: The BaseFilter change is a real correctness fix (values with %/_ in startsWith/endsWith filters were not being escaped), but there are no new TS tests covering this. Consider adding a test that verifies filterParams() escapes wildcards for a startsWith filter with a value like 100%.

  4. Comment style: The 6-line comment on isWildcardOperator is thorough but verbose for the context. A shorter version would match the codebase style better.

Security

The BaseFilter.ts change is particularly important from a security perspective — it closes a gap where user-supplied values containing % or _ could alter the LIKE pattern semantics in startsWith/endsWith filters.

Verdict

This is a solid, well-tested fix. The parse_like_pattern function is a nice improvement over the ad-hoc wildcard stripping. The suggestions above are minor — none are blockers.


Comment thread rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs Outdated
Comment thread packages/cubejs-schema-compiler/src/adapter/BaseFilter.ts Outdated
Comment thread packages/cubejs-schema-compiler/src/adapter/SnowflakeQuery.ts
Comment thread rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs
Comment thread rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs
Comment thread rust/cubesql/cubesql/src/compile/mod.rs
@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

❌ Patch coverage is 81.77340% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.86%. Comparing base (d5da121) to head (8c1f8f9).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...t/cubesql/cubesql/src/compile/engine/df/wrapper.rs 34.28% 23 Missing ⚠️
...besql/cubesql/src/compile/rewrite/rules/filters.rs 83.58% 11 Missing ⚠️
...bejs-schema-compiler/src/adapter/SnowflakeQuery.ts 0.00% 2 Missing ⚠️
rust/cubesql/cubesql/src/compile/mod.rs 98.92% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master   #10862    +/-   ##
========================================
  Coverage   78.86%   78.86%            
========================================
  Files         470      470            
  Lines       92289    92434   +145     
  Branches     3435     3435            
========================================
+ Hits        72784    72902   +118     
- Misses      19003    19030    +27     
  Partials      502      502            
Flag Coverage Δ
cube-backend 58.36% <66.66%> (+<0.01%) ⬆️
cubesql 83.47% <82.23%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: Alex Qyoun-ae <4062971+MazterQyou@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data source driver driver:dremio driver:duckdb javascript Pull requests that update Javascript code rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant