From f5610801e3c5be000bd37410be63a735d35f9fa4 Mon Sep 17 00:00:00 2001 From: Agniva De Sarker Date: Fri, 9 Jul 2021 23:38:52 +0530 Subject: [PATCH] PreferenceStore: Use native upsert for Postgres (#17894) * PreferenceStore: Use native upsert for Postgres Now that version 10 is minimum, we can start to use advanced postgres features. https://focalboard-community.octo.mattermost.com/workspace/zyoahc9uapdn3xdptac6jb69ic?id=285b80a3-257d-41f6-8cf4-ed80ca9d92e5&v=495cdb4d-c13a-4992-8eb9-80cfee2819a4&c=0445b560-91b9-469b-8f19-febf1881bcd6 ```release-note NONE ``` * fix lint issues ```release-note NONE ``` --- store/sqlstore/preference_store.go | 71 +++++++----------------------- 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/store/sqlstore/preference_store.go b/store/sqlstore/preference_store.go index e1a2a8aa98..da02890785 100644 --- a/store/sqlstore/preference_store.go +++ b/store/sqlstore/preference_store.go @@ -4,8 +4,6 @@ package sqlstore import ( - "fmt" - sq "github.com/Masterminds/squirrel" "github.com/mattermost/gorp" "github.com/mattermost/mattermost-server/v5/model" @@ -81,66 +79,27 @@ func (s SqlPreferenceStore) save(transaction *gorp.Transaction, preference *mode return err } + query := s.getQueryBuilder(). + Insert("Preferences"). + Columns("UserId", "Category", "Name", "Value"). + Values(preference.UserId, preference.Category, preference.Name, preference.Value) + if s.DriverName() == model.DATABASE_DRIVER_MYSQL { - queryString, args, err := s.getQueryBuilder(). - Insert("Preferences"). - Columns("UserId", "Category", "Name", "Value"). - Values(preference.UserId, preference.Category, preference.Name, preference.Value). - SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE Value = ?", preference.Value)). - ToSql() - - if err != nil { - return errors.Wrap(err, "failed to generate sqlquery") - } - - if _, err = transaction.Exec(queryString, args...); err != nil { - return errors.Wrap(err, "failed to save Preference") - } - return nil + query = query.SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE Value = ?", preference.Value)) } else if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { - - // postgres has no way to upsert values until version 9.5 and trying inserting and then updating causes transactions to abort - queryString, args, err := s.getQueryBuilder(). - Select("count(0)"). - From("Preferences"). - Where(sq.Eq{"UserId": preference.UserId}). - Where(sq.Eq{"Category": preference.Category}). - Where(sq.Eq{"Name": preference.Name}). - ToSql() - - if err != nil { - return errors.Wrap(err, "failed to generate sqlquery") - } - - count, err := transaction.SelectInt(queryString, args...) - if err != nil { - return errors.Wrap(err, "failed to count Preferences") - } - - if count == 1 { - return s.update(transaction, preference) - } - return s.insert(transaction, preference) - } - return store.NewErrNotImplemented("failed to update preference because of missing driver") -} - -func (s SqlPreferenceStore) insert(transaction *gorp.Transaction, preference *model.Preference) error { - if err := transaction.Insert(preference); err != nil { - if IsUniqueConstraintError(err, []string{"UserId", "preferences_pkey"}) { - return store.NewErrInvalidInput("Preference", "", fmt.Sprintf("<%s, %s, %s>", preference.UserId, preference.Category, preference.Name)) - } - return errors.Wrapf(err, "failed to save Preference with userId=%s, category=%s, name=%s", preference.UserId, preference.Category, preference.Name) + query = query.SuffixExpr(sq.Expr("ON CONFLICT (userid, category, name) DO UPDATE SET Value = ?", preference.Value)) + } else { + return store.NewErrNotImplemented("failed to update preference because of missing driver") } - return nil -} - -func (s SqlPreferenceStore) update(transaction *gorp.Transaction, preference *model.Preference) error { - if _, err := transaction.Update(preference); err != nil { - return errors.Wrapf(err, "failed to update Preference with userId=%s, category=%s, name=%s", preference.UserId, preference.Category, preference.Name) + queryString, args, err := query.ToSql() + if err != nil { + return errors.Wrap(err, "failed to generate sqlquery") } + if _, err = transaction.Exec(queryString, args...); err != nil { + return errors.Wrap(err, "failed to save Preference") + } return nil }