Merge pull request #789 from mpretty-cyro/fix/broken-group-mentions

Fixed an issue where mentions weren't working in groups
pull/793/head
Morgan Pretty 2 years ago committed by GitHub
commit e40f99458a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -29,75 +29,98 @@ public extension MentionInfo {
let profile: TypedTableAlias<Profile> = TypedTableAlias() let profile: TypedTableAlias<Profile> = TypedTableAlias()
let interaction: TypedTableAlias<Interaction> = TypedTableAlias() let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
let openGroup: TypedTableAlias<OpenGroup> = TypedTableAlias() let openGroup: TypedTableAlias<OpenGroup> = TypedTableAlias()
let groupMember: TypedTableAlias<GroupMember> = TypedTableAlias()
let prefixLiteral: SQL = SQL(stringLiteral: "\(targetPrefix.rawValue)%") let prefixLiteral: SQL = SQL(stringLiteral: "\(targetPrefix.rawValue)%")
let profileFullTextSearch: SQL = SQL(stringLiteral: Profile.fullTextSearchTableName) let profileFullTextSearch: SQL = SQL(stringLiteral: Profile.fullTextSearchTableName)
/// **Note:** The `\(MentionInfo.profileKey).*` value **MUST** be first /// The query needs to differ depending on the thread variant because the behaviour should be different:
let limitSQL: SQL? = (threadVariant == .openGroup ? SQL("LIMIT 20") : nil) ///
/// **Contact:** We should show the profile directly (filtered out if the pattern doesn't match)
/// **Closed Group:** We should show all profiles within the group, filtered by the pattern
/// **Open Group:** We should show only the 20 most recent profiles which match the pattern
let request: SQLRequest<MentionInfo> = { let request: SQLRequest<MentionInfo> = {
guard let pattern: FTS5Pattern = pattern else { let hasValidPattern: Bool = (pattern != nil && pattern?.rawPattern != "\"\"*")
let finalLimitSQL: SQL = (limitSQL ?? "") let targetJoin: SQL = {
guard hasValidPattern else { return "FROM \(Profile.self)" }
return """ return """
SELECT FROM \(profileFullTextSearch)
\(Profile.self).*, JOIN \(Profile.self) ON (
MAX(\(interaction[.timestampMs])), -- Want the newest interaction (for sorting) \(Profile.self).rowid = \(profileFullTextSearch).rowid AND
\(SQL("\(threadVariant) AS \(MentionInfo.threadVariantKey)")),
\(openGroup[.server]) AS \(MentionInfo.openGroupServerKey),
\(openGroup[.roomToken]) AS \(MentionInfo.openGroupRoomTokenKey)
FROM \(Profile.self)
JOIN \(Interaction.self) ON (
\(SQL("\(interaction[.threadId]) = \(threadId)")) AND
\(interaction[.authorId]) = \(profile[.id])
)
LEFT JOIN \(OpenGroup.self) ON \(SQL("\(openGroup[.threadId]) = \(threadId)"))
WHERE (
\(SQL("\(profile[.id]) != \(userPublicKey)")) AND ( \(SQL("\(profile[.id]) != \(userPublicKey)")) AND (
\(SQL("\(threadVariant) != \(SessionThread.Variant.openGroup)")) OR \(SQL("\(threadVariant) != \(SessionThread.Variant.openGroup)")) OR
\(SQL("\(profile[.id]) LIKE '\(prefixLiteral)'")) \(SQL("\(profile[.id]) LIKE '\(prefixLiteral)'"))
) )
) )
GROUP BY \(profile[.id])
ORDER BY \(interaction[.timestampMs].desc)
\(finalLimitSQL)
""" """
} }()
let targetWhere: SQL = {
// If we do have a search patern then use FTS guard let pattern: FTS5Pattern = pattern, pattern.rawPattern != "\"\"*" else {
let matchLiteral: SQL = SQL(stringLiteral: "\(Profile.Columns.nickname.name):\(pattern.rawPattern) OR \(Profile.Columns.name.name):\(pattern.rawPattern)") return """
let finalLimitSQL: SQL = (limitSQL ?? "") WHERE (
\(SQL("\(profile[.id]) != \(userPublicKey)")) AND (
return """ \(SQL("\(threadVariant) != \(SessionThread.Variant.openGroup)")) OR
SELECT \(SQL("\(profile[.id]) LIKE '\(prefixLiteral)'"))
\(Profile.self).*, )
MAX(\(interaction[.timestampMs])), -- Want the newest interaction (for sorting) )
\(SQL("\(threadVariant) AS \(MentionInfo.threadVariantKey)")), """
\(openGroup[.server]) AS \(MentionInfo.openGroupServerKey), }
\(openGroup[.roomToken]) AS \(MentionInfo.openGroupRoomTokenKey)
FROM \(profileFullTextSearch) let matchLiteral: SQL = SQL(stringLiteral: "\(Profile.Columns.nickname.name):\(pattern.rawPattern) OR \(Profile.Columns.name.name):\(pattern.rawPattern)")
JOIN \(Profile.self) ON (
\(Profile.self).rowid = \(profileFullTextSearch).rowid AND return "WHERE \(profileFullTextSearch) MATCH '\(matchLiteral)'"
\(SQL("\(profile[.id]) != \(userPublicKey)")) AND ( }()
\(SQL("\(threadVariant) != \(SessionThread.Variant.openGroup)")) OR
\(SQL("\(profile[.id]) LIKE '\(prefixLiteral)'"))
)
)
JOIN \(Interaction.self) ON (
\(SQL("\(interaction[.threadId]) = \(threadId)")) AND
\(interaction[.authorId]) = \(profile[.id])
)
LEFT JOIN \(OpenGroup.self) ON \(SQL("\(openGroup[.threadId]) = \(threadId)"))
WHERE \(profileFullTextSearch) MATCH '\(matchLiteral)' switch threadVariant {
GROUP BY \(profile[.id]) case .contact:
ORDER BY \(interaction[.timestampMs].desc) return SQLRequest("""
\(finalLimitSQL) SELECT
""" \(Profile.self).*,
\(SQL("\(threadVariant) AS \(MentionInfo.threadVariantKey)"))
\(targetJoin)
\(targetWhere) AND \(SQL("\(profile[.id]) = \(threadId)"))
""")
case .closedGroup:
return SQLRequest("""
SELECT
\(Profile.self).*,
\(SQL("\(threadVariant) AS \(MentionInfo.threadVariantKey)"))
\(targetJoin)
JOIN \(GroupMember.self) ON (
\(SQL("\(groupMember[.groupId]) = \(threadId)")) AND
\(groupMember[.profileId]) = \(profile[.id]) AND
\(SQL("\(groupMember[.role]) = \(GroupMember.Role.standard)"))
)
\(targetWhere)
GROUP BY \(profile[.id])
ORDER BY IFNULL(\(profile[.nickname]), \(profile[.name])) ASC
""")
case .openGroup:
return SQLRequest("""
SELECT
\(Profile.self).*,
MAX(\(interaction[.timestampMs])), -- Want the newest interaction (for sorting)
\(SQL("\(threadVariant) AS \(MentionInfo.threadVariantKey)")),
\(openGroup[.server]) AS \(MentionInfo.openGroupServerKey),
\(openGroup[.roomToken]) AS \(MentionInfo.openGroupRoomTokenKey)
\(targetJoin)
JOIN \(Interaction.self) ON (
\(SQL("\(interaction[.threadId]) = \(threadId)")) AND
\(interaction[.authorId]) = \(profile[.id])
)
JOIN \(OpenGroup.self) ON \(SQL("\(openGroup[.threadId]) = \(threadId)"))
\(targetWhere)
GROUP BY \(profile[.id])
ORDER BY \(interaction[.timestampMs].desc)
LIMIT 20
""")
}
}() }()
return request.adapted { db in return request.adapted { db in

Loading…
Cancel
Save