Add async/await counterparts to all DBObject methods
This commit is contained in:
parent
b564235a8d
commit
bf20055897
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "AgileDB"
|
||||
s.version = "6.4.0"
|
||||
s.version = "6.5.0"
|
||||
s.summary = "Save and retrieve full object graphs to SQLite"
|
||||
s.homepage = "https://github.com/AaronBratcher/AgileDB"
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ public func createSyncFileAtURL(_ localURL: URL!, lastSequence: Int, targetDBIns
|
|||
|
||||
|
||||
/**
|
||||
Processes a sync file created by another instance of ALBNoSQL This is a synchronous call.
|
||||
Processes a sync file created by another instance of AgileDB This is a synchronous call.
|
||||
|
||||
- parameter filePath: The path to the sync file.
|
||||
- parameter syncProgress: Optional function that will be called periodically giving the percent complete.
|
||||
|
@ -376,6 +376,8 @@ public func processSyncFileAtURL(_ localURL: URL!, syncProgress: syncProgressUpd
|
|||
```
|
||||
|
||||
# Revision History
|
||||
### 6.5 ###
|
||||
- All DBObject methods have async/await counterparts
|
||||
|
||||
### 6.4 ###
|
||||
- Updated DBObject encoding to support Dictonary, Codable Struct, [Dictionary], and [Codable Struct]
|
||||
|
|
|
@ -841,6 +841,32 @@ public final class AgileDB {
|
|||
return deleted
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously delete the value from the given table for the given key.
|
||||
|
||||
- parameter table: The table to return keys from.
|
||||
- parameter key: The key for the entry.
|
||||
|
||||
- returns: Bool Value was successfuly removed.
|
||||
*/
|
||||
@discardableResult
|
||||
public func deleteFromTable(_ table: DBTable, for key: String) async -> Bool {
|
||||
assert(key != "", "key must be provided")
|
||||
|
||||
return publisherQueue.sync { () -> Bool in
|
||||
let publishers = publishersContaining(key: key, in: table)
|
||||
|
||||
let successful = deleteForKey(table: table, key: key, autoDelete: false, sourceDB: dbInstanceKey, originalDB: dbInstanceKey)
|
||||
if successful {
|
||||
for publisher in publishers {
|
||||
publisher.updateSubject()
|
||||
}
|
||||
}
|
||||
|
||||
return successful
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Removes the given table and associated values.
|
||||
|
||||
|
|
|
@ -28,6 +28,21 @@ extension DBObject {
|
|||
self = dbObject
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchly instantiate object and populate with values from the database. If instantiation fails, nil is returned.
|
||||
|
||||
- parameter db: Database object holding the data.
|
||||
- parameter key: Key of the data entry.
|
||||
*/
|
||||
public init?(db: AgileDB, key: String) async {
|
||||
guard let dictionaryValue = try? await db.dictValueFromTable(Self.table, for: key)
|
||||
, let dbObject: Self = Self.dbObjectWithDict(dictionaryValue, db: db, for: key)
|
||||
else { return nil }
|
||||
|
||||
self = dbObject
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Save the object to the database. This will update the values in the database if the object is already present. At this time, this is not an atomic operation for nested Objects.
|
||||
|
||||
|
@ -61,6 +76,39 @@ extension DBObject {
|
|||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously save the object to the database. This will update the values in the database if the object is already present. At this time, this is not an atomic operation for nested Objects.
|
||||
|
||||
- parameter db: Database object to hold the data.
|
||||
- parameter expiration: Optional Date specifying when the data is to be automatically deleted. Default value is nil specifying no automatic deletion.
|
||||
- parameter saveNestedObjects: Save nested DBObjects and arrays of DBObjects. (autoDeleteAfter is not propegated to nested objects saves) Default value is true.
|
||||
|
||||
*/
|
||||
@discardableResult
|
||||
public func save(to db: AgileDB, autoDeleteAfter expiration: Date? = nil, saveNestedObjects: Bool = true) async -> Bool {
|
||||
if saveNestedObjects {
|
||||
let mirror = Mirror(reflecting: self)
|
||||
for child in mirror.children {
|
||||
if let dbObject = child.value as? DBObject {
|
||||
await dbObject.save(to: db)
|
||||
}
|
||||
|
||||
if let objectArray = child.value as? [DBObject] {
|
||||
for dbObject in objectArray {
|
||||
await dbObject.save(to: db)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard let dictValue = dictValue
|
||||
, db.setValueInTable(Self.table, for: key, to: dictValue, autoDeleteAfter: expiration)
|
||||
else { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove the object from the database
|
||||
|
||||
|
@ -73,6 +121,18 @@ extension DBObject {
|
|||
return db.deleteFromTable(Self.table, for: key)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously remove the object from the database
|
||||
|
||||
- parameter db: Database object that holds the data. This does not delete nested objects.
|
||||
|
||||
- returns: Discardable Bool value of a successful deletion.
|
||||
*/
|
||||
@discardableResult
|
||||
public func delete(from db: AgileDB) async -> Bool {
|
||||
return await db.deleteFromTable(Self.table, for: key)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously instantiate object and populate with values from the database.
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ class AsyncTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testAwaitTableHasAllKeys() async {
|
||||
func testAwaitTableHasAllKeys() {
|
||||
let table: DBTable = "asyncTable6"
|
||||
db.dropTable(table)
|
||||
db.setValueInTable(table, for: "testKey1", to: "{\"numValue\":2,\"value2\":1}", autoDeleteAfter: nil)
|
||||
|
@ -202,16 +202,12 @@ class AsyncTests: XCTestCase {
|
|||
db.setValueInTable(table, for: "testKey4", to: "{\"numValue\":1,\"value2\":1}", autoDeleteAfter: nil)
|
||||
db.setValueInTable(table, for: "testKey5", to: "{\"numValue\":2,\"value2\":2}", autoDeleteAfter: nil)
|
||||
|
||||
do {
|
||||
var hasKeys = try await db.tableHasAllKeys(table: table, keys: ["testKey1", "testKey2", "testKey3", "testKey4", "testKey5"])
|
||||
XCTAssertTrue(hasKeys)
|
||||
var hasKeys = db.tableHasAllKeys(table: table, keys: ["testKey1", "testKey2", "testKey3", "testKey4", "testKey5"]) ?? false
|
||||
XCTAssertTrue(hasKeys)
|
||||
|
||||
self.db.deleteFromTable(table, for: "testKey4")
|
||||
hasKeys = try await db.tableHasAllKeys(table: table, keys: ["testKey1", "testKey2", "testKey3", "testKey4", "testKey5"])
|
||||
XCTAssertFalse(hasKeys)
|
||||
} catch {
|
||||
XCTFail()
|
||||
}
|
||||
self.db.deleteFromTable(table, for: "testKey4")
|
||||
hasKeys = db.tableHasAllKeys(table: table, keys: ["testKey1", "testKey2", "testKey3", "testKey4", "testKey5"]) ?? false
|
||||
XCTAssertFalse(hasKeys)
|
||||
}
|
||||
|
||||
func testAwaitValueFromTable() async {
|
||||
|
|
|
@ -123,14 +123,14 @@ class DBObjectTests: XCTestCase {
|
|||
removeDB(for: String(describing: type(of: self)))
|
||||
}
|
||||
|
||||
func testSaveObject() throws {
|
||||
func testSaveObject() async throws {
|
||||
let date: Date = { Date() }()
|
||||
let purchaseDates = [date, date, date]
|
||||
|
||||
let transaction = Transaction(key: TransactionValue.key, date: date, accountKey: TransactionValue.accountKey, notes: TransactionValue.notes, amount: TransactionValue.amount, purchaseOrders: TransactionValue.purchaseOrders, purchaseDates: purchaseDates, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
guard let testTransaction = Transaction.init(db: db, key: TransactionValue.key) else { XCTFail(); return }
|
||||
guard let testTransaction = await Transaction.init(db: db, key: TransactionValue.key) else { XCTFail(); return }
|
||||
|
||||
let dateCompare = Calendar(identifier: .gregorian).compare(date, to: testTransaction.date, toGranularity: .nanosecond)
|
||||
let dateCompare0 = Calendar(identifier: .gregorian).compare(date, to: testTransaction.purchaseDates![0], toGranularity: .nanosecond)
|
||||
|
@ -154,7 +154,7 @@ class DBObjectTests: XCTestCase {
|
|||
let addresses = [address, address]
|
||||
|
||||
var addressHolder = AddressHolder(using: address, addresses: nil)
|
||||
addressHolder.save(to: db)
|
||||
await addressHolder.save(to: db)
|
||||
|
||||
let newHolder = try await AddressHolder.load(from: db, for: addressHolder.key)
|
||||
XCTAssertEqual(newHolder.address, address)
|
||||
|
@ -162,7 +162,7 @@ class DBObjectTests: XCTestCase {
|
|||
XCTAssertEqual(newHolder.authors, addressHolder.authors)
|
||||
|
||||
addressHolder = AddressHolder(using: address, addresses: addresses)
|
||||
addressHolder.save(to: db)
|
||||
await addressHolder.save(to: db)
|
||||
|
||||
let newHolder2 = try await AddressHolder.load(from: db, for: addressHolder.key)
|
||||
XCTAssertEqual(newHolder2.address, address)
|
||||
|
@ -171,33 +171,29 @@ class DBObjectTests: XCTestCase {
|
|||
XCTAssertEqual(newHolder.authors, addressHolder.authors)
|
||||
}
|
||||
|
||||
func testSaveNilValue() throws {
|
||||
func testSaveNilValue() async throws {
|
||||
let date = Date()
|
||||
let transaction = Transaction(key: TransactionValue.key, date: date, accountKey: TransactionValue.accountKey, amount: TransactionValue.amount, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
guard let testTransaction = Transaction.init(db: db, key: TransactionValue.key) else { XCTFail(); return }
|
||||
guard let testTransaction = await Transaction.init(db: db, key: TransactionValue.key) else { XCTFail(); return }
|
||||
|
||||
XCTAssertNil(testTransaction.notes)
|
||||
}
|
||||
|
||||
func testAsyncObject() throws {
|
||||
func testAsyncObject() async throws {
|
||||
let transaction = Transaction(key: TransactionValue.key, date: Date(), accountKey: TransactionValue.accountKey, notes: TransactionValue.notes, amount: TransactionValue.amount, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
let expectations = expectation(description: "DBObject Expectations")
|
||||
expectations.expectedFulfillmentCount = 1
|
||||
|
||||
Transaction.loadObjectFromDB(db, for: TransactionValue.key) { (_) in
|
||||
expectations.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 2, handler: nil)
|
||||
let transaction2 = try await Transaction.load(from: db, for: TransactionValue.key)
|
||||
XCTAssertEqual(transaction2.key, TransactionValue.key)
|
||||
XCTAssertEqual(transaction2.accountKey, TransactionValue.accountKey)
|
||||
}
|
||||
|
||||
func testLoadFromDB() async throws {
|
||||
let transaction = Transaction(key: TransactionValue.key, date: Date(), accountKey: TransactionValue.accountKey, notes: TransactionValue.notes, amount: TransactionValue.amount, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
do {
|
||||
let object = try await Transaction.load(from: db, for: TransactionValue.key)
|
||||
|
@ -208,13 +204,14 @@ class DBObjectTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testNestedSave() throws {
|
||||
func testNestedSave() async throws {
|
||||
let transaction = EncodingTransaction()
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
let loadedTransaction = try XCTUnwrap(EncodingTransaction(db: db, key: transaction.key))
|
||||
XCTAssertEqual(transaction.amount, loadedTransaction.amount)
|
||||
XCTAssertEqual(loadedTransaction.locations.count, 3)
|
||||
XCTAssertEqual(loadedTransaction.locations[0].manager.firstName, "Store")
|
||||
let loadedTransaction = await EncodingTransaction(db: db, key: transaction.key)
|
||||
let encodingTransaction = try XCTUnwrap(loadedTransaction)
|
||||
XCTAssertEqual(transaction.amount, encodingTransaction.amount)
|
||||
XCTAssertEqual(encodingTransaction.locations.count, 3)
|
||||
XCTAssertEqual(encodingTransaction.locations[0].manager.firstName, "Store")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,18 +28,18 @@ class DBResultsTests: XCTestCase {
|
|||
}
|
||||
|
||||
|
||||
func testDBResults() throws {
|
||||
func testDBResults() async throws {
|
||||
let date = Date()
|
||||
let keys = ["1", "2", "3"]
|
||||
|
||||
var transaction = Transaction(key: keys[0], date: date, accountKey: "A1", notes: TransactionValue.notes, amount: TransactionValue.amount, purchaseOrders: TransactionValue.purchaseOrders, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
transaction = Transaction(key: keys[1], date: date, accountKey: "A2", notes: TransactionValue.notes, amount: TransactionValue.amount, purchaseOrders: TransactionValue.purchaseOrders, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
transaction = Transaction(key: keys[2], date: date, accountKey: "A3", notes: TransactionValue.notes, amount: TransactionValue.amount, purchaseOrders: TransactionValue.purchaseOrders, isNew: TransactionValue.isNew)
|
||||
transaction.save(to: db)
|
||||
await transaction.save(to: db)
|
||||
|
||||
let transactions = DBResults<Transaction>(db: db, keys: keys)
|
||||
XCTAssertEqual(transactions.count, 3)
|
||||
|
|
Loading…
Reference in New Issue