Lighter
Lighter 是一套技术,用于在 Swift 中通过代码生成来访问 SQLite3 数据库,例如在 iOS 应用程序或服务器上。类似于 SwiftGen,但专门用于 SQLite3。
类型安全直达 SQL 模式。
当前技术状况:开发者编写与 SQLite 表匹配的 Swift 结构。 Enlighter 反转了这个过程,生成的 Swift 代码反映了 SQLite 表的实际定义。不会出错。 消除了"堆栈中总有某处是任意时刻"的情况。非常,非常,快速。
Lighter 基于数据库模式构建,因此在编译时就直接知道它的结构。对于常见操作,根本不需要任何映射,生成的代码运行速度与手写代码一样快(通常更快)。它直接将 Swift 结构绑定到 SQLite API。无依赖。
Lighter 本身是一个小型且便捷的 API,用于访问 SQLite 数据库。 然而,代码生成器 Enlighter 可以生成仅使用 SQLite API 的代码,不需要任何依赖,即技术债务。 不要引入第三方库,直接将必要的代码生成到您的应用程序中。Lighter 主要适用于两种场景:
在应用程序中附带 SQLite 数据库(例如包含产品数据库)。
SQLite 数据库是一种非常高效的方式来传输和访问小型和大型数据。它是捆绑大型 JSON 资源文件的替代方案,后者在每次启动时都需要完全解析到内存中。
使用 SQLite 数据库,只需加载所需的数据,而且数据库文件非常紧凑(例如没有重复的键)。
SQLite 数据库对于从网络下载数据也非常高效和有用!
维护快速的本地 SQL 缓存或数据库。
如果需求比完整的 ORM(如 CoreData)更简单,Lighter 可以成为生成整洁且类型安全的本地缓存或数据库 API 的绝佳方式。 它简单但使用方便,而且非常快,因为根本不需要运行时映射或解析。生成的代码直接将生成的结构绑定到 SQLite API。
数据库可以动态创建,也可以从作为应用程序资源一部分的预填充数据库文件创建。
也支持 Linux,Lighter 可以成为主要访问只读数据集或在单个主机上运行的简单服务器的绝佳选择。
概述
Lighter 的工作方式与其他"映射"工具或 SQLite 包装器相反。它不是编写动态生成 SQLite 表的 Swift 代码,而是为 SQLite 数据库生成 Swift 代码。 可以直接从 SQLite 数据库文件生成,也可以从创建 SQLite 数据库的 SQL 文件生成。
小型示例数据库(存储在 SQLite 数据库中或从 .sql 文件创建):
CREATE TABLE person (
person_id INTEGER PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
title TEXT NULL
);
CREATE TABLE address (
address_id INTEGER PRIMARY KEY NOT NULL,
street VARCHAR NULL,
city VARCHAR NULL,
person_id INTEGER,
FOREIGN KEY(person_id) REFERENCES person(person_id) ON DELETE CASCADE DEFERRABLE
);
可以以高度可配置的方式转换为如下结构:
struct ContactsDB {
struct Person: Identifiable, Hashable {
var id : Int
var name : String
var title : String?
}
struct Address: Identifiable, Hashable {
var id : Int
var street : String?
var city : String?
var personId : Int?
}
}
代码生成器可以生成仅使用原始 SQLite3 API 的无依赖代码,也可以生成使用 Lighter 库的代码。 Lighter 库不是一个 ORM,而只是一组允许类型安全查询的 Swift 协议(它仅用于支持代码生成器,而不是作为独立库使用)。
代码生成是如何工作的?
该设置旨在与 Swift Package Manager 的新 Swift Package Plugins 功能一起使用,该功能自 Swift 5.6 起可用(并在 Xcode 14+ 中公开)。
如果还不能使用 SPM 插件,也可以直接调用 sqlite2swift 工具。
如果您想支持该项目,Mac AppStore 上还有 Code for SQLite3 应用。它以更具交互性的方式执行与此 FOSS 项目相同的代码生成。
Lighter 包附带了一个名为 Enlighter 的"构建工具插件",可以自动将代码生成结果集成到构建过程中。 如果将其添加到目标中,它会扫描数据库和 SQL 文件,并为它们创建 Swift 访问器:
.target(name: "ContactsDB", dependencies: [ "Lighter" ],
resources: [ .copy("ContactsDB.sqlite3") ],
plugins: [ "Enlighter" ]) // <== 告诉 SPM 在此目标上使用 Enlighter
这种变体是完全自动的,即 ContactsDB
目标内的其他代码可以直接访问数据库类型(例如上面的 Person
结构)。
作为手动替代方案,提供了 Generate Code for SQLite "命令插件"。 这个插件执行与 Enlighter 相同的生成,但由开发者使用 Xcode 的"File / Packages"菜单显式运行。它将生成的代码放入应用程序的"Sources"文件夹中(可以在那里检查或修改)。
使用更高级的 Lighter API 访问数据库
// 打开嵌入在模块资源中的 SQLite 数据库:
let db = ContactsDB.module!
// 获取记录数:
print("存储的总人数:",
try db.people.fetchCount())
// 有多种过滤方式,包括普通的 Swift 闭包:
let people = try db.people.filter { person in
person.title == nil
}
// 直接支持主键和外键:
let person = try db.people.find(1)
let addresses = try db.addresses.fetch(for: person)
// 可以一次性更新,或者更好的是使用事务:
try await db.transaction { tx in
var person = try tx.people.find(2)!
// 更新记录
person.title = "ZEO"
try tx.update(person)
// 删除记录
try tx.delete(person)
// 重新插入相同的记录
let newPerson = try tx.insert(person) // 获得新 ID!
}
获取单个列
SQL 的优势之一是可以为了最大效率选择和更新单个列。只需获取所需的内容(而不是完整记录):
// 只获取 `id` 和 `name` 列:
let people = try await db.select(from: \.people, \.id, \.name) {
$0.id > 2 && $0.title == nil
}
// 批量更新特定列:
try db.update(\.people, set: \.title, to: nil, where: { record in
record.name.hasPrefix("Duck")
})
这些引用在模式层面上是完全类型安全的,只能指定包含在 person
表中的列。
无依赖的 SQLite3 API
该工具包也适用于不希望额外依赖 Lighter 的情况。对于这种情况,生成器可以生成与常规 SQLite API 一起工作的数据库特定 Swift API。
// 打开数据库,也可以直接使用 `sqlite3_open_v2`:
var db : OpaquePointer!
sqlite3_open_contacts("contacts.db", &db)
defer { sqlite3_close(db) }
// 通过主键获取 person:
let person = sqlite3_person_find(db, 2)
// 获取并过滤 people:
let people = sqlite3_people_fetch(db) {
$0.name.hasPrefix("Ja")
}
// 插入记录
var person = Person(id: 0, name: "Jason Bourne")
sqlite3_person_insert(db, &person)
代码生成器可以生成另一种风格,它将相同的函数附加到生成的类型上,例如:
let people = Person.fetch(in: db) { $0.name.hasPrefix("So") }
var person = Person.find(2, in: db)
person.name = "Bourne"
person.update(in: db)
person.delete(in: db)
person.insert(into: db)
使用原始 API 的主要优势是完全不需要额外的依赖。生成的函数是完全自包含的,可以直接复制粘贴到需要的地方。
感兴趣吗?👉 开始使用。
作者
Lighter 由 Helge Heß / ZeeZide 为您带来。 我们喜欢反馈、GitHub 星标、酷炫的合同工作,大概是您能想到的任何形式的赞美。
想支持我的工作吗? 购买一个应用: Code for SQLite3、 Past for iChat、 SVG Shaper、 HMScriptEditor。 你不必使用它!😀