Migrating Emoji store to use sqlx (#18301)
* Migrating Emoji store to use sqlx https://community-daily.mattermost.com/boards/workspace/zyoahc9uapdn3xdptac6jb69ic/285b80a3-257d-41f6-8cf4-ed80ca9d92e5/495cdb4d-c13a-4992-8eb9-80cfee2819a4?c=646cee9a-219c-49f3-8e0b-6ec2cff4deba ```release-note NONE ``` * Incorporate review suggestions ```release-note NONE ``` Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e542842bd1
Коммит
0953e3f0cf
@@ -42,3 +42,11 @@ func (ss *SqlStore) DBFromContext(ctx context.Context) *gorp.DbMap {
|
|||||||
}
|
}
|
||||||
return ss.GetReplica()
|
return ss.GetReplica()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DBXFromContext is a helper utility that returns the sqlx DB handle from a given context.
|
||||||
|
func (ss *SqlStore) DBXFromContext(ctx context.Context) *sqlxDBWrapper {
|
||||||
|
if hasMaster(ctx) {
|
||||||
|
return ss.GetMasterX()
|
||||||
|
}
|
||||||
|
return ss.GetReplicaX()
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
@@ -50,7 +51,10 @@ func (es SqlEmojiStore) Save(emoji *model.Emoji) (*model.Emoji, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := es.GetMaster().Insert(emoji); err != nil {
|
if _, err := es.GetMasterX().NamedExec(`INSERT INTO Emoji
|
||||||
|
(Id, CreateAt, UpdateAt, DeleteAt, CreatorId, Name)
|
||||||
|
VALUES
|
||||||
|
(:Id, :CreateAt, :UpdateAt, :DeleteAt, :CreatorId, :Name)`, emoji); err != nil {
|
||||||
return nil, errors.Wrap(err, "error saving emoji")
|
return nil, errors.Wrap(err, "error saving emoji")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,25 +70,26 @@ func (es SqlEmojiStore) GetByName(ctx context.Context, name string, allowFromCac
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (es SqlEmojiStore) GetMultipleByName(names []string) ([]*model.Emoji, error) {
|
func (es SqlEmojiStore) GetMultipleByName(names []string) ([]*model.Emoji, error) {
|
||||||
keys, params := MapStringsToQueryParams(names, "Emoji")
|
// Creating (?, ?, ?) len(names) number of times.
|
||||||
|
keys := strings.Join(strings.Fields(strings.Repeat("? ", len(names))), ",")
|
||||||
|
args := makeStringArgs(names)
|
||||||
|
|
||||||
var emojis []*model.Emoji
|
emojis := []*model.Emoji{}
|
||||||
|
if err := es.GetReplicaX().Select(&emojis,
|
||||||
if _, err := es.GetReplica().Select(&emojis,
|
|
||||||
`SELECT
|
`SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
Emoji
|
Emoji
|
||||||
WHERE
|
WHERE
|
||||||
Name IN `+keys+`
|
Name IN (`+keys+`)
|
||||||
AND DeleteAt = 0`, params); err != nil {
|
AND DeleteAt = 0`, args...); err != nil {
|
||||||
return nil, errors.Wrapf(err, "error getting emoji by names %v", names)
|
return nil, errors.Wrapf(err, "error getting emoji by names %v", names)
|
||||||
}
|
}
|
||||||
return emojis, nil
|
return emojis, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es SqlEmojiStore) GetList(offset, limit int, sort string) ([]*model.Emoji, error) {
|
func (es SqlEmojiStore) GetList(offset, limit int, sort string) ([]*model.Emoji, error) {
|
||||||
var emoji []*model.Emoji
|
emojis := []*model.Emoji{}
|
||||||
|
|
||||||
query := "SELECT * FROM Emoji WHERE DeleteAt = 0"
|
query := "SELECT * FROM Emoji WHERE DeleteAt = 0"
|
||||||
|
|
||||||
@@ -92,24 +97,24 @@ func (es SqlEmojiStore) GetList(offset, limit int, sort string) ([]*model.Emoji,
|
|||||||
query += " ORDER BY Name"
|
query += " ORDER BY Name"
|
||||||
}
|
}
|
||||||
|
|
||||||
query += " LIMIT :Limit OFFSET :Offset"
|
query += " LIMIT ? OFFSET ?"
|
||||||
|
|
||||||
if _, err := es.GetReplica().Select(&emoji, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
|
if err := es.GetReplicaX().Select(&emojis, query, limit, offset); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get list of emojis")
|
return nil, errors.Wrap(err, "could not get list of emojis")
|
||||||
}
|
}
|
||||||
return emoji, nil
|
return emojis, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es SqlEmojiStore) Delete(emoji *model.Emoji, time int64) error {
|
func (es SqlEmojiStore) Delete(emoji *model.Emoji, time int64) error {
|
||||||
if sqlResult, err := es.GetMaster().Exec(
|
if sqlResult, err := es.GetMasterX().Exec(
|
||||||
`UPDATE
|
`UPDATE
|
||||||
Emoji
|
Emoji
|
||||||
SET
|
SET
|
||||||
DeleteAt = :DeleteAt,
|
DeleteAt = ?,
|
||||||
UpdateAt = :UpdateAt
|
UpdateAt = ?
|
||||||
WHERE
|
WHERE
|
||||||
Id = :Id
|
Id = ?
|
||||||
AND DeleteAt = 0`, map[string]interface{}{"DeleteAt": time, "UpdateAt": time, "Id": emoji.Id}); err != nil {
|
AND DeleteAt = 0`, time, time, emoji.Id); err != nil {
|
||||||
return errors.Wrap(err, "could not delete emoji")
|
return errors.Wrap(err, "could not delete emoji")
|
||||||
} else if rows, _ := sqlResult.RowsAffected(); rows == 0 {
|
} else if rows, _ := sqlResult.RowsAffected(); rows == 0 {
|
||||||
return store.NewErrNotFound("Emoji", emoji.Id)
|
return store.NewErrNotFound("Emoji", emoji.Id)
|
||||||
@@ -119,7 +124,7 @@ func (es SqlEmojiStore) Delete(emoji *model.Emoji, time int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (es SqlEmojiStore) Search(name string, prefixOnly bool, limit int) ([]*model.Emoji, error) {
|
func (es SqlEmojiStore) Search(name string, prefixOnly bool, limit int) ([]*model.Emoji, error) {
|
||||||
var emojis []*model.Emoji
|
emojis := []*model.Emoji{}
|
||||||
|
|
||||||
name = sanitizeSearchTerm(name, "\\")
|
name = sanitizeSearchTerm(name, "\\")
|
||||||
|
|
||||||
@@ -130,16 +135,16 @@ func (es SqlEmojiStore) Search(name string, prefixOnly bool, limit int) ([]*mode
|
|||||||
|
|
||||||
term += name + "%"
|
term += name + "%"
|
||||||
|
|
||||||
if _, err := es.GetReplica().Select(&emojis,
|
if err := es.GetReplicaX().Select(&emojis,
|
||||||
`SELECT
|
`SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
Emoji
|
Emoji
|
||||||
WHERE
|
WHERE
|
||||||
Name LIKE :Name
|
Name LIKE ?
|
||||||
AND DeleteAt = 0
|
AND DeleteAt = 0
|
||||||
ORDER BY Name
|
ORDER BY Name
|
||||||
LIMIT :Limit`, map[string]interface{}{"Name": term, "Limit": limit}); err != nil {
|
LIMIT ?`, term, limit); err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not search emojis by name %s", name)
|
return nil, errors.Wrapf(err, "could not search emojis by name %s", name)
|
||||||
}
|
}
|
||||||
return emojis, nil
|
return emojis, nil
|
||||||
@@ -147,16 +152,16 @@ func (es SqlEmojiStore) Search(name string, prefixOnly bool, limit int) ([]*mode
|
|||||||
|
|
||||||
// getBy returns one active (not deleted) emoji, found by any one column (what/key).
|
// getBy returns one active (not deleted) emoji, found by any one column (what/key).
|
||||||
func (es SqlEmojiStore) getBy(ctx context.Context, what, key string) (*model.Emoji, error) {
|
func (es SqlEmojiStore) getBy(ctx context.Context, what, key string) (*model.Emoji, error) {
|
||||||
var emoji *model.Emoji
|
var emoji model.Emoji
|
||||||
|
|
||||||
err := es.DBFromContext(ctx).SelectOne(&emoji,
|
err := es.DBXFromContext(ctx).Get(&emoji,
|
||||||
`SELECT
|
`SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
Emoji
|
Emoji
|
||||||
WHERE
|
WHERE
|
||||||
`+what+` = :Key
|
`+what+` = ?
|
||||||
AND DeleteAt = 0`, map[string]string{"Key": key})
|
AND DeleteAt = 0`, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, store.NewErrNotFound("Emoji", fmt.Sprintf("%s=%s", what, key))
|
return nil, store.NewErrNotFound("Emoji", fmt.Sprintf("%s=%s", what, key))
|
||||||
@@ -165,5 +170,5 @@ func (es SqlEmojiStore) getBy(ctx context.Context, what, key string) (*model.Emo
|
|||||||
return nil, errors.Wrapf(err, "could not get emoji by %s with value %s", what, key)
|
return nil, errors.Wrapf(err, "could not get emoji by %s with value %s", what, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return emoji, nil
|
return &emoji, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,3 +124,11 @@ func constructMySQLJSONArgs(props map[string]string) ([]interface{}, string) {
|
|||||||
|
|
||||||
return args, argString
|
return args, argString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeStringArgs(params []string) []interface{} {
|
||||||
|
args := make([]interface{}, len(params))
|
||||||
|
for i, name := range params {
|
||||||
|
args[i] = name
|
||||||
|
}
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user