Skip to content

Commit 921f241

Browse files
committed
feat(database/gdb): Enhanced support for automatic escaping of special characters in the WhereLike method.
Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
1 parent ce3599a commit 921f241

5 files changed

Lines changed: 43 additions & 8 deletions

File tree

database/gdb/gdb_func.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,3 +1015,25 @@ func genTableNamesCacheKey(group string) string {
10151015
func genSoftTimeFieldNameTypeCacheKey(schema, table string, candidateFields []string) string {
10161016
return fmt.Sprintf(`getSoftFieldNameAndType:%s#%s#%s`, schema, table, strings.Join(candidateFields, "_"))
10171017
}
1018+
1019+
// EscapeLikeString escapes special characters in a string for LIKE operations.
1020+
// It escapes '\', '%', and '_' characters to prevent them from being interpreted
1021+
// as wildcard characters in SQL LIKE statements.
1022+
//
1023+
// The function follows standard SQL escaping rules:
1024+
// - '\' becomes '\\'
1025+
// - '%' becomes '\%'
1026+
// - '_' becomes '\_'
1027+
//
1028+
// Example:
1029+
//
1030+
// EscapeLikeString("john_doe%test\\data") returns "john\\_doe\\%test\\\\data"
1031+
func EscapeLikeString(s string) string {
1032+
// Escape backslashes first to prevent double escaping
1033+
s = strings.ReplaceAll(s, "\\", "\\\\")
1034+
// Escape percent signs
1035+
s = strings.ReplaceAll(s, "%", "\\%")
1036+
// Escape underscores
1037+
s = strings.ReplaceAll(s, "_", "\\_")
1038+
return s
1039+
}

database/gdb/gdb_model_builder_where.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111

1212
"github.com/gogf/gf/v2/text/gstr"
13+
"github.com/gogf/gf/v2/util/gconv"
1314
)
1415

1516
// doWhereType sets the condition statement for the model. The parameter `where` can be type of
@@ -114,7 +115,7 @@ func (b *WhereBuilder) WhereBetween(column string, min, max any) *WhereBuilder {
114115

115116
// WhereLike builds `column LIKE like` statement.
116117
func (b *WhereBuilder) WhereLike(column string, like string) *WhereBuilder {
117-
return b.Wheref(`%s LIKE ?`, b.model.QuoteWord(column), like)
118+
return b.Wheref(`%s LIKE ?`, b.model.QuoteWord(column), EscapeLikeString(like))
118119
}
119120

120121
// WhereIn builds `column IN (in)` statement.
@@ -138,7 +139,8 @@ func (b *WhereBuilder) WhereNotBetween(column string, min, max any) *WhereBuilde
138139

139140
// WhereNotLike builds `column NOT LIKE like` statement.
140141
func (b *WhereBuilder) WhereNotLike(column string, like any) *WhereBuilder {
141-
return b.Wheref(`%s NOT LIKE ?`, b.model.QuoteWord(column), like)
142+
likeStr := gconv.String(like)
143+
return b.Wheref(`%s NOT LIKE ?`, b.model.QuoteWord(column), EscapeLikeString(likeStr))
142144
}
143145

144146
// WhereNot builds `column != value` statement.

database/gdb/gdb_model_builder_where_prefix.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package gdb
88

9+
import "github.com/gogf/gf/v2/util/gconv"
10+
911
// WherePrefix performs as Where, but it adds prefix to each field in where statement.
1012
// Eg:
1113
// WherePrefix("order", "status", "paid") => WHERE `order`.`status`='paid'
@@ -54,7 +56,8 @@ func (b *WhereBuilder) WherePrefixBetween(prefix string, column string, min, max
5456

5557
// WherePrefixLike builds `prefix.column LIKE like` statement.
5658
func (b *WhereBuilder) WherePrefixLike(prefix string, column string, like any) *WhereBuilder {
57-
return b.Wheref(`%s.%s LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), like)
59+
likeStr := gconv.String(like)
60+
return b.Wheref(`%s.%s LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), EscapeLikeString(likeStr))
5861
}
5962

6063
// WherePrefixIn builds `prefix.column IN (in)` statement.
@@ -78,7 +81,8 @@ func (b *WhereBuilder) WherePrefixNotBetween(prefix string, column string, min,
7881

7982
// WherePrefixNotLike builds `prefix.column NOT LIKE like` statement.
8083
func (b *WhereBuilder) WherePrefixNotLike(prefix string, column string, like any) *WhereBuilder {
81-
return b.Wheref(`%s.%s NOT LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), like)
84+
likeStr := gconv.String(like)
85+
return b.Wheref(`%s.%s NOT LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), EscapeLikeString(likeStr))
8286
}
8387

8488
// WherePrefixNot builds `prefix.column != value` statement.

database/gdb/gdb_model_builder_whereor.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"fmt"
1111

1212
"github.com/gogf/gf/v2/text/gstr"
13+
"github.com/gogf/gf/v2/util/gconv"
1314
)
1415

1516
// WhereOr adds "OR" condition to the where statement.
@@ -83,7 +84,8 @@ func (b *WhereBuilder) WhereOrBetween(column string, min, max any) *WhereBuilder
8384

8485
// WhereOrLike builds `column LIKE 'like'` statement in `OR` conditions.
8586
func (b *WhereBuilder) WhereOrLike(column string, like any) *WhereBuilder {
86-
return b.WhereOrf(`%s LIKE ?`, b.model.QuoteWord(column), like)
87+
likeStr := gconv.String(like)
88+
return b.WhereOrf(`%s LIKE ?`, b.model.QuoteWord(column), EscapeLikeString(likeStr))
8789
}
8890

8991
// WhereOrIn builds `column IN (in)` statement in `OR` conditions.
@@ -107,7 +109,8 @@ func (b *WhereBuilder) WhereOrNotBetween(column string, min, max any) *WhereBuil
107109

108110
// WhereOrNotLike builds `column NOT LIKE like` statement in `OR` conditions.
109111
func (b *WhereBuilder) WhereOrNotLike(column string, like any) *WhereBuilder {
110-
return b.WhereOrf(`%s NOT LIKE ?`, b.model.QuoteWord(column), like)
112+
likeStr := gconv.String(like)
113+
return b.WhereOrf(`%s NOT LIKE ?`, b.model.QuoteWord(column), EscapeLikeString(likeStr))
111114
}
112115

113116
// WhereOrNotIn builds `column NOT IN (in)` statement.

database/gdb/gdb_model_builder_whereor_prefix.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package gdb
88

9+
import "github.com/gogf/gf/v2/util/gconv"
10+
911
// WhereOrPrefix performs as WhereOr, but it adds prefix to each field in where statement.
1012
// Eg:
1113
// WhereOrPrefix("order", "status", "paid") => WHERE xxx OR (`order`.`status`='paid')
@@ -56,7 +58,8 @@ func (b *WhereBuilder) WhereOrPrefixBetween(prefix string, column string, min, m
5658

5759
// WhereOrPrefixLike builds `prefix.column LIKE 'like'` statement in `OR` conditions.
5860
func (b *WhereBuilder) WhereOrPrefixLike(prefix string, column string, like any) *WhereBuilder {
59-
return b.WhereOrf(`%s.%s LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), like)
61+
likeStr := gconv.String(like)
62+
return b.WhereOrf(`%s.%s LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), EscapeLikeString(likeStr))
6063
}
6164

6265
// WhereOrPrefixIn builds `prefix.column IN (in)` statement in `OR` conditions.
@@ -80,7 +83,8 @@ func (b *WhereBuilder) WhereOrPrefixNotBetween(prefix string, column string, min
8083

8184
// WhereOrPrefixNotLike builds `prefix.column NOT LIKE 'like'` statement in `OR` conditions.
8285
func (b *WhereBuilder) WhereOrPrefixNotLike(prefix string, column string, like any) *WhereBuilder {
83-
return b.WhereOrf(`%s.%s NOT LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), like)
86+
likeStr := gconv.String(like)
87+
return b.WhereOrf(`%s.%s NOT LIKE ?`, b.model.QuoteWord(prefix), b.model.QuoteWord(column), EscapeLikeString(likeStr))
8488
}
8589

8690
// WhereOrPrefixNotIn builds `prefix.column NOT IN (in)` statement.

0 commit comments

Comments
 (0)