🐬 非阻塞、事件驱动的 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
,请使用可用的初始化方法。