Finalize Async/Await support
This commit is contained in:
parent
99c9385087
commit
2ef779202d
|
@ -228,7 +228,7 @@ public final class AgileDB {
|
|||
- throws: DBError
|
||||
*/
|
||||
|
||||
public func asyncTableHasKey(table: DBTable, key: String) async throws -> Bool {
|
||||
public func tableHasKey(table: DBTable, key: String) async throws -> Bool {
|
||||
let results = await bridgingTableHasKey(table: table, key: key)
|
||||
switch results {
|
||||
case .success(let hasKey):
|
||||
|
@ -256,7 +256,7 @@ public final class AgileDB {
|
|||
|
||||
- returns: DBActivityToken Returns a DBCommandToken that can be used to cancel the command before it executes If the database file cannot be opened nil is returned.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use await asyncTableHasKey instead")
|
||||
@available(*, deprecated, message: "Use await tableHasKey instead")
|
||||
@discardableResult
|
||||
public func tableHasKey(table: DBTable, key: String, queue: DispatchQueue? = nil, completion: @escaping (BoolResults) -> Void) -> DBCommandToken? {
|
||||
let openResults = openDB()
|
||||
|
@ -303,7 +303,7 @@ public final class AgileDB {
|
|||
- throws: DBError
|
||||
*/
|
||||
|
||||
public func asyncTableHasAllKeys(table: DBTable, keys: [String]) async throws -> Bool {
|
||||
public func tableHasAllKeys(table: DBTable, keys: [String]) async throws -> Bool {
|
||||
let results = await bridgingTableHasAllKeys(table: table, keys: keys)
|
||||
switch results {
|
||||
case .success(let hasKeys):
|
||||
|
@ -331,7 +331,7 @@ public final class AgileDB {
|
|||
|
||||
- returns: DBActivityToken Returns a DBCommandToken that can be used to cancel the command before it executes If the database file cannot be opened nil is returned.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use await asyncTableHasAllKeys instead")
|
||||
@available(*, deprecated, message: "Use await tableHasAllKeys instead")
|
||||
@discardableResult
|
||||
public func tableHasAllKeys(table: DBTable, keys: [String], queue: DispatchQueue? = nil, completion: @escaping (BoolResults) -> Void) -> DBCommandToken? {
|
||||
let openResults = openDB()
|
||||
|
@ -420,7 +420,7 @@ public final class AgileDB {
|
|||
- throws: DBError
|
||||
*/
|
||||
|
||||
public func asyncKeysInTable(_ table: DBTable, sortOrder: String? = nil, conditions: [DBCondition]? = nil, validateObjects: Bool = false) async throws -> [String] {
|
||||
public func keysInTable(_ table: DBTable, sortOrder: String? = nil, conditions: [DBCondition]? = nil, validateObjects: Bool = false) async throws -> [String] {
|
||||
let results = await bridgingKeysInTable(table, sortOrder: sortOrder, conditions: conditions, validateObjects: validateObjects)
|
||||
switch results {
|
||||
case .success(let keys):
|
||||
|
@ -463,7 +463,7 @@ public final class AgileDB {
|
|||
*/
|
||||
|
||||
@discardableResult
|
||||
@available(*, deprecated, message: "Use await asyncKeysInTable instead")
|
||||
@available(*, deprecated, message: "Use await keysInTable instead")
|
||||
public func keysInTable(_ table: DBTable, sortOrder: String? = nil, conditions: [DBCondition]? = nil, validateObjects: Bool = false, queue: DispatchQueue? = nil, completion: @escaping (KeyResults) -> Void) -> DBCommandToken? {
|
||||
let openResults = openDB()
|
||||
if case .failure(_) = openResults {
|
||||
|
@ -636,7 +636,7 @@ public final class AgileDB {
|
|||
- throws: DBError
|
||||
*/
|
||||
|
||||
public func asyncValueFromTable(_ table: DBTable, for key: String) async throws -> String {
|
||||
public func valueFromTable(_ table: DBTable, for key: String) async throws -> String {
|
||||
let results = await bridgingValueFromTable(table, for: key)
|
||||
|
||||
switch results {
|
||||
|
@ -669,7 +669,7 @@ public final class AgileDB {
|
|||
|
||||
*/
|
||||
@discardableResult
|
||||
@available(*, deprecated, message: "Use await asyncValueFromTable instead")
|
||||
@available(*, deprecated, message: "Use await valueFromTable instead")
|
||||
public func valueFromTable(_ table: DBTable, for key: String, queue: DispatchQueue? = nil, completion: @escaping (JsonResults) -> Void) -> DBCommandToken? {
|
||||
let openResults = openDB()
|
||||
if case .failure(_) = openResults, !tables.hasTable(table) {
|
||||
|
@ -738,7 +738,7 @@ public final class AgileDB {
|
|||
- throws: DBError
|
||||
*/
|
||||
|
||||
public func asyncDictValueFromTable(_ table: DBTable, for key: String) async throws -> [String: AnyObject] {
|
||||
public func dictValueFromTable(_ table: DBTable, for key: String) async throws -> [String: AnyObject] {
|
||||
let results = await bridgingDictValueFromTable(table, for: key)
|
||||
|
||||
switch results {
|
||||
|
@ -775,7 +775,7 @@ public final class AgileDB {
|
|||
- returns: Returns a DBCommandToken that can be used to cancel the command before it executes. If the database file cannot be opened or table does not exist nil is returned.
|
||||
*/
|
||||
@discardableResult
|
||||
@available(*, deprecated, message: "Use await asyncDictValueFromTable instead")
|
||||
@available(*, deprecated, message: "Use await dictValueFromTable instead")
|
||||
public func dictValueFromTable(_ table: DBTable, for key: String, queue: DispatchQueue? = nil, completion: @escaping (DictResults) -> Void) -> DBCommandToken? {
|
||||
let openResults = openDB()
|
||||
if case .failure(_) = openResults, !tables.hasTable(table) {
|
||||
|
@ -2038,7 +2038,7 @@ extension AgileDB {
|
|||
- throws: DBError
|
||||
*/
|
||||
|
||||
public func asyncSqlSelect(_ sql: String) async throws -> [DBRow] {
|
||||
public func sqlSelect(_ sql: String) async throws -> [DBRow] {
|
||||
let results = await bridgingSqlSelect(sql)
|
||||
|
||||
switch results {
|
||||
|
@ -2064,7 +2064,7 @@ extension AgileDB {
|
|||
|
||||
- returns: Result<[DBRow], DBError>
|
||||
*/
|
||||
@available(*, deprecated, message: "Use await asyncSqlSelect instead")
|
||||
@available(*, deprecated, message: "Use await sqlSelect instead")
|
||||
@discardableResult
|
||||
public func sqlSelect(_ sql: String, queue: DispatchQueue? = nil, completion: @escaping (RowResults) -> Void) -> DBCommandToken? {
|
||||
let openResults = openDB()
|
||||
|
|
|
@ -72,6 +72,25 @@ extension DBObject {
|
|||
public func delete(from db: AgileDB) -> Bool {
|
||||
return db.deleteFromTable(Self.table, for: key)
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously instantiate object and populate with values from the database.
|
||||
|
||||
- parameter db: Database object to hold the data.
|
||||
- parameter key: Key of the data entry.
|
||||
|
||||
- returns: DBObject.
|
||||
- throws: DBError
|
||||
*/
|
||||
|
||||
public static func loadFromDB(_ db: AgileDB, for key: String) async throws -> Self {
|
||||
let dictionaryValue = try await db.dictValueFromTable(table, for: key)
|
||||
guard let dbObject = dbObjectWithDict(dictionaryValue, db: db, for: key) else {
|
||||
throw DBError.cannotParseData
|
||||
}
|
||||
|
||||
return dbObject
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronously instantiate object and populate with values from the database before executing the passed block with object. If object could not be instantiated properly, block is not executed.
|
||||
|
@ -83,6 +102,7 @@ extension DBObject {
|
|||
|
||||
- returns: DBCommandToken that can be used to cancel the call before it executes. Nil is returned if database could not be opened.
|
||||
*/
|
||||
@available(*, deprecated, message: "Use await loadFromDB instead")
|
||||
@discardableResult
|
||||
public static func loadObjectFromDB(_ db: AgileDB, for key: String, queue: DispatchQueue? = nil, completion: @escaping (Self) -> Void) -> DBCommandToken? {
|
||||
let token = db.dictValueFromTable(table, for: key, queue: queue, completion: { (results) in
|
||||
|
|
|
@ -98,6 +98,7 @@ public enum DBError: Error {
|
|||
case damagedFile
|
||||
case cannotOpenFile
|
||||
case tableNotFound
|
||||
case cannotParseData
|
||||
case other(Int)
|
||||
}
|
||||
|
||||
|
@ -111,6 +112,7 @@ extension DBError: RawRepresentable {
|
|||
case 11: self = .damagedFile
|
||||
case 14: self = .cannotOpenFile
|
||||
case -1: self = .tableNotFound
|
||||
case -2: self = .cannotParseData
|
||||
default: self = .other(rawValue)
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +124,7 @@ extension DBError: RawRepresentable {
|
|||
case .damagedFile: return 11
|
||||
case .cannotOpenFile: return 14
|
||||
case .tableNotFound: return -1
|
||||
case .cannotParseData: return -2
|
||||
case .other(let value): return value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ class AsyncTests: XCTestCase {
|
|||
waitForExpectations(timeout: 20, handler: nil)
|
||||
}
|
||||
|
||||
func testAsyncTableKeys() async {
|
||||
func testAwaitKeysInTable() async {
|
||||
let table: DBTable = "asyncTable8"
|
||||
db.dropTable(table)
|
||||
db.setValueInTable(table, for: "testKey1", to: "{\"numValue\":2,\"value2\":1}", autoDeleteAfter: nil)
|
||||
|
@ -169,14 +169,14 @@ class AsyncTests: XCTestCase {
|
|||
db.setValueInTable(table, for: "testKey5", to: "{\"numValue\":2,\"value2\":2}", autoDeleteAfter: nil)
|
||||
|
||||
do {
|
||||
let rows = try await db.asyncKeysInTable(table)
|
||||
let rows = try await db.keysInTable(table)
|
||||
XCTAssert(rows.count == 5)
|
||||
} catch {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func testAsyncAwaitTableHasKey() async {
|
||||
func testAwaitTableHasKey() async {
|
||||
let table: DBTable = "asyncTable7"
|
||||
db.dropTable(table)
|
||||
db.setValueInTable(table, for: "testKey1", to: "{\"numValue\":2,\"value2\":1}", autoDeleteAfter: nil)
|
||||
|
@ -186,14 +186,14 @@ class AsyncTests: XCTestCase {
|
|||
db.setValueInTable(table, for: "testKey5", to: "{\"numValue\":2,\"value2\":2}", autoDeleteAfter: nil)
|
||||
|
||||
do {
|
||||
let hasKey = try await db.asyncTableHasKey(table: table, key: "testKey4")
|
||||
let hasKey = try await db.tableHasKey(table: table, key: "testKey4")
|
||||
XCTAssertTrue(hasKey)
|
||||
} catch {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func testAsyncAwaitTableHasAllKeys() async {
|
||||
func testAwaitTableHasAllKeys() async {
|
||||
let table: DBTable = "asyncTable6"
|
||||
db.dropTable(table)
|
||||
db.setValueInTable(table, for: "testKey1", to: "{\"numValue\":2,\"value2\":1}", autoDeleteAfter: nil)
|
||||
|
@ -203,18 +203,18 @@ class AsyncTests: XCTestCase {
|
|||
db.setValueInTable(table, for: "testKey5", to: "{\"numValue\":2,\"value2\":2}", autoDeleteAfter: nil)
|
||||
|
||||
do {
|
||||
var hasKeys = try await db.asyncTableHasAllKeys(table: table, keys: ["testKey1","testKey2","testKey3","testKey4","testKey5"])
|
||||
var hasKeys = try await db.tableHasAllKeys(table: table, keys: ["testKey1","testKey2","testKey3","testKey4","testKey5"])
|
||||
XCTAssertTrue(hasKeys)
|
||||
|
||||
self.db.deleteFromTable(table, for: "testKey4")
|
||||
hasKeys = try await db.asyncTableHasAllKeys(table: table, keys: ["testKey1","testKey2","testKey3","testKey4","testKey5"])
|
||||
hasKeys = try await db.tableHasAllKeys(table: table, keys: ["testKey1","testKey2","testKey3","testKey4","testKey5"])
|
||||
XCTAssertFalse(hasKeys)
|
||||
} catch {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func testAsyncAwaitValues() async {
|
||||
func testAwaitValueFromTable() async {
|
||||
let table: DBTable = "asyncTable5"
|
||||
db.dropTable(table)
|
||||
db.setValueInTable(table, for: "testKey1", to: "{\"numValue\":2,\"value2\":1}", autoDeleteAfter: nil)
|
||||
|
@ -224,7 +224,7 @@ class AsyncTests: XCTestCase {
|
|||
db.setValueInTable(table, for: "testKey5", to: "{\"numValue\":2,\"value2\":2}", autoDeleteAfter: nil)
|
||||
|
||||
do {
|
||||
let value = try await db.asyncValueFromTable(table, for: "testKey3")
|
||||
let value = try await db.valueFromTable(table, for: "testKey3")
|
||||
let jsonData = value.data(using: .utf8)!
|
||||
let jsonObject: [String: Int] = try! JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as! [String: Int]
|
||||
XCTAssertTrue(jsonObject["numValue"] == 2)
|
||||
|
|
|
@ -131,6 +131,19 @@ class DBObjectTests: XCTestCase {
|
|||
|
||||
waitForExpectations(timeout: 2, handler: nil)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
do {
|
||||
let object = try await Transaction.loadFromDB(db, for: TransactionValue.key)
|
||||
XCTAssertEqual(object.accountKey, TransactionValue.accountKey)
|
||||
XCTAssertEqual(object.amount, TransactionValue.amount)
|
||||
} catch {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func testNestedSave() throws {
|
||||
let transaction = EncodingTransaction()
|
||||
|
|
31
README.md
31
README.md
|
@ -4,6 +4,7 @@
|
|||
- A SQLite database wrapper written in Swift that requires no SQL knowledge to use.
|
||||
- No need to keep track of columns used in the database; it's automatic.
|
||||
- Completely thread safe since it uses it's own Thread subclass.
|
||||
- Works with Async/Await
|
||||
- Use the publish method to work with Combine and SwiftUI
|
||||
|
||||
## Installation Options ##
|
||||
|
@ -17,9 +18,8 @@
|
|||
- For any method that returns an optional, that value is nil if an error occured and could not return a proper value.
|
||||
|
||||
## DBObject Protocol ##
|
||||
DBbjects can have the following types: DBObject, Int, Double, String, Date, Bool, [DBObject], [Int], [Double], [String], [Date]. All properties may be optional. For DBObject properties, the key is stored so the referenced objects can be edited and saved independently
|
||||
|
||||
Bool properties read from the database will be interpreted as follows: An integer 0 = false and any other number is true. For string values "1", "yes", "YES", "true", and "TRUE" evaluate to true.
|
||||
- DBbjects can have the following types saved and read to the DB: DBObject, Int, Double, String, Date, Bool, [DBObject], [Int], [Double], [String], [Date]. All properties may be optional. For DBObject properties, the key is stored so the referenced objects can be edited and saved independently
|
||||
- Bool properties read from the database will be interpreted as follows: An integer 0 = false and any other number is true. For string values "1", "yes", "YES", "true", and "TRUE" evaluate to true.
|
||||
|
||||
### Protocol Definition ###
|
||||
```swift
|
||||
|
@ -39,6 +39,16 @@ public protocol DBObject: Codable {
|
|||
*/
|
||||
public init?(db: AgileDB, key: String)
|
||||
|
||||
/**
|
||||
Asynchronously instantiates object and populate with values from the database.
|
||||
|
||||
- parameter db: Database object holding the data.
|
||||
- parameter key: Key of the data entry.
|
||||
|
||||
- throws: DBError
|
||||
*/
|
||||
public init(db: AgileDB, key: String) async throws
|
||||
|
||||
|
||||
/**
|
||||
Save the object's encoded values to the database.
|
||||
|
@ -52,6 +62,18 @@ public init?(db: AgileDB, key: String)
|
|||
public func save(to db: AgileDB, autoDeleteAfter expiration: Date? = nil) -> Bool
|
||||
|
||||
|
||||
/**
|
||||
Asynchronously instantiate object and populate with values from the database.
|
||||
|
||||
- parameter db: Database object to hold the data.
|
||||
- parameter key: Key of the data entry.
|
||||
|
||||
- returns: DBObject
|
||||
- throws: DBError
|
||||
*/
|
||||
public static func loadFromDB(_ db: AgileDB, for key: String) -> Self?
|
||||
|
||||
|
||||
/**
|
||||
Asynchronously instantiate object and populate with values from the database before executing the passed block with object. If object could not be instantiated properly, block is not executed.
|
||||
|
||||
|
@ -385,6 +407,9 @@ public func processSyncFileAtURL(_ localURL: URL!, syncProgress: syncProgressUpd
|
|||
|
||||
# Revision History
|
||||
|
||||
### 6.3 ###
|
||||
- Add async/await support
|
||||
|
||||
### 6.2 ###
|
||||
- New method: tableHasAllKeys and it's asynchronous equivilent
|
||||
|
||||
|
|
Loading…
Reference in New Issue