From d9c8130d08cc85a354f02167643e4edf19b3cfd1 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki <7413593+a8m@users.noreply.github.com> Date: Thu, 13 Aug 2020 17:26:19 +0300 Subject: [PATCH] dialect/sql: configure contains-fold per dialect (#666) --- dialect/sql/builder.go | 13 ++++++++++--- dialect/sql/builder_test.go | 13 +++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/dialect/sql/builder.go b/dialect/sql/builder.go index c3cef2408..aa08e81f8 100644 --- a/dialect/sql/builder.go +++ b/dialect/sql/builder.go @@ -1138,13 +1138,20 @@ func (p *Predicate) Contains(col, sub string) *Predicate { func ContainsFold(col, sub string) *Predicate { return (&Predicate{}).ContainsFold(col, sub) } // ContainsFold is a helper predicate that applies the LIKE predicate with case-folding. -// The recommendation is to avoid using it, and to use a dialect specific feature, like -// `ILIKE` in PostgreSQL, and `COLLATE` clause in MySQL. func (p *Predicate) ContainsFold(col, sub string) *Predicate { return p.append(func(b *Builder) { f := &Func{} f.SetDialect(b.dialect) - b.Ident(f.Lower(col)).WriteString(" LIKE ") + switch b.dialect { + case dialect.MySQL: + // We assume the CHARACTER SET is configured to utf8mb4, + // because this how it is defined in dialect/sql/schema. + b.Ident(col).WriteString(" COLLATE utf8mb4_general_ci LIKE ") + case dialect.Postgres: + b.Ident(col).WriteString(" ILIKE ") + default: // SQLite. + b.Ident(f.Lower(col)).WriteString(" LIKE ") + } b.Arg("%" + strings.ToLower(sub) + "%") }) } diff --git a/dialect/sql/builder_test.go b/dialect/sql/builder_test.go index f4f6ad5ca..ac5759afe 100644 --- a/dialect/sql/builder_test.go +++ b/dialect/sql/builder_test.go @@ -802,7 +802,8 @@ func TestBuilder(t *testing.T) { wantArgs: []interface{}{"bar", "baz"}, }, { - input: Select(). + input: Dialect(dialect.SQLite). + Select(). From(Table("users")). Where(ContainsFold("name", "Ariel").And().ContainsFold("nick", "Bar")), wantQuery: "SELECT * FROM `users` WHERE LOWER(`name`) LIKE ? AND LOWER(`nick`) LIKE ?", @@ -813,7 +814,15 @@ func TestBuilder(t *testing.T) { Select(). From(Table("users")). Where(ContainsFold("name", "Ariel").And().ContainsFold("nick", "Bar")), - wantQuery: `SELECT * FROM "users" WHERE LOWER("name") LIKE $1 AND LOWER("nick") LIKE $2`, + wantQuery: `SELECT * FROM "users" WHERE "name" ILIKE $1 AND "nick" ILIKE $2`, + wantArgs: []interface{}{"%ariel%", "%bar%"}, + }, + { + input: Dialect(dialect.MySQL). + Select(). + From(Table("users")). + Where(ContainsFold("name", "Ariel").And().ContainsFold("nick", "Bar")), + wantQuery: "SELECT * FROM `users` WHERE `name` COLLATE utf8mb4_general_ci LIKE ? AND `nick` COLLATE utf8mb4_general_ci LIKE ?", wantArgs: []interface{}{"%ariel%", "%bar%"}, }, {