PostgresNIO

Documentation MIT License Continuous Integration Swift 5.8+ SSWG Incubation Level: Graduated

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

特性

API 文档

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

开始入门

对示例感兴趣?我们在 Snippets 文件夹中准备了一个简单的 Birthday example

添加依赖项

PostgresNIO 作为依赖项添加到您的 Package.swift

  dependencies: [
    .package(url: "https://github.com/vapor/postgres-nio.git", from: "1.21.0"),
    ...
  ]

PostgresNIO 添加到您想要在其中使用的目标

  targets: [
    .target(name: "MyFancyTarget", dependencies: [
      .product(name: "PostgresNIO", package: "postgres-nio"),
    ])
  ]

创建客户端

要创建一个 PostgresClient,它为您池化连接,首先创建一个配置对象

import PostgresNIO

let config = PostgresClient.Configuration(
  host: "localhost",
  port: 5432,
  username: "my_username",
  password: "my_password",
  database: "my_database",
  tls: .disable
)

接下来,您可以使用它创建客户端

let client = PostgresClient(configuration: config)

创建客户端后,您必须 run()

await withTaskGroup(of: Void.self) { taskGroup in
    taskGroup.addTask {
        await client.run() // !important
    }

    // You can use the client while the `client.run()` method is not cancelled.

    // To shutdown the client, cancel its run method, by cancelling the taskGroup.
    taskGroup.cancelAll()
}

查询

一旦客户端运行,就可以将查询发送到服务器。这很简单

let rows = try await client.query("SELECT id, username, birthday FROM users")

查询将返回一个 PostgresRowSequence,它是一个 PostgresRow 的 AsyncSequence。可以逐个迭代行

for try await row in rows {
  // do something with the row
}

从 PostgresRow 解码

但是,在大多数情况下,将行的字段请求为一组 Swift 类型要容易得多

for try await (id, username, birthday) in rows.decode((Int, String, Date).self) {
  // do something with the datatypes.
}

类型必须实现 PostgresDecodable 协议才能从行中解码。PostgresNIO 为大多数 Swift 内置类型以及 Foundation 提供的一些类型提供了默认实现

使用参数查询

也支持将参数化查询发送到数据库(以最酷的方式)

let id = 1
let username = "fancyuser"
let birthday = Date()
try await client.query("""
  INSERT INTO users (id, username, birthday) VALUES (\(id), \(username), \(birthday))
  """, 
  logger: logger
)

虽然乍一看这看起来像是 SQL 注入 😱 的经典案例,但 PostgresNIO 的 API 确保了这种用法的安全性。query(_:logger:) 方法的第一个参数不是普通的 String,而是一个 PostgresQuery,它实现了 Swift 的 ExpressibleByStringInterpolation 协议。PostgresNIO 使用提供的字符串的字面部分作为 SQL 查询,并将每个插值替换为参数绑定。只有实现了 PostgresEncodable 协议的值才能以这种方式进行插值。与 PostgresDecodable 一样,PostgresNIO 为大多数常见类型提供了默认实现。

某些查询不会从服务器接收任何行(最常见的是没有 RETURNING 子句的 INSERTUPDATEDELETE 查询,更不用说大多数 DDL 查询)。为了支持这一点,query(_:logger:) 方法被标记为 @discardableResult,这样如果未使用返回值,编译器就不会发出警告。

安全性

有关安全流程的详细信息,请参阅 SECURITY.md