Remove use of dialect.LikeStr (#104460)

* Fix TestIntegrationUpdatingProvisionionedDashboards* tests when running on Spanner by fixing case-insensitive search for dashboard title.

* Fix use of case-insensitive LIKE when running on Spanner.

* Fix use of LikeStr in anonstore.

* Fix use of LikeStr in ngalert/store and org/orgimpl.

* Fix use of LikeStr in queryhistory search.

* Fix use of LikeStr in serviceaccounts.

* Fix use of LikeStr in serviceaccounts.

* Fix use of LikeStr in services/team.

* Remove LikeStr method.
pull/102414/merge
Peter Štibraný 3 weeks ago committed by GitHub
parent d7ebaafa94
commit e85acf047a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 12
      pkg/services/annotations/annotationsimpl/xorm_store.go
  2. 4
      pkg/services/annotations/annotationsimpl/xorm_store_test.go
  3. 4
      pkg/services/anonymous/anonimpl/anonstore/database.go
  4. 22
      pkg/services/anonymous/anonimpl/impl_test.go
  5. 11
      pkg/services/ngalert/store/alert_rule.go
  6. 8
      pkg/services/org/orgimpl/store.go
  7. 4
      pkg/services/org/orgimpl/store_test.go
  8. 6
      pkg/services/queryhistory/queryhistory_search_test.go
  9. 10
      pkg/services/queryhistory/writers.go
  10. 15
      pkg/services/serviceaccounts/database/store.go
  11. 11
      pkg/services/serviceaccounts/database/store_test.go
  12. 6
      pkg/services/sqlstore/migrator/dialect.go
  13. 4
      pkg/services/sqlstore/migrator/postgres_dialect.go
  14. 3
      pkg/services/sqlstore/searchstore/filters.go
  15. 10
      pkg/services/team/teamimpl/store.go
  16. 3
      pkg/services/team/teamimpl/store_test.go

@ -476,8 +476,16 @@ func (r *xormRepositoryImpl) GetTags(ctx context.Context, query annotations.Tags
sql.WriteString(`WHERE annotation.org_id = ?`)
params = append(params, query.OrgID)
sql.WriteString(` AND (` + tagKey + ` ` + r.db.GetDialect().LikeStr() + ` ? OR ` + tagValue + ` ` + r.db.GetDialect().LikeStr() + ` ?)`)
params = append(params, `%`+query.Tag+`%`, `%`+query.Tag+`%`)
sql.WriteString(` AND (`)
s, p := r.db.GetDialect().LikeOperator(tagKey, true, query.Tag, true)
sql.WriteString(s)
params = append(params, p)
sql.WriteString(" OR ")
s, p = r.db.GetDialect().LikeOperator(tagValue, true, query.Tag, true)
sql.WriteString(s)
params = append(params, p)
sql.WriteString(")")
sql.WriteString(` GROUP BY ` + tagKey + `,` + tagValue)
sql.WriteString(` ORDER BY ` + tagKey + `,` + tagValue)

@ -533,7 +533,7 @@ func TestIntegrationAnnotations(t *testing.T) {
t.Run("Should find tags by key", func(t *testing.T) {
result, err := store.GetTags(context.Background(), annotations.TagsQuery{
OrgID: 1,
Tag: "server",
Tag: "SeRvEr", // Use mixed-case to test LIKE case-insensitivity
})
require.NoError(t, err)
require.Len(t, result.Tags, 1)
@ -544,7 +544,7 @@ func TestIntegrationAnnotations(t *testing.T) {
t.Run("Should find tags by value", func(t *testing.T) {
result, err := store.GetTags(context.Background(), annotations.TagsQuery{
OrgID: 1,
Tag: "outage",
Tag: "Outage", // Use mixed-case to test LIKE case-insensitivity
})
require.NoError(t, err)
require.Len(t, result.Tags, 2)

@ -285,8 +285,8 @@ func (s *AnonDBStore) SearchDevices(ctx context.Context, query *SearchDeviceQuer
sess.Where("d.updated_at BETWEEN ? AND ?", query.From.UTC(), query.To.UTC())
if query.Query != "" {
queryWithWildcards := "%" + strings.ReplaceAll(query.Query, "\\", "") + "%"
sess.Where("d.client_ip "+s.sqlStore.GetDialect().LikeStr()+" ?", queryWithWildcards)
sql, param := s.sqlStore.GetDialect().LikeOperator("d.client_ip", true, strings.ReplaceAll(query.Query, "\\", ""), true)
sess.Where(sql, param)
}
// get total

@ -307,7 +307,27 @@ func TestIntegrationDeviceService_SearchDevice(t *testing.T) {
UserAgent: "",
},
},
}
{
name: "device with IPv6 address and case-insensitive search",
insertDevices: []*anonstore.Device{
{
DeviceID: "32mdo31deeqwes",
ClientIP: "[2001:db8:3333:4444:cccc:DDDD:eeee:FFFF]:1000", // Using mixed-case to test case insensitivity
},
},
searchQuery: anonstore.SearchDeviceQuery{
Query: "CCCC", // Different case to test case insensitivity
Page: 1,
Limit: 50,
From: fixedTime,
To: fixedTime.Add(1 * time.Hour),
},
expectedCount: 1,
expectedDevice: &anonstore.Device{
DeviceID: "32mdo31deeqwes",
ClientIP: "[2001:db8:3333:4444:cccc:DDDD:eeee:FFFF]:1000",
},
}}
store := db.InitTestDB(t)
cfg := setting.NewCfg()
cfg.Anonymous.Enabled = true

@ -114,10 +114,10 @@ func (st DBstore) getLatestVersionOfRulesByUID(ctx context.Context, orgID int64,
rows, err := sess.SQL(fmt.Sprintf(`
SELECT v1.* FROM alert_rule_version AS v1
INNER JOIN (
SELECT rule_guid, MAX(id) AS id
FROM alert_rule_version
WHERE rule_org_id = ?
AND rule_uid IN (%s)
SELECT rule_guid, MAX(id) AS id
FROM alert_rule_version
WHERE rule_org_id = ?
AND rule_uid IN (%s)
GROUP BY rule_guid
) AS v2 ON v1.rule_guid = v2.rule_guid AND v1.id = v2.id
`, strings.Join(in, ",")), append([]any{orgID}, args...)...).Rows(new(alertRuleVersion))
@ -1015,7 +1015,8 @@ func (st DBstore) filterByContentInNotificationSettings(value string, sess *xorm
// this escapes escaped double quote (\") to \\\"
search = strings.ReplaceAll(strings.ReplaceAll(search, `\`, `\\`), `"`, `\"`)
}
return sess.And(fmt.Sprintf("notification_settings %s ?", st.SQLStore.GetDialect().LikeStr()), "%"+search+"%"), nil
sql, param := st.SQLStore.GetDialect().LikeOperator("notification_settings", true, search, true)
return sess.And(sql, param), nil
}
func (st DBstore) filterImportedPrometheusRules(value bool, sess *xorm.Session) (*xorm.Session, error) {

@ -585,9 +585,11 @@ func (ss *sqlStore) SearchOrgUsers(ctx context.Context, query *org.SearchOrgUser
}
if query.Query != "" {
queryWithWildcards := "%" + query.Query + "%"
whereConditions = append(whereConditions, "(email "+ss.dialect.LikeStr()+" ? OR name "+ss.dialect.LikeStr()+" ? OR login "+ss.dialect.LikeStr()+" ?)")
whereParams = append(whereParams, queryWithWildcards, queryWithWildcards, queryWithWildcards)
sql1, param1 := ss.dialect.LikeOperator("email", true, query.Query, true)
sql2, param2 := ss.dialect.LikeOperator("name", true, query.Query, true)
sql3, param3 := ss.dialect.LikeOperator("login", true, query.Query, true)
whereConditions = append(whereConditions, fmt.Sprintf("(%s OR %s OR %s)", sql1, sql2, sql3))
whereParams = append(whereParams, param1, param2, param3)
}
if len(whereConditions) > 0 {

@ -405,7 +405,7 @@ func TestIntegrationOrgUserDataAccess(t *testing.T) {
t.Run("Can get organization users with query", func(t *testing.T) {
query := org.SearchOrgUsersQuery{
OrgID: ac1.OrgID,
Query: "ac1",
Query: "AC1", // Use different-case to test case-insensitive search
User: &user.SignedInUser{
OrgID: ac1.OrgID,
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
@ -420,7 +420,7 @@ func TestIntegrationOrgUserDataAccess(t *testing.T) {
t.Run("Can get organization users with query and limit", func(t *testing.T) {
query := org.SearchOrgUsersQuery{
OrgID: ac1.OrgID,
Query: "ac",
Query: "aC", // Use mixed-case to test case-insensitive search
Limit: 1,
User: &user.SignedInUser{
OrgID: ac1.OrgID,

@ -110,7 +110,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) {
testScenarioWithMultipleQueriesInQueryHistory(t, "When users tries to get queries including search string, it should return correct queries",
func(t *testing.T, sc scenarioContext) {
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
sc.reqContext.Req.Form.Add("searchString", "2")
sc.reqContext.Req.Form.Add("searchString", "TeSt") // Using mixed-case to test case-insensitive search
resp := sc.service.searchHandler(sc.reqContext)
var response QueryHistorySearchResponse
err := json.Unmarshal(resp.Body(), &response)
@ -225,7 +225,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) {
sc.reqContext.Req.Form.Add("to", strconv.FormatInt(sc.service.now().UnixMilli(), 10))
sc.reqContext.Req.Form.Add("from", strconv.FormatInt(sc.service.now().UnixMilli()-60*1000, 10))
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
sc.reqContext.Req.Form.Add("searchString", "2")
sc.reqContext.Req.Form.Add("searchString", "TeSt") // Using mixed-case to test case-insensitive search
resp := sc.service.searchHandler(sc.reqContext)
var response QueryHistorySearchResponse
err := json.Unmarshal(resp.Body(), &response)
@ -239,7 +239,7 @@ func TestIntegrationGetQueriesFromQueryHistory(t *testing.T) {
sc.reqContext.Req.Form.Add("to", "now")
sc.reqContext.Req.Form.Add("from", "now-1m")
sc.reqContext.Req.Form.Add("datasourceUid", testDsUID1)
sc.reqContext.Req.Form.Add("searchString", "2")
sc.reqContext.Req.Form.Add("searchString", "TeSt") // Using mixed-case to test case-insensitive search
resp := sc.service.searchHandler(sc.reqContext)
var response QueryHistorySearchResponse
err := json.Unmarshal(resp.Body(), &response)

@ -34,9 +34,15 @@ func writeStarredSQL(query SearchInQueryHistoryQuery, sqlStore db.DB, builder *d
}
func writeFiltersSQL(query SearchInQueryHistoryQuery, user *user.SignedInUser, sqlStore db.DB, builder *db.SQLBuilder) {
params := []any{user.OrgID, user.UserID, query.From, query.To, "%" + query.SearchString + "%", "%" + query.SearchString + "%"}
queriesSQL, queriesParam := sqlStore.GetDialect().LikeOperator("query_history.queries", true, query.SearchString, true)
commentSQL, commentParam := sqlStore.GetDialect().LikeOperator("query_history.comment", true, query.SearchString, true)
params := []any{user.OrgID, user.UserID, query.From, query.To, queriesParam, commentParam}
var sql bytes.Buffer
sql.WriteString(" WHERE query_history.org_id = ? AND query_history.created_by = ? AND query_history.created_at >= ? AND query_history.created_at <= ? AND (query_history.queries " + sqlStore.GetDialect().LikeStr() + " ? OR query_history.comment " + sqlStore.GetDialect().LikeStr() + " ?) ")
sql.WriteString(" WHERE query_history.org_id = ? AND query_history.created_by = ? AND query_history.created_at >= ? AND query_history.created_at <= ? AND (")
sql.WriteString(queriesSQL)
sql.WriteString(" OR ")
sql.WriteString(commentSQL)
sql.WriteString(") ")
if len(query.DatasourceUIDs) > 0 {
q := "?" + strings.Repeat(",?", len(query.DatasourceUIDs)-1)

@ -327,9 +327,11 @@ func (s *ServiceAccountsStoreImpl) SearchOrgServiceAccounts(ctx context.Context,
whereParams = append(whereParams, acFilter.Args...)
if query.Query != "" {
queryWithWildcards := "%" + query.Query + "%"
whereConditions = append(whereConditions, "(email "+s.sqlStore.GetDialect().LikeStr()+" ? OR name "+s.sqlStore.GetDialect().LikeStr()+" ? OR login "+s.sqlStore.GetDialect().LikeStr()+" ?)")
whereParams = append(whereParams, queryWithWildcards, queryWithWildcards, queryWithWildcards)
sql1, param1 := s.sqlStore.GetDialect().LikeOperator("email", true, query.Query, true)
sql2, param2 := s.sqlStore.GetDialect().LikeOperator("name", true, query.Query, true)
sql3, param3 := s.sqlStore.GetDialect().LikeOperator("login", true, query.Query, true)
whereConditions = append(whereConditions, fmt.Sprintf("(%s OR %s OR %s)", sql1, sql2, sql3))
whereParams = append(whereParams, param1, param2, param3)
}
switch query.Filter {
@ -348,10 +350,9 @@ func (s *ServiceAccountsStoreImpl) SearchOrgServiceAccounts(ctx context.Context,
"is_disabled = ?")
whereParams = append(whereParams, s.sqlStore.GetDialect().BooleanValue(true))
case serviceaccounts.FilterOnlyExternal:
whereConditions = append(
whereConditions,
"login "+s.sqlStore.GetDialect().LikeStr()+" ?")
whereParams = append(whereParams, serviceaccounts.ExtSvcLoginPrefix(query.OrgID)+"%")
sql, param := s.sqlStore.GetDialect().LikeOperator("login", false, serviceaccounts.ExtSvcLoginPrefix(query.OrgID), true)
whereConditions = append(whereConditions, sql)
whereParams = append(whereParams, param)
default:
s.log.Warn("Invalid filter user for service account filtering", "service account search filtering", query.Filter)
}

@ -2,6 +2,7 @@ package database
import (
"context"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@ -334,7 +335,7 @@ func TestIntegrationStore_MigrateApiKeys(t *testing.T) {
desc: "api key should be migrated to service account token",
serviceAccounts: []user.CreateUserCommand{},
key: tests.TestApiKey{Name: "test1", Role: org.RoleEditor, OrgId: 1},
expectedLogin: "sa-autogen-1-test1",
expectedLogin: "sa-AuToGeN-1-test1", // Using mixed-case to test case-insensitive search.
expectedErr: nil,
},
{
@ -343,7 +344,7 @@ func TestIntegrationStore_MigrateApiKeys(t *testing.T) {
{Login: "sa-autogen-1-test2"},
},
key: tests.TestApiKey{Name: "test2", Role: org.RoleEditor, OrgId: 1},
expectedLogin: "sa-autogen-1-test2-001",
expectedLogin: "sa-AuToGeN-1-test2-001", // Using mixed-case to test case-insensitive search.
expectedErr: nil,
},
{
@ -361,7 +362,7 @@ func TestIntegrationStore_MigrateApiKeys(t *testing.T) {
{Login: "sa-autogen-1-test3-009"},
},
key: tests.TestApiKey{Name: "test3", Role: org.RoleEditor, OrgId: 1},
expectedLogin: "sa-autogen-1-test3-010",
expectedLogin: "sa-AuToGeN-1-test3-010", // Using mixed-case to test case-insensitive search.
expectedErr: nil,
},
{
@ -429,7 +430,7 @@ func TestIntegrationStore_MigrateApiKeys(t *testing.T) {
require.Equal(t, int64(1), serviceAccounts.TotalCount)
saMigrated := serviceAccounts.ServiceAccounts[0]
require.Equal(t, string(key.Role), saMigrated.Role)
require.Equal(t, c.expectedLogin, saMigrated.Login)
require.Equal(t, strings.ToLower(c.expectedLogin), saMigrated.Login)
tokens, err := store.ListTokens(context.Background(), &serviceaccounts.GetSATokensQuery{
OrgID: &key.OrgID,
@ -700,7 +701,7 @@ func TestIntegrationServiceAccountsStoreImpl_SearchOrgServiceAccounts(t *testing
desc: "should return service accounts with sa-1-satest login",
query: &serviceaccounts.SearchOrgServiceAccountsQuery{
OrgID: orgID,
Query: "sa-1-satest",
Query: "SA-1-SaTeSt", // Using mixed-case to test case-insensitive search
SignedInUser: userWithPerm,
Filter: serviceaccounts.FilterIncludeAll,
CountTokens: true,

@ -27,8 +27,6 @@ type Dialect interface {
ShowCreateNull() bool
SQLType(col *Column) string
SupportEngine() bool
// Deprecated. This doesn't work correctly for all databases.
LikeStr() string
// LikeOperator returns SQL snippet and query parameter for case-insensitive LIKE operation, with optional wildcards (%) before/after the pattern.
LikeOperator(column string, wildcardBefore bool, pattern string, wildcardAfter bool) (string, string)
Default(col *Column) string
@ -152,10 +150,6 @@ func (b *BaseDialect) AndStr() string {
return "AND"
}
func (b *BaseDialect) LikeStr() string {
return "LIKE"
}
func (b *BaseDialect) LikeOperator(column string, wildcardBefore bool, pattern string, wildcardAfter bool) (string, string) {
param := pattern
if wildcardBefore {

@ -31,10 +31,6 @@ func (db *PostgresDialect) Quote(name string) string {
return "\"" + name + "\""
}
func (db *PostgresDialect) LikeStr() string {
return "ILIKE"
}
func (db *PostgresDialect) LikeOperator(column string, wildcardBefore bool, pattern string, wildcardAfter bool) (string, string) {
param := pattern
if wildcardBefore {

@ -48,7 +48,8 @@ type TitleFilter struct {
}
func (f TitleFilter) Where() (string, []any) {
return fmt.Sprintf("dashboard.title %s ?", f.Dialect.LikeStr()), []any{"%" + f.Title + "%"}
sql, params := f.Dialect.LikeOperator("dashboard.title", true, f.Title, true)
return sql, []any{params}
}
type FolderFilter struct {

@ -186,8 +186,6 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) (
Teams: make([]*team.TeamDTO, 0),
}
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
queryWithWildcards := "%" + query.Query + "%"
var sql bytes.Buffer
params := make([]any, 0)
@ -201,8 +199,9 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) (
params = append(params, query.OrgID)
if query.Query != "" {
sql.WriteString(` and team.name ` + ss.db.GetDialect().LikeStr() + ` ?`)
params = append(params, queryWithWildcards)
like, param := ss.db.GetDialect().LikeOperator("team.name", true, query.Query, true)
sql.WriteString(" and " + like)
params = append(params, param)
}
if query.Name != "" {
@ -250,7 +249,8 @@ func (ss *xormStore) Search(ctx context.Context, query *team.SearchTeamsQuery) (
countSess.Where("team.org_id=?", query.OrgID)
if query.Query != "" {
countSess.Where(`name `+ss.db.GetDialect().LikeStr()+` ?`, queryWithWildcards)
like, param := ss.db.GetDialect().LikeOperator("name", true, query.Query, true)
countSess.Where(like, param)
}
if query.Name != "" {

@ -243,7 +243,8 @@ func TestIntegrationTeamCommandsAndQueries(t *testing.T) {
})
t.Run("Should be able to search for teams", func(t *testing.T) {
query := &team.SearchTeamsQuery{OrgID: testOrgID, Query: "group", Page: 1, SignedInUser: testUser}
// Use mixed-case to test case-insensitive search.
query := &team.SearchTeamsQuery{OrgID: testOrgID, Query: "GrOuP", Page: 1, SignedInUser: testUser}
queryResult, err := teamSvc.SearchTeams(context.Background(), query)
require.NoError(t, err)
require.Equal(t, len(queryResult.Teams), 2)

Loading…
Cancel
Save