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+"%", "%"+normalizedSearch+"%",
)) ))
case "postgres": case "postgres":
// For PostgreSQL, try to use unaccent extension if available // For PostgreSQL, use REPLACE-based normalization to avoid unaccent dependency
// Fall back to REPLACE-based normalization if not available normalizeFunc := buildGenericNormalizeExpression(s.C(field))
normalizeFunc := buildPostgreSQLNormalizeExpression(s.C(field)) // Use sql.P() for proper PostgreSQL parameter binding ($1, $2, etc.)
s.Where(sql.ExprP( s.Where(sql.P(func(b *sql.Builder) {
"LOWER("+normalizeFunc+") LIKE ?", b.WriteString("LOWER(")
"%"+normalizedSearch+"%", b.WriteString(normalizeFunc)
)) b.WriteString(") LIKE ")
b.Arg("%" + normalizedSearch + "%")
}))
default: default:
// Default fallback using REPLACE for common accented characters // Default fallback using REPLACE for common accented characters
normalizeFunc := buildGenericNormalizeExpression(s.C(field)) normalizeFunc := buildGenericNormalizeExpression(s.C(field))
@@ -56,15 +58,6 @@ func buildSQLiteNormalizeExpression(fieldExpr string) string {
return buildGenericNormalizeExpression(fieldExpr) 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 // buildGenericNormalizeExpression creates a database-agnostic expression to normalize common accented characters
func buildGenericNormalizeExpression(fieldExpr string) string { func buildGenericNormalizeExpression(fieldExpr string) string {
// Chain REPLACE functions to handle the most common accented characters // 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 ó") 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) { func TestAccentInsensitivePredicateCreation(t *testing.T) {
tests := []struct { tests := []struct {
name string name string