This commit is contained in:
Justin Mazzocchi 2020-09-04 19:05:15 -07:00
parent 703dbfdf3c
commit 51e6a41bd3
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
13 changed files with 132 additions and 128 deletions

View file

@ -4,7 +4,7 @@ import Foundation
import GRDB import GRDB
import Mastodon import Mastodon
struct StoredAccount: Codable, Hashable { struct AccountRecord: Codable, Hashable {
let id: String let id: String
let username: String let username: String
let acct: String let acct: String
@ -27,7 +27,7 @@ struct StoredAccount: Codable, Hashable {
let movedId: String? let movedId: String?
} }
extension StoredAccount: FetchableRecord, PersistableRecord { extension AccountRecord: FetchableRecord, PersistableRecord {
static func databaseJSONDecoder(for column: String) -> JSONDecoder { static func databaseJSONDecoder(for column: String) -> JSONDecoder {
MastodonDecoder() MastodonDecoder()
} }
@ -37,8 +37,8 @@ extension StoredAccount: FetchableRecord, PersistableRecord {
} }
} }
extension StoredAccount { extension AccountRecord {
static let moved = belongsTo(StoredAccount.self, key: "moved") static let moved = belongsTo(AccountRecord.self, key: "moved")
init(account: Account) { init(account: Account) {
id = account.id id = account.id

View file

@ -5,13 +5,13 @@ import GRDB
import Mastodon import Mastodon
struct AccountResult: Codable, Hashable, FetchableRecord { struct AccountResult: Codable, Hashable, FetchableRecord {
let account: StoredAccount let account: AccountRecord
let moved: StoredAccount? let moved: AccountRecord?
} }
extension QueryInterfaceRequest where RowDecoder == StoredAccount { extension QueryInterfaceRequest where RowDecoder == AccountRecord {
var accountResultRequest: AnyFetchRequest<AccountResult> { var accountResultRequest: AnyFetchRequest<AccountResult> {
AnyFetchRequest(including(optional: StoredAccount.moved)) AnyFetchRequest(including(optional: AccountRecord.moved))
.asRequest(of: AccountResult.self) .asRequest(of: AccountResult.self)
} }
} }

View file

@ -133,13 +133,13 @@ public extension ContentDatabase {
ValueObservation.tracking(timeline.statuses.fetchAll) ValueObservation.tracking(timeline.statuses.fetchAll)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseQueue) .publisher(in: databaseQueue)
.map { [$0.map(Status.init(statusResult:))] } .map { [$0.map(Status.init(result:))] }
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
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 StoredStatus.filter(Column("id") == parentID).statusResultRequest.fetchOne(db) else { guard let parent = try StatusRecord.filter(Column("id") == parentID).statusResultRequest.fetchOne(db) else {
return [[]] return [[]]
} }
@ -150,7 +150,7 @@ public extension ContentDatabase {
} }
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseQueue) .publisher(in: databaseQueue)
.map { $0.map { $0.map(Status.init(statusResult:)) } } .map { $0.map { $0.map(Status.init(result:)) } }
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
@ -193,7 +193,7 @@ private extension ContentDatabase {
var migrator = DatabaseMigrator() var migrator = DatabaseMigrator()
migrator.registerMigration("createStatuses") { db in migrator.registerMigration("createStatuses") { db in
try db.create(table: "storedAccount", ifNotExists: true) { t in try db.create(table: "accountRecord", ifNotExists: true) { t in
t.column("id", .text).notNull().primaryKey(onConflict: .replace) t.column("id", .text).notNull().primaryKey(onConflict: .replace)
t.column("username", .text).notNull() t.column("username", .text).notNull()
t.column("acct", .text).notNull() t.column("acct", .text).notNull()
@ -213,14 +213,14 @@ private extension ContentDatabase {
t.column("emojis", .blob).notNull() t.column("emojis", .blob).notNull()
t.column("bot", .boolean).notNull() t.column("bot", .boolean).notNull()
t.column("discoverable", .boolean) t.column("discoverable", .boolean)
t.column("movedId", .text).indexed().references("storedAccount", column: "id") t.column("movedId", .text).indexed().references("accountRecord", column: "id")
} }
try db.create(table: "storedStatus", ifNotExists: true) { t in try db.create(table: "statusRecord", ifNotExists: true) { t in
t.column("id", .text).notNull().primaryKey(onConflict: .replace) t.column("id", .text).notNull().primaryKey(onConflict: .replace)
t.column("uri", .text).notNull() t.column("uri", .text).notNull()
t.column("createdAt", .datetime).notNull() t.column("createdAt", .datetime).notNull()
t.column("accountId", .text).indexed().notNull().references("storedAccount", column: "id") t.column("accountId", .text).indexed().notNull().references("accountRecord", column: "id")
t.column("content", .text).notNull() t.column("content", .text).notNull()
t.column("visibility", .text).notNull() t.column("visibility", .text).notNull()
t.column("sensitive", .boolean).notNull() t.column("sensitive", .boolean).notNull()
@ -236,7 +236,7 @@ private extension ContentDatabase {
t.column("url", .text) t.column("url", .text)
t.column("inReplyToId", .text) t.column("inReplyToId", .text)
t.column("inReplyToAccountId", .text) t.column("inReplyToAccountId", .text)
t.column("reblogId", .text).indexed().references("storedStatus", column: "id") t.column("reblogId", .text).indexed().references("statusRecord", column: "id")
t.column("poll", .blob) t.column("poll", .blob)
t.column("card", .blob) t.column("card", .blob)
t.column("language", .text) t.column("language", .text)
@ -261,7 +261,7 @@ private extension ContentDatabase {
t.column("statusId", .text) t.column("statusId", .text)
.indexed() .indexed()
.notNull() .notNull()
.references("storedStatus", column: "id", onDelete: .cascade, onUpdate: .cascade) .references("statusRecord", column: "id", onDelete: .cascade, onUpdate: .cascade)
t.primaryKey(["timelineId", "statusId"], onConflict: .replace) t.primaryKey(["timelineId", "statusId"], onConflict: .replace)
} }
@ -270,11 +270,11 @@ private extension ContentDatabase {
t.column("parentId", .text) t.column("parentId", .text)
.indexed() .indexed()
.notNull() .notNull()
.references("storedStatus", column: "id", onDelete: .cascade, onUpdate: .cascade) .references("statusRecord", column: "id", onDelete: .cascade, onUpdate: .cascade)
t.column("statusId", .text) t.column("statusId", .text)
.indexed() .indexed()
.notNull() .notNull()
.references("storedStatus", column: "id", onDelete: .cascade, onUpdate: .cascade) .references("statusRecord", column: "id", onDelete: .cascade, onUpdate: .cascade)
t.column("section", .text).notNull() t.column("section", .text).notNull()
t.column("index", .integer).notNull() t.column("index", .integer).notNull()

View file

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

View file

@ -4,7 +4,7 @@ import Foundation
import GRDB import GRDB
import Mastodon import Mastodon
struct StoredStatus: Codable, Hashable { struct StatusRecord: Codable, Hashable {
let id: String let id: String
let uri: String let uri: String
let createdAt: Date let createdAt: Date
@ -36,7 +36,7 @@ struct StoredStatus: Codable, Hashable {
let pinned: Bool? let pinned: Bool?
} }
extension StoredStatus: FetchableRecord, PersistableRecord { extension StatusRecord: FetchableRecord, PersistableRecord {
static func databaseJSONDecoder(for column: String) -> JSONDecoder { static func databaseJSONDecoder(for column: String) -> JSONDecoder {
MastodonDecoder() MastodonDecoder()
} }
@ -46,31 +46,31 @@ extension StoredStatus: FetchableRecord, PersistableRecord {
} }
} }
extension StoredStatus { extension StatusRecord {
static let account = belongsTo(StoredAccount.self, key: "account", using: ForeignKey([Column("accountId")])) static let account = belongsTo(AccountRecord.self, key: "account", using: ForeignKey([Column("accountId")]))
static let accountMoved = hasOne(StoredAccount.self, static let accountMoved = hasOne(AccountRecord.self,
through: Self.account, through: Self.account,
using: StoredAccount.moved, using: AccountRecord.moved,
key: "accountMoved") key: "accountMoved")
static let reblogAccount = hasOne(StoredAccount.self, static let reblogAccount = hasOne(AccountRecord.self,
through: Self.reblog, through: Self.reblog,
using: Self.account, using: Self.account,
key: "reblogAccount") key: "reblogAccount")
static let reblogAccountMoved = hasOne(StoredAccount.self, static let reblogAccountMoved = hasOne(AccountRecord.self,
through: Self.reblogAccount, through: Self.reblogAccount,
using: StoredAccount.moved, using: AccountRecord.moved,
key: "reblogAccountMoved") key: "reblogAccountMoved")
static let reblog = belongsTo(StoredStatus.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(StatusContextJoin.self, using: ForeignKey([Column("parentID")]))
.filter(Column("section") == StatusContextJoin.Section.ancestors.rawValue) .filter(Column("section") == StatusContextJoin.Section.ancestors.rawValue)
.order(Column("index")) .order(Column("index"))
static let descendantJoins = hasMany(StatusContextJoin.self, using: ForeignKey([Column("parentID")])) static let descendantJoins = hasMany(StatusContextJoin.self, using: ForeignKey([Column("parentID")]))
.filter(Column("section") == StatusContextJoin.Section.descendants.rawValue) .filter(Column("section") == StatusContextJoin.Section.descendants.rawValue)
.order(Column("index")) .order(Column("index"))
static let ancestors = hasMany(StoredStatus.self, static let ancestors = hasMany(StatusRecord.self,
through: ancestorJoins, through: ancestorJoins,
using: StatusContextJoin.status) using: StatusContextJoin.status)
static let descendants = hasMany(StoredStatus.self, static let descendants = hasMany(StatusRecord.self,
through: descendantJoins, through: descendantJoins,
using: StatusContextJoin.status) using: StatusContextJoin.status)

View file

@ -5,12 +5,12 @@ import GRDB
import Mastodon import Mastodon
struct StatusResult: Codable, Hashable, FetchableRecord { struct StatusResult: Codable, Hashable, FetchableRecord {
let account: StoredAccount let account: AccountRecord
let accountMoved: StoredAccount? let accountMoved: AccountRecord?
let status: StoredStatus let status: StatusRecord
let reblogAccount: StoredAccount? let reblogAccount: AccountRecord?
let reblogAccountMoved: StoredAccount? let reblogAccountMoved: AccountRecord?
let reblog: StoredStatus? let reblog: StatusRecord?
} }
extension StatusResult { extension StatusResult {
@ -25,13 +25,13 @@ extension StatusResult {
} }
} }
extension QueryInterfaceRequest where RowDecoder == StoredStatus { extension QueryInterfaceRequest where RowDecoder == StatusRecord {
var statusResultRequest: AnyFetchRequest<StatusResult> { var statusResultRequest: AnyFetchRequest<StatusResult> {
AnyFetchRequest(including(required: StoredStatus.account) AnyFetchRequest(including(required: StatusRecord.account)
.including(optional: StoredStatus.accountMoved) .including(optional: StatusRecord.accountMoved)
.including(optional: StoredStatus.reblogAccount) .including(optional: StatusRecord.reblogAccount)
.including(optional: StoredStatus.reblogAccountMoved) .including(optional: StatusRecord.reblogAccountMoved)
.including(optional: StoredStatus.reblog)) .including(optional: StatusRecord.reblog))
.asRequest(of: StatusResult.self) .asRequest(of: StatusResult.self)
} }
} }

View file

@ -7,5 +7,5 @@ struct TimelineStatusJoin: Codable, FetchableRecord, PersistableRecord {
let timelineId: String let timelineId: String
let statusId: String let statusId: String
static let status = belongsTo(StoredStatus.self) static let status = belongsTo(StatusRecord.self)
} }

View file

@ -7,42 +7,44 @@ import Mastodon
extension Account { extension Account {
func save(_ db: Database) throws { func save(_ db: Database) throws {
if let moved = moved { if let moved = moved {
try StoredAccount(account: moved).save(db) try AccountRecord(account: moved).save(db)
} }
try StoredAccount(account: self).save(db) try AccountRecord(account: self).save(db)
} }
convenience init(accountResult: AccountResult) { convenience init(result: AccountResult) {
var moved: Account? var moved: Account?
if let movedResult = accountResult.moved { if let movedRecord = result.moved {
moved = Self(storedAccount: movedResult, moved: nil) moved = Self(record: movedRecord, moved: nil)
} }
self.init(storedAccount: accountResult.account, moved: moved) self.init(record: result.account, moved: moved)
} }
}
convenience init(storedAccount: StoredAccount, moved: Account?) { private extension Account {
self.init(id: storedAccount.id, convenience init(record: AccountRecord, moved: Account?) {
username: storedAccount.username, self.init(id: record.id,
acct: storedAccount.acct, username: record.username,
displayName: storedAccount.displayName, acct: record.acct,
locked: storedAccount.locked, displayName: record.displayName,
createdAt: storedAccount.createdAt, locked: record.locked,
followersCount: storedAccount.followersCount, createdAt: record.createdAt,
followingCount: storedAccount.followingCount, followersCount: record.followersCount,
statusesCount: storedAccount.statusesCount, followingCount: record.followingCount,
note: storedAccount.note, statusesCount: record.statusesCount,
url: storedAccount.url, note: record.note,
avatar: storedAccount.avatar, url: record.url,
avatarStatic: storedAccount.avatarStatic, avatar: record.avatar,
header: storedAccount.header, avatarStatic: record.avatarStatic,
headerStatic: storedAccount.headerStatic, header: record.header,
fields: storedAccount.fields, headerStatic: record.headerStatic,
emojis: storedAccount.emojis, fields: record.fields,
bot: storedAccount.bot, emojis: record.emojis,
discoverable: storedAccount.discoverable, bot: record.bot,
discoverable: record.discoverable,
moved: moved) moved: moved)
} }
} }

View file

@ -10,54 +10,56 @@ extension Status {
if let reblog = reblog { if let reblog = reblog {
try reblog.account.save(db) try reblog.account.save(db)
try StoredStatus(status: reblog).save(db) try StatusRecord(status: reblog).save(db)
} }
try StoredStatus(status: self).save(db) try StatusRecord(status: self).save(db)
} }
convenience init(statusResult: StatusResult) { convenience init(result: StatusResult) {
var reblog: Status? var reblog: Status?
if let reblogResult = statusResult.reblog, let reblogAccount = statusResult.reblogAccountResult { if let reblogResult = result.reblog, let reblogAccountResult = result.reblogAccountResult {
reblog = Status(storedStatus: reblogResult, account: Account(accountResult: reblogAccount), reblog: nil) reblog = Status(record: reblogResult, account: Account(result: reblogAccountResult), reblog: nil)
} }
self.init(storedStatus: statusResult.status, self.init(record: result.status,
account: Account(accountResult: statusResult.accountResult), account: Account(result: result.accountResult),
reblog: reblog) reblog: reblog)
} }
}
convenience init(storedStatus: StoredStatus, account: Account, reblog: Status?) { private extension Status {
convenience init(record: StatusRecord, account: Account, reblog: Status?) {
self.init( self.init(
id: storedStatus.id, id: record.id,
uri: storedStatus.uri, uri: record.uri,
createdAt: storedStatus.createdAt, createdAt: record.createdAt,
account: account, account: account,
content: storedStatus.content, content: record.content,
visibility: storedStatus.visibility, visibility: record.visibility,
sensitive: storedStatus.sensitive, sensitive: record.sensitive,
spoilerText: storedStatus.spoilerText, spoilerText: record.spoilerText,
mediaAttachments: storedStatus.mediaAttachments, mediaAttachments: record.mediaAttachments,
mentions: storedStatus.mentions, mentions: record.mentions,
tags: storedStatus.tags, tags: record.tags,
emojis: storedStatus.emojis, emojis: record.emojis,
reblogsCount: storedStatus.reblogsCount, reblogsCount: record.reblogsCount,
favouritesCount: storedStatus.favouritesCount, favouritesCount: record.favouritesCount,
repliesCount: storedStatus.repliesCount, repliesCount: record.repliesCount,
application: storedStatus.application, application: record.application,
url: storedStatus.url, url: record.url,
inReplyToId: storedStatus.inReplyToId, inReplyToId: record.inReplyToId,
inReplyToAccountId: storedStatus.inReplyToAccountId, inReplyToAccountId: record.inReplyToAccountId,
reblog: reblog, reblog: reblog,
poll: storedStatus.poll, poll: record.poll,
card: storedStatus.card, card: record.card,
language: storedStatus.language, language: record.language,
text: storedStatus.text, text: record.text,
favourited: storedStatus.favourited, favourited: record.favourited,
reblogged: storedStatus.reblogged, reblogged: record.reblogged,
muted: storedStatus.muted, muted: record.muted,
bookmarked: storedStatus.bookmarked, bookmarked: record.bookmarked,
pinned: storedStatus.pinned) pinned: record.pinned)
} }
} }

View file

@ -36,7 +36,7 @@ extension Timeline: FetchableRecord, PersistableRecord {
extension Timeline { extension Timeline {
static let statusJoins = hasMany(TimelineStatusJoin.self) static let statusJoins = hasMany(TimelineStatusJoin.self)
static let statuses = hasMany( static let statuses = hasMany(
StoredStatus.self, StatusRecord.self,
through: statusJoins, through: statusJoins,
using: TimelineStatusJoin.status) using: TimelineStatusJoin.status)
.order(Column("createdAt").desc) .order(Column("createdAt").desc)

View file

@ -39,7 +39,7 @@ public struct IdentityDatabase {
public extension IdentityDatabase { public extension IdentityDatabase {
func createIdentity(id: UUID, url: URL) -> AnyPublisher<Never, Error> { func createIdentity(id: UUID, url: URL) -> AnyPublisher<Never, Error> {
databaseQueue.writePublisher( databaseQueue.writePublisher(
updates: StoredIdentity( updates: IdentityRecord(
id: id, id: id,
url: url, url: url,
lastUsedAt: Date(), lastUsedAt: Date(),
@ -53,14 +53,14 @@ public extension IdentityDatabase {
} }
func deleteIdentity(id: UUID) -> AnyPublisher<Never, Error> { func deleteIdentity(id: UUID) -> AnyPublisher<Never, Error> {
databaseQueue.writePublisher(updates: StoredIdentity.filter(Column("id") == id).deleteAll) databaseQueue.writePublisher(updates: IdentityRecord.filter(Column("id") == id).deleteAll)
.ignoreOutput() .ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func updateLastUsedAt(identityID: UUID) -> AnyPublisher<Never, Error> { func updateLastUsedAt(identityID: UUID) -> AnyPublisher<Never, Error> {
databaseQueue.writePublisher { databaseQueue.writePublisher {
try StoredIdentity try IdentityRecord
.filter(Column("id") == identityID) .filter(Column("id") == identityID)
.updateAll($0, Column("lastUsedAt").set(to: Date())) .updateAll($0, Column("lastUsedAt").set(to: Date()))
} }
@ -76,7 +76,7 @@ public extension IdentityDatabase {
title: instance.title, title: instance.title,
thumbnail: instance.thumbnail) thumbnail: instance.thumbnail)
.save($0) .save($0)
try StoredIdentity try IdentityRecord
.filter(Column("id") == identityID) .filter(Column("id") == identityID)
.updateAll($0, Column("instanceURI").set(to: instance.uri)) .updateAll($0, Column("instanceURI").set(to: instance.uri))
} }
@ -105,9 +105,9 @@ public extension IdentityDatabase {
func updatePreferences(_ preferences: Identity.Preferences, func updatePreferences(_ preferences: Identity.Preferences,
forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> { forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> {
databaseQueue.writePublisher { databaseQueue.writePublisher {
let data = try StoredIdentity.databaseJSONEncoder(for: "preferences").encode(preferences) let data = try IdentityRecord.databaseJSONEncoder(for: "preferences").encode(preferences)
try StoredIdentity try IdentityRecord
.filter(Column("id") == identityID) .filter(Column("id") == identityID)
.updateAll($0, Column("preferences").set(to: data)) .updateAll($0, Column("preferences").set(to: data))
} }
@ -119,14 +119,14 @@ public extension IdentityDatabase {
deviceToken: String? = nil, deviceToken: String? = nil,
forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> { forIdentityID identityID: UUID) -> AnyPublisher<Never, Error> {
databaseQueue.writePublisher { databaseQueue.writePublisher {
let data = try StoredIdentity.databaseJSONEncoder(for: "pushSubscriptionAlerts").encode(alerts) let data = try IdentityRecord.databaseJSONEncoder(for: "pushSubscriptionAlerts").encode(alerts)
try StoredIdentity try IdentityRecord
.filter(Column("id") == identityID) .filter(Column("id") == identityID)
.updateAll($0, Column("pushSubscriptionAlerts").set(to: data)) .updateAll($0, Column("pushSubscriptionAlerts").set(to: data))
if let deviceToken = deviceToken { if let deviceToken = deviceToken {
try StoredIdentity try IdentityRecord
.filter(Column("id") == identityID) .filter(Column("id") == identityID)
.updateAll($0, Column("lastRegisteredDeviceToken").set(to: deviceToken)) .updateAll($0, Column("lastRegisteredDeviceToken").set(to: deviceToken))
} }
@ -137,10 +137,10 @@ public extension IdentityDatabase {
func identityObservation(id: UUID) -> AnyPublisher<Identity, Error> { func identityObservation(id: UUID) -> AnyPublisher<Identity, Error> {
ValueObservation.tracking( ValueObservation.tracking(
StoredIdentity IdentityRecord
.filter(Column("id") == id) .filter(Column("id") == id)
.including(optional: StoredIdentity.instance) .including(optional: IdentityRecord.instance)
.including(optional: StoredIdentity.account) .including(optional: IdentityRecord.account)
.asRequest(of: IdentityResult.self) .asRequest(of: IdentityResult.self)
.fetchOne) .fetchOne)
.removeDuplicates() .removeDuplicates()
@ -174,7 +174,7 @@ public extension IdentityDatabase {
} }
func mostRecentlyUsedIdentityIDObservation() -> AnyPublisher<UUID?, Error> { func mostRecentlyUsedIdentityIDObservation() -> AnyPublisher<UUID?, Error> {
ValueObservation.tracking(StoredIdentity.select(Column("id")).order(Column("lastUsedAt").desc).fetchOne) ValueObservation.tracking(IdentityRecord.select(Column("id")).order(Column("lastUsedAt").desc).fetchOne)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseQueue, scheduling: .immediate) .publisher(in: databaseQueue, scheduling: .immediate)
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -194,10 +194,10 @@ private extension IdentityDatabase {
private static let name = "Identity" private static let name = "Identity"
private static func identitiesRequest() -> QueryInterfaceRequest<IdentityResult> { private static func identitiesRequest() -> QueryInterfaceRequest<IdentityResult> {
StoredIdentity IdentityRecord
.order(Column("lastUsedAt").desc) .order(Column("lastUsedAt").desc)
.including(optional: StoredIdentity.instance) .including(optional: IdentityRecord.instance)
.including(optional: StoredIdentity.account) .including(optional: IdentityRecord.account)
.asRequest(of: IdentityResult.self) .asRequest(of: IdentityResult.self)
} }
@ -212,7 +212,7 @@ private extension IdentityDatabase {
t.column("thumbnail", .text) t.column("thumbnail", .text)
} }
try db.create(table: "storedIdentity", ifNotExists: true) { t in try db.create(table: "identityRecord", ifNotExists: true) { t in
t.column("id", .text).notNull().primaryKey(onConflict: .replace) t.column("id", .text).notNull().primaryKey(onConflict: .replace)
t.column("url", .text).notNull() t.column("url", .text).notNull()
t.column("lastUsedAt", .datetime).notNull() t.column("lastUsedAt", .datetime).notNull()
@ -229,7 +229,7 @@ private extension IdentityDatabase {
t.column("identityID", .text) t.column("identityID", .text)
.notNull() .notNull()
.indexed() .indexed()
.references("storedIdentity", column: "id", onDelete: .cascade) .references("identityRecord", column: "id", onDelete: .cascade)
t.column("username", .text).notNull() t.column("username", .text).notNull()
t.column("displayName", .text).notNull() t.column("displayName", .text).notNull()
t.column("url", .text).notNull() t.column("url", .text).notNull()

View file

@ -4,7 +4,7 @@ import Foundation
import GRDB import GRDB
import Mastodon import Mastodon
struct StoredIdentity: Codable, Hashable, FetchableRecord, PersistableRecord { struct IdentityRecord: Codable, Hashable, FetchableRecord, PersistableRecord {
let id: UUID let id: UUID
let url: URL let url: URL
let lastUsedAt: Date let lastUsedAt: Date
@ -14,7 +14,7 @@ struct StoredIdentity: Codable, Hashable, FetchableRecord, PersistableRecord {
let pushSubscriptionAlerts: PushSubscription.Alerts let pushSubscriptionAlerts: PushSubscription.Alerts
} }
extension StoredIdentity { extension IdentityRecord {
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")

View file

@ -5,7 +5,7 @@ import GRDB
import Mastodon import Mastodon
struct IdentityResult: Codable, Hashable, FetchableRecord { struct IdentityResult: Codable, Hashable, FetchableRecord {
let identity: StoredIdentity let identity: IdentityRecord
let instance: Identity.Instance? let instance: Identity.Instance?
let account: Identity.Account? let account: Identity.Account?
let pushSubscriptionAlerts: PushSubscription.Alerts let pushSubscriptionAlerts: PushSubscription.Alerts