Add shared YAP extension for SignalServiceAddress lookup
This commit is contained in:
parent
7d94af3287
commit
52545fa0c4
2
Pods
2
Pods
@ -1 +1 @@
|
||||
Subproject commit 7fcaa35aac69aa47443b920ef4c6553bd1f8d9d3
|
||||
Subproject commit 3d393009e3fded14568792745f55eb8faccf44a0
|
||||
48
SignalServiceKit/src/Contacts/AnyThreadFinder.swift
Normal file
48
SignalServiceKit/src/Contacts/AnyThreadFinder.swift
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
class AnyContactThreadFinder: NSObject {
|
||||
let grdbAdapter = GRDBContactThreadFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnyContactThreadFinder {
|
||||
@objc(contactThreadForAddress:transaction:)
|
||||
func contactThread(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> TSContactThread? {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.contactThread(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class GRDBContactThreadFinder: NSObject {
|
||||
func contactThread(for address: SignalServiceAddress, transaction: GRDBReadTransaction) -> TSContactThread? {
|
||||
if let account = contactThreadForUUID(address.uuid, transaction: transaction) {
|
||||
return account
|
||||
} else if let account = contactThreadForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return account
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func contactThreadForUUID(_ uuid: UUID?, transaction: GRDBReadTransaction) -> TSContactThread? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
let sql = "SELECT * FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .contactUUID) = ?"
|
||||
return TSContactThread.grdbFetchOne(sql: sql, arguments: [uuidString], transaction: transaction) as? TSContactThread
|
||||
}
|
||||
|
||||
private func contactThreadForPhoneNumber(_ phoneNumber: String?, transaction: GRDBReadTransaction) -> TSContactThread? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
let sql = "SELECT * FROM \(ThreadRecord.databaseTableName) WHERE \(threadColumn: .contactPhoneNumber) = ?"
|
||||
return TSContactThread.grdbFetchOne(sql: sql, arguments: [phoneNumber], transaction: transaction) as? TSContactThread
|
||||
}
|
||||
}
|
||||
@ -4,36 +4,26 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SignalAccountFinder {
|
||||
associatedtype ReadTransaction
|
||||
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: ReadTransaction) -> SignalAccount?
|
||||
}
|
||||
|
||||
@objc
|
||||
class AnySignalAccountFinder: NSObject {
|
||||
typealias ReadTransaction = SDSAnyReadTransaction
|
||||
|
||||
let grdbAdapter = GRDBSignalAccountFinder()
|
||||
let yapdbAdapter = YAPDBSignalAccountFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnySignalAccountFinder: SignalAccountFinder {
|
||||
extension AnySignalAccountFinder {
|
||||
@objc(signalAccountForAddress:transaction:)
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> SignalAccount? {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalAccount(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.signalAccount(for: address, transaction: transaction)
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class GRDBSignalAccountFinder: NSObject, SignalAccountFinder {
|
||||
typealias ReadTransaction = GRDBReadTransaction
|
||||
|
||||
class GRDBSignalAccountFinder: NSObject {
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: GRDBReadTransaction) -> SignalAccount? {
|
||||
if let account = signalAccountForUUID(address.uuid, transaction: transaction) {
|
||||
return account
|
||||
@ -56,109 +46,3 @@ class GRDBSignalAccountFinder: NSObject, SignalAccountFinder {
|
||||
return SignalAccount.grdbFetchOne(sql: sql, arguments: [phoneNumber], transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalAccountFinder: NSObject, SignalAccountFinder {
|
||||
typealias ReadTransaction = YapDatabaseReadTransaction
|
||||
|
||||
private static let uuidColumn = "recipient_uuid"
|
||||
private static let phoneNumberColumn = "recipient_phone_number"
|
||||
private static let phoneNumberIndex = "index_signal_accounts_on_recipientPhoneNumber"
|
||||
private static let uuidIndex = "index_signal_accounts_on_recipientUUID"
|
||||
|
||||
func signalAccount(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> SignalAccount? {
|
||||
if let account = signalAccountForUUID(address.uuid, transaction: transaction) {
|
||||
return account
|
||||
} else if let account = signalAccountForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return account
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func signalAccountForUUID(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> SignalAccount? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalAccountFinder.uuidIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalAccountFinder.uuidColumn, uuidString)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalAccount?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? SignalAccount else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
private func signalAccountForPhoneNumber(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> SignalAccount? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalAccountFinder.phoneNumberIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalAccountFinder.phoneNumberColumn, phoneNumber)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalAccount?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? SignalAccount else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndex)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndex)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(uuidColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let account = object as? SignalAccount else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[uuidColumn] = account.recipientUUID
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(phoneNumberColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let account = object as? SignalAccount else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[phoneNumberColumn] = account.recipientPhoneNumber
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,41 +4,31 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol SignalRecipientFinder {
|
||||
associatedtype ReadTransaction
|
||||
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: ReadTransaction) -> SignalRecipient?
|
||||
}
|
||||
|
||||
@objc
|
||||
public class AnySignalRecipientFinder: NSObject {
|
||||
typealias ReadTransaction = SDSAnyReadTransaction
|
||||
|
||||
class AnySignalRecipientFinder: NSObject {
|
||||
let grdbAdapter = GRDBSignalRecipientFinder()
|
||||
let yapdbAdapter = YAPDBSignalRecipientFinder()
|
||||
let yapdbAdapter = YAPDBSignalServiceAddressIndex()
|
||||
}
|
||||
|
||||
extension AnySignalRecipientFinder: SignalRecipientFinder {
|
||||
extension AnySignalRecipientFinder {
|
||||
@objc(signalRecipientForAddress:transaction:)
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> SignalRecipient? {
|
||||
switch transaction.readTransaction {
|
||||
case .grdbRead(let transaction):
|
||||
return grdbAdapter.signalRecipient(for: address, transaction: transaction)
|
||||
case .yapRead(let transaction):
|
||||
return yapdbAdapter.signalRecipient(for: address, transaction: transaction)
|
||||
return yapdbAdapter.fetchOne(for: address, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class GRDBSignalRecipientFinder: NSObject, SignalRecipientFinder {
|
||||
typealias ReadTransaction = GRDBReadTransaction
|
||||
|
||||
class GRDBSignalRecipientFinder: NSObject {
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: GRDBReadTransaction) -> SignalRecipient? {
|
||||
if let recipient = signalRecipientForUUID(address.uuid, transaction: transaction) {
|
||||
return recipient
|
||||
} else if let recipient = signalRecipientForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return recipient
|
||||
if let account = signalRecipientForUUID(address.uuid, transaction: transaction) {
|
||||
return account
|
||||
} else if let account = signalRecipientForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return account
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@ -56,109 +46,3 @@ class GRDBSignalRecipientFinder: NSObject, SignalRecipientFinder {
|
||||
return SignalRecipient.grdbFetchOne(sql: sql, arguments: [phoneNumber], transaction: transaction)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalRecipientFinder: NSObject, SignalRecipientFinder {
|
||||
typealias ReadTransaction = YapDatabaseReadTransaction
|
||||
|
||||
private static let uuidColumn = "recipient_uuid"
|
||||
private static let phoneNumberColumn = "recipient_phone_number"
|
||||
private static let phoneNumberIndex = "index_signal_recipients_on_recipientPhoneNumber"
|
||||
private static let uuidIndex = "index_signal_recipients_on_recipientUUID"
|
||||
|
||||
func signalRecipient(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> SignalRecipient? {
|
||||
if let recipient = signalRecipientForUUID(address.uuid, transaction: transaction) {
|
||||
return recipient
|
||||
} else if let recipient = signalRecipientForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return recipient
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func signalRecipientForUUID(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> SignalRecipient? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalRecipientFinder.uuidIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalRecipientFinder.uuidColumn, uuidString)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalRecipient?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = recipient
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
private func signalRecipientForPhoneNumber(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> SignalRecipient? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalRecipientFinder.phoneNumberIndex) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", YAPDBSignalRecipientFinder.phoneNumberColumn, phoneNumber)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: SignalRecipient?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
owsFailDebug("Unexpected object type \(type(of: object))")
|
||||
return
|
||||
}
|
||||
matchedAccount = recipient
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndex)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndex)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(uuidColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[uuidColumn] = recipient.recipientUUID
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
setup.addColumn(phoneNumberColumn, with: .text)
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let recipient = object as? SignalRecipient else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[phoneNumberColumn] = recipient.recipientPhoneNumber
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,12 @@ NSUInteger const TSContactThreadSchemaVersion = 1;
|
||||
return SDSDatabaseStorage.shared;
|
||||
}
|
||||
|
||||
+ (AnyContactThreadFinder *)threadFinder
|
||||
{
|
||||
return [AnyContactThreadFinder new];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// --- CODE GENERATION MARKER
|
||||
@ -114,10 +120,7 @@ isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting
|
||||
{
|
||||
OWSAssertDebug(contactAddress);
|
||||
|
||||
// TODO
|
||||
TSContactThread *thread
|
||||
= (TSContactThread *)[self anyFetchWithUniqueId:"c" + contactAddress.transitional_phoneNumber
|
||||
transaction:transaction];
|
||||
TSContactThread *thread = [self.threadFinder contactThreadForAddress:contactAddress transaction:transaction];
|
||||
|
||||
if (!thread) {
|
||||
thread = [[TSContactThread alloc] initWithContactAddress:contactAddress];
|
||||
@ -142,9 +145,7 @@ isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting
|
||||
+ (nullable instancetype)getThreadWithContactAddress:(SignalServiceAddress *)contactAddress
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
// TODO
|
||||
return (TSContactThread *)[TSContactThread anyFetchWithUniqueId:"c" + contactAddress.transitional_phoneNumber
|
||||
transaction:transaction];
|
||||
return [self.threadFinder contactThreadForAddress:contactAddress transaction:transaction];
|
||||
}
|
||||
|
||||
- (SignalServiceAddress *)contactAddress
|
||||
@ -194,7 +195,9 @@ isArchivedByLegacyTimestampForSorting:isArchivedByLegacyTimestampForSorting
|
||||
+ (nullable SignalServiceAddress *)contactAddressFromThreadId:(NSString *)threadId
|
||||
transaction:(SDSAnyReadTransaction *)transaction
|
||||
{
|
||||
return nil;
|
||||
TSContactThread *_Nullable contactThread = (TSContactThread *)[TSContactThread anyFetchWithUniqueId:threadId
|
||||
transaction:transaction];
|
||||
return contactThread.contactAddress;
|
||||
}
|
||||
|
||||
+ (nullable NSString *)legacyContactPhoneNumberFromThreadId:(NSString *)threadId
|
||||
|
||||
@ -0,0 +1,145 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol YAPDBSignalServiceAddressIndexable {
|
||||
static var indexablePhoneNumberColumnName: String { get }
|
||||
static var indexableUUIDColumnName: String { get }
|
||||
var indexableUUIDValue: String? { get }
|
||||
var indexablePhoneNumberValue: String? { get }
|
||||
}
|
||||
|
||||
extension SignalAccount: YAPDBSignalServiceAddressIndexable {
|
||||
static var indexablePhoneNumberColumnName = "recipient_phone_number"
|
||||
static var indexableUUIDColumnName = "recipient_uuid"
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
extension SignalRecipient: YAPDBSignalServiceAddressIndexable {
|
||||
static var indexablePhoneNumberColumnName = "recipient_phone_number"
|
||||
static var indexableUUIDColumnName = "recipient_uuid"
|
||||
var indexableUUIDValue: String? { return recipientUUID }
|
||||
var indexablePhoneNumberValue: String? { return recipientPhoneNumber }
|
||||
}
|
||||
|
||||
extension TSContactThread: YAPDBSignalServiceAddressIndexable {
|
||||
static var indexablePhoneNumberColumnName = "contact_phone_number"
|
||||
static var indexableUUIDColumnName = "contact_uuid"
|
||||
var indexableUUIDValue: String? { return contactUUID }
|
||||
var indexablePhoneNumberValue: String? { return contactPhoneNumber }
|
||||
}
|
||||
|
||||
@objc
|
||||
class YAPDBSignalServiceAddressIndex: NSObject {
|
||||
private static let indexableTypes: [YAPDBSignalServiceAddressIndexable.Type] = [
|
||||
SignalAccount.self,
|
||||
SignalRecipient.self,
|
||||
TSContactThread.self
|
||||
]
|
||||
|
||||
private static let phoneNumberIndexName = "index_on_recipientPhoneNumber"
|
||||
private static let uuidIndexName = "index_on_recipientUUID"
|
||||
|
||||
func fetchOne<T: YAPDBSignalServiceAddressIndexable>(for address: SignalServiceAddress, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
if let result: T = fetchOneForUUID(address.uuid, transaction: transaction) {
|
||||
return result
|
||||
} else if let result: T = fetchOneForPhoneNumber(address.phoneNumber, transaction: transaction) {
|
||||
return result
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchOneForUUID<T: YAPDBSignalServiceAddressIndexable>(_ uuid: UUID?, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
guard let uuidString = uuid?.uuidString else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalServiceAddressIndex.uuidIndexName) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", T.indexableUUIDColumnName, uuidString)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: T?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? T else {
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
private func fetchOneForPhoneNumber<T: YAPDBSignalServiceAddressIndexable>(_ phoneNumber: String?, transaction: YapDatabaseReadTransaction) -> T? {
|
||||
guard let phoneNumber = phoneNumber else { return nil }
|
||||
|
||||
guard let ext = transaction.ext(YAPDBSignalServiceAddressIndex.phoneNumberIndexName) as? YapDatabaseSecondaryIndexTransaction else {
|
||||
owsFailDebug("Unexpected transaction type for extension")
|
||||
return nil
|
||||
}
|
||||
|
||||
let queryFormat = String(format: "WHERE %@ = \"%@\"", T.indexablePhoneNumberColumnName, phoneNumber)
|
||||
let query = YapDatabaseQuery(string: queryFormat, parameters: [])
|
||||
|
||||
var matchedAccount: T?
|
||||
|
||||
ext.enumerateKeysAndObjects(matching: query) { _, _, object, stop in
|
||||
guard let account = object as? T else {
|
||||
return
|
||||
}
|
||||
matchedAccount = account
|
||||
stop.pointee = true
|
||||
}
|
||||
|
||||
return matchedAccount
|
||||
}
|
||||
|
||||
@objc
|
||||
static func asyncRegisterDatabaseExtensions(_ storage: OWSStorage) {
|
||||
storage.asyncRegister(indexUUIDExtension(), withName: uuidIndexName)
|
||||
storage.asyncRegister(indexPhoneNumberExtension(), withName: phoneNumberIndexName)
|
||||
}
|
||||
|
||||
private static func indexUUIDExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
|
||||
for columnName in Set(indexableTypes.map { $0.indexableUUIDColumnName }) {
|
||||
setup.addColumn(columnName, with: .text)
|
||||
}
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let indexableObject = object as? YAPDBSignalServiceAddressIndexable else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[type(of: indexableObject).indexableUUIDColumnName] = indexableObject.indexableUUIDValue
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
|
||||
private static func indexPhoneNumberExtension() -> YapDatabaseSecondaryIndex {
|
||||
let setup = YapDatabaseSecondaryIndexSetup()
|
||||
|
||||
for columnName in Set(indexableTypes.map { $0.indexablePhoneNumberColumnName }) {
|
||||
setup.addColumn(columnName, with: .text)
|
||||
}
|
||||
|
||||
let handler = YapDatabaseSecondaryIndexHandler.withObjectBlock { _, dict, _, _, object in
|
||||
guard let indexableObject = object as? YAPDBSignalServiceAddressIndexable else {
|
||||
return
|
||||
}
|
||||
|
||||
dict[type(of: indexableObject).indexablePhoneNumberColumnName] = indexableObject.indexablePhoneNumberValue
|
||||
}
|
||||
|
||||
return YapDatabaseSecondaryIndex(setup: setup, handler: handler, versionTag: "1")
|
||||
}
|
||||
}
|
||||
@ -502,6 +502,32 @@ public class GRDBDatabaseStorageAdapter: NSObject {
|
||||
on: SignalAccountRecord.databaseTableName,
|
||||
columns: [SignalAccountRecord.columnName(.recipientUUID)]
|
||||
)
|
||||
|
||||
// Signal Recipient Indices
|
||||
try db.create(
|
||||
index: "index_signal_recipients_on_recipientPhoneNumber",
|
||||
on: SignalAccountRecord.databaseTableName,
|
||||
columns: [SignalAccountRecord.columnName(.recipientPhoneNumber)]
|
||||
)
|
||||
|
||||
try db.create(
|
||||
index: "index_signal_recipients_on_recipientUUID",
|
||||
on: SignalAccountRecord.databaseTableName,
|
||||
columns: [SignalAccountRecord.columnName(.recipientUUID)]
|
||||
)
|
||||
|
||||
// Thread Indices
|
||||
try db.create(
|
||||
index: "index_thread_on_contactPhoneNumber",
|
||||
on: ThreadRecord.databaseTableName,
|
||||
columns: [ThreadRecord.columnName(.contactPhoneNumber)]
|
||||
)
|
||||
|
||||
try db.create(
|
||||
index: "index_tsthread_on_contactUUID",
|
||||
on: ThreadRecord.databaseTableName,
|
||||
columns: [ThreadRecord.columnName(.contactUUID)]
|
||||
)
|
||||
}
|
||||
return migrator
|
||||
}()
|
||||
|
||||
@ -230,8 +230,7 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage, dispatch_block_t
|
||||
[YAPDBMediaGalleryFinder asyncRegisterDatabaseExtensionsWithPrimaryStorage:self];
|
||||
[TSDatabaseView asyncRegisterLazyRestoreAttachmentsDatabaseView:self];
|
||||
[YAPDBJobRecordFinderSetup asyncRegisterDatabaseExtensionObjCWithStorage:self];
|
||||
[YAPDBSignalAccountFinder asyncRegisterDatabaseExtensions:self];
|
||||
[YAPDBSignalRecipientFinder asyncRegisterDatabaseExtensions:self];
|
||||
[YAPDBSignalServiceAddressIndex asyncRegisterDatabaseExtensions:self];
|
||||
|
||||
[self.database
|
||||
flushExtensionRequestsWithCompletionQueue:dispatch_get_global_queue(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user