Contents

vapor/postgres-kit

PostgresKit is an [SQLKit] driver for PostgreSQL clients.

Overview

PostgresKit supports building and serializing Postgres-dialect SQL queries using [SQLKit]'s API. PostgresKit uses [PostgresNIO] to connect and communicate with the database server asynchronously. [AsyncKit] is used to provide connection pooling.

Important: It is strongly recommended that users who leverage PostgresKit directly (e.g. absent the Fluent ORM layer) take advantage of PostgresNIO's [PostgresClient] API for connection management rather than relying upon the legacy AsyncKit API.

Usage

Reference this package in your Package.swift to include it in your project.

.package(url: "https://github.com/vapor/postgres-kit.git", from: "2.0.0")

Supported Platforms

PostgresKit supports the following platforms:

  • Ubuntu 20.04+
  • macOS 10.15+

Configuration

Database connection options and credentials are specified using a `SQLPostgresConfiguration` struct.

import PostgresKit

let configuration = SQLPostgresConfiguration(
    hostname: "localhost",
    username: "vapor_username",
    password: "vapor_password",
    database: "vapor_database"
)

URL-based configuration is also supported.

guard let configuration = SQLPostgresConfiguration(url: "postgres://...") else {
    ...
}

To connect via unix-domain sockets, use `SQLPostgresConfiguration/init(unixDomainSocketPath:username:password:database:) instead of SQLPostgresConfiguration/init(hostname:port:username:password:database:tls:)`.

let configuration = SQLPostgresConfiguration(
    unixDomainSocketPath: "/path/to/socket",
    username: "vapor_username",
    password: "vapor_password",
    database: "vapor_database"
)

Connection Pool (Modern PostgresNIO)

You don't need a `SQLPostgresConfiguration to create a PostgresClient, an instance of PostgresNIO's modern connection pool. Instead, use PostgresClient`'s native configuration type:

let configuration = PostgresClient.Configuration(
    host: "localhost",
    username: "vapor_username",
    password: "vapor_password",
    database: "vapor_database",
    tls: .prefer(.makeClientConfiguration())
)
let psqlClient = PostgresClient(configuration: configuration)

// Start a Task to run the client:
let clientTask = Task { await client.run() }
// Or, if you're using ServiceLifecycle, add the client to a ServiceGroup:
await serviceGroup.addServiceUnlessShutdown(client)

You can then lease a PostgresConnection from the client:

try await client.withConnection { conn in
    print(conn) // PostgresConnection managed by PostgresClient's connection pool
}

[!NOTE] PostgresClient.Configuration does not support URL-based configuration. If you want to handle URLs, you can create an instance of SQLPostgresConfiguration and translate it into a PostgresClient.Configuration:

extension PostgresClient.Configuration {
  init(from configuration: PostgresConnection.Configuration) {
    let tls: PostgresClient.Configuration.TLS = switch (configuration.tls.isEnforced, configuration.tls.isAllowed) {
      case (true, _): .require(configuration.tls.sslContext!.configuration)
      case (_, true): .prefer(configuration.tls.sslContext!.configuration)
      default: .disable
    }

    if let host = configuration.host, let port = configuration.port {
      self.init(host: host, port: port, username: configuration.username, password: configuration.password, database: configuration.database, tls: tls)
    } else if let socket = configuration.unixSocketPath {
      self.init(unixSocketPath: socket, username: configuration.username, password: configuration.password, database: configuration.database)
    } else {
      fatalError("Preconfigured channels not supported")
    }
  }
}

guard let sqlConfiguration = SQLPostgresConfiguration(url: "...") else { ... }
let clientConfiguration = PostgresClient.Configuration(configuration: sqlConfiguration.coreConfiguration)

Connection Pool (Legacy AsyncKit)

[!WARNING] AsyncKit is deprecated; using it is strongly discouraged. You should not use this setup unless you are also working with FluentKit, which at the time of this writing is not compatible with PostgresClient.

Once you have a `SQLPostgresConfiguration`, you can use it to create a connection source and pool.

let eventLoopGroup: EventLoopGroup = NIOSingletons.posixEventLoopGroup
let pools = EventLoopGroupConnectionPool(
    source: PostgresConnectionSource(configuration: configuration), 
    on: eventLoopGroup
)

// When you're done:
try await pools.shutdownAsync()

First create a `PostgresConnectionSource` using the configuration struct. This type is responsible for creating new connections to your database server as needed.

Next, use the connection source to create an EventLoopGroupConnectionPool. You will also need to pass an EventLoopGroup. For more information on creating an EventLoopGroup, visit [SwiftNIO's documentation]. Make sure to shutdown the connection pool before it deinitializes.

EventLoopGroupConnectionPool is a collection of pools for each event loop. When using EventLoopGroupConnectionPool directly, random event loops will be chosen as needed.

pools.withConnection { conn in
    print(conn) // PostgresConnection on randomly chosen event loop
}

To get a pool for a specific event loop, use pool(for:). This returns an EventLoopConnectionPool.

let eventLoop: EventLoop = ...
let pool = pools.pool(for: eventLoop)

pool.withConnection { conn in
    print(conn) // PostgresConnection on eventLoop
}

PostgresDatabase

Both EventLoopGroupConnectionPool and EventLoopConnectionPool can be used to create instances of PostgresDatabase.

let postgres = pool.database(logger: ...) // PostgresDatabase
let rows = try await postgres.simpleQuery("SELECT version()")

Visit [PostgresNIO's docs] for more information on using PostgresDatabase.

SQLDatabase

A PostgresDatabase can be used to create an instance of SQLDatabase.

let sql = postgres.sql() // SQLDatabase
let planets = try await sql.select().column("*").from("planets").all()

Visit [SQLKit's docs] for more information on using SQLDatabase.

[SQLKit]: https://github.com/vapor/sql-kit [SQLKit's docs]: https://api.vapor.codes/sqlkit/documentation/sqlkit [PostgresNIO]: https://github.com/vapor/postgres-nio [PostgresNIO's docs]: https://api.vapor.codes/postgresnio/documentation/postgresnio [AsyncKit]: https://github.com/vapor/async-kit [PostgresClient]: https://api.vapor.codes/postgresnio/documentation/postgresnio/postgresclient [SwiftNIO's documentation]: https://swiftpackageindex.com/apple/swift-nio/documentation/nio

Package Metadata

Repository: vapor/postgres-kit

Default branch: main

README: README.md