MySQLNIO

Documentation Team Chat MIT License Continuous Integration Swift 5.7+


🐬 非阻塞、事件驱动的 Swift 客户端,用于 MySQL,构建于 SwiftNIO 之上。

使用 MySQLNIO

使用标准的 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 排除了一些重要的概念,例如

如果您正在寻找要在项目中使用 MySQL 客户端软件包,请查看以下构建在 MySQLNIO 之上的更高级别软件包

依赖项

此软件包有四个依赖项

此软件包没有额外的系统依赖项。

API 文档

查看 MySQLNIO API 文档 以详细了解所有类、结构体、协议等等。

入门指南

本节将快速浏览一下 MySQLNIO 的使用方法。

创建连接

进行查询的第一步是创建一个新的 MySQLConnection。创建连接的最低要求是 SocketAddressEventLoop 和凭据。

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 的方法

您还可以为 connect 提供一些额外的参数。

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()

行和数据

simpleQueryquery 都返回相同的 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,请使用可用的初始化方法。