Created
July 21, 2021 19:26
-
-
Save EricRabil/f9c2fb79dee8fa89596c00c3d0693b3c to your computer and use it in GitHub Desktop.
SQLite.swift expansion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import SQLite | |
protocol TableActionable { | |
associatedtype SelfType | |
@discardableResult | |
func insert(db: Connection) throws -> SelfType | |
@discardableResult | |
func update(db: Connection) throws -> SelfType | |
@discardableResult | |
func delete(db: Connection) throws -> SelfType | |
} | |
protocol TableBase: TableActionable, Codable where SelfType: Codable { | |
static var table: Table { get } | |
static func create(inDatabase database: Connection) throws | |
static func allRecords(db: Connection) throws -> [SelfType] | |
static func selectMany(db: Connection, _ filter: Table) throws -> [SelfType] | |
static func selectOne(db: Connection, _ filter: Table) throws -> SelfType? | |
static func deleteWhere(db: Connection, _ filter: Table) throws | |
/// updates the record after the closure completes | |
func updating(db: Connection, _ cb: () throws -> ()) throws | |
var table: Table { get } | |
var selector: Table { get } | |
} | |
protocol ConnectionProviding { | |
static var connection: Connection { get } | |
var connection: Connection { get } | |
} | |
protocol TableActionableImpliedConnection: TableActionable { | |
func insert() throws -> SelfType | |
func update() throws -> SelfType | |
func delete() throws -> SelfType | |
} | |
extension ConnectionProviding { | |
var connection: Connection { | |
Self.connection | |
} | |
} | |
extension TableBase { | |
var table: Table { | |
Self.table | |
} | |
static func allRecords(db: Connection) throws -> [SelfType] { | |
try db.prepare(table).map { | |
try $0.decode() | |
} | |
} | |
static func selectMany(db: Connection, _ filter: Table) throws -> [SelfType] { | |
try db.prepare(filter).map { | |
try $0.decode() | |
} | |
} | |
static func selectOne(db: Connection, _ filter: Table) throws -> SelfType? { | |
if let row = try db.pluck(filter) { | |
return try row.decode() as SelfType | |
} else { | |
return nil | |
} | |
} | |
static func deleteWhere(db: Connection, _ filter: Table) throws { | |
try db.run(filter.delete()) | |
} | |
func updating(db: Connection, _ cb: () throws -> ()) throws { | |
try cb() | |
try self.update(db: db) | |
} | |
func insert(db: Connection) throws -> Self { | |
try db.run(Self.table.insert(self)) | |
return self | |
} | |
func update(db: Connection) throws -> Self { | |
try db.run(selector.update(self)) | |
return self | |
} | |
func delete(db: Connection) throws -> Self { | |
try db.run(selector.delete()) | |
return self | |
} | |
} | |
// MARK: - Array APIs | |
extension Array where Element: TableActionable { | |
@inline(__always) | |
fileprivate func _transact(_ db: Connection, _ cb: (Element, Connection) throws -> ()) throws { | |
try db.transaction { | |
for record in self { | |
try cb(record, db) | |
} | |
} | |
} | |
} | |
extension Array: TableActionable where Element: TableActionable { | |
typealias SelfType = [Element] | |
func insert(db: Connection) throws -> [Element] { | |
try _transact(db) { element, db in | |
try element.insert(db: db) | |
} | |
return self | |
} | |
func update(db: Connection) throws -> [Element] { | |
try _transact(db) { element, db in | |
try element.update(db: db) | |
} | |
return self | |
} | |
func delete(db: Connection) throws -> [Element] { | |
try _transact(db) { element, db in | |
try element.delete(db: db) | |
} | |
return self | |
} | |
} | |
extension Array: ConnectionProviding where Element: ConnectionProviding { | |
@inline(__always) | |
static var connection: Connection { | |
Element.connection | |
} | |
} | |
// Make ConnectionProviding TableActionableImpliedConnection when it is TableActionable | |
extension TableActionable where Self: ConnectionProviding { | |
@inline(__always) | |
@discardableResult | |
func insert() throws -> SelfType { | |
try insert(db: connection) | |
} | |
@inline(__always) | |
@discardableResult | |
func update() throws -> SelfType { | |
try update(db: connection) | |
} | |
@inline(__always) | |
@discardableResult | |
func delete() throws -> SelfType { | |
try delete(db: connection) | |
} | |
} | |
extension TableBase where Self: ConnectionProviding { | |
@inline(__always) | |
static func allRecords() throws -> [SelfType] { | |
try allRecords(db: connection) | |
} | |
@inline(__always) | |
static func selectOne(_ filter: Table) throws -> SelfType? { | |
try selectOne(db: connection, filter) | |
} | |
@inline(__always) | |
static func selectMany(_ filter: Table) throws -> [SelfType] { | |
try selectMany(db: connection, filter) | |
} | |
@inline(__always) | |
static func deleteWhere(_ filter: Table) throws { | |
try deleteWhere(db: connection, filter) | |
} | |
@inline(__always) | |
func updating(_ cb: () throws -> ()) throws { | |
try updating(db: connection, cb) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment