Restructure 是一个为 iOS、macOS 和 tvOS 提供的 SQLite 的封装库。 它相当固执己见,也就是说,它完全按照我想要的方式工作。 随意使用它、fork 它,或者对它做任何你想做的事情。
从 2.0.0 版本开始,Restructure 是一个 Swift Package Manager 项目。 使用适当的工具将 Restructure 包含到您的项目中。
可以使用文件路径打开数据库,也可以完全在内存中运行。
// File backed database
let restructure = try Restructure(path: "/path/to/data.db")
// Memory backed database
let restructure = try Restructure()
// Closing the database
restructure.close()
Restructure 支持 SQLite 的标准机制。
// Execute a statement
try restructure.execute(query: "CREATE TABLE foo (name TEXT, age INTEGER)")
// Insert data
let insertStatement = try restructure.prepare(query: "INSERT INTO foo (name, age) VALUES (:name, :age)")
insertStatement.bind(value: "Bar", for: "name")
insertStatement.bind(value: 42, for: "age")
try insertStatement.perform()
// Update data
let updateStatement = try restructure.prepare(query: "UPDATE foo SET age = :age WHERE name = :name")
updateStatement.bind(value: 43, for: "age")
updateStatement.bind(value: "Bar", for: "name")
try updateStatement.perform()
// Reuse a statement
updateStatement.reset()
updateStatement.bind(value: 44, for: "age")
updateStatement.bind(value: "Bar", for: "name")
try updateStatement.perform()
// Fetch Data
let selectStatement = try restructure.prepare(query: "SELECT name, age FROM foo")
if case let row(row) = selectStatement.step() {
let name: String = row["name"]
let age: Int = row["age"]
}
注意:语句会自动结束。
数据转换由框架处理。 当绑定数据时,它使用 SQLite 可用的最接近的数据类型进行绑定。 当从行中提取值时,数据被转换为变量的显式类型。 必须定义变量类型才能提取数据。 然后使用 SQLite 执行任何 数据类型转换。
Restructure 目前支持以下数据类型
为了帮助获取数据,所有语句都是 Sequence
类型,可以迭代。 迭代器为每次成功的 step
操作返回一行。
let statement = try restructure.prepare(query: "SELECT name, age FROM foo")
for row in statement {
let name: String = row["name"]
let age: Int = row["age"]
}
Restructure 支持存储数据数组。 这是通过编码数据并将其像普通值一样存储来完成的。 可以使用二进制 plist 或 JSON 进行编码。
// Make all arrays in Restructure binary plists
restructure.arrayStrategy = .bplist
// Make a specific statement use JSON
statement.arrayStrategy = .json
// Get and fetch an array of Integers
statement.bind(value:[1,2,3], for: "values")
let values: [Int] = row["values"]
日期可以存储在 SQLite 支持的格式中。 通常这意味着
// Make all dates in Restructure julian
restructure.arrayStrategy = .real
// Make a specific statement use epoch
statement.arrayStrategy = .integer
// Get and fetch a date
statement.bind(value: Date(), for: "date")
let date: Date = row["date"]
您可以使用 StatementEncoder
和 Encodable
数据准备一个语句
struct Foo: Encodable {
let a: Int64?
let b: String
let c: Double
let d: Int
let e: Data
}
let foo = Foo(a: nil, b: "1", c: 2.0, d: 3, e: Data(bytes: [0x4, 0x5, 0x6], count: 3))
let statement = try! restructure.prepare(query: "INSERT INTO foo (b, c, d, e) VALUES (:b, :c, :d, :e)")
let encoder = StatementEncoder()
try encoder.encode(foo, to: statement)
您可以使用 RowDecoder
和 Decodable
数据从行中提取数据
struct Foo: Encodable {
let a: Int64?
let b: String
let c: Double
let d: Int
let e: Data
}
let statement = try! restructure.prepare(query: "SELECT a, b, c, d, e FROM foo LIMIT 1")
let decoder = RowDecoder()
for row in statement }
let foo = try! decoder.decode(Foo.self, from: row)
}
您可以使用动态成员查找,通过直接属性访问从行中提取数据。
let statement = try! restructure.prepare(query: "SELECT a, b, c, d, e FROM foo LIMIT 1")
guard case let .row(row) = statement.step() else {
/// Handle error
}
let a: Int = row.a
let b: String = row.b
let c: Double = row.c
Restructure 对象具有 userVersion
属性来跟踪数据库的版本。 这可以用于任何目的,但最好用于迁移。
// Run an initial migration
try restructure.migrate(version: 1) {
// Execute statements here
}
// Run another migration
try restructure.migrate(version: 2) {
// Execute more statements here
}
每次运行 migrate
后,userVersion
值都会递增。 对于已经运行过的版本,后续的迁移运行将被忽略。
Restructure 不保证线程安全。 它与底层 SQLite 库一样安全。
Codable
支持仅支持单个对象。 不支持数据层次结构。
UInt64
不被支持作为数据类型,因为 SQLite 仅支持有符号 64 位整数。