summaryrefslogtreecommitdiffstats
path: root/store
diff options
context:
space:
mode:
Diffstat (limited to 'store')
-rw-r--r--store/sql_channel_store.go3
-rw-r--r--store/sql_post_store.go103
-rw-r--r--store/sql_post_store_test.go102
-rw-r--r--store/sql_store.go148
-rw-r--r--store/sql_team_store.go10
-rw-r--r--store/sql_user_store.go28
-rw-r--r--store/store.go1
7 files changed, 262 insertions, 133 deletions
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index d503d2225..d2e3943df 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -37,8 +37,7 @@ func NewSqlChannelStore(sqlStore *SqlStore) ChannelStore {
}
func (s SqlChannelStore) UpgradeSchemaIfNeeded() {
- s.CreateColumnIfNotExists("Channels", "ExtraUpdateAt", "TotalMsgCount", "bigint(20)", "0")
- s.CreateColumnIfNotExists("Channels", "CreatorId", "ExtraUpdateAt", "varchar(26)", "")
+ s.CreateColumnIfNotExists("Channels", "CreatorId", "varchar(26)", "character varying(26)", "")
}
func (s SqlChannelStore) CreateIndexesIfNotExists() {
diff --git a/store/sql_post_store.go b/store/sql_post_store.go
index 479caf838..297d60397 100644
--- a/store/sql_post_store.go
+++ b/store/sql_post_store.go
@@ -5,10 +5,11 @@ package store
import (
"fmt"
+ "regexp"
+ "strings"
+
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
- "strconv"
- "strings"
)
type SqlPostStore struct {
@@ -36,11 +37,6 @@ func NewSqlPostStore(sqlStore *SqlStore) PostStore {
}
func (s SqlPostStore) UpgradeSchemaIfNeeded() {
-
- // These execs are for upgrading currently created databases to full utf8mb4 compliance
- // Will be removed as seen fit for upgrading
- s.GetMaster().Exec("ALTER TABLE Posts charset=utf8mb4")
- s.GetMaster().Exec("ALTER TABLE Posts MODIFY COLUMN Message varchar(4000) CHARACTER SET utf8mb4")
}
func (s SqlPostStore) CreateIndexesIfNotExists() {
@@ -158,14 +154,6 @@ func (s SqlPostStore) Get(id string) StoreChannel {
result.Err = model.NewAppError("SqlPostStore.GetPost", "We couldn't get the post", "id="+id+err.Error())
}
- if post.ImgCount > 0 {
- post.Filenames = []string{}
- for i := 0; int64(i) < post.ImgCount; i++ {
- fileUrl := "/api/v1/files/get_image/" + post.ChannelId + "/" + post.Id + "/" + strconv.Itoa(i+1) + ".png"
- post.Filenames = append(post.Filenames, fileUrl)
- }
- }
-
pl.AddPost(&post)
pl.AddOrder(id)
@@ -265,25 +253,11 @@ func (s SqlPostStore) GetPosts(channelId string, offset int, limit int) StoreCha
list := &model.PostList{Order: make([]string, 0, len(posts))}
for _, p := range posts {
- if p.ImgCount > 0 {
- p.Filenames = []string{}
- for i := 0; int64(i) < p.ImgCount; i++ {
- fileUrl := "/api/v1/files/get_image/" + p.ChannelId + "/" + p.Id + "/" + strconv.Itoa(i+1) + ".png"
- p.Filenames = append(p.Filenames, fileUrl)
- }
- }
list.AddPost(p)
list.AddOrder(p.Id)
}
for _, p := range parents {
- if p.ImgCount > 0 {
- p.Filenames = []string{}
- for i := 0; int64(i) < p.ImgCount; i++ {
- fileUrl := "/api/v1/files/get_image/" + p.ChannelId + "/" + p.Id + "/" + strconv.Itoa(i+1) + ".png"
- p.Filenames = append(p.Filenames, fileUrl)
- }
- }
list.AddPost(p)
}
@@ -299,6 +273,64 @@ func (s SqlPostStore) GetPosts(channelId string, offset int, limit int) StoreCha
return storeChannel
}
+func (s SqlPostStore) GetPostsSince(channelId string, time int64) StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ var posts []*model.Post
+ _, err := s.GetReplica().Select(&posts,
+ `(SELECT
+ *
+ FROM
+ Posts
+ WHERE
+ (UpdateAt > :Time
+ AND ChannelId = :ChannelId)
+ LIMIT 1000)
+ UNION
+ (SELECT
+ *
+ FROM
+ Posts
+ WHERE
+ Id
+ IN
+ (SELECT * FROM (SELECT
+ RootId
+ FROM
+ Posts
+ WHERE
+ UpdateAt > :Time
+ AND ChannelId = :ChannelId
+ LIMIT 1000) temp_tab))
+ ORDER BY CreateAt DESC`,
+ map[string]interface{}{"ChannelId": channelId, "Time": time})
+
+ if err != nil {
+ result.Err = model.NewAppError("SqlPostStore.GetPostsSince", "We couldn't get the posts for the channel", "channelId="+channelId+err.Error())
+ } else {
+
+ list := &model.PostList{Order: make([]string, 0, len(posts))}
+
+ for _, p := range posts {
+ list.AddPost(p)
+ if p.UpdateAt > time {
+ list.AddOrder(p.Id)
+ }
+ }
+
+ result.Data = list
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
func (s SqlPostStore) getRootPosts(channelId string, offset int, limit int) StoreChannel {
storeChannel := make(StoreChannel)
@@ -328,7 +360,7 @@ func (s SqlPostStore) getParentsPosts(channelId string, offset int, limit int) S
var posts []*model.Post
_, err := s.GetReplica().Select(&posts,
- `SELECT
+ `SELECT
q2.*
FROM
Posts q2
@@ -336,7 +368,7 @@ func (s SqlPostStore) getParentsPosts(channelId string, offset int, limit int) S
(SELECT DISTINCT
q3.RootId
FROM
- (SELECT
+ (SELECT
RootId
FROM
Posts
@@ -344,7 +376,8 @@ func (s SqlPostStore) getParentsPosts(channelId string, offset int, limit int) S
ChannelId = :ChannelId1
AND DeleteAt = 0
ORDER BY CreateAt DESC
- LIMIT :Limit OFFSET :Offset) q3) q1 ON q1.RootId = q2.RootId
+ LIMIT :Limit OFFSET :Offset) q3
+ WHERE q3.RootId != '') q1 ON q1.RootId = q2.Id
WHERE
ChannelId = :ChannelId2
AND DeleteAt = 0
@@ -386,6 +419,12 @@ func (s SqlPostStore) Search(teamId string, userId string, terms string, isHasht
var posts []*model.Post
if utils.Cfg.SqlSettings.DriverName == "postgres" {
+
+ // Parse text for wildcards
+ if wildcard, err := regexp.Compile("\\*($| )"); err == nil {
+ terms = wildcard.ReplaceAllLiteralString(terms, ":* ")
+ }
+
searchQuery := fmt.Sprintf(`SELECT
*
FROM
diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go
index 336a20d98..d48dea51c 100644
--- a/store/sql_post_store_test.go
+++ b/store/sql_post_store_test.go
@@ -4,11 +4,11 @@
package store
import (
- "github.com/mattermost/platform/model"
- "github.com/mattermost/platform/utils"
"strings"
"testing"
"time"
+
+ "github.com/mattermost/platform/model"
)
func TestPostStoreSave(t *testing.T) {
@@ -374,6 +374,91 @@ func TestPostStoreGetPostsWtihDetails(t *testing.T) {
t.Fatal("invalid order")
}
+ if len(r1.Posts) != 5 { //the last 4, + o1 (o3 and o2a's parent)
+ t.Fatal("wrong size")
+ }
+
+ if r1.Posts[o1.Id].Message != o1.Message {
+ t.Fatal("Missing parent")
+ }
+}
+
+func TestPostStoreGetPostsSince(t *testing.T) {
+ Setup()
+ o0 := &model.Post{}
+ o0.ChannelId = model.NewId()
+ o0.UserId = model.NewId()
+ o0.Message = "a" + model.NewId() + "b"
+ o0 = (<-store.Post().Save(o0)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o1 := &model.Post{}
+ o1.ChannelId = model.NewId()
+ o1.UserId = model.NewId()
+ o1.Message = "a" + model.NewId() + "b"
+ o1 = (<-store.Post().Save(o1)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o2 := &model.Post{}
+ o2.ChannelId = o1.ChannelId
+ o2.UserId = model.NewId()
+ o2.Message = "a" + model.NewId() + "b"
+ o2.ParentId = o1.Id
+ o2.RootId = o1.Id
+ o2 = (<-store.Post().Save(o2)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o2a := &model.Post{}
+ o2a.ChannelId = o1.ChannelId
+ o2a.UserId = model.NewId()
+ o2a.Message = "a" + model.NewId() + "b"
+ o2a.ParentId = o1.Id
+ o2a.RootId = o1.Id
+ o2a = (<-store.Post().Save(o2a)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o3 := &model.Post{}
+ o3.ChannelId = o1.ChannelId
+ o3.UserId = model.NewId()
+ o3.Message = "a" + model.NewId() + "b"
+ o3.ParentId = o1.Id
+ o3.RootId = o1.Id
+ o3 = (<-store.Post().Save(o3)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o4 := &model.Post{}
+ o4.ChannelId = o1.ChannelId
+ o4.UserId = model.NewId()
+ o4.Message = "a" + model.NewId() + "b"
+ o4 = (<-store.Post().Save(o4)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o5 := &model.Post{}
+ o5.ChannelId = o1.ChannelId
+ o5.UserId = model.NewId()
+ o5.Message = "a" + model.NewId() + "b"
+ o5.ParentId = o4.Id
+ o5.RootId = o4.Id
+ o5 = (<-store.Post().Save(o5)).Data.(*model.Post)
+
+ r1 := (<-store.Post().GetPostsSince(o1.ChannelId, o1.CreateAt)).Data.(*model.PostList)
+
+ if r1.Order[0] != o5.Id {
+ t.Fatal("invalid order")
+ }
+
+ if r1.Order[1] != o4.Id {
+ t.Fatal("invalid order")
+ }
+
+ if r1.Order[2] != o3.Id {
+ t.Fatal("invalid order")
+ }
+
+ if r1.Order[3] != o2a.Id {
+ t.Fatal("invalid order")
+ }
+
if len(r1.Posts) != 6 {
t.Fatal("wrong size")
}
@@ -462,11 +547,9 @@ func TestPostStoreSearch(t *testing.T) {
t.Fatal("returned wrong serach result")
}
- if utils.Cfg.SqlSettings.DriverName == "mysql" {
- r5 := (<-store.Post().Search(teamId, userId, "matter*", false)).Data.(*model.PostList)
- if len(r5.Order) != 1 && r5.Order[0] != o1.Id {
- t.Fatal("returned wrong serach result")
- }
+ r5 := (<-store.Post().Search(teamId, userId, "matter*", false)).Data.(*model.PostList)
+ if len(r5.Order) != 1 && r5.Order[0] != o1.Id {
+ t.Fatal("returned wrong serach result")
}
r6 := (<-store.Post().Search(teamId, userId, "#hashtag", true)).Data.(*model.PostList)
@@ -488,4 +571,9 @@ func TestPostStoreSearch(t *testing.T) {
if len(r9.Order) != 2 {
t.Fatal("returned wrong search result")
}
+
+ r10 := (<-store.Post().Search(teamId, userId, "matter* jer*", false)).Data.(*model.PostList)
+ if len(r10.Order) != 2 {
+ t.Fatal("returned wrong search result")
+ }
}
diff --git a/store/sql_store.go b/store/sql_store.go
index 0d4f76a72..98c67d668 100644
--- a/store/sql_store.go
+++ b/store/sql_store.go
@@ -123,13 +123,29 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle
}
func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool {
- // XXX TODO FIXME this should be removed after 0.6.0
if utils.Cfg.SqlSettings.DriverName == "postgres" {
- return false
- }
+ count, err := ss.GetMaster().SelectInt(
+ `SELECT COUNT(0)
+ FROM pg_attribute
+ WHERE attrelid = $1::regclass
+ AND attname = $2
+ AND NOT attisdropped`,
+ strings.ToLower(tableName),
+ strings.ToLower(columnName),
+ )
+
+ if err != nil {
+ l4g.Critical("Failed to check if column exists %v", err)
+ time.Sleep(time.Second)
+ panic("Failed to check if column exists " + err.Error())
+ }
+
+ return count > 0
- count, err := ss.GetMaster().SelectInt(
- `SELECT
+ } else if utils.Cfg.SqlSettings.DriverName == "mysql" {
+
+ count, err := ss.GetMaster().SelectInt(
+ `SELECT
COUNT(0) AS column_exists
FROM
information_schema.COLUMNS
@@ -137,81 +153,101 @@ func (ss SqlStore) DoesColumnExist(tableName string, columnName string) bool {
TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = ?
AND COLUMN_NAME = ?`,
- tableName,
- columnName,
- )
- if err != nil {
- l4g.Critical("Failed to check if column exists %v", err)
+ tableName,
+ columnName,
+ )
+
+ if err != nil {
+ l4g.Critical("Failed to check if column exists %v", err)
+ time.Sleep(time.Second)
+ panic("Failed to check if column exists " + err.Error())
+ }
+
+ return count > 0
+
+ } else {
+ l4g.Critical("Failed to check if column exists because of missing driver")
time.Sleep(time.Second)
- panic("Failed to check if column exists " + err.Error())
+ panic("Failed to check if column exists because of missing driver")
}
- return count > 0
}
-func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, afterName string, colType string, defaultValue string) bool {
-
- // XXX TODO FIXME this should be removed after 0.6.0
- if utils.Cfg.SqlSettings.DriverName == "postgres" {
- return false
- }
+func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, mySqlColType string, postgresColType string, defaultValue string) bool {
if ss.DoesColumnExist(tableName, columnName) {
return false
}
- _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + colType + " DEFAULT '" + defaultValue + "'" + " AFTER " + afterName)
- if err != nil {
- l4g.Critical("Failed to create column %v", err)
+ if utils.Cfg.SqlSettings.DriverName == "postgres" {
+ _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + postgresColType + " DEFAULT '" + defaultValue + "'")
+ if err != nil {
+ l4g.Critical("Failed to create column %v", err)
+ time.Sleep(time.Second)
+ panic("Failed to create column " + err.Error())
+ }
+
+ return true
+
+ } else if utils.Cfg.SqlSettings.DriverName == "mysql" {
+ _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + mySqlColType + " DEFAULT '" + defaultValue + "'")
+ if err != nil {
+ l4g.Critical("Failed to create column %v", err)
+ time.Sleep(time.Second)
+ panic("Failed to create column " + err.Error())
+ }
+
+ return true
+
+ } else {
+ l4g.Critical("Failed to create column because of missing driver")
time.Sleep(time.Second)
- panic("Failed to create column " + err.Error())
+ panic("Failed to create column because of missing driver")
}
-
- return true
}
-func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
+// func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
- // XXX TODO FIXME this should be removed after 0.6.0
- if utils.Cfg.SqlSettings.DriverName == "postgres" {
- return false
- }
+// // XXX TODO FIXME this should be removed after 0.6.0
+// if utils.Cfg.SqlSettings.DriverName == "postgres" {
+// return false
+// }
- if !ss.DoesColumnExist(tableName, columnName) {
- return false
- }
+// if !ss.DoesColumnExist(tableName, columnName) {
+// return false
+// }
- _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
- if err != nil {
- l4g.Critical("Failed to drop column %v", err)
- time.Sleep(time.Second)
- panic("Failed to drop column " + err.Error())
- }
+// _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
+// if err != nil {
+// l4g.Critical("Failed to drop column %v", err)
+// time.Sleep(time.Second)
+// panic("Failed to drop column " + err.Error())
+// }
- return true
-}
+// return true
+// }
-func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
+// func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
- // XXX TODO FIXME this should be removed after 0.6.0
- if utils.Cfg.SqlSettings.DriverName == "postgres" {
- return false
- }
+// // XXX TODO FIXME this should be removed after 0.6.0
+// if utils.Cfg.SqlSettings.DriverName == "postgres" {
+// return false
+// }
- if !ss.DoesColumnExist(tableName, oldColumnName) {
- return false
- }
+// if !ss.DoesColumnExist(tableName, oldColumnName) {
+// return false
+// }
- _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType)
+// _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType)
- if err != nil {
- l4g.Critical("Failed to rename column %v", err)
- time.Sleep(time.Second)
- panic("Failed to drop column " + err.Error())
- }
+// if err != nil {
+// l4g.Critical("Failed to rename column %v", err)
+// time.Sleep(time.Second)
+// panic("Failed to drop column " + err.Error())
+// }
- return true
-}
+// return true
+// }
func (ss SqlStore) CreateIndexIfNotExists(indexName string, tableName string, columnName string) {
ss.createIndexIfNotExists(indexName, tableName, columnName, false)
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index 7b0be0540..2784f8630 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -5,7 +5,6 @@ package store
import (
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/utils"
)
type SqlTeamStore struct {
@@ -29,15 +28,6 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore {
}
func (s SqlTeamStore) UpgradeSchemaIfNeeded() {
- defaultValue := "0"
- if utils.Cfg.TeamSettings.AllowValetDefault {
- defaultValue = "1"
- }
- s.CreateColumnIfNotExists("Teams", "AllowValet", "AllowedDomains", "tinyint(1)", defaultValue)
- if !s.DoesColumnExist("Teams", "DisplayName") {
- s.RenameColumnIfExists("Teams", "Name", "DisplayName", "varchar(64)")
- s.RenameColumnIfExists("Teams", "Domain", "Name", "varchar(64)")
- }
}
func (s SqlTeamStore) CreateIndexesIfNotExists() {
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index 4b1189c2e..64a18545a 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -5,9 +5,9 @@ package store
import (
"fmt"
- "strings"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
+ "strings"
)
type SqlUserStore struct {
@@ -40,32 +40,8 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore {
}
func (us SqlUserStore) UpgradeSchemaIfNeeded() {
- us.CreateColumnIfNotExists("Users", "LastPictureUpdate", "LastPasswordUpdate", "bigint(20)", "0")
-
- // migrating the FullName column to Nickname and adding the FirstName and LastName columns for MM-825
- if us.RenameColumnIfExists("Users", "FullName", "Nickname", "varchar(64)") {
- us.CreateColumnIfNotExists("Users", "FirstName", "Nickname", "varchar(64)", "")
- us.CreateColumnIfNotExists("Users", "LastName", "FirstName", "varchar(64)", "")
-
- // infer values of first and last name by splitting the previous full name
- if _, err := us.GetMaster().Exec("UPDATE Users SET FirstName = SUBSTRING_INDEX(SUBSTRING_INDEX(Nickname, ' ', 1), ' ', -1)"); err != nil {
- panic("Failed to set first name from nickname " + err.Error())
- }
-
- // only set the last name from full names that are comprised of multiple words (ie that have at least one space in them)
- if _, err := us.GetMaster().Exec("Update Users SET LastName = SUBSTRING(Nickname, INSTR(Nickname, ' ') + 1) " +
- "WHERE CHAR_LENGTH(REPLACE(Nickname, ' ', '')) < CHAR_LENGTH(Nickname)"); err != nil {
- panic("Failed to set last name from nickname " + err.Error())
- }
- }
-
- us.CreateColumnIfNotExists("Users", "AuthService", "AuthData", "varchar(32)", "") // for OAuth Client
-
- us.CreateColumnIfNotExists("Users", "FailedAttempts", "LastPictureUpdate", "int(11)", "0")
}
-//func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string, afterName string, colType string, defaultValue string) bool {
-
func (us SqlUserStore) CreateIndexesIfNotExists() {
us.CreateIndexIfNotExists("idx_users_team_id", "Users", "TeamId")
us.CreateIndexIfNotExists("idx_users_email", "Users", "Email")
@@ -168,7 +144,7 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha
nonUsernameKeys := []string{}
splitKeys := strings.Split(user.NotifyProps["mention_keys"], ",")
for _, key := range splitKeys {
- if key != oldUser.Username && key != "@" + oldUser.Username {
+ if key != oldUser.Username && key != "@"+oldUser.Username {
nonUsernameKeys = append(nonUsernameKeys, key)
}
}
diff --git a/store/store.go b/store/store.go
index 8dbf12b55..271caa366 100644
--- a/store/store.go
+++ b/store/store.go
@@ -75,6 +75,7 @@ type PostStore interface {
Get(id string) StoreChannel
Delete(postId string, time int64) StoreChannel
GetPosts(channelId string, offset int, limit int) StoreChannel
+ GetPostsSince(channelId string, time int64) StoreChannel
GetEtag(channelId string) StoreChannel
Search(teamId string, userId string, terms string, isHashtagSearch bool) StoreChannel
}