fix: exact-name symbol lookup silently fails on snake_case names#15
Merged
Conversation
find_symbols_filtered escapes LIKE metacharacters (`%`, `_`, `\`) with a backslash via escape_like_pattern / glob_to_like_pattern, but none of the LIKE clauses declared `ESCAPE '\'`. In SQLite the backslash is not the escape character unless declared, so an escaped `\_` was matched literally as "backslash followed by any character" — meaning any symbol whose name contains an underscore (`run_sql`, `discover_files`, `open_sql_sandbox`) never matched an exact-name query and returned zero rows. Because snake_case is the dominant identifier style in Rust/Go/Python/C, this silently broke the primary lookup path for most real symbols across `query find`, `query callers`, `query deps`, `query impact`, `explain`, and `source`. The `impact` case was the most dangerous: it reported "No impact detected" instead of an error, reading as "safe to change". Add `ESCAPE '\'` to all three LIKE clauses (name/qualified_name, the file_path glob filter, and the starts_with prefix match in ORDER BY). The existing tests never caught this because they only exercised underscore-free names (`new`, `main`, `targetfn`); add a regression test that looks up a snake_case name by exact match and asserts the underscore is treated literally (does not wildcard-match `runsql`).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
query find,query callers,query deps,query impact,explain, andsourcereturn "not found" for any symbol whose name contains an underscore — i.e. most snake_case identifiers in Rust/Go/Python/C codebases.The symbols are indexed —
ctx sql,search, andsemanticall find them. Only the LIKE-based exact-name path fails.Root cause
find_symbols_filtered(src/db/schema.rs) escapes LIKE metacharacters (%,_,\) with a backslash (escape_like_pattern, andglob_to_like_patternfor the file filter), but none of the LIKE clauses declaredESCAPE '\'. In SQLite the backslash is not the escape character unless declared, so the escaped\_was matched literally as "backslash + any char" — which never matches a name likerun_sql. Substrings without underscores matched fine, which is why the bug hid in plain sight.The
impactvariant is the most dangerous: it returns "No impact detected" rather than an error, which a caller (human or agent) reads as "safe to change."Fix
Add
ESCAPE '\'to all three affected LIKE clauses:name/qualified_namesubstring matchfile_pathglob filterstarts_withprefix match in theORDER BYWhy the tests missed it
The existing
find_symbols_filteredtests only used underscore-free names (new,main,targetfn). This PR addstest_find_symbols_with_underscore_name, which looks up a snake_case name by exact match and asserts the underscore is treated literally (does not wildcard-matchrunsql) and that exact match still ranks ahead of the longer prefix match.Verification
cargo fmt --checkandcargo clippy --all-targets -D warningsclean.query find run_sql,explain open_sql_sandbox, andquery impact find_symbols_filteredall now resolve correctly.