This commit is contained in:
Justin Mazzocchi 2020-09-28 23:06:25 -07:00
parent 7335615b64
commit f5dcb762d1
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
14 changed files with 195 additions and 71 deletions

View file

@ -14,8 +14,8 @@ public struct AccountList: Codable, FetchableRecord, PersistableRecord {
extension AccountList { extension AccountList {
static let joins = hasMany( static let joins = hasMany(
AccountListJoin.self, AccountListJoin.self,
using: ForeignKey([Column("listId")])) using: ForeignKey([AccountListJoin.Columns.listId]))
.order(Column("index")) .order(AccountListJoin.Columns.index)
static let accounts = hasMany( static let accounts = hasMany(
AccountRecord.self, AccountRecord.self,
through: joins, through: joins,

View file

@ -8,5 +8,13 @@ struct AccountListJoin: Codable, FetchableRecord, PersistableRecord {
let listId: UUID let listId: UUID
let index: Int let index: Int
static let account = belongsTo(AccountRecord.self, using: ForeignKey([Column("accountId")])) static let account = belongsTo(AccountRecord.self, using: ForeignKey([Columns.accountId]))
}
extension AccountListJoin {
enum Columns {
static let accountId = Column(AccountListJoin.CodingKeys.accountId)
static let listId = Column(AccountListJoin.CodingKeys.listId)
static let index = Column(AccountListJoin.CodingKeys.index)
}
} }

View file

@ -8,5 +8,13 @@ struct AccountPinnedStatusJoin: Codable, FetchableRecord, PersistableRecord {
let statusId: String let statusId: String
let index: Int let index: Int
static let status = belongsTo(StatusRecord.self, using: ForeignKey([Column("statusId")])) static let status = belongsTo(StatusRecord.self, using: ForeignKey([Columns.statusId]))
}
extension AccountPinnedStatusJoin {
enum Columns {
static let accountId = Column(AccountPinnedStatusJoin.CodingKeys.accountId)
static let statusId = Column(AccountPinnedStatusJoin.CodingKeys.statusId)
static let index = Column(AccountPinnedStatusJoin.CodingKeys.index)
}
} }

View file

@ -27,6 +27,31 @@ struct AccountRecord: Codable, Hashable {
let movedId: String? let movedId: String?
} }
extension AccountRecord {
enum Columns {
static let id = Column(AccountRecord.CodingKeys.id)
static let username = Column(AccountRecord.CodingKeys.username)
static let acct = Column(AccountRecord.CodingKeys.acct)
static let displayName = Column(AccountRecord.CodingKeys.displayName)
static let locked = Column(AccountRecord.CodingKeys.locked)
static let createdAt = Column(AccountRecord.CodingKeys.createdAt)
static let followersCount = Column(AccountRecord.CodingKeys.followersCount)
static let followingCount = Column(AccountRecord.CodingKeys.followingCount)
static let statusesCount = Column(AccountRecord.CodingKeys.statusesCount)
static let note = Column(AccountRecord.CodingKeys.note)
static let url = Column(AccountRecord.CodingKeys.url)
static let avatar = Column(AccountRecord.CodingKeys.avatar)
static let avatarStatic = Column(AccountRecord.CodingKeys.avatarStatic)
static let header = Column(AccountRecord.CodingKeys.header)
static let headerStatic = Column(AccountRecord.CodingKeys.headerStatic)
static let fields = Column(AccountRecord.CodingKeys.fields)
static let emojis = Column(AccountRecord.CodingKeys.emojis)
static let bot = Column(AccountRecord.CodingKeys.bot)
static let discoverable = Column(AccountRecord.CodingKeys.discoverable)
static let movedId = Column(AccountRecord.CodingKeys.movedId)
}
}
extension AccountRecord: FetchableRecord, PersistableRecord { extension AccountRecord: FetchableRecord, PersistableRecord {
static func databaseJSONDecoder(for column: String) -> JSONDecoder { static func databaseJSONDecoder(for column: String) -> JSONDecoder {
MastodonDecoder() MastodonDecoder()
@ -41,8 +66,8 @@ extension AccountRecord {
static let moved = belongsTo(AccountRecord.self, key: "moved") static let moved = belongsTo(AccountRecord.self, key: "moved")
static let pinnedStatusJoins = hasMany( static let pinnedStatusJoins = hasMany(
AccountPinnedStatusJoin.self, AccountPinnedStatusJoin.self,
using: ForeignKey([Column("accountId")])) using: ForeignKey([AccountPinnedStatusJoin.Columns.accountId]))
.order(Column("index")) .order(AccountPinnedStatusJoin.Columns.index)
static let pinnedStatuses = hasMany( static let pinnedStatuses = hasMany(
StatusRecord.self, StatusRecord.self,
through: pinnedStatusJoins, through: pinnedStatusJoins,

View file

@ -8,5 +8,13 @@ struct AccountStatusJoin: Codable, FetchableRecord, PersistableRecord {
let statusId: String let statusId: String
let collection: ProfileCollection let collection: ProfileCollection
static let status = belongsTo(StatusRecord.self, using: ForeignKey([Column("statusId")])) static let status = belongsTo(StatusRecord.self, using: ForeignKey([Columns.statusId]))
}
extension AccountStatusJoin {
enum Columns {
static let accountId = Column(AccountStatusJoin.CodingKeys.accountId)
static let statusId = Column(AccountStatusJoin.CodingKeys.statusId)
static let collection = Column(AccountStatusJoin.CodingKeys.collection)
}
} }

View file

@ -73,9 +73,9 @@ public extension ContentDatabase {
} }
try StatusContextJoin.filter( try StatusContextJoin.filter(
Column("parentId") == parentID StatusContextJoin.Columns.parentId == parentID
&& Column("section") == section.rawValue && StatusContextJoin.Columns.section == section.rawValue
&& !statuses.map(\.id).contains(Column("statusId"))) && !statuses.map(\.id).contains(StatusContextJoin.Columns.statusId))
.deleteAll($0) .deleteAll($0)
} }
} }
@ -92,8 +92,8 @@ public extension ContentDatabase {
} }
try AccountPinnedStatusJoin.filter( try AccountPinnedStatusJoin.filter(
Column("accountId") == accountID AccountPinnedStatusJoin.Columns.accountId == accountID
&& !pinnedStatuses.map(\.id).contains(Column("statusId"))) && !pinnedStatuses.map(\.id).contains(AccountPinnedStatusJoin.Columns.statusId))
.deleteAll($0) .deleteAll($0)
} }
.ignoreOutput() .ignoreOutput()
@ -137,8 +137,8 @@ public extension ContentDatabase {
} }
try Timeline try Timeline
.filter(!(Timeline.authenticatedDefaults.map(\.id) + lists.map(\.id)).contains(Column("id")) .filter(!(Timeline.authenticatedDefaults.map(\.id) + lists.map(\.id)).contains(Timeline.Columns.id)
&& Column("listTitle") != nil) && Timeline.Columns.listTitle != nil)
.deleteAll($0) .deleteAll($0)
} }
.ignoreOutput() .ignoreOutput()
@ -152,7 +152,7 @@ public extension ContentDatabase {
} }
func deleteList(id: String) -> AnyPublisher<Never, Error> { func deleteList(id: String) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher(updates: Timeline.filter(Column("id") == id).deleteAll) databaseWriter.writePublisher(updates: Timeline.filter(Timeline.Columns.id == id).deleteAll)
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
@ -163,7 +163,7 @@ public extension ContentDatabase {
try filter.save($0) try filter.save($0)
} }
try Filter.filter(!filters.map(\.id).contains(Column("id"))).deleteAll($0) try Filter.filter(!filters.map(\.id).contains(Filter.Columns.id)).deleteAll($0)
} }
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -176,7 +176,7 @@ public extension ContentDatabase {
} }
func deleteFilter(id: String) -> AnyPublisher<Never, Error> { func deleteFilter(id: String) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher(updates: Filter.filter(Column("id") == id).deleteAll) databaseWriter.writePublisher(updates: Filter.filter(Filter.Columns.id == id).deleteAll)
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
@ -191,7 +191,9 @@ public extension ContentDatabase {
func contextObservation(parentID: String) -> AnyPublisher<[[Status]], Error> { func contextObservation(parentID: String) -> AnyPublisher<[[Status]], Error> {
ValueObservation.tracking { db -> [[StatusResult]] in ValueObservation.tracking { db -> [[StatusResult]] in
guard let parent = try StatusRecord.filter(Column("id") == parentID).statusResultRequest.fetchOne(db) else { guard let parent = try StatusRecord.filter(StatusRecord.Columns.id == parentID)
.statusResultRequest
.fetchOne(db) else {
return [[]] return [[]]
} }
@ -212,16 +214,16 @@ public extension ContentDatabase {
ValueObservation.tracking { db -> [[StatusResult]] in ValueObservation.tracking { db -> [[StatusResult]] in
let statuses = try StatusRecord.filter( let statuses = try StatusRecord.filter(
AccountStatusJoin AccountStatusJoin
.select(Column("statusId"), as: String.self) .select(AccountStatusJoin.Columns.statusId, as: String.self)
.filter(sql: "accountId = ? AND collection = ?", arguments: [accountID, collection.rawValue]) .filter(sql: "accountId = ? AND collection = ?", arguments: [accountID, collection.rawValue])
.contains(Column("id"))) .contains(StatusRecord.Columns.id))
.order(Column("createdAt").desc) .order(StatusRecord.Columns.createdAt.desc)
.statusResultRequest .statusResultRequest
.fetchAll(db) .fetchAll(db)
if if
case .statuses = collection, case .statuses = collection,
let accountRecord = try AccountRecord.filter(Column("id") == accountID).fetchOne(db) { let accountRecord = try AccountRecord.filter(AccountRecord.Columns.id == accountID).fetchOne(db) {
let pinnedStatuses = try accountRecord.pinnedStatuses.fetchAll(db) let pinnedStatuses = try accountRecord.pinnedStatuses.fetchAll(db)
return [pinnedStatuses, statuses] return [pinnedStatuses, statuses]
@ -236,8 +238,8 @@ public extension ContentDatabase {
} }
func listsObservation() -> AnyPublisher<[Timeline], Error> { func listsObservation() -> AnyPublisher<[Timeline], Error> {
ValueObservation.tracking(Timeline.filter(Column("listTitle") != nil) ValueObservation.tracking(Timeline.filter(Timeline.Columns.listTitle != nil)
.order(Column("listTitle").asc) .order(Timeline.Columns.listTitle.asc)
.fetchAll) .fetchAll)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter) .publisher(in: databaseWriter)
@ -245,7 +247,8 @@ public extension ContentDatabase {
} }
func activeFiltersObservation(date: Date, context: Filter.Context? = nil) -> AnyPublisher<[Filter], Error> { func activeFiltersObservation(date: Date, context: Filter.Context? = nil) -> AnyPublisher<[Filter], Error> {
ValueObservation.tracking(Filter.filter(Column("expiresAt") == nil || Column("expiresAt") > date).fetchAll) ValueObservation.tracking(
Filter.filter(Filter.Columns.expiresAt == nil || Filter.Columns.expiresAt > date).fetchAll)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter) .publisher(in: databaseWriter)
.map { .map {
@ -257,14 +260,14 @@ public extension ContentDatabase {
} }
func expiredFiltersObservation(date: Date) -> AnyPublisher<[Filter], Error> { func expiredFiltersObservation(date: Date) -> AnyPublisher<[Filter], Error> {
ValueObservation.tracking(Filter.filter(Column("expiresAt") < date).fetchAll) ValueObservation.tracking(Filter.filter(Filter.Columns.expiresAt < date).fetchAll)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter) .publisher(in: databaseWriter)
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func accountObservation(id: String) -> AnyPublisher<Account?, Error> { func accountObservation(id: String) -> AnyPublisher<Account?, Error> {
ValueObservation.tracking(AccountRecord.filter(Column("id") == id).accountResultRequest.fetchOne) ValueObservation.tracking(AccountRecord.filter(AccountRecord.Columns.id == id).accountResultRequest.fetchOne)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter) .publisher(in: databaseWriter)
.map { .map {
@ -424,7 +427,7 @@ private extension ContentDatabase {
func clean() { func clean() {
databaseWriter.asyncWrite { databaseWriter.asyncWrite {
try TimelineStatusJoin.filter(Column("timelineId") != Timeline.home.id).deleteAll($0) try TimelineStatusJoin.filter(TimelineStatusJoin.Columns.timelineId != Timeline.home.id).deleteAll($0)
try StatusContextJoin.deleteAll($0) try StatusContextJoin.deleteAll($0)
try AccountPinnedStatusJoin.deleteAll($0) try AccountPinnedStatusJoin.deleteAll($0)
try AccountStatusJoin.deleteAll($0) try AccountStatusJoin.deleteAll($0)

View file

@ -14,5 +14,14 @@ struct StatusContextJoin: Codable, FetchableRecord, PersistableRecord {
let section: Section let section: Section
let index: Int let index: Int
static let status = belongsTo(StatusRecord.self, using: ForeignKey([Column("statusId")])) static let status = belongsTo(StatusRecord.self, using: ForeignKey([Columns.statusId]))
}
extension StatusContextJoin {
enum Columns {
static let parentId = Column(StatusContextJoin.CodingKeys.parentId)
static let statusId = Column(StatusContextJoin.CodingKeys.statusId)
static let section = Column(StatusContextJoin.CodingKeys.section)
static let index = Column(StatusContextJoin.CodingKeys.index)
}
} }

View file

@ -36,6 +36,40 @@ struct StatusRecord: Codable, Hashable {
let pinned: Bool? let pinned: Bool?
} }
extension StatusRecord {
enum Columns {
static let id = Column(StatusRecord.CodingKeys.id)
static let uri = Column(StatusRecord.CodingKeys.uri)
static let createdAt = Column(StatusRecord.CodingKeys.createdAt)
static let accountId = Column(StatusRecord.CodingKeys.accountId)
static let content = Column(StatusRecord.CodingKeys.content)
static let visibility = Column(StatusRecord.CodingKeys.visibility)
static let sensitive = Column(StatusRecord.CodingKeys.sensitive)
static let spoilerText = Column(StatusRecord.CodingKeys.spoilerText)
static let mediaAttachments = Column(StatusRecord.CodingKeys.mediaAttachments)
static let mentions = Column(StatusRecord.CodingKeys.mentions)
static let tags = Column(StatusRecord.CodingKeys.tags)
static let emojis = Column(StatusRecord.CodingKeys.emojis)
static let reblogsCount = Column(StatusRecord.CodingKeys.reblogsCount)
static let favouritesCount = Column(StatusRecord.CodingKeys.favouritesCount)
static let repliesCount = Column(StatusRecord.CodingKeys.repliesCount)
static let application = Column(StatusRecord.CodingKeys.application)
static let url = Column(StatusRecord.CodingKeys.url)
static let inReplyToId = Column(StatusRecord.CodingKeys.inReplyToId)
static let inReplyToAccountId = Column(StatusRecord.CodingKeys.inReplyToAccountId)
static let reblogId = Column(StatusRecord.CodingKeys.reblogId)
static let poll = Column(StatusRecord.CodingKeys.poll)
static let card = Column(StatusRecord.CodingKeys.card)
static let language = Column(StatusRecord.CodingKeys.language)
static let text = Column(StatusRecord.CodingKeys.text)
static let favourited = Column(StatusRecord.CodingKeys.favourited)
static let reblogged = Column(StatusRecord.CodingKeys.reblogged)
static let muted = Column(StatusRecord.CodingKeys.muted)
static let bookmarked = Column(StatusRecord.CodingKeys.bookmarked)
static let pinned = Column(StatusRecord.CodingKeys.pinned)
}
}
extension StatusRecord: FetchableRecord, PersistableRecord { extension StatusRecord: FetchableRecord, PersistableRecord {
static func databaseJSONDecoder(for column: String) -> JSONDecoder { static func databaseJSONDecoder(for column: String) -> JSONDecoder {
MastodonDecoder() MastodonDecoder()
@ -47,7 +81,8 @@ extension StatusRecord: FetchableRecord, PersistableRecord {
} }
extension StatusRecord { extension StatusRecord {
static let account = belongsTo(AccountRecord.self, key: "account", using: ForeignKey([Column("accountId")])) static let account = belongsTo(AccountRecord.self, key: "account",
using: ForeignKey([StatusRecord.Columns.accountId]))
static let accountMoved = hasOne(AccountRecord.self, static let accountMoved = hasOne(AccountRecord.self,
through: Self.account, through: Self.account,
using: AccountRecord.moved, using: AccountRecord.moved,
@ -61,12 +96,16 @@ extension StatusRecord {
using: AccountRecord.moved, using: AccountRecord.moved,
key: "reblogAccountMoved") key: "reblogAccountMoved")
static let reblog = belongsTo(StatusRecord.self, key: "reblog") static let reblog = belongsTo(StatusRecord.self, key: "reblog")
static let ancestorJoins = hasMany(StatusContextJoin.self, using: ForeignKey([Column("parentID")])) static let ancestorJoins = hasMany(
.filter(Column("section") == StatusContextJoin.Section.ancestors.rawValue) StatusContextJoin.self,
.order(Column("index")) using: ForeignKey([StatusContextJoin.Columns.parentId]))
static let descendantJoins = hasMany(StatusContextJoin.self, using: ForeignKey([Column("parentID")])) .filter(StatusContextJoin.Columns.section == StatusContextJoin.Section.ancestors.rawValue)
.filter(Column("section") == StatusContextJoin.Section.descendants.rawValue) .order(StatusContextJoin.Columns.index)
.order(Column("index")) static let descendantJoins = hasMany(
StatusContextJoin.self,
using: ForeignKey([StatusContextJoin.Columns.parentId]))
.filter(StatusContextJoin.Columns.section == StatusContextJoin.Section.descendants.rawValue)
.order(StatusContextJoin.Columns.index)
static let ancestors = hasMany(StatusRecord.self, static let ancestors = hasMany(StatusRecord.self,
through: ancestorJoins, through: ancestorJoins,
using: StatusContextJoin.status) using: StatusContextJoin.status)

View file

@ -9,3 +9,10 @@ struct TimelineStatusJoin: Codable, FetchableRecord, PersistableRecord {
static let status = belongsTo(StatusRecord.self) static let status = belongsTo(StatusRecord.self)
} }
extension TimelineStatusJoin {
enum Columns {
static let timelineId = Column(TimelineStatusJoin.CodingKeys.timelineId)
static let statusId = Column(TimelineStatusJoin.CodingKeys.statusId)
}
}

View file

@ -5,6 +5,15 @@ import GRDB
import Mastodon import Mastodon
extension Filter: FetchableRecord, PersistableRecord { extension Filter: FetchableRecord, PersistableRecord {
enum Columns: String, ColumnExpression {
case id
case phrase
case context
case expiresAt
case irreversible
case wholeWord
}
public static func databaseJSONDecoder(for column: String) -> JSONDecoder { public static func databaseJSONDecoder(for column: String) -> JSONDecoder {
MastodonDecoder() MastodonDecoder()
} }

View file

@ -1,10 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import GRDB
extension OrderedRequest {
func orderedByIDSequence(_ ids: [String]) -> Self {
fatalError()
}
}

View file

@ -6,7 +6,8 @@ import Mastodon
extension Timeline: FetchableRecord, PersistableRecord { extension Timeline: FetchableRecord, PersistableRecord {
enum Columns: String, ColumnExpression { enum Columns: String, ColumnExpression {
case id, listTitle case id
case listTitle
} }
public init(row: Row) { public init(row: Row) {
@ -42,7 +43,7 @@ extension Timeline {
StatusRecord.self, StatusRecord.self,
through: statusJoins, through: statusJoins,
using: TimelineStatusJoin.status) using: TimelineStatusJoin.status)
.order(Column("createdAt").desc) .order(StatusRecord.Columns.createdAt.desc)
var statuses: QueryInterfaceRequest<StatusResult> { var statuses: QueryInterfaceRequest<StatusResult> {
request(for: Self.statuses).statusResultRequest request(for: Self.statuses).statusResultRequest

View file

@ -51,7 +51,7 @@ public extension IdentityDatabase {
} }
func deleteIdentity(id: UUID) -> AnyPublisher<Never, Error> { func deleteIdentity(id: UUID) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher(updates: IdentityRecord.filter(Column("id") == id).deleteAll) databaseWriter.writePublisher(updates: IdentityRecord.filter(IdentityRecord.Columns.id == id).deleteAll)
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
@ -59,8 +59,8 @@ public extension IdentityDatabase {
func updateLastUsedAt(identityID: UUID) -> AnyPublisher<Never, Error> { func updateLastUsedAt(identityID: UUID) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher { databaseWriter.writePublisher {
try IdentityRecord try IdentityRecord
.filter(Column("id") == identityID) .filter(IdentityRecord.Columns.id == identityID)
.updateAll($0, Column("lastUsedAt").set(to: Date())) .updateAll($0, IdentityRecord.Columns.lastUsedAt.set(to: Date()))
} }
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -75,8 +75,8 @@ public extension IdentityDatabase {
thumbnail: instance.thumbnail) thumbnail: instance.thumbnail)
.save($0) .save($0)
try IdentityRecord try IdentityRecord
.filter(Column("id") == identityID) .filter(IdentityRecord.Columns.id == identityID)
.updateAll($0, Column("instanceURI").set(to: instance.uri)) .updateAll($0, IdentityRecord.Columns.instanceURI.set(to: instance.uri))
} }
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -103,8 +103,8 @@ public extension IdentityDatabase {
func confirmIdentity(id: UUID) -> AnyPublisher<Never, Error> { func confirmIdentity(id: UUID) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher { databaseWriter.writePublisher {
try IdentityRecord try IdentityRecord
.filter(Column("id") == id) .filter(IdentityRecord.Columns.id == id)
.updateAll($0, Column("pending").set(to: false)) .updateAll($0, IdentityRecord.Columns.pending.set(to: false))
} }
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -113,7 +113,7 @@ public extension IdentityDatabase {
func updatePreferences(_ preferences: Mastodon.Preferences, func updatePreferences(_ preferences: Mastodon.Preferences,
forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> { forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher { databaseWriter.writePublisher {
guard let storedPreferences = try IdentityRecord.filter(Column("id") == identityID) guard let storedPreferences = try IdentityRecord.filter(IdentityRecord.Columns.id == identityID)
.fetchOne($0)? .fetchOne($0)?
.preferences else { .preferences else {
throw IdentityDatabaseError.identityNotFound throw IdentityDatabaseError.identityNotFound
@ -136,16 +136,18 @@ public extension IdentityDatabase {
deviceToken: Data? = nil, deviceToken: Data? = nil,
forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> { forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher { databaseWriter.writePublisher {
let data = try IdentityRecord.databaseJSONEncoder(for: "pushSubscriptionAlerts").encode(alerts) let data = try IdentityRecord.databaseJSONEncoder(
for: IdentityRecord.Columns.pushSubscriptionAlerts.name)
.encode(alerts)
try IdentityRecord try IdentityRecord
.filter(Column("id") == identityID) .filter(IdentityRecord.Columns.id == identityID)
.updateAll($0, Column("pushSubscriptionAlerts").set(to: data)) .updateAll($0, IdentityRecord.Columns.pushSubscriptionAlerts.set(to: data))
if let deviceToken = deviceToken { if let deviceToken = deviceToken {
try IdentityRecord try IdentityRecord
.filter(Column("id") == identityID) .filter(IdentityRecord.Columns.id == identityID)
.updateAll($0, Column("lastRegisteredDeviceToken").set(to: deviceToken)) .updateAll($0, IdentityRecord.Columns.lastRegisteredDeviceToken.set(to: deviceToken))
} }
} }
.ignoreOutput() .ignoreOutput()
@ -155,7 +157,7 @@ public extension IdentityDatabase {
func identityObservation(id: UUID, immediate: Bool) -> AnyPublisher<Identity, Error> { func identityObservation(id: UUID, immediate: Bool) -> AnyPublisher<Identity, Error> {
ValueObservation.tracking( ValueObservation.tracking(
IdentityRecord IdentityRecord
.filter(Column("id") == id) .filter(IdentityRecord.Columns.id == id)
.identityResultRequest .identityResultRequest
.fetchOne) .fetchOne)
.removeDuplicates() .removeDuplicates()
@ -171,7 +173,7 @@ public extension IdentityDatabase {
func identitiesObservation() -> AnyPublisher<[Identity], Error> { func identitiesObservation() -> AnyPublisher<[Identity], Error> {
ValueObservation.tracking( ValueObservation.tracking(
IdentityRecord IdentityRecord
.order(Column("lastUsedAt").desc) .order(IdentityRecord.Columns.lastUsedAt.desc)
.identityResultRequest .identityResultRequest
.fetchAll) .fetchAll)
.removeDuplicates() .removeDuplicates()
@ -183,9 +185,9 @@ public extension IdentityDatabase {
func recentIdentitiesObservation(excluding: UUID) -> AnyPublisher<[Identity], Error> { func recentIdentitiesObservation(excluding: UUID) -> AnyPublisher<[Identity], Error> {
ValueObservation.tracking( ValueObservation.tracking(
IdentityRecord IdentityRecord
.order(Column("lastUsedAt").desc) .order(IdentityRecord.Columns.lastUsedAt.desc)
.identityResultRequest .identityResultRequest
.filter(Column("id") != excluding) .filter(IdentityRecord.Columns.id != excluding)
.limit(9) .limit(9)
.fetchAll) .fetchAll)
.removeDuplicates() .removeDuplicates()
@ -195,7 +197,9 @@ public extension IdentityDatabase {
} }
func immediateMostRecentlyUsedIdentityIDObservation() -> AnyPublisher<UUID?, Error> { func immediateMostRecentlyUsedIdentityIDObservation() -> AnyPublisher<UUID?, Error> {
ValueObservation.tracking(IdentityRecord.select(Column("id")).order(Column("lastUsedAt").desc).fetchOne) ValueObservation.tracking(
IdentityRecord.select(IdentityRecord.Columns.id)
.order(IdentityRecord.Columns.lastUsedAt.desc).fetchOne)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter, scheduling: .immediate) .publisher(in: databaseWriter, scheduling: .immediate)
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -204,9 +208,9 @@ public extension IdentityDatabase {
func identitiesWithOutdatedDeviceTokens(deviceToken: Data) -> AnyPublisher<[Identity], Error> { func identitiesWithOutdatedDeviceTokens(deviceToken: Data) -> AnyPublisher<[Identity], Error> {
databaseWriter.readPublisher( databaseWriter.readPublisher(
value: IdentityRecord value: IdentityRecord
.order(Column("lastUsedAt").desc) .order(IdentityRecord.Columns.lastUsedAt.desc)
.identityResultRequest .identityResultRequest
.filter(Column("lastRegisteredDeviceToken") != deviceToken) .filter(IdentityRecord.Columns.lastRegisteredDeviceToken != deviceToken)
.fetchAll) .fetchAll)
.map { $0.map(Identity.init(result:)) } .map { $0.map(Identity.init(result:)) }
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -218,11 +222,12 @@ private extension IdentityDatabase {
static func writePreferences(_ preferences: Identity.Preferences, id: UUID) -> (Database) throws -> Void { static func writePreferences(_ preferences: Identity.Preferences, id: UUID) -> (Database) throws -> Void {
{ {
let data = try IdentityRecord.databaseJSONEncoder(for: "preferences").encode(preferences) let data = try IdentityRecord.databaseJSONEncoder(
for: IdentityRecord.Columns.preferences.name).encode(preferences)
try IdentityRecord try IdentityRecord
.filter(Column("id") == id) .filter(IdentityRecord.Columns.id == id)
.updateAll($0, Column("preferences").set(to: data)) .updateAll($0, IdentityRecord.Columns.preferences.set(to: data))
} }
} }

View file

@ -17,6 +17,18 @@ struct IdentityRecord: Codable, Hashable, FetchableRecord, PersistableRecord {
} }
extension IdentityRecord { extension IdentityRecord {
enum Columns {
static let id = Column(IdentityRecord.CodingKeys.id)
static let url = Column(IdentityRecord.CodingKeys.url)
static let authenticated = Column(IdentityRecord.CodingKeys.authenticated)
static let pending = Column(IdentityRecord.CodingKeys.pending)
static let lastUsedAt = Column(IdentityRecord.CodingKeys.lastUsedAt)
static let preferences = Column(IdentityRecord.CodingKeys.preferences)
static let instanceURI = Column(IdentityRecord.CodingKeys.instanceURI)
static let lastRegisteredDeviceToken = Column(IdentityRecord.CodingKeys.lastRegisteredDeviceToken)
static let pushSubscriptionAlerts = Column(IdentityRecord.CodingKeys.pushSubscriptionAlerts)
}
static let instance = belongsTo(Identity.Instance.self, key: "instance") static let instance = belongsTo(Identity.Instance.self, key: "instance")
static let account = hasOne(Identity.Account.self, key: "account") static let account = hasOne(Identity.Account.self, key: "account")