🐬 非阻塞、事件驱动的 Swift 客户端,用于 MySQL,构建于 SwiftNIO 之上。
使用标准的 SwiftPM 语法将 MySQLNIO 作为依赖项包含在您的 Package.swift 文件中。
.package(url: "https://github.com/vapor/mysql-nio.git", from: "1.0.0")
MySQLNIO 支持以下平台
MySQLNIO 是一个客户端包,用于连接、授权和查询 MySQL 服务器。该模块的核心是 NIO 通道处理器,用于解析和序列化 MySQL 专有线路协议中的消息。这些通道处理器以请求/响应风格的连接类型组合在一起,为执行查询提供了一个方便的、类似客户端的接口。
开箱即用地提供了对简单(文本)和参数化(预处理语句)查询的支持,以及一个 MySQLData 类型,用于处理 MySQL 线路格式和原生 Swift 类型之间的转换。
大多数 Swift MySQL 客户端的实现都基于 libmysqlclient C 库,该库在内部处理传输。直接在 MySQL 线路协议之上使用 SwiftNIO 构建库应该为 MySQL 数据库产生更可靠、可维护和高性能的接口。
此软件包旨在成为 Swift 的低级、无倾向性的 MySQL 线路协议实现。希望更高级别的软件包可以共享 MySQLNIO 作为与 MySQL 服务器交互的基础,而无需重复复杂的逻辑。
因此,为了简洁起见,MySQLNIO 排除了一些重要的概念,例如
Codable 集成如果您正在寻找要在项目中使用 MySQL 客户端软件包,请查看以下构建在 MySQLNIO 之上的更高级别软件包
此软件包有四个依赖项
apple/swift-nio 用于 IOapple/swift-nio-ssl 用于 TLSapple/swift-log 用于日志记录apple/swift-crypto 用于加密此软件包没有额外的系统依赖项。
查看 MySQLNIO API 文档 以详细了解所有类、结构体、协议等等。
本节将快速浏览一下 MySQLNIO 的使用方法。
进行查询的第一步是创建一个新的 MySQLConnection。创建连接的最低要求是 SocketAddress、EventLoop 和凭据。
import MySQLNIO
let eventLoop: any EventLoop = ...
let conn = try await MySQLConnection(
to: .makeAddressResolvingHost("my.mysql.server", port: 3306),
username: "test_username",
database: "test_database",
password: "test_password",
on: eventLoop
).get()
注意:这些示例为了简单起见将使用 wait()。如果您在主线程上使用 MySQLNIO,例如用于 CLI 工具或测试,则这是合适的。但是,您永远不应在事件循环上使用 wait()。
有几种创建 SocketAddress 的方法
init(ipAddress: String, port: Int)init(unixDomainSocketPath: String)makeAddressResolvingHost(_ host: String, port: Int)您还可以为 connect 提供一些额外的参数。
tlsConfiguration 一个可选的 TLSConfiguration 结构体。如果 MySQL 服务器支持 TLS,将使用此结构体。传递 nil 以选择不使用 TLS。serverHostname 一个可选的 String,与 tlsConfiguration 结合使用,以指定服务器的主机名。connect 将返回一个 future MySQLConnection,如果无法连接,则返回错误。
与服务器的交互围绕 MySQLDatabase 协议展开。此协议包括诸如 query(_:) 之类的方法,用于执行 SQL 查询和读取结果行。
MySQLConnection 是此软件包提供的 MySQLDatabase 的默认实现。假设此处的客户端是来自先前示例的连接。
import MySQLNIO
let db: any MySQLDatabase = ...
// now we can use client to do queries
简单(文本)查询允许您在连接的 MySQL 服务器上执行 SQL 字符串。这些查询不支持绑定参数,因此任何发送的值都必须手动转义。
这些查询最适用于模式或事务查询,或简单的 selects。请注意,简单查询返回的值将以效率较低的文本格式传输。
simpleQuery 有两个重载,一个返回行数组,另一个接受一个闭包,用于处理返回的每一行。
let rows = try await db.simpleQuery("SELECT @@version").get()
print(rows) // [["@@version": "8.x.x"]]
try await db.simpleQuery("SELECT @@version") { row in
print(row) // ["@@version": "8.x.x"]
}.get()
参数化(预处理语句)查询允许您在连接的 MySQL 服务器上执行 SQL 字符串。这些查询支持将绑定参数作为单独的参数传递。每个参数在 SQL 字符串中使用占位符(?)表示。
这些查询最适用于选择、插入和更新数据。这些查询的数据使用高效的二进制格式传输。
就像 simpleQuery 一样,query 也提供两个重载。一个返回行数组,另一个接受一个闭包,用于处理返回的每一行。
let rows = try await db.query("SELECT * FROM planets WHERE name = ?", ["Earth"]).get()
print(rows) // [["id": 42, "name": "Earth"]]
try await db.query("SELECT * FROM planets WHERE name = ?", ["Earth"]) { row in
print(row) // ["id": 42, "name": "Earth"]
}.get()
simpleQuery 和 query 都返回相同的 MySQLRow 类型。可以使用 column(_:table:) 方法从行中获取列。
let row: any MySQLRow = ...
let version = row.column("name")
print(version) // MySQLData?
MySQLRow 列存储为 MySQLData。此结构体包含 MySQL 返回的原始字节以及一些用于解析它们的信息,例如
MySQLData 有多种便捷方法,用于将列数据转换为可用的 Swift 类型。
let data: MySQLData = ...
print(data.string) // String?
print(data.int) // Int?
print(data.int8) // Int8?
print(data.int16) // Int16?
print(data.int32) // Int32?
print(data.int64) // Int64?
print(data.uint) // UInt?
print(data.uint8) // UInt8?
print(data.uint16) // UInt16?
print(data.uint32) // UInt32?
print(data.uint64) // UInt64?
print(data.bool) // Bool?
try print(data.json(as: Foo.self)) // Foo?
print(data.float) // Float?
print(data.double) // Double?
print(data.date) // Date?
print(data.uuid) // UUID?
print(data.decimal) // Decimal?
print(data.time) // MySQLTime?
MySQLData 也用于通过参数化值将数据发送到服务器。要从 Swift 类型创建 MySQLData,请使用可用的初始化方法。