diff options
Diffstat (limited to 'store')
-rw-r--r-- | store/sql_channel_store.go | 3 | ||||
-rw-r--r-- | store/sql_post_store.go | 103 | ||||
-rw-r--r-- | store/sql_post_store_test.go | 102 | ||||
-rw-r--r-- | store/sql_store.go | 148 | ||||
-rw-r--r-- | store/sql_team_store.go | 10 | ||||
-rw-r--r-- | store/sql_user_store.go | 28 | ||||
-rw-r--r-- | store/store.go | 1 |
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 } |