Fix accent-insensitive search for Postgres databases (#932)

This commit is contained in:
Matias Godoy
2025-08-05 02:35:22 +02:00
committed by GitHub
parent 0d3151ae5c
commit 362c0bb3e6
2 changed files with 39 additions and 55 deletions

View File

@@ -33,13 +33,15 @@ func AccentInsensitiveContains(field string, searchValue string) predicate.Item
"%"+normalizedSearch+"%",
))
case "postgres":
// For PostgreSQL, try to use unaccent extension if available
// Fall back to REPLACE-based normalization if not available
normalizeFunc := buildPostgreSQLNormalizeExpression(s.C(field))
s.Where(sql.ExprP(
"LOWER("+normalizeFunc+") LIKE ?",
"%"+normalizedSearch+"%",
))
// For PostgreSQL, use REPLACE-based normalization to avoid unaccent dependency
normalizeFunc := buildGenericNormalizeExpression(s.C(field))
// Use sql.P() for proper PostgreSQL parameter binding ($1, $2, etc.)
s.Where(sql.P(func(b *sql.Builder) {
b.WriteString("LOWER(")
b.WriteString(normalizeFunc)
b.WriteString(") LIKE ")
b.Arg("%" + normalizedSearch + "%")
}))
default:
// Default fallback using REPLACE for common accented characters
normalizeFunc := buildGenericNormalizeExpression(s.C(field))
@@ -56,15 +58,6 @@ func buildSQLiteNormalizeExpression(fieldExpr string) string {
return buildGenericNormalizeExpression(fieldExpr)
}
// buildPostgreSQLNormalizeExpression creates a PostgreSQL expression to normalize accented characters
func buildPostgreSQLNormalizeExpression(fieldExpr string) string {
// Use a CASE statement to check if unaccent function exists before using it
// This prevents errors when the unaccent extension is not installed
return "CASE WHEN EXISTS (SELECT 1 FROM pg_proc WHERE proname = 'unaccent') " +
"THEN unaccent(" + fieldExpr + ") " +
"ELSE " + buildGenericNormalizeExpression(fieldExpr) + " END"
}
// buildGenericNormalizeExpression creates a database-agnostic expression to normalize common accented characters
func buildGenericNormalizeExpression(fieldExpr string) string {
// Chain REPLACE functions to handle the most common accented characters

View File

@@ -58,15 +58,6 @@ func TestSQLiteNormalizeExpression(t *testing.T) {
assert.Contains(t, result, "'ó'", "Should handle Spanish ó")
}
func TestPostgreSQLNormalizeExpression(t *testing.T) {
result := buildPostgreSQLNormalizeExpression("test_field")
// Should contain unaccent function and CASE WHEN logic
assert.Contains(t, result, "unaccent(")
assert.Contains(t, result, "CASE WHEN EXISTS")
assert.Contains(t, result, "test_field")
}
func TestAccentInsensitivePredicateCreation(t *testing.T) {
tests := []struct {
name string