summaryrefslogtreecommitdiffstats
path: root/store/sqlstore/plugin_store.go
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-11-27 17:23:35 -0500
committerGitHub <noreply@github.com>2017-11-27 17:23:35 -0500
commit6176bcff6977bda71f4fde10a52dde6d7d7ceb9a (patch)
treeb4a4a22879f4b88ffc4fb59f46ca69d441569ddd /store/sqlstore/plugin_store.go
parente85ec3830164ffdfbe8fd5696ab99446b38a01ef (diff)
downloadchat-6176bcff6977bda71f4fde10a52dde6d7d7ceb9a.tar.gz
chat-6176bcff6977bda71f4fde10a52dde6d7d7ceb9a.tar.bz2
chat-6176bcff6977bda71f4fde10a52dde6d7d7ceb9a.zip
PLT-8131 (part2) Add plugin key value store support (#7902)
* Add plugin key value store support * Add localization strings * Updates per feedback
Diffstat (limited to 'store/sqlstore/plugin_store.go')
-rw-r--r--store/sqlstore/plugin_store.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/store/sqlstore/plugin_store.go b/store/sqlstore/plugin_store.go
new file mode 100644
index 000000000..c7c075d8a
--- /dev/null
+++ b/store/sqlstore/plugin_store.go
@@ -0,0 +1,92 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package sqlstore
+
+import (
+ "database/sql"
+ "fmt"
+ "net/http"
+
+ "github.com/mattermost/mattermost-server/model"
+ "github.com/mattermost/mattermost-server/store"
+)
+
+type SqlPluginStore struct {
+ SqlStore
+}
+
+func NewSqlPluginStore(sqlStore SqlStore) store.PluginStore {
+ s := &SqlPluginStore{sqlStore}
+
+ for _, db := range sqlStore.GetAllConns() {
+ table := db.AddTableWithName(model.PluginKeyValue{}, "PluginKeyValueStore").SetKeys(false, "PluginId", "Key")
+ table.ColMap("Value").SetMaxSize(8192)
+ }
+
+ return s
+}
+
+func (ps SqlPluginStore) CreateIndexesIfNotExists() {
+}
+
+func (ps SqlPluginStore) SaveOrUpdate(kv *model.PluginKeyValue) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ if result.Err = kv.IsValid(); result.Err != nil {
+ return
+ }
+
+ if ps.DriverName() == model.DATABASE_DRIVER_POSTGRES {
+ // Unfortunately PostgreSQL pre-9.5 does not have an atomic upsert, so we use
+ // separate update and insert queries to accomplish our upsert
+ if rowsAffected, err := ps.GetMaster().Update(kv); err != nil {
+ result.Err = model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ } else if rowsAffected == 0 {
+ // No rows were affected by the update, so let's try an insert
+ if err := ps.GetMaster().Insert(kv); err != nil {
+ // If the error is from unique constraints violation, it's the result of a
+ // valid race and we can report success. Otherwise we have a real error and
+ // need to return it
+ if !IsUniqueConstraintError(err, []string{"PRIMARY", "PluginId", "Key", "PKey"}) {
+ result.Err = model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+ }
+ } else if ps.DriverName() == model.DATABASE_DRIVER_MYSQL {
+ if _, err := ps.GetMaster().Exec("INSERT INTO PluginKeyValueStore (PluginId, PKey, PValue) VALUES(:PluginId, :Key, :Value) ON DUPLICATE KEY UPDATE PValue = :Value", map[string]interface{}{"PluginId": kv.PluginId, "Key": kv.Key, "Value": kv.Value}); err != nil {
+ result.Err = model.NewAppError("SqlPluginStore.SaveOrUpdate", "store.sql_plugin_store.save.app_error", nil, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+
+ result.Data = kv
+ })
+}
+
+func (ps SqlPluginStore) Get(pluginId, key string) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ var kv *model.PluginKeyValue
+
+ if err := ps.GetReplica().SelectOne(&kv, "SELECT * FROM PluginKeyValueStore WHERE PluginId = :PluginId AND PKey = :Key", map[string]interface{}{"PluginId": pluginId, "Key": key}); err != nil {
+ if err == sql.ErrNoRows {
+ result.Err = model.NewAppError("SqlPluginStore.Get", "store.sql_plugin_store.get.app_error", nil, fmt.Sprintf("plugin_id=%v, key=%v, err=%v", pluginId, key, err.Error()), http.StatusNotFound)
+ } else {
+ result.Err = model.NewAppError("SqlPluginStore.Get", "store.sql_plugin_store.get.app_error", nil, fmt.Sprintf("plugin_id=%v, key=%v, err=%v", pluginId, key, err.Error()), http.StatusInternalServerError)
+ }
+ } else {
+ result.Data = kv
+ }
+ })
+}
+
+func (ps SqlPluginStore) Delete(pluginId, key string) store.StoreChannel {
+ return store.Do(func(result *store.StoreResult) {
+ if _, err := ps.GetMaster().Exec("DELETE FROM PluginKeyValueStore WHERE PluginId = :PluginId AND PKey = :Key", map[string]interface{}{"PluginId": pluginId, "Key": key}); err != nil {
+ result.Err = model.NewAppError("SqlPluginStore.Delete", "store.sql_plugin_store.delete.app_error", nil, fmt.Sprintf("plugin_id=%v, key=%v, err=%v", pluginId, key, err.Error()), http.StatusInternalServerError)
+ } else {
+ result.Data = true
+ }
+ })
+}