diff --git a/Frameworks/Database/ArticlesTable.swift b/Frameworks/Database/ArticlesTable.swift index 2130b9bea..d68482723 100644 --- a/Frameworks/Database/ArticlesTable.swift +++ b/Frameworks/Database/ArticlesTable.swift @@ -166,26 +166,15 @@ private extension ArticlesTable { // MARK: Fetching - func articleWithRow(_ row: FMResultSet) -> Article? { - - guard let article = Article(row: row, accountID: accountID) else { - return nil - } - - // Note: the row is a result of a JOIN query with the statuses table, - // so we can get the status at the same time and avoid additional database lookups. - -// article.status = statusesTable.statusWithRow(row) - return article - } - func articlesWithResultSet(_ resultSet: FMResultSet, _ database: FMDatabase) -> Set
{ // Create set of stub Articles without related objects. // Then fetch the related objects, given the set of articleIDs. // Then create set of Articles *with* related objects and return it. + + let (stubArticles, statuses) = stubArticlesAndStatuses(with: resultSet) - let stubArticles = resultSet.mapToSet(articleWithRow) + statusesTable.addIfNotCached(statuses) if stubArticles.isEmpty { return stubArticles } @@ -202,23 +191,44 @@ private extension ArticlesTable { } // Create articles with related objects. - - var articles = Set
() - for stubArticle in articles { - - let articleID = stubArticle.articleID - - let authors = authorsMap?.authors(for: articleID) - let attachments = attachmentsMap?.attachments(for: articleID) - let tags = tagsMap?.tags(for: articleID) - - let realArticle = stubArticle.articleByAttaching(authors, attachments, tags) - articles.insert(realArticle) - } - + + let articles = Set(stubArticles.map { articleWithAttachedRelatedObjects($0, authorsMap, attachmentsMap, tagsMap) }) return articles } + func stubArticlesAndStatuses(with resultSet: FMResultSet) -> (Set
, Set) { + + var stubArticles = Set
() + var statuses = Set() + + // Note: the resultSet is a result of a JOIN query with the statuses table, + // so we can get the statuses at the same time and avoid additional database lookups. + + while resultSet.next() { + if let stubArticle = Article(row: resultSet, accountID: accountID) { + stubArticles.insert(stubArticle) + } + if let status = statusesTable.statusWithRow(resultSet) { + statuses.insert(status) + } + } + resultSet.close() + + return (stubArticles, statuses) + } + + func articleWithAttachedRelatedObjects(_ stubArticle: Article, _ authorsMap: RelatedObjectsMap?, _ attachmentsMap: RelatedObjectsMap?, _ tagsMap: RelatedObjectsMap?) -> Article { + + let articleID = stubArticle.articleID + + let authors = authorsMap?.authors(for: articleID) + let attachments = attachmentsMap?.attachments(for: articleID) + let tags = tagsMap?.tags(for: articleID) + + let realArticle = stubArticle.articleByAttaching(authors, attachments, tags) + return realArticle + } + func fetchArticlesWithWhereClause(_ database: FMDatabase, whereClause: String, parameters: [AnyObject], withLimits: Bool) -> Set
{ // Don’t fetch articles that shouldn’t appear in the UI. The rules: diff --git a/Frameworks/Database/StatusesTable.swift b/Frameworks/Database/StatusesTable.swift index 9f14fd8a1..b90edac3b 100644 --- a/Frameworks/Database/StatusesTable.swift +++ b/Frameworks/Database/StatusesTable.swift @@ -27,7 +27,9 @@ final class StatusesTable: DatabaseTable { self.queue = queue } - + + // MARK: Cache + func cachedStatus(for articleID: String) -> ArticleStatus? { assert(Thread.isMainThread) @@ -35,6 +37,22 @@ final class StatusesTable: DatabaseTable { return cache[articleID] } + func addIfNotCached(_ statuses: Set) { + + if statuses.isEmpty { + return + } + + if Thread.isMainThread { + self.cache.addIfNotCached(statuses) + } + else { + DispatchQueue.main.async { + self.cache.addIfNotCached(statuses) + } + } + } + // MARK: Creating/Updating func ensureStatusesForArticleIDs(_ articleIDs: Set, _ completion: @escaping StatusesCompletionBlock) { @@ -71,11 +89,6 @@ final class StatusesTable: DatabaseTable { updateRowsWithValue(NSNumber(value: flag), valueKey: statusKey, whereKey: DatabaseKey.articleID, matches: Array(articleIDs), database: database) } -} - -// MARK: - Private - -private extension StatusesTable { // MARK: Fetching @@ -91,6 +104,11 @@ private extension StatusesTable { let articleStatus = ArticleStatus(articleID: articleID, dateArrived: dateArrived, row: row) return articleStatus } +} + +// MARK: - Private + +private extension StatusesTable { // MARK: Cache diff --git a/ToDo.opml b/ToDo.opml index f2d6ad87b..3bbebcd20 100644 --- a/ToDo.opml +++ b/ToDo.opml @@ -6,12 +6,12 @@ --> ToDo Tue, 12 Sep 2017 20:15:17 GMT - 11,16,17,20,24,29,31,34,37,39,40,44,49,52,54,56,58,67,72,78,83 - 59 - 248 - 30 - 762 - 1007 + 11,16,17,20,24,29,31,34,37,39,40,44,48,51,53,55,57,66,71,77,82 + 0 + 523 + 40 + 772 + 1282 @@ -72,7 +72,6 @@ -