一个适用于 Mac 和 Linux 的 Mysql 原生客户端和查询构建器。
这个库由 Prorsum 驱动。
SwiftKnex 旨在用于我公司的生产服务。
欢迎并鼓励所有开发者为 SwiftKnex 做出贡献。
要为 SwiftKnex 贡献功能或想法,请提交一个 issue! 如果你发现错误,当然你可以创建 PR(s) 目录。
let config = KnexConfig(
host: "localhost",
user: "user",
database: "my_database",
isShowSQLLog: true
)
let con = try KnexConnection(config: config)
let knex = con.knex()
let results = try knex.table("users").where("id" == 1).fetch()
print(results)
你可以像 SQL 一样链式调用条件子句,这非常具有表现力。
let results = try knex
.table("users")
.where(between("id", 1, 1000))
.limit(10)
.offset(10)
.fetch()
print(result)
let results = try knex
.table("users")
.join("payments")
.on("users.id" == "payment.user_id")
.where("users.id" == 1)
.limit(10)
.offset(10)
.fetch()
print(results)
let results = try knex
.select(count("id").as("count"))
.table("users")
.fetch()
print(results)
let results = try knex
.table("users")
.where(("country" == "Japan" && "age" > 20) || "country" == "USA")
print(results)
let results = try knex
.table(
Table(
QueryBuilder()
.table("users")
.where("country" == "USA")
)
).as("t1")
)
.where("t1.id" == 1)
print(results)
let results = try knex
.table("users")
.where(SwiftKnex.in("id",
QueryBuilder()
.select(col("id"))
.table("t1")
.where("country" == "USA")
)).fetch()
print(results)
SwiftKnex 可以将比较公式作为函数求值。 如果你在 where
子句中输入 "id" == 1
,它会被视为 function
(不是 BOOL) 并转换为 SQL 比较字面量。
SwiftKnex | Mysql |
---|---|
where("id" == 1) | where id = 1 |
where("id" > 1) | where id > 1 |
where("id" >= 1) | where id >= 1 |
where("id" < 1) | where id < 1 |
where("id" <= 1) | where id <= 1 |
where("id" != 1) | where id != 1 |
SwiftKnex 提供条件作为函数。 以下是当前可用的条件列表。
where(_ filter: ConditionFilter)
knex().where(like("name", "%a%"))
knex().where(in("id", [1, 2, 3]))
knex().where(notIn("id", [1, 2, 3]))
knex().where(between("date", "2017-01-01", "2017-01-31"))
knex().where(notBetween("date", "2017-01-01", "2017-01-31"))
knex().where(isNull("deleted_at"))
knex().where(isNotNull("deleted_at"))
knex().where(raw("id = ?", [1]))
or(_ filter: ConditionFilter)
knex().where(in("id", [1, 2, 3])).or(in("id", [4, 5, 6]))
当然,它支持其他子句。 你可以使用 knex()
的方法链来使用它们。
knex().table("a").join("b")
knex().table("a").leftJoin("b")
knex().table("a").rightJoin("b")
knex().table("a").innerJoin("b")
knex().table("a").join("b").on("a.id" == "b.a_id")
knex().limit(10)
knex().limit(10).offset(100)
knex().order(by: "created_at", .desc)
knex().group(by: "company")
knex().group(by: "company").having(in("name", ["Google", "Apple"]))
定义你的实体并确认 Entity
协议,并将行作为你指定的类型获取。
struct User: Entity, Serializable {
let id: Int
let name: String
let email: String
let age: Int
let country: String?
init(row: Row) throws {
self.id = row["id"] as! Int
self.name = row["name"] as! String
self.email = row["email"] as! String
self.age = row["age"] as! Int
self.country = row["country"] as? String
}
func serialize() throws -> [String: Any] {
return [
"name": name,
"email": email,
"age": age,
"country": country
]
}
}
// fetch rows as User(s)
let users: [User] = try! con.knex()
.table("users")
.where("country" == "Japan")
.fetch()
print(users.first)
// Insert User(should confirm Serializable)
let result = try! con.knex().insert(into: "users", values: user)
print(result?.insertId)
let result = try knex().insert(into: "users", values: ["id": 1, "name": "bar"])
print(result.affectedRows)
let result = try knex().table("users").where("id" == 1).update(sets: ["name": "foobar"])
print(result.affectedRows)
let result = try knex().table("users").where("id" == 1).delete()
print(result.affectedRows)
do {
try con.knex().transaction { trx in // BEGIN TRANSCTION
try con.knex().table("users").where("id" == 1).update(sets: ["name": "foo"], trx: trx)
try con.knex().table("users").where("id" == 2).update(sets: ["name": "bar"], trx: trx)
try con.knex().table("users").where("id" == 3).update(sets: ["name": "foobar"], trx: trx)
}
// COMMIT
} catch {
// ROLLBACK
}
let create = Create(table: "users", fields: [
Schema.integer("id").asPrimaryKey().asAutoIncrement(),
Schema.string("name"),
Schema.string("email").asUnique(),
Schema.datetime("last_logined_at").asIndex()
])
.hasTimeStamps() // add created_at and updated_at
try knex().execRaw(sql: create.toDDL())
SwiftKnex | Mysql 类型 |
---|---|
Schema.string | VARCHAR |
Schema.integer | INT |
Schema.bigInteger | BIGINT |
Schema.dateTime | DATETIME |
Schema.text | TEXT |
Schema.mediumText | MEDIUMTEXT |
Schema.float | FLOAT |
Schema.double | DOUBLE |
Schema.boolean | TINYINT(1) |
Schema.json | JSON |
default(as value: Any) (默认值)
after(for name: String) (在指定字段后)
asPrimaryKey() (作为主键)
asAutoIncrement() (作为自增)
asNotNullable() (作为非空)
asUnsigned() (作为无符号)
charset(_ char: Charset) (字符集)
asUnique() (作为唯一键)
asIndex() (作为索引)
let drop = Drop(table: "users")
try knex().execRaw(sql: drop.toDDL())
你可以使用 SwiftKnex 执行原始 SQL。
try knex().execRaw(sql: "SELECT * from users where id = ?", params: [1])
SwiftKnex 支持数据库迁移和回滚功能。
Package.swift
import PackageDescription
let package = Package(
name: "MyApp",
dependencies: [
.Package(url: "https://github.com/noppoMan/SwiftKnex.git", majorVersion: 0, minor: 1)
]
)
运行 swift build
$ swift build
然后,SwiftKnexMigration
可执行二进制文件将在 .build/debug 目录中创建。
下一步是在你的 Sources/Migration
目录中使用 ./build/debug/Migration create {ResourceName}
创建迁移类文件。
这是一个创建 CreateUser
迁移文件的示例。
.build/debug/SwiftKnexMigration create CreateUser
#
# Created /YourProject/Sources/Migration/20170116015823_CreateUser.swift
#
创建迁移类文件后,像下面这样编辑它。
创建的迁移类具有以下方法。
在 migrate:latest 上执行
在 migrate:rollback 上执行
import SwiftKnex
import Foundation
class Migration_20170116015823_CreateUser: Migratable {
var name: String {
return "\(Mirror(reflecting: self).subjectType)"
}
func up(_ migrator: Migrator) throws {
let create = Create(
table: "users",
fields: [
Schema.integer("id").asPrimaryKey().asAutoIncrement(),
Schema.string("name").asIndex().asNotNullable(),
Schema.string("email").asUnique().asNotNullable()
])
.hasTimestamps()
.index(columns: ["name", "email"], unique: true)
try migrator.run(create)
}
func down(_ migrator: Migrator) throws {
try migrator.run(Drop(table: "users"))
}
}
在 {$PROJ}/Sources/Migration
目录中创建 main.swift
,该目录由前一节中的 Migrate create
创建。
然后将以下代码复制/粘贴到你的 {$PROJ}/Sources/Migration/main.swift
中,然后将 knexMigrations
数组中的类名替换为正确的名称,并根据你的环境更改数据库配置。
你需要在每次创建迁移资源时将新的类名添加到 knexMigrations
中。
main.swift 示例
import SwiftKnex
let knexMigrations: [Migratable] = [
Migration_20170116015823_CreateUser()
]
let config = KnexConfig(
host: "localhost",
user: "root",
database: "swift_knex_test"
)
try Migrator.run(config: config, arguments: CommandLine.arguments, knexMigrations: knexMigrations)
编辑 main.swift 后,运行 swift build
swift build
之后,你只需要运行迁移即可。
当前支持的命令是
migrate:latest
: 执行最近未迁移的文件的迁移。migrate:rollback
: 回滚最近执行的迁移。(回滚单位按 batch
编号分组).build/debug/Migration migrate:latest
.build/debug/Migration migrate:rollback
待办事项
使用 Prorsum 进行 Go 风格的异步查询执行和同步。
import Prorsum
let chan = Channel<ResultSet>.make()
go {
let rows = try! knex().table("users").where("id" == 1).fetch()
try chan.send(rows!)
}
go {
let rows = try! knex().table("users").where("id" == 2).fetch()
try chan.send(rows!)
}
print(try! chan.receive())
print(try! chan.receive())
SwiftKnex 中使用的基本连接和查询库。
待办事项
Prorsum 在 MIT 许可证下发布。 有关详细信息,请参阅 LICENSE。