Skip to content

[Robustness] ServiceRepository.SearchAsync — Name LIKE @Pattern is case-sensitive for non-ASCII characters; rest of the repo uses LOWER(...) = LOWER(...) #881

@Christophe-Rogiers

Description

@Christophe-Rogiers

Severity: Warning

File: src/Servy.Infrastructure/Data/ServiceRepository.cs

Location: SearchAsync, line ~247-251

var sql = @\"
    SELECT * FROM Services 
    WHERE Name LIKE @Pattern ESCAPE '\' 
       OR Description LIKE @Pattern ESCAPE '\' 
    ORDER BY Name COLLATE NOCASE ASC;\";

Problem

SQLite's default LIKE is case-insensitive only for ASCII letters (A–Z / a–z). For any non-ASCII character — accented letters, Cyrillic, CJK, etc. — LIKE is case-sensitive, unless the case_sensitive_like PRAGMA is changed (it is not, here) or an ICU/SQLITE_UNICODE collation is loaded (no extension is loaded — see AppDbContext connection string).

Concrete impact:

  • A service named Wexflöw (German store / Spanish-speaking customers, Eastern-European deployments) does not match a search for wexflöw — but does match Wexflöw. The user sees a confusing, partial-match-only filter.
  • A service named Müller-Reporter does not match müller. The fix at the schema level (the unique index LOWER(Name)) and at every other lookup path (LOWER(Name) = LOWER(@Name)) already does the right thing — SearchAsync is the only one that bypasses it.
  • The ORDER BY already uses COLLATE NOCASE, which makes the inconsistency more visible (sort order is case-insensitive Unicode-aware-ish, filter is not).

Suggested fix

Force the comparison to be lower-cased on both sides, the same way every other method in this repo does:

var sql = @\"
    SELECT * FROM Services 
    WHERE LOWER(Name)        LIKE LOWER(@Pattern) ESCAPE '\' 
       OR LOWER(Description) LIKE LOWER(@Pattern) ESCAPE '\' 
    ORDER BY Name COLLATE NOCASE ASC;\";

(@Pattern is already lower-cased indirectly via the user's input, but the LOWER on both sides is what flips the ASCII-only behaviour to the SQLite "both-sides-lower" path. The escape character needs to be escaped properly in the literal — '\\' becomes \ in the SQL string.)

That keeps the filter behaviour aligned with the rest of the repository and with the user's expectation set by the (correctly Unicode-collated) ORDER BY.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions