[MM-5046] Fix emails search for Postgres DB (#21590)
* Support emails search in Postgres * Add @ exception for postgres * update comment Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
@@ -35,9 +35,16 @@ var searchPostStoreTests = []searchTest{
|
|||||||
Tags: []string{EnginePostgres, EngineMySql, EngineElasticSearch},
|
Tags: []string{EnginePostgres, EngineMySql, EngineElasticSearch},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// Postgres supports search with and without quotes
|
||||||
Name: "Should be able to search for email addresses with or without quotes",
|
Name: "Should be able to search for email addresses with or without quotes",
|
||||||
Fn: testSearchEmailAddresses,
|
Fn: testSearchEmailAddresses,
|
||||||
Tags: []string{EngineElasticSearch},
|
Tags: []string{EnginePostgres, EngineElasticSearch},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// MySql supports search with quotes only
|
||||||
|
Name: "Should be able to search for email addresses with quotes",
|
||||||
|
Fn: testSearchEmailAddressesWithQuotes,
|
||||||
|
Tags: []string{EngineMySql},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Should be able to search when markdown underscores are applied",
|
Name: "Should be able to search when markdown underscores are applied",
|
||||||
@@ -242,11 +249,6 @@ var searchPostStoreTests = []searchTest{
|
|||||||
Fn: testSlashShouldNotBeCharSeparator,
|
Fn: testSlashShouldNotBeCharSeparator,
|
||||||
Tags: []string{EngineMySql, EngineElasticSearch},
|
Tags: []string{EngineMySql, EngineElasticSearch},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "Should be able to search emails without quoting them",
|
|
||||||
Fn: testSearchEmailsWithoutQuotes,
|
|
||||||
Tags: []string{EngineElasticSearch},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "Should be able to search in comments",
|
Name: "Should be able to search in comments",
|
||||||
Fn: testSupportSearchInComments,
|
Fn: testSupportSearchInComments,
|
||||||
@@ -366,9 +368,9 @@ func testSearchExactPhraseInQuotes(t *testing.T, th *SearchTestHelper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSearchEmailAddresses(t *testing.T, th *SearchTestHelper) {
|
func testSearchEmailAddresses(t *testing.T, th *SearchTestHelper) {
|
||||||
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test email test@test.com", "", model.PostTypeDefault, 0, false)
|
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "email test@test.com", "", model.PostTypeDefault, 0, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test email test2@test.com", "", model.PostTypeDefault, 0, false)
|
_, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "email test2@test.com", "", model.PostTypeDefault, 0, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer th.deleteUserPosts(th.User.Id)
|
defer th.deleteUserPosts(th.User.Id)
|
||||||
|
|
||||||
@@ -391,6 +393,21 @@ func testSearchEmailAddresses(t *testing.T, th *SearchTestHelper) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSearchEmailAddressesWithQuotes(t *testing.T, th *SearchTestHelper) {
|
||||||
|
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "email test@test.com", "", model.PostTypeDefault, 0, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "email test2@test.com", "", model.PostTypeDefault, 0, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer th.deleteUserPosts(th.User.Id)
|
||||||
|
|
||||||
|
params := &model.SearchParams{Terms: "\"test@test.com\""}
|
||||||
|
results, err := th.Store.Post().SearchPostsForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, results.Posts, 1)
|
||||||
|
th.checkPostInSearchResults(t, p1.Id, results.Posts)
|
||||||
|
}
|
||||||
|
|
||||||
func testSearchMarkdownUnderscores(t *testing.T, th *SearchTestHelper) {
|
func testSearchMarkdownUnderscores(t *testing.T, th *SearchTestHelper) {
|
||||||
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "_start middle end_ _another_", "", model.PostTypeDefault, 0, false)
|
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "_start middle end_ _another_", "", model.PostTypeDefault, 0, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -1769,21 +1786,6 @@ func testSlashShouldNotBeCharSeparator(t *testing.T, th *SearchTestHelper) {
|
|||||||
th.checkPostInSearchResults(t, p1.Id, results.Posts)
|
th.checkPostInSearchResults(t, p1.Id, results.Posts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSearchEmailsWithoutQuotes(t *testing.T, th *SearchTestHelper) {
|
|
||||||
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message test@test.com", "", model.PostTypeDefault, 0, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
_, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "message test2@test.com", "", model.PostTypeDefault, 0, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer th.deleteUserPosts(th.User.Id)
|
|
||||||
|
|
||||||
params := &model.SearchParams{Terms: "test@test.com"}
|
|
||||||
results, err := th.Store.Post().SearchPostsForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Len(t, results.Posts, 1)
|
|
||||||
th.checkPostInSearchResults(t, p1.Id, results.Posts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testSupportSearchInComments(t *testing.T, th *SearchTestHelper) {
|
func testSupportSearchInComments(t *testing.T, th *SearchTestHelper) {
|
||||||
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message test@test.com", "", model.PostTypeDefault, 0, false)
|
p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message test@test.com", "", model.PostTypeDefault, 0, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -606,8 +606,7 @@ func (fs SqlFileInfoStore) Search(paramsList []*model.SearchParams, userId, team
|
|||||||
terms := params.Terms
|
terms := params.Terms
|
||||||
excludedTerms := params.ExcludedTerms
|
excludedTerms := params.ExcludedTerms
|
||||||
|
|
||||||
// these chars have special meaning and can be treated as spaces
|
for _, c := range fs.specialSearchChars() {
|
||||||
for _, c := range specialSearchChar {
|
|
||||||
terms = strings.Replace(terms, c, " ", -1)
|
terms = strings.Replace(terms, c, " ", -1)
|
||||||
excludedTerms = strings.Replace(excludedTerms, c, " ", -1)
|
excludedTerms = strings.Replace(excludedTerms, c, " ", -1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1788,18 +1788,6 @@ func (s *SqlPostStore) getParentsPostsPostgreSQL(channelId string, offset int, l
|
|||||||
return posts, nil
|
return posts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var specialSearchChar = []string{
|
|
||||||
"<",
|
|
||||||
">",
|
|
||||||
"+",
|
|
||||||
"-",
|
|
||||||
"(",
|
|
||||||
")",
|
|
||||||
"~",
|
|
||||||
"@",
|
|
||||||
":",
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNthRecentPostTime returns the CreateAt time of the nth most recent post.
|
// GetNthRecentPostTime returns the CreateAt time of the nth most recent post.
|
||||||
func (s *SqlPostStore) GetNthRecentPostTime(n int64) (int64, error) {
|
func (s *SqlPostStore) GetNthRecentPostTime(n int64) (int64, error) {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
@@ -1989,8 +1977,7 @@ func (s *SqlPostStore) search(teamId string, userId string, params *model.Search
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// these chars have special meaning and can be treated as spaces
|
for _, c := range s.specialSearchChars() {
|
||||||
for _, c := range specialSearchChar {
|
|
||||||
terms = strings.Replace(terms, c, " ", -1)
|
terms = strings.Replace(terms, c, " ", -1)
|
||||||
excludedTerms = strings.Replace(excludedTerms, c, " ", -1)
|
excludedTerms = strings.Replace(excludedTerms, c, " ", -1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,6 +335,28 @@ func (ss *SqlStore) DriverName() string {
|
|||||||
return *ss.settings.DriverName
|
return *ss.settings.DriverName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// specialSearchChars have special meaning and can be treated as spaces
|
||||||
|
func (ss *SqlStore) specialSearchChars() []string {
|
||||||
|
chars := []string{
|
||||||
|
"<",
|
||||||
|
">",
|
||||||
|
"+",
|
||||||
|
"-",
|
||||||
|
"(",
|
||||||
|
")",
|
||||||
|
"~",
|
||||||
|
":",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Postgres can handle "@" without any errors
|
||||||
|
// Also helps postgres in enabling search for EmailAddresses
|
||||||
|
if ss.DriverName() != model.DatabaseDriverPostgres {
|
||||||
|
chars = append(chars, "@")
|
||||||
|
}
|
||||||
|
|
||||||
|
return chars
|
||||||
|
}
|
||||||
|
|
||||||
// computeBinaryParam returns whether the data source uses binary_parameters
|
// computeBinaryParam returns whether the data source uses binary_parameters
|
||||||
// when using Postgres
|
// when using Postgres
|
||||||
func (ss *SqlStore) computeBinaryParam() (bool, error) {
|
func (ss *SqlStore) computeBinaryParam() (bool, error) {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user