services/user: Fix userimpl tests when running on Spanner. (#103715)
Fix userimpl tests when running on Spanner.
This commit is contained in:
@@ -27,7 +27,10 @@ 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
|
||||
// BooleanValue can be used as an argument in SELECT or INSERT statements. For constructing
|
||||
// raw SQL queries, please use BooleanStr instead.
|
||||
@@ -153,6 +156,17 @@ 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 {
|
||||
param = "%" + param
|
||||
}
|
||||
if wildcardAfter {
|
||||
param = param + "%"
|
||||
}
|
||||
return fmt.Sprintf("%s LIKE ?", column), param
|
||||
}
|
||||
|
||||
func (b *BaseDialect) OrStr() string {
|
||||
return "OR"
|
||||
}
|
||||
|
||||
@@ -35,6 +35,17 @@ 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 {
|
||||
param = "%" + param
|
||||
}
|
||||
if wildcardAfter {
|
||||
param = param + "%"
|
||||
}
|
||||
return fmt.Sprintf("%s ILIKE ?", column), param
|
||||
}
|
||||
|
||||
func (db *PostgresDialect) AutoIncrStr() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/spanner"
|
||||
@@ -44,6 +45,18 @@ func NewSpannerDialect() Dialect {
|
||||
func (s *SpannerDialect) AutoIncrStr() string { return s.d.AutoIncrStr() }
|
||||
func (s *SpannerDialect) Quote(name string) string { return s.d.Quote(name) }
|
||||
func (s *SpannerDialect) SupportEngine() bool { return s.d.SupportEngine() }
|
||||
|
||||
func (s *SpannerDialect) LikeOperator(column string, wildcardBefore bool, pattern string, wildcardAfter bool) (string, string) {
|
||||
param := strings.ToLower(pattern)
|
||||
if wildcardBefore {
|
||||
param = "%" + param
|
||||
}
|
||||
if wildcardAfter {
|
||||
param = param + "%"
|
||||
}
|
||||
return fmt.Sprintf("LOWER(%s) LIKE ?", column), param
|
||||
}
|
||||
|
||||
func (s *SpannerDialect) IndexCheckSQL(tableName, indexName string) (string, []any) {
|
||||
return s.d.IndexCheckSql(tableName, indexName)
|
||||
}
|
||||
|
||||
@@ -2,15 +2,11 @@ package userimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/mattn/go-sqlite3"
|
||||
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -76,8 +72,9 @@ func (ss *sqlStore) Insert(ctx context.Context, cmd *user.User) (int64, error) {
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return 0, handleSQLError(err)
|
||||
return 0, handleSQLError(ss.dialect, err)
|
||||
}
|
||||
|
||||
return cmd.ID, nil
|
||||
@@ -482,8 +479,6 @@ func (ss *sqlStore) Search(ctx context.Context, query *user.SearchUsersQuery) (*
|
||||
Users: make([]*user.UserSearchHitDTO, 0),
|
||||
}
|
||||
err := ss.db.WithDbSession(ctx, func(dbSess *db.Session) error {
|
||||
queryWithWildcards := "%" + query.Query + "%"
|
||||
|
||||
whereConditions := make([]string, 0)
|
||||
whereParams := make([]any, 0)
|
||||
sess := dbSess.Table("user").Alias("u")
|
||||
@@ -512,8 +507,11 @@ func (ss *sqlStore) Search(ctx context.Context, query *user.SearchUsersQuery) (*
|
||||
whereParams = append(whereParams, acFilter.Args...)
|
||||
|
||||
if 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)
|
||||
emailSql, emailArg := ss.dialect.LikeOperator("email", true, query.Query, true)
|
||||
nameSql, nameArg := ss.dialect.LikeOperator("name", true, query.Query, true)
|
||||
loginSql, loginArg := ss.dialect.LikeOperator("login", true, query.Query, true)
|
||||
whereConditions = append(whereConditions, fmt.Sprintf("(%s OR %s OR %s)", emailSql, nameSql, loginSql))
|
||||
whereParams = append(whereParams, emailArg, nameArg, loginArg)
|
||||
}
|
||||
|
||||
if query.IsDisabled != nil {
|
||||
@@ -606,29 +604,9 @@ func setOptional[T any](v *T, add func(v T)) {
|
||||
}
|
||||
}
|
||||
|
||||
func handleSQLError(err error) error {
|
||||
if isUniqueConstraintError(err) {
|
||||
func handleSQLError(dialect migrator.Dialect, err error) error {
|
||||
if dialect.IsUniqueConstraintViolation(err) {
|
||||
return user.ErrUserAlreadyExists
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func isUniqueConstraintError(err error) bool {
|
||||
// check mysql error code
|
||||
var me *mysql.MySQLError
|
||||
if errors.As(err, &me) && me.Number == 1062 {
|
||||
return true
|
||||
}
|
||||
|
||||
// for postgres we check the error message
|
||||
if strings.Contains(err.Error(), "duplicate key value") {
|
||||
return true
|
||||
}
|
||||
|
||||
var se sqlite3.Error
|
||||
if errors.As(err, &se) && se.ExtendedCode == sqlite3.ErrConstraintUnique {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user