mirror of https://github.com/go-gitea/gitea.git
Fix non-ASCII search on database (#18437)
Use `ToASCIIUpper` for SQLite database on issues search, this because `UPPER(x)` on SQLite only transforms ASCII letters. Resolves #18429
This commit is contained in:
parent
7f2530e004
commit
bb5f859ec0
|
@ -23,6 +23,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/references"
|
"code.gitea.io/gitea/modules/references"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
@ -1862,7 +1863,12 @@ func GetRepoIssueStats(repoID, uid int64, filterMode int, isPull bool) (numOpen,
|
||||||
func SearchIssueIDsByKeyword(ctx context.Context, kw string, repoIDs []int64, limit, start int) (int64, []int64, error) {
|
func SearchIssueIDsByKeyword(ctx context.Context, kw string, repoIDs []int64, limit, start int) (int64, []int64, error) {
|
||||||
repoCond := builder.In("repo_id", repoIDs)
|
repoCond := builder.In("repo_id", repoIDs)
|
||||||
subQuery := builder.Select("id").From("issue").Where(repoCond)
|
subQuery := builder.Select("id").From("issue").Where(repoCond)
|
||||||
|
// SQLite's UPPER function only transforms ASCII letters.
|
||||||
|
if setting.Database.UseSQLite3 {
|
||||||
|
kw = util.ToUpperASCII(kw)
|
||||||
|
} else {
|
||||||
kw = strings.ToUpper(kw)
|
kw = strings.ToUpper(kw)
|
||||||
|
}
|
||||||
cond := builder.And(
|
cond := builder.And(
|
||||||
repoCond,
|
repoCond,
|
||||||
builder.Or(
|
builder.Or(
|
||||||
|
|
|
@ -170,3 +170,14 @@ func CryptoRandomBytes(length int64) ([]byte, error) {
|
||||||
_, err := rand.Read(buf)
|
_, err := rand.Read(buf)
|
||||||
return buf, err
|
return buf, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUpperASCII returns s with all ASCII letters mapped to their upper case.
|
||||||
|
func ToUpperASCII(s string) string {
|
||||||
|
b := []byte(s)
|
||||||
|
for i, c := range b {
|
||||||
|
if 'a' <= c && c <= 'z' {
|
||||||
|
b[i] -= 'a' - 'A'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
|
@ -186,3 +186,37 @@ func Test_OptionalBool(t *testing.T) {
|
||||||
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("t"))
|
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("t"))
|
||||||
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("True"))
|
assert.Equal(t, OptionalBoolTrue, OptionalBoolParse("True"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test case for any function which accepts and returns a single string.
|
||||||
|
type StringTest struct {
|
||||||
|
in, out string
|
||||||
|
}
|
||||||
|
|
||||||
|
var upperTests = []StringTest{
|
||||||
|
{"", ""},
|
||||||
|
{"ONLYUPPER", "ONLYUPPER"},
|
||||||
|
{"abc", "ABC"},
|
||||||
|
{"AbC123", "ABC123"},
|
||||||
|
{"azAZ09_", "AZAZ09_"},
|
||||||
|
{"longStrinGwitHmixofsmaLLandcAps", "LONGSTRINGWITHMIXOFSMALLANDCAPS"},
|
||||||
|
{"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", "LONG\u0250STRING\u0250WITH\u0250NONASCII\u2C6FCHARS"},
|
||||||
|
{"\u0250\u0250\u0250\u0250\u0250", "\u0250\u0250\u0250\u0250\u0250"},
|
||||||
|
{"a\u0080\U0010FFFF", "A\u0080\U0010FFFF"},
|
||||||
|
{"lél", "LéL"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToUpperASCII(t *testing.T) {
|
||||||
|
for _, tc := range upperTests {
|
||||||
|
assert.Equal(t, ToUpperASCII(tc.in), tc.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkToUpper(b *testing.B) {
|
||||||
|
for _, tc := range upperTests {
|
||||||
|
b.Run(tc.in, func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
ToUpperASCII(tc.in)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue