Full Code of vapor/postgres-kit for AI

main 7c079553e9cd cached
28 files
121.6 KB
29.5k tokens
1 requests
Download .txt
Repository: vapor/postgres-kit
Branch: main
Commit: 7c079553e9cd
Files: 28
Total size: 121.6 KB

Directory structure:
gitextract_j417607q/

├── .github/
│   ├── CODEOWNERS
│   ├── dependabot.yml
│   └── workflows/
│       ├── api-docs.yml
│       └── test.yml
├── .gitignore
├── .spi.yml
├── LICENSE
├── Package.swift
├── README.md
├── Sources/
│   └── PostgresKit/
│       ├── ConnectionPool+Postgres.swift
│       ├── Deprecations/
│       │   ├── PostgresColumnType.swift
│       │   ├── PostgresConfiguration.swift
│       │   ├── PostgresConnectionSource+PostgresConfiguration.swift
│       │   ├── PostgresDataDecoder.swift
│       │   ├── PostgresDataEncoder.swift
│       │   └── PostgresDatabase+SQL+Deprecated.swift
│       ├── Docs.docc/
│       │   ├── PostgresKit.md
│       │   └── theme-settings.json
│       ├── Exports.swift
│       ├── PostgresConnectionSource.swift
│       ├── PostgresDataTranslation.swift
│       ├── PostgresDatabase+SQL.swift
│       ├── PostgresDialect.swift
│       ├── PostgresRow+SQL.swift
│       └── SQLPostgresConfiguration.swift
└── Tests/
    └── PostgresKitTests/
        ├── PostgresKitTests.swift
        ├── SQLPostgresConfigurationTests.swift
        └── Utilities.swift

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODEOWNERS
================================================
*                            @gwynne
/.github/CONTRIBUTING.md     @gwynne @0xTim
/.github/workflows/*.yml     @gwynne @0xTim
/.github/workflows/test.yml  @gwynne
/.spi.yml                    @gwynne @0xTim
/.gitignore                  @gwynne @0xTim
/LICENSE                     @gwynne @0xTim
/README.md                   @gwynne @0xTim


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"
    groups:
      dependencies:
        patterns:
          - "*"


================================================
FILE: .github/workflows/api-docs.yml
================================================
name: deploy-api-docs
on:
  push:
    branches:
      - main
permissions:
  contents: read
  id-token: write

jobs:
  build-and-deploy:
     uses: vapor/api-docs/.github/workflows/build-and-deploy-docs-workflow.yml@main
     secrets: inherit
     with:
       package_name: postgres-kit
       modules: PostgresKit
       pathsToInvalidate: /postgreskit/*


================================================
FILE: .github/workflows/test.yml
================================================
name: test
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
on:
  pull_request: { types: [opened, reopened, synchronize, ready_for_review] }
  push: { branches: [ main ] }
permissions:
  contents: read
env:
  LOG_LEVEL: info
  POSTGRES_HOSTNAME_A: &postgres_host_a 'psql-a'
  POSTGRES_HOSTNAME_B: &postgres_host_b 'psql-b'
  POSTGRES_HOSTNAME: *postgres_host_a
  POSTGRES_DB_A: &postgres_db_a 'test_database'
  POSTGRES_DB_B: &postgres_db_b 'test_database'
  POSTGRES_DB: *postgres_db_a
  POSTGRES_USER_A: &postgres_user_a 'test_username'
  POSTGRES_USER_B: &postgres_user_b 'test_username'
  POSTGRES_USER: *postgres_user_a
  POSTGRES_PASSWORD_A: &postgres_pass_a 'test_password'
  POSTGRES_PASSWORD_B: &postgres_pass_b 'test_password'
  POSTGRES_PASSWORD: *postgres_pass_a

jobs:
  api-breakage:
    if: ${{ github.event_name == 'pull_request' && !(github.event.pull_request.draft || false) }}
    runs-on: ubuntu-latest
    container: swift:noble
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with: { 'fetch-depth': 0 }
      - name: API breaking changes
        run: |
          git config --global --add safe.directory "${GITHUB_WORKSPACE}"
          swift package diagnose-api-breaking-changes origin/main

  linux-unit:
    if: ${{ !(github.event.pull_request.draft || false) }}
    strategy:
      fail-fast: false
      matrix:
        postgres-image:
          - postgres:18
          - postgres:16
          - postgres:14
        swift-image:
          - swift:6.0-noble
          - swift:6.1-noble
          - swift:6.2-noble
        include:
          - postgres-image: postgres:18
            postgres-auth: scram-sha-256
          - postgres-image: postgres:16
            postgres-auth: md5
          - postgres-image: postgres:14
            postgres-auth: trust
    runs-on: ubuntu-latest
    container: ${{ matrix.swift-image }}
    services:
      *postgres_host_a:
        image: ${{ matrix.postgres-image }}
        env:
          POSTGRES_USER: *postgres_user_a
          POSTGRES_DB: *postgres_db_a
          POSTGRES_PASSWORD: *postgres_pass_a
          POSTGRES_HOST_AUTH_METHOD: ${{ matrix.postgres-auth }}
          POSTGRES_INITDB_ARGS: --auth-host=${{ matrix.postgres-auth }}
    steps:
      - name: Install curl
        run: apt-get update -y -q && apt-get install -y curl
      - name: Check out package
        uses: actions/checkout@v6
      - name: Run local tests
        run: swift test --enable-code-coverage --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable
      - name: Upload coverage data
        uses: vapor/swift-codecov-action@v0.3
        with:
          codecov_token: ${{ secrets.CODECOV_TOKEN || '' }}

  linux-integration:
    if: ${{ !(github.event.pull_request.draft || false) }}
    runs-on: ubuntu-latest
    container: swift:6.2-noble
    services:
      *postgres_host_a:
        image: postgres:18
        env:
          POSTGRES_USER: *postgres_user_a
          POSTGRES_DB: *postgres_db_a
          POSTGRES_PASSWORD: *postgres_pass_a
          POSTGRES_HOST_AUTH_METHOD: scram-sha-256
          POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256
      *postgres_host_b:
        image: postgres:16
        env:
          POSTGRES_USER: *postgres_user_b
          POSTGRES_DB: *postgres_db_b
          POSTGRES_PASSWORD: *postgres_pass_b
          POSTGRES_HOST_AUTH_METHOD: scram-sha-256
          POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256
    steps:
      - name: Check out package
        uses: actions/checkout@v6
        with: { path: 'postgres-kit' }
      - name: Check out fluent-postgres-driver dependent
        uses: actions/checkout@v6
        with: { repository: 'vapor/fluent-postgres-driver', path: 'fluent-postgres-driver' }
      - name: Use local package
        run: swift package --package-path fluent-postgres-driver edit postgres-kit --path postgres-kit
      - name: Run fluent-postgres-kit tests
        run: swift test --package-path fluent-postgres-driver

  macos-unit:
    if: ${{ !(github.event.pull_request.draft || false) }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - macos-version: macos-15
            xcode-version: latest-stable
          - macos-version: macos-26
            xcode-version: latest-stable
    runs-on: ${{ matrix.macos-version }}
    env:
      POSTGRES_HOSTNAME: 127.0.0.1
      POSTGRES_DB: postgres
    steps:
      - name: Select latest available Xcode
        uses: maxim-lobanov/setup-xcode@v1
        with:
          xcode-version: ${{ matrix.xcode-version }}
      - name: Install Postgres, setup DB and auth, and wait for server start
        run: |
          brew upgrade || true
          export PGDATA=/tmp/vapor-postgres-test
          brew install "postgresql@18" && brew link --force "postgresql@18"
          initdb --locale=C --auth-host "scram-sha-256" -U "${POSTGRES_USER}" --pwfile=<(echo "${POSTGRES_PASSWORD}")
          pg_ctl start --wait
        timeout-minutes: 15
      - name: Checkout code
        uses: actions/checkout@v6
      - name: Run local tests
        run: swift test --enable-code-coverage --explicit-target-dependency-import-check error -Xswiftc -require-explicit-sendable
      - name: Upload coverage data
        uses: vapor/swift-codecov-action@v0.3
        with:
          codecov_token: ${{ secrets.CODECOV_TOKEN || '' }}

  musl:
    runs-on: ubuntu-latest
    container: swift:6.2-noble
    timeout-minutes: 30
    steps:
      - name: Check out code
        uses: actions/checkout@v6
      - name: Install SDK
        run: swift sdk install https://download.swift.org/swift-6.2.3-release/static-sdk/swift-6.2.3-RELEASE/swift-6.2.3-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum f30ec724d824ef43b5546e02ca06a8682dafab4b26a99fbb0e858c347e507a2c
      - name: Build
        run: swift build --swift-sdk x86_64-swift-linux-musl


================================================
FILE: .gitignore
================================================
.DS_Store
/.build
/Packages
/*.xcodeproj
Package.resolved
DerivedData
.swiftpm
Tests/LinuxMain.swift


================================================
FILE: .spi.yml
================================================
version: 1
metadata:
  authors: "Maintained by the Vapor Core Team with hundreds of contributions from the Vapor Community."
external_links:
  documentation: "https://api.vapor.codes/postgreskit/documentation/postgreskit/"


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2018 Qutheory, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Package.swift
================================================
// swift-tools-version:6.0
import PackageDescription

let package = Package(
    name: "postgres-kit",
    platforms: [
        .macOS(.v10_15),
        .iOS(.v13),
        .watchOS(.v6),
        .tvOS(.v13),
    ],
    products: [
        .library(name: "PostgresKit", targets: ["PostgresKit"]),
    ],
    dependencies: [
        .package(url: "https://github.com/vapor/postgres-nio.git", from: "1.27.0"),
        .package(url: "https://github.com/vapor/sql-kit.git", from: "3.33.2"),
        .package(url: "https://github.com/vapor/async-kit.git", from: "1.21.0"),
    ],
    targets: [
        .target(
            name: "PostgresKit",
            dependencies: [
                .product(name: "AsyncKit", package: "async-kit"),
                .product(name: "PostgresNIO", package: "postgres-nio"),
                .product(name: "SQLKit", package: "sql-kit"),
            ],
            swiftSettings: swiftSettings
        ),
        .testTarget(
            name: "PostgresKitTests",
            dependencies: [
                .target(name: "PostgresKit"),
                .product(name: "SQLKitBenchmark", package: "sql-kit"),
            ],
            swiftSettings: swiftSettings
        ),
    ]
)

var swiftSettings: [SwiftSetting] { [
    .enableUpcomingFeature("ExistentialAny"),
    //.enableUpcomingFeature("InternalImportsByDefault"),
    .enableUpcomingFeature("MemberImportVisibility"),
    .enableUpcomingFeature("InferIsolatedConformances"),
    //.enableUpcomingFeature("NonisolatedNonsendingByDefault"),
    .enableUpcomingFeature("ImmutableWeakCaptures"),
] }


================================================
FILE: README.md
================================================
<p align="center">
<img src="https://design.vapor.codes/images/vapor-postgreskit.svg" height="96" alt="PostgresKit">
<br>
<br>
<a href="https://docs.vapor.codes/4.0/"><img src="https://design.vapor.codes/images/readthedocs.svg" alt="Documentation"></a>
<a href="https://discord.gg/vapor"><img src="https://design.vapor.codes/images/discordchat.svg" alt="Team Chat"></a>
<a href="LICENSE"><img src="https://design.vapor.codes/images/mitlicense.svg" alt="MIT License"></a>
<a href="https://github.com/vapor/postgres-kit/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/vapor/postgres-kit/test.yml?event=push&style=plastic&logo=github&label=tests&logoColor=%23ccc" alt="Continuous Integration"></a>
<a href="https://codecov.io/github/vapor/postgres-kit"><img src="https://img.shields.io/codecov/c/github/vapor/postgres-kit?style=plastic&logo=codecov&label=codecov" alt="Code Coverage"></a>
<a href="https://swift.org"><img src="https://design.vapor.codes/images/swift60up.svg" alt="Swift 6.0+"></a>
</p>

<br>

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.

```swift
.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. 

```swift
import PostgresKit

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

URL-based configuration is also supported.

```swift
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:)``.

```swift
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:

```swift
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:

```swift
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`:
> 
> ```swift
> 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.

```swift
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.

```swift
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`. 

```swift
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`.

```swift
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`.

```swift
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


================================================
FILE: Sources/PostgresKit/ConnectionPool+Postgres.swift
================================================
@preconcurrency import AsyncKit
import Logging
import NIOCore
import PostgresNIO

extension EventLoopGroupConnectionPool where Source == PostgresConnectionSource {
    public func database(logger: Logger) -> any PostgresDatabase {
        _EventLoopGroupConnectionPoolPostgresDatabase(pool: self, logger: logger)
    }
}

extension EventLoopConnectionPool where Source == PostgresConnectionSource {
    public func database(logger: Logger) -> any PostgresDatabase {
        _EventLoopConnectionPoolPostgresDatabase(pool: self, logger: logger)
    }
}

private struct _EventLoopGroupConnectionPoolPostgresDatabase: PostgresDatabase {
    let pool: EventLoopGroupConnectionPool<PostgresConnectionSource>
    let logger: Logger

    var eventLoop: any EventLoop {
        self.pool.eventLoopGroup.any()
    }

    func send(_ request: any PostgresRequest, logger: Logger) -> EventLoopFuture<Void> {
        self.pool.withConnection(logger: logger) { $0.send(request, logger: logger) }
    }

    func withConnection<T>(_ closure: @escaping (PostgresConnection) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
        self.pool.withConnection(logger: self.logger, closure)
    }
}

private struct _EventLoopConnectionPoolPostgresDatabase: PostgresDatabase {
    let pool: EventLoopConnectionPool<PostgresConnectionSource>
    let logger: Logger

    var eventLoop: any EventLoop {
        self.pool.eventLoop
    }

    func send(_ request: any PostgresRequest, logger: Logger) -> EventLoopFuture<Void> {
        self.pool.withConnection(logger: logger) { $0.send(request, logger: logger) }
    }

    func withConnection<T>(_ closure: @escaping (PostgresConnection) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
        self.pool.withConnection(logger: self.logger, closure)
    }
}


================================================
FILE: Sources/PostgresKit/Deprecations/PostgresColumnType.swift
================================================
import SQLKit

/// Postgres-specific column types.
@available(*, deprecated, message: "Use `PostgresDataType` instead.")
public struct PostgresColumnType: SQLExpression, Hashable {
    public static var blob: PostgresColumnType { .varbit }

    /// signed eight-byte integer
    public static var int8: PostgresColumnType { .bigint }

    /// signed eight-byte integer
    public static var bigint: PostgresColumnType { .init(.bigint) }

    /// autoincrementing eight-byte integer
    public static var serial8: PostgresColumnType { .bigserial }

    /// autoincrementing eight-byte integer
    public static var bigserial: PostgresColumnType { .init(.bigserial) }

    /// fixed-length bit string
    public static var bit: PostgresColumnType { .init(.bit(nil)) }

    /// fixed-length bit string
    public static func bit(_ n: Int) -> PostgresColumnType { .init(.bit(n)) }

    /// variable-length bit string
    public static var varbit: PostgresColumnType { .init(.varbit(nil)) }

    /// variable-length bit string
    public static func varbit(_ n: Int) -> PostgresColumnType { .init(.varbit(n)) }

    /// logical Boolean (true/false)
    public static var bool: PostgresColumnType { .boolean }

    /// logical Boolean (true/false)
    public static var boolean: PostgresColumnType { .init(.boolean) }

    /// rectangular box on a plane
    public static var box: PostgresColumnType { .init(.box) }

    /// binary data (“byte array”)
    public static var bytea: PostgresColumnType { .init(.bytea) }

    /// fixed-length character string
    public static var char: PostgresColumnType { .init(.char(nil)) }

    /// fixed-length character string
    public static func char(_ n: Int) -> PostgresColumnType { .init(.char(n)) }

    /// variable-length character string
    public static var varchar: PostgresColumnType { .init(.varchar(nil)) }

    /// variable-length character string
    public static func varchar(_ n: Int) -> PostgresColumnType { .init(.varchar(n)) }

    /// IPv4 or IPv6 network address
    public static var cidr: PostgresColumnType { .init(.cidr) }

    /// circle on a plane
    public static var circle: PostgresColumnType { .init(.circle) }

    /// calendar date (year, month, day)
    public static var date: PostgresColumnType { .init(.date) }

    /// floating-point number (8 bytes)
    public static var float8: PostgresColumnType { .doublePrecision }

    /// floating-point number (8 bytes)
    public static var doublePrecision: PostgresColumnType { .init(.doublePrecision) }

    /// IPv4 or IPv6 host address
    public static var inet: PostgresColumnType { .init(.inet) }

    /// signed four-byte integer
    public static var int: PostgresColumnType { .integer }

    /// signed four-byte integer
    public static var int4: PostgresColumnType { .integer }

    /// signed four-byte integer
    public static var integer: PostgresColumnType { .init(.integer) }

    /// time span
    public static var interval: PostgresColumnType { .init(.interval) }

    /// textual JSON data
    public static var json: PostgresColumnType { .init(.json) }

    /// binary JSON data, decomposed
    public static var jsonb: PostgresColumnType { .init(.jsonb) }

    /// infinite line on a plane
    public static var line: PostgresColumnType { .init(.line) }

    /// line segment on a plane
    public static var lseg: PostgresColumnType { .init(.lseg) }

    /// MAC (Media Access Control) address
    public static var macaddr: PostgresColumnType { .init(.macaddr) }

    /// MAC (Media Access Control) address (EUI-64 format)
    public static var macaddr8: PostgresColumnType { .init(.macaddr8) }

    /// currency amount
    public static var money: PostgresColumnType { .init(.money) }

    /// exact numeric of selectable precision
    public static var decimal: PostgresColumnType { .init(.numeric(nil, nil)) }

    /// exact numeric of selectable precision
    public static func decimal(_ p: Int, _ s: Int) -> PostgresColumnType { .init(.numeric(p, s)) }

    /// exact numeric of selectable precision
    public static func numeric(_ p: Int, _ s: Int) -> PostgresColumnType { .init(.numeric(p, s)) }

    /// exact numeric of selectable precision
    public static var numeric: PostgresColumnType { .init(.numeric(nil, nil)) }

    /// geometric path on a plane
    public static var path: PostgresColumnType { .init(.path) }

    /// PostgreSQL Log Sequence Number
    public static var pgLSN: PostgresColumnType { .init(.pgLSN) }

    /// geometric point on a plane
    public static var point: PostgresColumnType { .init(.point) }

    /// closed geometric path on a plane
    public static var polygon: PostgresColumnType { .init(.polygon) }

    /// single precision floating-point number (4 bytes)
    public static var float4: PostgresColumnType { .real }

    /// single precision floating-point number (4 bytes)
    public static var real: PostgresColumnType { .init(.real) }

    /// signed two-byte integer
    public static var int2: PostgresColumnType { .smallint }

    /// signed two-byte integer
    public static var smallint: PostgresColumnType { .init(.smallint) }

    /// autoincrementing two-byte integer
    public static var serial2: PostgresColumnType { .smallserial }

    /// autoincrementing two-byte integer
    public static var smallserial: PostgresColumnType { .init(.smallserial) }

    /// autoincrementing four-byte integer
    public static var serial4: PostgresColumnType { .serial }

    /// autoincrementing four-byte integer
    public static var serial: PostgresColumnType { .init(.serial) }

    /// variable-length character string
    public static var text: PostgresColumnType { .init(.text) }

    /// time of day (no time zone)
    public static var time: PostgresColumnType { .init(.time(nil)) }

    /// time of day (no time zone)
    public static func time(_ n: Int) -> PostgresColumnType { .init(.time(n)) }

    /// time of day, including time zone
    public static var timetz: PostgresColumnType { .init(.timetz(nil)) }

    /// time of day, including time zone
    public static func timetz(_ n: Int) -> PostgresColumnType { .init(.timetz(n)) }

    /// date and time (no time zone)
    public static var timestamp: PostgresColumnType { .init(.timestamp(nil)) }

    /// date and time (no time zone)
    public static func timestamp(_ n: Int) -> PostgresColumnType { .init(.timestamp(n)) }

    /// date and time, including time zone
    public static var timestamptz: PostgresColumnType { .init(.timestamptz(nil)) }

    /// date and time, including time zone
    public static func timestamptz(_ n: Int) -> PostgresColumnType { .init(.timestamptz(n)) }

    /// text search query
    public static var tsquery: PostgresColumnType { .init(.tsquery) }

    /// text search document
    public static var tsvector: PostgresColumnType { .init(.tsvector) }

    /// user-level transaction ID snapshot
    public static var txidSnapshot: PostgresColumnType { .init(.txidSnapshot) }

    /// universally unique identifier
    public static var uuid: PostgresColumnType { .init(.uuid) }

    /// XML data
    public static var xml: PostgresColumnType { .init(.xml) }

    /// User-defined type
    public static func custom(_ name: String) -> PostgresColumnType { .init(.custom(name)) }

    /// Creates an array type from a `PostgreSQLDataType`.
    public static func array(_ type: PostgresColumnType) -> PostgresColumnType { .init(.array(of: type.primitive)) }

    private let primitive: Primitive
    private init(_ primitive: Primitive) { self.primitive = primitive }

    enum Primitive: CustomStringConvertible, Hashable, Sendable {
        case bigint /// signed eight-byte integer
        case bigserial /// autoincrementing eight-byte integer
        case bit(Int?) /// fixed-length bit string
        case varbit(Int?) /// variable-length bit string
        case boolean /// logical Boolean (true/false)
        case box /// rectangular box on a plane
        case bytea /// binary data (“byte array”)
        case char(Int?) /// fixed-length character string
        case varchar(Int?) /// variable-length character string
        case cidr /// IPv4 or IPv6 network address
        case circle /// circle on a plane
        case date /// calendar date (year, month, day)
        case doublePrecision /// floating-point number (8 bytes)
        case inet /// IPv4 or IPv6 host address
        case integer /// signed four-byte integer
        case interval /// time span
        case json /// textual JSON data
        case jsonb /// binary JSON data, decomposed
        case line /// infinite line on a plane
        case lseg /// line segment on a plane
        case macaddr /// MAC (Media Access Control) address
        case macaddr8 /// MAC (Media Access Control) address (EUI-64 format)
        case money /// currency amount
        case numeric(Int?, Int?) /// exact numeric of selectable precision
        case path /// geometric path on a plane
        case pgLSN /// PostgreSQL Log Sequence Number
        case point /// geometric point on a plane
        case polygon /// closed geometric path on a plane
        case real /// single precision floating-point number (4 bytes)
        case smallint /// signed two-byte integer
        case smallserial /// autoincrementing two-byte integer
        case serial /// autoincrementing four-byte integer
        case text /// variable-length character string
        case time(Int?) /// time of day (no time zone)
        case timetz(Int?) /// time of day, including time zone
        case timestamp(Int?) /// date and time (no time zone)
        case timestamptz(Int?) /// date and time, including time zone
        case tsquery /// text search query
        case tsvector /// text search document
        case txidSnapshot /// user-level transaction ID snapshot
        case uuid /// universally unique identifier
        case xml /// XML data
        case custom(String) /// User-defined type
        indirect case array(of: Primitive) /// Array

        /// See `CustomStringConvertible.description`.
        var description: String {
            switch self {
            case .bigint: return "BIGINT"
            case .bigserial: return "BIGSERIAL"
            case .varbit(let n): return n.map { "VARBIT(\($0))" } ?? "VARBIT"
            case .varchar(let n): return n.map { "VARCHAR(\($0))" } ?? "VARCHAR"
            case .bit(let n): return n.map { "BIT(\($0))" } ?? "BIT"
            case .boolean: return "BOOLEAN"
            case .box: return "BOX"
            case .bytea: return "BYTEA"
            case .char(let n): return n.map { "CHAR(\($0))" } ?? "CHAR"
            case .cidr: return "CIDR"
            case .circle: return "CIRCLE"
            case .date: return "DATE"
            case .doublePrecision: return "DOUBLE PRECISION"
            case .inet: return "INET"
            case .integer: return "INTEGER"
            case .interval: return "INTERVAL"
            case .json: return "JSON"
            case .jsonb: return "JSONB"
            case .line: return "LINE"
            case .lseg: return "LSEG"
            case .macaddr: return "MACADDR"
            case .macaddr8: return "MACADDER8"
            case .money: return "MONEY"
            case .numeric(let s, let p): return strictMap(s, p) { "NUMERIC(\($0), \($1))" } ?? "NUMERIC"
            case .path: return "PATH"
            case .pgLSN: return "PG_LSN"
            case .point: return "POINT"
            case .polygon: return "POLYGON"
            case .real: return "REAL"
            case .smallint: return "SMALLINT"
            case .smallserial: return "SMALLSERIAL"
            case .serial: return "SERIAL"
            case .text: return "TEXT"
            case .time(let p): return p.map { "TIME(\($0))" } ?? "TIME"
            case .timetz(let p): return p.map { "TIMETZ(\($0))" } ?? "TIMETZ"
            case .timestamp(let p): return p.map { "TIMESTAMP(\($0))" } ?? "TIMESTAMP"
            case .timestamptz(let p):  return p.map { "TIMESTAMPTZ(\($0))" } ?? "TIMESTAMPTZ"
            case .tsquery: return "TSQUERY"
            case .tsvector: return "TSVECTOR"
            case .txidSnapshot: return "TXID_SNAPSHOT"
            case .uuid: return "UUID"
            case .xml: return "XML"
            case .custom(let custom): return custom
            case .array(let element): return "\(element)[]"
            }
        }
    }

    // See `SQLExpression.serialize(to:)`.
    public func serialize(to serializer: inout SQLSerializer) {
        serializer.write(self.primitive.description)
    }
}


================================================
FILE: Sources/PostgresKit/Deprecations/PostgresConfiguration.swift
================================================
import Foundation
import NIOCore
import NIOSSL

@available(*, deprecated, message: "Use `SQLPostgresConfiguration` instead.")
public struct PostgresConfiguration {
    public var address: () throws -> SocketAddress
    public var username: String
    public var password: String?
    public var database: String?
    public var tlsConfiguration: TLSConfiguration?

    /// Require connection to provide `BackendKeyData`.
    /// For use with Amazon RDS Proxy, this must be set to false.
    ///
    /// - Default: true
    public var requireBackendKeyData: Bool = true

    /// Optional `search_path` to set on new connections.
    public var searchPath: [String]?

    /// IANA-assigned port number for PostgreSQL
    /// `UInt16(getservbyname("postgresql", "tcp").pointee.s_port).byteSwapped`
    public static var ianaPortNumber: Int { 5432 }

    internal var _hostname: String?
    internal var _port: Int?

    public init?(url: String) {
        guard let url = URL(string: url) else {
            return nil
        }
        self.init(url: url)
    }
    
    public init?(url: URL) {
        guard let comp = URLComponents(url: url, resolvingAgainstBaseURL: true),
              comp.scheme?.hasPrefix("postgres") ?? false,
              let hostname = comp.host, let username = comp.user
        else {
            return nil
        }
        let password = comp.password, port = comp.port ?? Self.ianaPortNumber
        let wantTLS = (comp.queryItems ?? []).contains { ["ssl=true", "sslmode=require"].contains($0.description) }
        
        self.init(
            hostname: hostname,
            port: port,
            username: username,
            password: password,
            database: url.lastPathComponent,
            tlsConfiguration: wantTLS ? .makeClientConfiguration() : nil
        )
    }

    public init(
        unixDomainSocketPath: String,
        username: String,
        password: String? = nil,
        database: String? = nil
    ) {
        self.address = {
            return try SocketAddress.init(unixDomainSocketPath: unixDomainSocketPath)
        }
        self.username = username
        self.password = password
        self.database = database
        self.tlsConfiguration = nil
        self._hostname = nil
        self._port = nil
    }
    
    public init(
        hostname: String,
        port: Int = Self.ianaPortNumber,
        username: String,
        password: String? = nil,
        database: String? = nil,
        tlsConfiguration: TLSConfiguration? = nil
    ) {
        self.address = {
            return try SocketAddress.makeAddressResolvingHost(hostname, port: port)
        }
        self.username = username
        self.database = database
        self.password = password
        self.tlsConfiguration = tlsConfiguration
        self._hostname = hostname
        self._port = port
    }
}


================================================
FILE: Sources/PostgresKit/Deprecations/PostgresConnectionSource+PostgresConfiguration.swift
================================================
import Atomics
import Logging
import NIOCore
import NIOSSL
import PostgresNIO

extension PostgresConnectionSource {
    @available(*, deprecated, message: "Use `sqlConfiguration` instead.")
    public var configuration: PostgresConfiguration {
        if let hostname = self.sqlConfiguration.coreConfiguration.host,
           let port = self.sqlConfiguration.coreConfiguration.port
        {
            var oldConfig = PostgresConfiguration(
                hostname: hostname, port: port,
                username: self.sqlConfiguration.coreConfiguration.username, password: self.sqlConfiguration.coreConfiguration.password,
                database: self.sqlConfiguration.coreConfiguration.database,
                tlsConfiguration: self.sqlConfiguration.coreConfiguration.tls.sslContext.map { _ in .makeClientConfiguration() }
            )
            oldConfig.requireBackendKeyData = self.sqlConfiguration.coreConfiguration.options.requireBackendKeyData
            oldConfig.searchPath = self.sqlConfiguration.searchPath
            return oldConfig
        } else if let socketPath = self.sqlConfiguration.coreConfiguration.unixSocketPath {
            var oldConfig = PostgresConfiguration(
                unixDomainSocketPath: socketPath,
                username: self.sqlConfiguration.coreConfiguration.username, password: self.sqlConfiguration.coreConfiguration.password,
                database: self.sqlConfiguration.coreConfiguration.database
            )
            oldConfig.requireBackendKeyData = self.sqlConfiguration.coreConfiguration.options.requireBackendKeyData
            oldConfig.searchPath = self.sqlConfiguration.searchPath
            return oldConfig
        } else {
            return .init(hostname: "<invalid>", port: 0, username: "", password: nil, database: nil, tlsConfiguration: nil)
        }
    }
    
    @available(*, deprecated, message: "Use `sqlConfiguration` instead.")
    public var sslContext: Result<NIOSSLContext?, any Error> { .success(self.sqlConfiguration.coreConfiguration.tls.sslContext) }
    
    @available(*, deprecated, message: "Use `init(sqlConfiguration:)` instead.")
    public init(configuration: PostgresConfiguration) {
        self.init(sqlConfiguration: .init(legacyConfiguration: configuration))
    }
}

extension SQLPostgresConfiguration {
    // N.B.: This is public only for the sake of deprecated support in FluentPostgresDriver. Don't use it.
    @available(*, deprecated, message: "This initializer is not intended for public use. Stop using `PostgresConfigration`.")
    public init(legacyConfiguration configuration: PostgresConfiguration) {
        if let hostname = configuration._hostname, let port = configuration._port {
            self.init(
                hostname: hostname, port: port,
                username: configuration.username, password: configuration.password,
                database: configuration.database,
                tls: configuration.tlsConfiguration.flatMap { try? .require(.init(configuration: $0)) } ?? .disable
            )
            self.coreConfiguration.options.requireBackendKeyData = configuration.requireBackendKeyData
            self.searchPath = configuration.searchPath
        } else if let address = try? configuration.address(), let socketPath = address.pathname {
            self.init(
                unixDomainSocketPath: socketPath,
                username: configuration.username, password: configuration.password,
                database: configuration.database
            )
            self.coreConfiguration.options.requireBackendKeyData = configuration.requireBackendKeyData
            self.searchPath = configuration.searchPath
        } else {
            fatalError("Nonsensical legacy configuration format")
        }
    }
}


================================================
FILE: Sources/PostgresKit/Deprecations/PostgresDataDecoder.swift
================================================
import Foundation
import PostgresNIO

@available(*, deprecated, message: "Use `PostgresDecodingContext` instead.")
public final class PostgresDataDecoder {
    public let json: any PostgresJSONDecoder

    public init(json: any PostgresJSONDecoder = PostgresNIO._defaultJSONDecoder) {
        self.json = json
    }

    public func decode<T>(_: T.Type, from data: PostgresData) throws -> T
        where T: Decodable
    {
        // If `T` can be converted directly, just do so.
        if let convertible = T.self as? any PostgresDataConvertible.Type {
            guard let value = convertible.init(postgresData: data) else {
                throw DecodingError.typeMismatch(T.self, .init(
                    codingPath: [],
                    debugDescription: "Could not convert PostgreSQL data to \(T.self): \(data as Any)"
                ))
            }
            return value as! T
        } else {
            // Probably a Postgres array, JSON array/object, or enum type not using @Enum. See if it can be "unwrapped"
            // as a single-value decoding container, since this is much faster than attempting a JSON decode, or as an
            // array in the Postgres-native sense; this will handle "box" types such as `RawRepresentable` enums while
            // still allowing falling back to JSON.
            do {
                return try T.init(from: GiftBoxUnwrapDecoder(decoder: self, data: data))
            } catch DecodingError.dataCorrupted {
                // Couldn't unwrap it either. Fall back to attempting a JSON decode.
                guard let jsonData = data.jsonb ?? data.json else {
                    throw Error.unexpectedDataType(data.type, expected: "jsonb/json")
                }
                return try self.json.decode(T.self, from: jsonData)
            }
        }
    }

    enum Error: Swift.Error, CustomStringConvertible {
        case unexpectedDataType(PostgresDataType, expected: String)
        case nestingNotSupported

        var description: String {
            switch self {
            case .unexpectedDataType(let type, let expected):
                return "Unexpected data type: \(type). Expected \(expected)."
            case .nestingNotSupported:
                return "Decoding nested containers is not supported."
            }
        }
    }

    private final class GiftBoxUnwrapDecoder: Decoder, SingleValueDecodingContainer {
        var codingPath: [any CodingKey] { [] }
        var userInfo: [CodingUserInfoKey : Any] { [:] }

        let dataDecoder: PostgresDataDecoder
        let data: PostgresData

        init(decoder: PostgresDataDecoder, data: PostgresData) {
            self.dataDecoder = decoder
            self.data = data
        }
        
        func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key: CodingKey {
            throw DecodingError.dataCorruptedError(in: self, debugDescription: "Dictionary containers must be JSON-encoded")
        }

        func unkeyedContainer() throws -> any UnkeyedDecodingContainer {
            guard let array = self.data.array else {
                throw DecodingError.dataCorruptedError(in: self, debugDescription: "Non-natively typed arrays must be JSON-encoded")
            }
            return ArrayContainer(data: array, dataDecoder: self.dataDecoder)
        }
        
        struct ArrayContainer: UnkeyedDecodingContainer {
            let data: [PostgresData]
            let dataDecoder: PostgresDataDecoder
            var codingPath: [any CodingKey] { [] }
            var count: Int? { self.data.count }
            var isAtEnd: Bool { self.currentIndex >= self.data.count }
            var currentIndex: Int = 0
            
            mutating func decodeNil() throws -> Bool {
                // Do _not_ shorten this using `defer`, otherwise `currentIndex` is incorrectly incremented.
                if self.data[self.currentIndex].value == nil {
                    self.currentIndex += 1
                    return true
                }
                return false
            }
            
            mutating func decode<T>(_: T.Type) throws -> T where T: Decodable {
                // Do _not_ shorten this using `defer`, otherwise `currentIndex` is incorrectly incremented.
                let result = try self.dataDecoder.decode(T.self, from: self.data[self.currentIndex])
                self.currentIndex += 1
                return result
            }
            
            mutating func nestedContainer<NewKey: CodingKey>(keyedBy _: NewKey.Type) throws -> KeyedDecodingContainer<NewKey> {
                throw DecodingError.dataCorruptedError(in: self, debugDescription: "Data nesting is not supported")
            }
            
            mutating func nestedUnkeyedContainer() throws -> any UnkeyedDecodingContainer {
                throw DecodingError.dataCorruptedError(in: self, debugDescription: "Data nesting is not supported")
            }
            
            mutating func superDecoder() throws -> any Decoder {
                throw DecodingError.dataCorruptedError(in: self, debugDescription: "Data nesting is not supported")
            }
        }
        
        func singleValueContainer() throws -> any SingleValueDecodingContainer {
            return self
        }
        
        func decodeNil() -> Bool {
            self.data.value == nil
        }

        func decode<T>(_: T.Type) throws -> T where T: Decodable {
            // Recurse back into the data decoder, don't repeat its logic here.
            return try self.dataDecoder.decode(T.self, from: self.data)
        }
    }

    @available(*, deprecated, renamed: "json")
    public var jsonDecoder: JSONDecoder {
        return self.json as! JSONDecoder
    }
}


================================================
FILE: Sources/PostgresKit/Deprecations/PostgresDataEncoder.swift
================================================
import Foundation
import PostgresNIO

@available(*, deprecated, message: "Use `PostgresJSONEncoder` and `PostgresEncodable` instead.")
public final class PostgresDataEncoder {
    public let json: any PostgresJSONEncoder

    public init(json: any PostgresJSONEncoder = PostgresNIO._defaultJSONEncoder) {
        self.json = json
    }

    public func encode(_ value: any Encodable) throws -> PostgresData {
        if let custom = value as? any PostgresDataConvertible, let data = custom.postgresData {
            return data
        } else {
            let encoder = _Encoder(parent: self)
            do {
                try value.encode(to: encoder)
                switch encoder.value {
                case .invalid: throw _Encoder.AssociativeValueSentinel() // this is usually "nothing was encoded at all", not an associative value, but the desired action is the same
                case .scalar(let scalar): return scalar
                case .indexed(let indexed):
                    let elementType = indexed.contents.first?.type ?? .jsonb
                    assert(indexed.contents.allSatisfy { $0.type == elementType }, "Type \(type(of: value)) was encoded as a heterogenous array; this is unsupported.")
                    return PostgresData(array: indexed.contents, elementType: elementType)
                }
            } catch is _Encoder.AssociativeValueSentinel {
                return try PostgresData(jsonb: self.json.encode(value))
            }
        }
    }

    private final class _Encoder: Encoder {
        struct AssociativeValueSentinel: Error {}
        enum Value {
            final class RefArray<T> { var contents: [T] = [] }
            case invalid, indexed(RefArray<PostgresData>), scalar(PostgresData)
            
            var isValid: Bool { if case .invalid = self { return false }; return true }
            mutating func requestIndexed(for encoder: _Encoder) {
                switch self {
                case .scalar(_): preconditionFailure("Invalid request for both single-value and unkeyed containers from the same encoder.")
                case .invalid: self = .indexed(.init()) // no existing value, make new array
                case .indexed(_): break // existing array, adopt it for appending (support for superEncoder())
                }
            }
            mutating func storeScalar(_ scalar: PostgresData) {
                switch self {
                case .indexed(_), .scalar(_): preconditionFailure("Invalid request for multiple containers from the same encoder.")
                case .invalid: self = .scalar(scalar) // no existing value, store the incoming
                }
            }
            var indexedCount: Int {
                switch self {
                case .invalid, .scalar(_): preconditionFailure("Internal error in encoder (requested indexed count from non-indexed state)")
                case .indexed(let ref): return ref.contents.count
                }
            }
            mutating func addToIndexed(_ scalar: PostgresData) {
                switch self {
                case .invalid, .scalar(_): preconditionFailure("Internal error in encoder (attempted store to indexed in non-indexed state)")
                case .indexed(let ref): ref.contents.append(scalar)
                }
            }
        }
        
        var userInfo: [CodingUserInfoKey : Any] { [:] }; var codingPath: [any CodingKey] { [] }
        var parent: PostgresDataEncoder, value: Value
        
        init(parent: PostgresDataEncoder, value: Value = .invalid) { (self.parent, self.value) = (parent, value) }
        func container<K: CodingKey>(keyedBy: K.Type) -> KeyedEncodingContainer<K> {
            precondition(!self.value.isValid, "Requested multiple containers from the same encoder.")
            return .init(_FailingKeyedContainer())
        }
        func unkeyedContainer() -> any UnkeyedEncodingContainer {
            self.value.requestIndexed(for: self)
            return _UnkeyedValueContainer(encoder: self)
        }
        func singleValueContainer() -> any SingleValueEncodingContainer {
            precondition(!self.value.isValid, "Requested multiple containers from the same encoder.")
            return _SingleValueContainer(encoder: self)
        }
        
        struct _UnkeyedValueContainer: UnkeyedEncodingContainer {
            let encoder: _Encoder; var codingPath: [any CodingKey] { self.encoder.codingPath }
            var count: Int { self.encoder.value.indexedCount }
            mutating func encodeNil() throws { self.encoder.value.addToIndexed(.null) }
            mutating func encode<T: Encodable>(_ value: T) throws { self.encoder.value.addToIndexed(try self.encoder.parent.encode(value)) }
            mutating func nestedContainer<K: CodingKey>(keyedBy: K.Type) -> KeyedEncodingContainer<K> { self.superEncoder().container(keyedBy: K.self) }
            mutating func nestedUnkeyedContainer() -> any UnkeyedEncodingContainer { self.superEncoder().unkeyedContainer() }
            mutating func superEncoder() -> any Encoder { _Encoder(parent: self.encoder.parent, value: self.encoder.value) } // NOT the same as self.encoder
        }

        struct _SingleValueContainer: SingleValueEncodingContainer {
            let encoder: _Encoder; var codingPath: [any CodingKey] { self.encoder.codingPath }
            func encodeNil() throws { self.encoder.value.storeScalar(.null) }
            func encode<T: Encodable>(_ value: T) throws { self.encoder.value.storeScalar(try self.encoder.parent.encode(value)) }
        }
        
        /// This pair of types is only necessary because we can't directly throw an error from various Encoder and
        /// encoding container methods. We define duplicate types rather than the old implementation's use of a
        /// no-action keyed container because it can save a significant amount of time otherwise spent uselessly calling
        /// nested methods in some cases.
        struct _TaintedEncoder: Encoder, UnkeyedEncodingContainer, SingleValueEncodingContainer {
            var userInfo: [CodingUserInfoKey : Any] { [:] }; var codingPath: [any CodingKey] { [] }; var count: Int { 0 }
            func container<K: CodingKey>(keyedBy: K.Type) -> KeyedEncodingContainer<K> { .init(_FailingKeyedContainer()) }
            func nestedContainer<K: CodingKey>(keyedBy: K.Type) -> KeyedEncodingContainer<K> { .init(_FailingKeyedContainer()) }
            func unkeyedContainer() -> any UnkeyedEncodingContainer { self }
            func nestedUnkeyedContainer() -> any UnkeyedEncodingContainer { self }
            func singleValueContainer() -> any SingleValueEncodingContainer { self }
            func superEncoder() -> any Encoder { self }
            func encodeNil() throws { throw AssociativeValueSentinel() }
            func encode<T: Encodable>(_: T) throws { throw AssociativeValueSentinel() }
        }
        struct _FailingKeyedContainer<K: CodingKey>: KeyedEncodingContainerProtocol {
            var codingPath: [any CodingKey] { [] }
            func encodeNil(forKey: K) throws { throw AssociativeValueSentinel() }
            func encode<T: Encodable>(_: T, forKey: K) throws { throw AssociativeValueSentinel() }
            func nestedContainer<NK: CodingKey>(keyedBy: NK.Type, forKey: K) -> KeyedEncodingContainer<NK> { .init(_FailingKeyedContainer<NK>()) }
            func nestedUnkeyedContainer(forKey: K) -> any UnkeyedEncodingContainer { _TaintedEncoder() }
            func superEncoder() -> any Encoder { _TaintedEncoder() }
            func superEncoder(forKey: K) -> any Encoder { _TaintedEncoder() }
        }
    }
}


================================================
FILE: Sources/PostgresKit/Deprecations/PostgresDatabase+SQL+Deprecated.swift
================================================
import Foundation
import PostgresNIO
import SQLKit

@available(*, deprecated, message: "Use `.sql(jsonEncoder:jsonDecoder:)` instead.")
extension PostgresDatabase {
    @inlinable public func sql(encoder: PostgresDataEncoder) -> any SQLDatabase { self.sql(encoder: encoder, decoder: .init()) }
    @inlinable public func sql(decoder: PostgresDataDecoder) -> any SQLDatabase { self.sql(encoder: .init(), decoder: decoder) }
    @inlinable public func sql(encoder: PostgresDataEncoder, decoder: PostgresDataDecoder) -> any SQLDatabase {
        self.sql(
            encodingContext: .init(jsonEncoder: TypeErasedPostgresJSONEncoder(json: encoder.json)),
            decodingContext: .init(jsonDecoder: TypeErasedPostgresJSONDecoder(json: decoder.json))
        )
    }
}

extension PostgresRow {
    @available(*, deprecated, message: "Use `.sql(jsonDecoder:)` instead.")
    @inlinable public func sql(decoder: PostgresDataDecoder) -> any SQLRow {
        self.sql(decodingContext: .init(jsonDecoder: TypeErasedPostgresJSONDecoder(json: decoder.json)))
    }
}

@usableFromInline
struct TypeErasedPostgresJSONDecoder: PostgresJSONDecoder {
    let json: any PostgresJSONDecoder
    @usableFromInline init(json: any PostgresJSONDecoder) { self.json = json }
    @usableFromInline func decode<T: Decodable>(_: T.Type, from data: Data) throws -> T { try self.json.decode(T.self, from: data) }
    @usableFromInline func decode<T: Decodable>(_: T.Type, from buffer: ByteBuffer) throws -> T { try self.json.decode(T.self, from: buffer) }
}

@usableFromInline
struct TypeErasedPostgresJSONEncoder: PostgresJSONEncoder {
    let json: any PostgresJSONEncoder
    @usableFromInline init(json: any PostgresJSONEncoder) { self.json = json }
    @usableFromInline func encode<T: Encodable>(_ value: T) throws -> Data { try self.json.encode(value) }
    @usableFromInline func encode<T: Encodable>(_ value: T, into buffer: inout ByteBuffer) throws { try self.json.encode(value, into: &buffer) }
}



================================================
FILE: Sources/PostgresKit/Docs.docc/PostgresKit.md
================================================
# ``PostgresKit``

@Metadata {
    @TitleHeading(Package)
}

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.

```swift
.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. 

```swift
import PostgresKit

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

URL-based configuration is also supported.

```swift
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:)``.

```swift
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:

```swift
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; be sure you cancel this task before exiting:
let clientTask = Task { await psqlClient.run() }
// Or, if you're using ServiceLifecycle, add the client to a ServiceGroup:
await serviceGroup.addServiceUnlessShutdown(psqlClient)
```

You can then lease a `PostgresConnection` from the client:

```swift
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`:
> 
> ```swift
> 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.

```swift
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.

```swift
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`. 

```swift
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`.

```swift
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`.

```swift
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


================================================
FILE: Sources/PostgresKit/Docs.docc/theme-settings.json
================================================
{
  "theme": {
    "aside": { "border-radius": "16px", "border-width": "3px", "border-style": "double" },
    "border-radius": "0",
    "button": { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
    "code":   { "border-radius": "16px", "border-width": "1px", "border-style": "solid" },
    "color": {
      "psqlkit": "#336791",
      "documentation-intro-fill": "radial-gradient(circle at top, var(--color-psqlkit) 30%, #000 100%)",
      "documentation-intro-accent": "var(--color-psqlkit)",
      "hero-eyebrow": "white",
      "documentation-intro-figure": "white",
      "hero-title": "white",
      "logo-base":  { "dark": "#fff", "light": "#000" },
      "logo-shape": { "dark": "#000", "light": "#fff" },
      "fill":       { "dark": "#000", "light": "#fff" }
    },
    "icons": { "technology": "/postgreskit/images/PostgresKit/vapor-postgreskit-logo.svg" }
  },
  "features": {
    "quickNavigation": { "enable": true },
    "i18n": { "enable": true }
  }
}


================================================
FILE: Sources/PostgresKit/Exports.swift
================================================
@_documentation(visibility: internal) @_exported import AsyncKit
@_documentation(visibility: internal) @_exported import PostgresNIO
@_documentation(visibility: internal) @_exported import SQLKit
@_documentation(visibility: internal) @_exported import struct Foundation.URL


================================================
FILE: Sources/PostgresKit/PostgresConnectionSource.swift
================================================
import AsyncKit
import Logging
import NIOConcurrencyHelpers
import NIOCore
import NIOSSL
import PostgresNIO
import SQLKit

public struct PostgresConnectionSource: ConnectionPoolSource {
    public let sqlConfiguration: SQLPostgresConfiguration

    private static let idGenerator = NIOLockedValueBox<Int>(0)

    public init(sqlConfiguration: SQLPostgresConfiguration) {
        self.sqlConfiguration = sqlConfiguration
    }

    public func makeConnection(
        logger: Logger,
        on eventLoop: any EventLoop
    ) -> EventLoopFuture<PostgresConnection> {
        let connectionFuture = PostgresConnection.connect(
            on: eventLoop,
            configuration: self.sqlConfiguration.coreConfiguration,
            id: Self.idGenerator.withLockedValue {
                $0 += 1
                return $0
            },
            logger: logger
        )

        if let searchPath = self.sqlConfiguration.searchPath {
            return connectionFuture.flatMap { conn in
                conn.sql(queryLogLevel: nil)
                    .raw("SET search_path TO \(idents: searchPath, joinedBy: ",")")
                    .run()
                    .map { _ in conn }
            }
        } else {
            return connectionFuture
        }
    }
}

extension PostgresNIO.PostgresConnection: AsyncKit.ConnectionPoolItem {}


================================================
FILE: Sources/PostgresKit/PostgresDataTranslation.swift
================================================
import Foundation
import PostgresNIO

/// Quick and dirty `CodingKey`, borrowed from FluentKit. If `CodingKeyRepresentable` wasn't broken by design
/// (specifically, it can't be back-deployed before macOS 12.3 etc., even though it was introduced in Swift 5.6),
/// we'd use that instead.
private struct SomeCodingKey: CodingKey, Hashable {
    let stringValue: String, intValue: Int?
    init(stringValue: String) { (self.stringValue, self.intValue) = (stringValue, Int(stringValue)) }
    init(intValue: Int) { (self.stringValue, self.intValue) = ("\(intValue)", intValue) }
}

extension PostgresCell {
    fileprivate var codingKey: any CodingKey {
        PostgresKit.SomeCodingKey(stringValue: !self.columnName.isEmpty ? "\(self.columnName) (\(self.columnIndex))" : "\(self.columnIndex)")
    }
}

/// Sidestep problems with URL coding behavior by making it conform directly to Postgres coding.
extension URL {
    public static var psqlType: PostgresDataType {
        String.psqlType
    }

    public static var psqlFormat: PostgresFormat {
        String.psqlFormat
    }

    @inlinable
    public func encode(
        into byteBuffer: inout ByteBuffer,
        context: PostgresEncodingContext<some PostgresJSONEncoder>
    ) {
        self.absoluteString.encode(into: &byteBuffer, context: context)
    }

    @inlinable
    public init(
        from buffer: inout ByteBuffer,
        type: PostgresDataType,
        format: PostgresFormat,
        context: PostgresDecodingContext<some PostgresJSONDecoder>
    ) throws {
        let string = try String(from: &buffer, type: type, format: format, context: context)

        if let url = URL(string: string) {
            self = url
        }
        // Also support the broken encoding we were emitting for awhile there.
        else if string.hasPrefix("\""), string.hasSuffix("\""), let url = URL(string: String(string.dropFirst().dropLast())) {
            self = url
        } else {
            throw PostgresDecodingError.Code.failure
        }
    }
}

extension URL: @retroactive PostgresNonThrowingEncodable, @retroactive PostgresDecodable {}

struct PostgresDataTranslation {
    /// This typealias serves to limit the deprecation noise caused by `PostgresDataConvertible` to a single
    /// warning, down from what would otherwise be a minimum of two. It has no other purpose.
    fileprivate typealias PostgresLegacyDataConvertible = PostgresDataConvertible

    static func decode<T: Decodable, D: PostgresJSONDecoder>(
        _: T.Type = T.self,
        from cell: PostgresCell,
        in context: PostgresDecodingContext<D>,
        file: String = #fileID,
        line: Int = #line
    ) throws -> T {
        try self.decode(
            codingPath: [cell.codingKey],
            userInfo: [:],
            T.self,
            from: cell,
            in: context,
            file: file,
            line: line
        )
    }

    fileprivate static func decode<T: Decodable, D: PostgresJSONDecoder>(
        codingPath: [any CodingKey],
        userInfo: [CodingUserInfoKey: Any],
        _: T.Type = T.self,
        from cell: PostgresCell,
        in context: PostgresDecodingContext<D>,
        file: String,
        line: Int
    ) throws -> T {
        /// Preferred modern fast-path: Direct conformance to `PostgresDecodable`, let the cell decode.
        if let fastPathType = T.self as? any PostgresDecodable.Type {
            let cellToDecode: PostgresCell

            if cell.dataType.isUserDefined && (T.self is String.Type || T.self is String?.Type) {
                /// Workaround for Fluent's enum "support":
                ///
                /// If we're trying to decode a string and the real cell's data type is in the user-defined range,
                /// assume we're dealing with a Fluent enum and pretend that the cell has a string data type instead.
                cellToDecode = .init(
                    bytes: cell.bytes,
                    dataType: .name,
                    format: cell.format,
                    columnName: cell.columnName,
                    columnIndex: cell.columnIndex
                )
            } else if cell.format == .binary && [.char, .varchar, .text].contains(cell.dataType) && T.self is Decimal.Type {
                /// Workaround for Fluent's assumption that Decimal strings work:
                ///
                /// If the cell's data type is a binary-format string-like, and we're trying to decode a `Decimal`,
                /// reinterpret the cell as a text-format numeric value so that the `PostgresCodable` conformance of
                /// `Decimal` will work as written.
                cellToDecode = .init(
                    bytes: cell.bytes,
                    dataType: .numeric,
                    format: .text,
                    columnName: cell.columnName,
                    columnIndex: cell.columnIndex
                )
            } else if cell.format == .binary && cell.dataType == .numeric && T.self is Double.Type {
                /// Workaround for Fluent's expectation that Postgres's `numeric/decimal` can be decoded as `Double`:
                ///
                /// If the cell is a binary-format numeric value and we're trying to decode a `Double`, use
                /// `PostgresData` to manually interpret the cell as a `PostgresNumeric` and use that result to convert
                /// to `Double`.
                guard let value = PostgresData(type: cell.dataType, formatCode: cell.format, value: cell.bytes).numeric?.double else {
                    throw DecodingError.dataCorrupted(.init(codingPath: codingPath, debugDescription: "Invalid numeric value encoding"))
                }
                return value as! T
            } else {
                /// No workarounds needed, use the cell as-is.
                cellToDecode = cell
            }
            return try cellToDecode.decode(fastPathType, context: context, file: file, line: line) as! T

        /// Legacy "fast"-path: Direct conformance to `PostgresDataConvertible`; use is deprecated.
        } else if let legacyPathType = T.self as? any PostgresLegacyDataConvertible.Type {
            let legacyData = PostgresData(type: cell.dataType, typeModifier: nil, formatCode: cell.format, value: cell.bytes)

            guard let result = legacyPathType.init(postgresData: legacyData) else {
                throw DecodingError.typeMismatch(T.self, .init(codingPath: codingPath,
                    debugDescription: "Couldn't get '\(T.self)' from PSQL type \(cell.dataType): \(legacyData as Any)"
                ))
            }
            return result as! T
        }

        /// Slow path: Descend through the `Decodable` machinery until we fail or find something we can convert.
        else {
            do {
                return try T.init(from: ArrayAwareBoxUwrappingDecoder<T, D>(
                    codingPath: codingPath,
                    userInfo: userInfo,
                    cell: cell,
                    context: context,
                    file: file, line: line
                ))
            } catch DecodingError.dataCorrupted(let errContext) {
                /// Glacial path: Attempt to decode as plain JSON.
                guard cell.dataType == .json || cell.dataType == .jsonb else {
                    throw DecodingError.dataCorrupted(.init(
                        codingPath: codingPath,
                        debugDescription: "Unable to interpret value of PSQL type \(cell.dataType) as Swift type \(T.self): \(cell.bytes.map { "\($0)" } ?? "null")",
                        underlyingError: DecodingError.dataCorrupted(errContext)
                    ))
                }
                if cell.dataType == .jsonb, cell.format == .binary, let buffer = cell.bytes {
                    // Account for the leading JSONB version byte
                    return try context.jsonDecoder.decode(T.self, from: buffer.getSlice(at: buffer.readerIndex + 1, length: buffer.readableBytes - 1) ?? .init())
                } else {
                    return try context.jsonDecoder.decode(T.self, from: cell.bytes ?? .init())
                }
            } catch let error as PostgresDecodingError {
                /// We effectively transform PostgresDecodingErrors into plain DecodingErrors here, mostly so the full
                /// coding path, which gives us the original type(s) involved, is preserved.
                let context = DecodingError.Context(
                    codingPath: codingPath,
                    debugDescription: "\(String(reflecting: error))",
                    underlyingError: error
                )

                switch error.code {
                case .typeMismatch: throw DecodingError.typeMismatch(T.self, context)
                case .missingData: throw DecodingError.valueNotFound(T.self, context)
                default: throw DecodingError.dataCorrupted(context)
                }
            }
        }
    }

    static func encode<T: Encodable, E: PostgresJSONEncoder>(
        value: T,
        in context: PostgresEncodingContext<E>,
        to bindings: inout PostgresBindings,
        file: String = #fileID,
        line: Int = #line
    ) throws {
        /// Preferred modern fast-path: Direct conformance to `PostgresEncodable`
        if let fastPathValue = value as? any PostgresEncodable {
            try bindings.append(fastPathValue, context: context)
        }
        /// Legacy "fast"-path: Direct conformance to `PostgresDataConvertible`; use is deprecated.
        else if let legacyPathValue = value as? any PostgresDataTranslation.PostgresLegacyDataConvertible {
            guard let legacyData = legacyPathValue.postgresData else {
                throw EncodingError.invalidValue(value, .init(codingPath: [], debugDescription: "Couldn't get PSQL encoding from value '\(value)' of Swift type \(T.self)/\(type(of: value))"))
            }
            bindings.append(legacyData)
        }
        /// Slow path: Descend through the `Encodable` machinery until we fail or find something we can convert.
        else {
            try bindings.append(self.encode(codingPath: [], userInfo: [:], value: value, in: context, file: file, line: line))
        }
    }

    internal /*fileprivate*/ static func encode<T: Encodable, E: PostgresJSONEncoder>(
        codingPath: [any CodingKey],
        userInfo: [CodingUserInfoKey: Any],
        value: T,
        in context: PostgresEncodingContext<E>,
        file: String,
        line: Int
    ) throws -> PostgresData {
        // TODO: Avoid repeating the conformance checks here, or at the very least only repeat them after a second level of nesting...
        if let fastPathValue = value as? any PostgresEncodable {
            var buffer = ByteBuffer()
            try fastPathValue.encode(into: &buffer, context: context)
            return PostgresData(type: type(of: fastPathValue).psqlType, typeModifier: nil, formatCode: type(of: fastPathValue).psqlFormat, value: buffer)
        } else if let legacyPathValue = value as? any PostgresDataTranslation.PostgresLegacyDataConvertible {
            guard let legacyData = legacyPathValue.postgresData else {
                throw EncodingError.invalidValue(value, .init(codingPath: [], debugDescription: "Couldn't get PSQL encoding from value '\(value)' of Swift type \(T.self)/\(type(of: value))"))
            }
            return legacyData
        }
        // TODO: Make all of this work without relying on the legacy PostgresData array machinery
        do {
            let encoder = ArrayAwareBoxWrappingPostgresEncoder(codingPath: codingPath, userInfo: userInfo, context: context, file: file, line: line)
            try value.encode(to: encoder)
            switch encoder.value {
            case .invalid: throw ArrayAwareBoxWrappingPostgresEncoder<E>.FallbackSentinel()
            case .scalar(let scalar): return scalar
            case .indexed(let ref):
                let elementType = ref.contents.first?.type ?? .jsonb
                assert(ref.contents.allSatisfy { $0.type == elementType }, "Type \(T.self)/\(type(of: value)) was encoded as a heterogenous array; this is unsupported.")
                return PostgresData(array: ref.contents, elementType: elementType)
            }
        } catch is ArrayAwareBoxWrappingPostgresEncoder<E>.FallbackSentinel {
            /// Glacial path: Fall back to encoding directly to JSON.
            return try PostgresData(jsonb: context.jsonEncoder.encode(value))
        }
    }
}

private final class ArrayAwareBoxUwrappingDecoder<T0: Decodable, D: PostgresJSONDecoder>: Decoder, SingleValueDecodingContainer {
    let codingPath: [any CodingKey]
    let userInfo: [CodingUserInfoKey: Any]
    let cell: PostgresCell
    let context: PostgresDecodingContext<D>
    let file: String, line: Int
 
    init(codingPath: [any CodingKey], userInfo: [CodingUserInfoKey: Any], cell: PostgresCell, context: PostgresDecodingContext<D>, file: String, line: Int) {
        self.codingPath = codingPath
        self.cell = cell
        self.context = context
        self.file = file
        self.line = line
        self.userInfo = userInfo
    }

    struct ArrayContainer: UnkeyedDecodingContainer {
        let data: [PostgresData]
        let decoder: ArrayAwareBoxUwrappingDecoder

        var codingPath: [any CodingKey] {
            self.decoder.codingPath
        }

        var count: Int? {
            self.data.count
        }

        var isAtEnd: Bool {
            self.currentIndex >= self.data.count
        }

        var currentIndex = 0

        mutating func decodeNil() throws -> Bool {
            guard self.data[self.currentIndex].value == nil else { return false }
            self.currentIndex += 1
            return true
        }

        mutating func decode<T: Decodable>(_: T.Type) throws -> T {
            // TODO: Don't fake a cell.
            let data = self.data[self.currentIndex], cell = PostgresCell(
                bytes: data.value, dataType: data.type, format: data.formatCode,
                columnName: self.decoder.cell.columnName, columnIndex: self.decoder.cell.columnIndex
            )

            let result = try PostgresDataTranslation.decode(
                codingPath: self.codingPath + [PostgresKit.SomeCodingKey(intValue: self.currentIndex)],
                userInfo: self.decoder.userInfo,
                T.self, from: cell, in: self.decoder.context,
                file: self.decoder.file, line: self.decoder.line
            )
            self.currentIndex += 1
            return result
        }

        private var rejectNestingError: DecodingError { .dataCorruptedError(in: self, debugDescription: "Data nesting is not supported") }
        mutating func nestedContainer<K: CodingKey>(keyedBy: K.Type) throws -> KeyedDecodingContainer<K> { throw self.rejectNestingError }
        mutating func nestedUnkeyedContainer() throws -> any UnkeyedDecodingContainer { throw self.rejectNestingError }
        mutating func superDecoder() throws -> any Decoder { throw self.rejectNestingError }
    }

    func container<Key: CodingKey>(keyedBy: Key.Type) throws -> KeyedDecodingContainer<Key> {
        throw DecodingError.dataCorrupted(.init(codingPath: self.codingPath, debugDescription: "Dictionary containers must be JSON-encoded"))
    }

    func unkeyedContainer() throws -> any UnkeyedDecodingContainer {
        // TODO: Find a better way to figure out arrays
        guard let array = PostgresData(type: self.cell.dataType, typeModifier: nil, formatCode: self.cell.format, value: self.cell.bytes).array else {
            throw DecodingError.dataCorrupted(.init(codingPath: self.codingPath, debugDescription: "Non-natively typed arrays must be JSON-encoded"))
        }
        return ArrayContainer(data: array, decoder: self)
    }

    func singleValueContainer() throws -> any SingleValueDecodingContainer { self }

    func decodeNil() -> Bool { self.cell.bytes == nil }

    func decode<T: Decodable>(_: T.Type) throws -> T {
        try PostgresDataTranslation.decode(
            codingPath: self.codingPath + [PostgresKit.SomeCodingKey(stringValue: "(Unwrapping(\(T0.self)))")], userInfo: self.userInfo,
            T.self, from: self.cell, in: self.context, file: self.file, line: self.line
        )
    }
}

private final class ArrayAwareBoxWrappingPostgresEncoder<E: PostgresJSONEncoder>: Encoder, SingleValueEncodingContainer {
    enum Value {
        final class ArrayRef<T> { var contents: [T] = [] }

        case invalid
        case indexed(ArrayRef<PostgresData>)
        case scalar(PostgresData)
        
        var isValid: Bool { if case .invalid = self { return false }; return true }

        mutating func store(scalar: PostgresData) {
            if case .invalid = self { self = .scalar(scalar) } // no existing value, store the incoming
            else { preconditionFailure("Invalid request for multiple containers from the same encoder.") }
        }

        mutating func requestIndexed() {
            switch self {
            case .scalar(_): preconditionFailure("Invalid request for both single-value and unkeyed containers from the same encoder.")
            case .invalid: self = .indexed(.init()) // no existing value, make new array
            case .indexed(_): break // existing array, adopt it for appending (support for superEncoder())
            }
        }

        var indexedCount: Int {
            if case .indexed(let ref) = self { return ref.contents.count }
            else { preconditionFailure("Internal error in encoder (requested indexed count from non-indexed state)") }
        }

        mutating func store(indexedScalar: PostgresData) {
            if case .indexed(let ref) = self { ref.contents.append(indexedScalar) }
            else { preconditionFailure("Internal error in encoder (attempted store to indexed in non-indexed state)") }
        }
    }

    var codingPath: [any CodingKey]
    let userInfo: [CodingUserInfoKey: Any]
    let context: PostgresEncodingContext<E>
    let file: String, line: Int
    var value: Value

    init(codingPath: [any CodingKey], userInfo: [CodingUserInfoKey: Any], context: PostgresEncodingContext<E>, file: String, line: Int, value: Value = .invalid) {
        self.codingPath = codingPath
        self.userInfo = userInfo
        self.context = context
        self.file = file
        self.line = line
        self.value = value
    }

    func container<K: CodingKey>(keyedBy: K.Type) -> KeyedEncodingContainer<K> {
        precondition(!self.value.isValid, "Requested multiple containers from the same encoder.")
        return .init(FailureEncoder())
    }

    func unkeyedContainer() -> any UnkeyedEncodingContainer {
        self.value.requestIndexed()
        return ArrayContainer(encoder: self)
    }

    func singleValueContainer() -> any SingleValueEncodingContainer {
        precondition(!self.value.isValid, "Requested multiple containers from the same encoder.")
        return self
    }

    struct ArrayContainer: UnkeyedEncodingContainer {
        let encoder: ArrayAwareBoxWrappingPostgresEncoder
        var codingPath: [any CodingKey] { self.encoder.codingPath }
        var count: Int { self.encoder.value.indexedCount }
        mutating func encodeNil() throws { self.encoder.value.store(indexedScalar: .null) }
        mutating func encode<T: Encodable>(_ value: T) throws {
            self.encoder.value.store(indexedScalar: try PostgresDataTranslation.encode(
                codingPath: self.codingPath + [PostgresKit.SomeCodingKey(intValue: self.count)], userInfo: self.encoder.userInfo,
                value: value, in: self.encoder.context,
                file: self.encoder.file, line: self.encoder.line
            ))
        }
        mutating func nestedContainer<K: CodingKey>(keyedBy: K.Type) -> KeyedEncodingContainer<K> { self.superEncoder().container(keyedBy: K.self) }
        mutating func nestedUnkeyedContainer() -> any UnkeyedEncodingContainer { self.superEncoder().unkeyedContainer() }
        mutating func superEncoder() -> any Encoder { ArrayAwareBoxWrappingPostgresEncoder(
            codingPath: self.codingPath + [PostgresKit.SomeCodingKey(intValue: self.count)], userInfo: self.encoder.userInfo,
            context: self.encoder.context,
            file: self.encoder.file, line: self.encoder.line,
            value: self.encoder.value
        ) } // NOT the same as self.encoder
    }

    func encodeNil() throws { self.value.store(scalar: .null) }
    func encode<T: Encodable>(_ value: T) throws {
        self.value.store(scalar: try PostgresDataTranslation.encode(
            codingPath: self.codingPath, userInfo: self.userInfo, value: value, in: self.context, file: self.file, line: self.line
        ))
    }

    struct FallbackSentinel: Error {}

    /// This is a workaround for the inability of encoders to throw errors in various places. It's still better than fatalError()ing.
    struct FailureEncoder<K: CodingKey>: Encoder, KeyedEncodingContainerProtocol, UnkeyedEncodingContainer, SingleValueEncodingContainer {
        let codingPath = [any CodingKey](), userInfo = [CodingUserInfoKey: Any](), count = 0
        init() {}; init() where K == PostgresKit.SomeCodingKey {}
        func encodeNil() throws { throw FallbackSentinel() }
        func encodeNil(forKey: K) throws { throw FallbackSentinel() }
        func encode<T: Encodable>(_: T) throws { throw FallbackSentinel() }
        func encode<T: Encodable>(_: T, forKey: K) throws { throw FallbackSentinel() }
        func nestedContainer<N: CodingKey>(keyedBy: N.Type) -> KeyedEncodingContainer<N> { .init(FailureEncoder<N>()) }
        func nestedContainer<N: CodingKey>(keyedBy: N.Type, forKey: K) -> KeyedEncodingContainer<N> { .init(FailureEncoder<N>()) }
        func nestedUnkeyedContainer() -> any UnkeyedEncodingContainer { self }
        func nestedUnkeyedContainer(forKey: K) -> any UnkeyedEncodingContainer { self }
        func superEncoder() -> any Encoder { self }
        func superEncoder(forKey: K) -> any Encoder { self }
        func container<N: CodingKey>(keyedBy: N.Type) -> KeyedEncodingContainer<N> { .init(FailureEncoder<N>()) }
        func unkeyedContainer() -> any UnkeyedEncodingContainer { self }
        func singleValueContainer() -> any SingleValueEncodingContainer { self }
    }
}


================================================
FILE: Sources/PostgresKit/PostgresDatabase+SQL.swift
================================================
import Logging
import PostgresNIO
import SQLKit

extension PostgresDatabase {
    @inlinable
    public func sql(queryLogLevel: Logger.Level? = .debug) -> some SQLDatabase {
        self.sql(encodingContext: .default, decodingContext: .default, queryLogLevel: queryLogLevel)
    }

    public func sql(
        encodingContext: PostgresEncodingContext<some PostgresJSONEncoder>,
        decodingContext: PostgresDecodingContext<some PostgresJSONDecoder>,
        queryLogLevel: Logger.Level? = .debug
    ) -> some SQLDatabase {
        PostgresSQLDatabase(
            database: self,
            encodingContext: encodingContext,
            decodingContext: decodingContext,
            queryLogLevel: queryLogLevel
        )
    }
}

private struct PostgresSQLDatabase<PDatabase: PostgresDatabase, E: PostgresJSONEncoder, D: PostgresJSONDecoder> {
    let database: PDatabase
    let encodingContext: PostgresEncodingContext<E>
    let decodingContext: PostgresDecodingContext<D>
    let queryLogLevel: Logger.Level?
}

extension PostgresSQLDatabase: SQLDatabase, PostgresDatabase {
    var logger: Logger {
        self.database.logger
    }

    var eventLoop: any EventLoop {
        self.database.eventLoop
    }

    var version: (any SQLDatabaseReportedVersion)? {
        nil  // PSQL doesn't send version in wire protocol, must use SQL to read it
    }

    var dialect: any SQLDialect {
        PostgresDialect()
    }

    func execute(sql query: any SQLExpression, _ onRow: @escaping @Sendable (any SQLRow) -> Void) -> EventLoopFuture<Void> {
        let (sql, binds) = self.serialize(query)

        if let queryLogLevel = self.queryLogLevel {
            self.logger.log(level: queryLogLevel, "Executing query", metadata: ["sql": .string(sql), "binds": .array(binds.map { .string("\($0)") })])
        }
        return self.eventLoop.makeCompletedFuture {
            var bindings = PostgresBindings(capacity: binds.count)
            for bind in binds {
                try PostgresDataTranslation.encode(value: bind, in: self.encodingContext, to: &bindings)
            }
            return bindings
        }.flatMap { bindings in self.database.withConnection {
            $0.query(
                .init(unsafeSQL: sql, binds: bindings),
                logger: $0.logger,
                { onRow($0.sql(decodingContext: self.decodingContext)) }
            )
        } }.map { _ in }
    }

    func execute(
        sql query: any SQLExpression,
        _ onRow: @escaping @Sendable (any SQLRow) -> Void
    ) async throws {
        let (sql, binds) = self.serialize(query)

        if let queryLogLevel = self.queryLogLevel {
            self.logger.log(level: queryLogLevel, "Executing query", metadata: ["sql": .string(sql), "binds": .array(binds.map { .string("\($0)") })])
        }

        var bindings = PostgresBindings(capacity: binds.count)
        for bind in binds {
            try PostgresDataTranslation.encode(value: bind, in: self.encodingContext, to: &bindings)
        }

        _ = try await self.database.withConnection {
            $0.query(
                .init(unsafeSQL: sql, binds: bindings),
                logger: $0.logger,
                { onRow($0.sql(decodingContext: self.decodingContext)) }
            )
        }.get()
    }

    func send(_ request: any PostgresRequest, logger: Logger) -> EventLoopFuture<Void> {
        self.database.send(request, logger: logger)
    }

    func withConnection<T>(_ closure: @escaping (PostgresConnection) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
        self.database.withConnection(closure)
    }

    func withSession<R: Sendable>(_ closure: @escaping @Sendable (any SQLDatabase) async throws -> R) async throws -> R {
        try await self.withConnection { c in
            c.eventLoop.makeFutureWithTask {
                try await closure(c.sql(
                    encodingContext: self.encodingContext,
                    decodingContext: self.decodingContext,
                    queryLogLevel: self.queryLogLevel
                ))
            }
        }.get()
    }
}


================================================
FILE: Sources/PostgresKit/PostgresDialect.swift
================================================
import SQLKit

public struct PostgresDialect: SQLDialect {
    public init() {}

    public var name: String {
        "postgresql"
    }

    public var identifierQuote: any SQLExpression {
        SQLRaw(#"""#)
    }

    public var literalStringQuote: any SQLExpression {
        SQLRaw("'")
    }

    public var supportsAutoIncrement: Bool {
        true
    }

    public var autoIncrementClause: any SQLExpression {
        SQLRaw("GENERATED BY DEFAULT AS IDENTITY")
    }

    public var autoIncrementFunction: (any SQLExpression)? {
        nil
    }

    public func bindPlaceholder(at position: Int) -> any SQLExpression {
        SQLRaw("$\(position)")
    }

    public func literalBoolean(_ value: Bool) -> any SQLExpression {
        SQLRaw("\(value)")
    }

    public var literalDefault: any SQLExpression {
        SQLRaw("DEFAULT")
    }

    public var supportsIfExists: Bool {
        true
    }

    public var enumSyntax: SQLEnumSyntax {
        .typeName
    }

    public var supportsDropBehavior: Bool {
        true
    }

    public var supportsReturning: Bool {
        true
    }

    public var triggerSyntax: SQLTriggerSyntax {
        .init(
            create: [.supportsForEach, .postgreSQLChecks, .supportsCondition, .conditionRequiresParentheses, .supportsConstraints],
            drop: [.supportsCascade, .supportsTableName]
        )
    }

    public var alterTableSyntax: SQLAlterTableSyntax {
        .init(
            alterColumnDefinitionClause: SQLRaw("ALTER COLUMN"),
            alterColumnDefinitionTypeKeyword: SQLRaw("SET DATA TYPE")
        )
    }

    public func customDataType(for dataType: SQLDataType) -> (any SQLExpression)? {
        if case .custom(let expr) = dataType, (expr as? SQLRaw)?.sql == "TIMESTAMP" {
            return SQLRaw("TIMESTAMPTZ")
        } else if case .blob = dataType {
            return SQLRaw("BYTEA")
        } else {
            return nil
        }
    }

    public var upsertSyntax: SQLUpsertSyntax {
        .standard
    }

    public var unionFeatures: SQLUnionFeatures {
        [
            .union, .unionAll,
            .intersect, .intersectAll,
            .except, .exceptAll,
            .explicitDistinct,
            .parenthesizedSubqueries,
        ]
    }

    public var sharedSelectLockExpression: (any SQLExpression)? {
        SQLRaw("FOR SHARE")
    }

    public var exclusiveSelectLockExpression: (any SQLExpression)? {
        SQLRaw("FOR UPDATE")
    }

    public func nestedSubpathExpression(in column: any SQLExpression, for path: [String]) -> (any SQLExpression)? {
        guard !path.isEmpty else { return nil }

        let descender = SQLList(
            [column] + path.dropLast().map(SQLLiteral.string(_:)),
            separator: SQLRaw("->")
        )
        let accessor = SQLList(
            [descender, SQLLiteral.string(path.last!)],
            separator: SQLRaw("->>")
        )

        return SQLGroupExpression(accessor)
    }
}


================================================
FILE: Sources/PostgresKit/PostgresRow+SQL.swift
================================================
import Foundation
import PostgresNIO
import SQLKit

extension PostgresRow {
    @inlinable
    public func sql() -> some SQLRow {
        self.sql(decodingContext: .default)
    }

    public func sql(decodingContext: PostgresDecodingContext<some PostgresJSONDecoder>) -> some SQLRow {
        _PostgresSQLRow(randomAccessView: self.makeRandomAccess(), decodingContext: decodingContext)
    }
}

private struct _PostgresSQLRow<D: PostgresJSONDecoder> {
    let randomAccessView: PostgresRandomAccessRow
    let decodingContext: PostgresDecodingContext<D>

    enum _Error: Error {
        case missingColumn(String)
    }
}

extension _PostgresSQLRow: SQLRow {
    var allColumns: [String] {
        self.randomAccessView.map { $0.columnName }
    }

    func contains(column: String) -> Bool {
        self.randomAccessView.contains(column)
    }

    func decodeNil(column: String) throws -> Bool {
        !self.randomAccessView.contains(column) || self.randomAccessView[column].bytes == nil
    }

    func decode<T: Decodable>(column: String, as type: T.Type) throws -> T {
        guard self.randomAccessView.contains(column) else {
            throw _Error.missingColumn(column)
        }

        return try PostgresDataTranslation.decode(T.self, from: self.randomAccessView[column], in: self.decodingContext)
    }
}


================================================
FILE: Sources/PostgresKit/SQLPostgresConfiguration.swift
================================================
import Foundation
import NIOCore
import NIOSSL
import PostgresNIO

/// Provides configuration paramters for establishing PostgreSQL database connections.
public struct SQLPostgresConfiguration: Sendable {
    /// IANA-assigned port number for PostgreSQL
    /// `UInt16(getservbyname("postgresql", "tcp").pointee.s_port).byteSwapped`
    public static var ianaPortNumber: Int { 5432 }

    // See `PostgresNIO.PostgresConnection.Configuration`.
    public var coreConfiguration: PostgresConnection.Configuration

    /// Optional `search_path` to set on new connections.
    public var searchPath: [String]?

    /// Create a ``SQLPostgresConfiguration`` from a string containing a properly formatted URL.
    ///
    /// See ``init(url:)`` for details on the allowed format for connection URLs.
    public init(url: String) throws {
        guard let url = URL(string: url) else {
            throw URLError(.badURL, userInfo: [NSURLErrorFailingURLStringErrorKey: url])
        }
        try self.init(url: url)
    }
    
    /// Create a ``SQLPostgresConfiguration`` from a properly formatted URL.
    ///
    /// The supported URL formats are:
    ///
    ///     postgres://username:password@hostname:port/database?tlsmode=mode
    ///     postgres+tcp://username:password@hostname:port/database?tlsmode=mode
    ///     postgres+uds://username:password@localhost/path?tlsmode=mode#database
    ///
    /// The `postgres+tcp` scheme requests a connection over TCP. The `postgres` scheme is an alias
    /// for `postgres+tcp`. Only the `hostname` and `username` components are required.
    ///
    /// The `postgres+uds` scheme requests a connection via a UNIX domain socket. The `username` and
    /// `path` components are required. The authority must always be empty or `localhost`, and may not
    /// specify a port.
    ///
    /// The allowed `mode` values for `tlsmode` are:
    ///
    /// Value|Behavior
    /// -|-
    /// `disable`|Don't use TLS, even if the server supports it.
    /// `prefer`|Use TLS if possible.
    /// `require`|Enforce TLS support.
    ///
    /// If no `tlsmode` is specified, the default mode is `prefer` for TCP connections, or `disable`
    /// for UDS connections. If more than one mode is specified, the last one wins. Whenever a TLS
    /// connection is made, full certificate verification (both chain of trust and hostname match)
    /// is always enforced, regardless of the mode used.
    ///
    /// For compatibility with `libpq` and previous versions of this package, any of "`sslmode`",
    /// "`tls`", or "`ssl`" may be used instead of "`tlsmode`". There are also various aliases for
    /// each of the TLS mode names, as follows:
    ///
    /// - "`disable`": "`false`"
    /// - "`prefer`": "`allow`", "`true`"
    /// - "`require`": "`verify-ca`", "`verify-full`"
    ///
    /// The aliases always have the same semantics as the "canonical" modes, despite any differences
    /// suggested by their names.
    ///
    /// Also for compatibility, the URL scheme may also be `postgresql` or `postgresql+uds`.
    ///
    /// > Note: It is possible to emulate `libpq`'s definitions for `prefer` (TLS if available with
    /// > no certificate verification), `require` (TLS enforced, but also without certificate
    /// > verification) and `verify-ca` (TLS enforced with no hostname verification) by manually
    /// > specifying the TLS configuration instead of using a URL. It is not possible, by design, to
    /// > emulate `libpq`'s `allow` mode (TLS only if there is no alternative). It is _strongly_
    /// > recommended for both security and privacy reasons to always leave full certificate
    /// > verification enabled whenever possible. See NIOSSL's [`TLSConfiguration`](tlsconfig) for
    /// > additional information and recommendations.
    ///
    /// [tlsconfig]:
    /// https://swiftpackageindex.com/apple/swift-nio-ssl/documentation/niossl/tlsconfiguration
    public init(url: URL) throws {
        guard let comp = URLComponents(url: url, resolvingAgainstBaseURL: true), let username = comp.user else {
            throw URLError(.badURL, userInfo: [NSURLErrorFailingURLErrorKey: url, NSURLErrorFailingURLStringErrorKey: url.absoluteString])
        }
        
        func decideTLSConfig(from queryItems: [URLQueryItem], defaultMode: String) throws -> PostgresConnection.Configuration.TLS {
            switch queryItems.last(where: { ["tlsmode", "sslmode", "ssl", "tls"].contains($0.name.lowercased()) })?.value ?? defaultMode {
            case "verify-full", "verify-ca", "require":
                return try .require(.init(configuration: .makeClientConfiguration()))
            case "prefer", "allow", "true":
                return try .prefer(.init(configuration: .makeClientConfiguration()))
            case "disable", "false":
                return .disable
            default:
                throw URLError(.badURL, userInfo: [NSURLErrorFailingURLErrorKey: url, NSURLErrorFailingURLStringErrorKey: url.absoluteString])
            }
        }
        
        switch comp.scheme {
        case "postgres", "postgres+tcp", "postgresql", "postgresql+tcp":
            guard let hostname = comp.host, !hostname.isEmpty else {
                throw URLError(.badURL, userInfo: [NSURLErrorFailingURLErrorKey: url, NSURLErrorFailingURLStringErrorKey: url.absoluteString])
            }
            self.init(
                hostname: hostname, port: comp.port ?? Self.ianaPortNumber,
                username: username, password: comp.password,
                database: url.lastPathComponent.isEmpty ? nil : url.lastPathComponent,
                tls: try decideTLSConfig(from: comp.queryItems ?? [], defaultMode: "prefer")
            )
        case "postgres+uds", "postgresql+uds":
            guard (comp.host?.isEmpty ?? true || comp.host == "localhost"), comp.port == nil, !comp.path.isEmpty, comp.path != "/" else {
                throw URLError(.badURL, userInfo: [NSURLErrorFailingURLErrorKey: url, NSURLErrorFailingURLStringErrorKey: url.absoluteString])
            }
            var coreConfig = PostgresConnection.Configuration(unixSocketPath: comp.path, username: username, password: comp.password, database: comp.fragment)
            coreConfig.tls = try decideTLSConfig(from: comp.queryItems ?? [], defaultMode: "disable")
            self.init(coreConfiguration: coreConfig)
        default:
            throw URLError(.badURL, userInfo: [NSURLErrorFailingURLErrorKey: url, NSURLErrorFailingURLStringErrorKey: url.absoluteString])
        }
    }
    
    /// Create a ``SQLPostgresConfiguration`` for connecting to a server with a hostname and optional port.
    ///
    /// This specifies a TCP connection. If you're unsure which kind of connection you want, you almost
    /// definitely want this one.
    public init(
        hostname: String, port: Int = Self.ianaPortNumber,
        username: String, password: String? = nil,
        database: String? = nil,
        tls: PostgresConnection.Configuration.TLS
    ) {
        self.init(coreConfiguration: .init(host: hostname, port: port, username: username, password: password, database: database, tls: tls))
    }
    
    /// Create a ``SQLPostgresConfiguration`` for connecting to a server through a UNIX domain socket.
    public init(
        unixDomainSocketPath: String,
        username: String, password: String? = nil,
        database: String? = nil
    ) {
        self.init(coreConfiguration: .init(unixSocketPath: unixDomainSocketPath, username: username, password: password, database: database))
    }
    
    /// Create a ``SQLPostgresConfiguration`` for establishing a connection to a server over a
    /// preestablished `NIOCore.Channel`.
    ///
    /// This is provided for calling code which wants to manage the underlying connection transport on its
    /// own, such as when tunneling a connection through SSH.
    public init(
        establishedChannel: any Channel,
        username: String, password: String? = nil,
        database: String? = nil
    ) {
        self.init(coreConfiguration: .init(establishedChannel: establishedChannel, username: username, password: password, database: database))
    }

    public init(
        coreConfiguration: PostgresConnection.Configuration,
        searchPath: [String]? = nil
    ) {
        self.coreConfiguration = coreConfiguration
        self.searchPath = searchPath
    }
}


================================================
FILE: Tests/PostgresKitTests/PostgresKitTests.swift
================================================
import Foundation
import Logging
import NIOCore
import PostgresNIO
import SQLKitBenchmark
import Testing
@testable import PostgresKit

extension AllSuites {

@Suite
struct PostgresKitTests {
    @Test
    func sqlKitBenchmark() async throws {
        let conn = try await PostgresConnection.test(on: self.eventLoop)

        await #expect(throws: Never.self) {
            let benchmark = SQLBenchmarker(on: conn.sql())

            try await benchmark.runAllTests()
        }
        try await conn.close()
    }

    @Test
    func leak() async throws {
        struct Foo: Codable {
            var id: String
            var description: String?
            var latitude: Double
            var longitude: Double
            var created_by: String
            var created_at: Date
            var modified_by: String
            var modified_at: Date
        }
        
        let conn = try await PostgresConnection.test(on: self.eventLoop)
        let db = conn.sql()

        await #expect(throws: Never.self) {
            try await db.drop(table: "foos").ifExists().run()
            try await db.create(table: "foos")
                .column("id", type: .text, .primaryKey(autoIncrement: false))
                .column("description", type: .text)
                .column("latitude", type: .custom(SQLRaw("DOUBLE PRECISION")))
                .column("longitude", type: .custom(SQLRaw("DOUBLE PRECISION")))
                .column("created_by", type: .text)
                .column("created_at", type: .custom(SQLRaw("TIMESTAMPTZ")))
                .column("modified_by", type: .text)
                .column("modified_at", type: .custom(SQLRaw("TIMESTAMPTZ")))
                .run()

            for i in 0..<5_000 {
                let zipcode = Foo(
                    id: UUID().uuidString,
                    description: "test \(i)",
                    latitude: Double.random(in: 0...100),
                    longitude: Double.random(in: 0...100),
                    created_by: "test",
                    created_at: Date(),
                    modified_by: "test",
                    modified_at: Date()
                )
                try await db.insert(into: "foos")
                    .model(zipcode)
                    .run()
            }
        }
        try? await db.raw("DROP TABLE IF EXISTS \(ident: "foos")").run()
        try await conn.close()
    }

    @Test
    func arrayEncoding() async throws {
        let conn = try await PostgresConnection.test(on: self.eventLoop)

        struct Foo: Codable {
            var bar: Int
        }

        await #expect(throws: Never.self) {
            let foos: [Foo] = [.init(bar: 1), .init(bar: 2)]
            try await conn.sql().raw("SELECT \(bind: foos)::JSONB[] as \(ident: "foos")").run()
        }
        try await conn.close()
    }

    @Test
    func decodeModelWithNil() async throws {
        let conn = try await PostgresConnection.test(on: self.eventLoop)

        await #expect(throws: Never.self) {
            let rows = try await conn.sql().raw("SELECT \(literal: "foo")::text as \(ident: "foo"), \(SQLLiteral.null) as \(ident: "bar"), \(literal: "baz")::text as \(ident: "baz")").all()
            let row = rows[0]

            struct Test: Codable {
                var foo: String
                var bar: String?
                var baz: String?
            }

            let test = try row.decode(model: Test.self)
            #expect(test.foo == "foo")
            #expect(test.bar == nil)
            #expect(test.baz == "baz")
        }
        try await conn.close()
    }

    @Test
    func eventLoopGroupSQL() async throws {
        var configuration = SQLPostgresConfiguration.test
        configuration.searchPath = ["foo", "bar", "baz"]
        let source = PostgresConnectionSource(sqlConfiguration: configuration)
        let pool = EventLoopGroupConnectionPool(source: source, on: MultiThreadedEventLoopGroup.singleton)
        let db = pool.database(logger: .init(label: "test")).sql()

        await #expect(throws: Never.self) {
            try await #expect(db.raw("SELECT version()").all().count == 1)
        }
        try await pool.shutdownAsync()
    }

    @Test
    func integerArrayEncoding() async throws {
        let connection = try await PostgresConnection.test(on: self.eventLoop)

        await #expect(throws: Never.self) {
            let sql = connection.sql()
            _ = try await sql.raw("DROP TABLE IF EXISTS \(ident: "foo")").run()
            try await sql.withSession { db in
                _ = try await db.create(table: "foo").column("bar", type: .custom(SQLRaw("bigint[]")), .notNull).run()
                _ = try await db.insert(into: "foo").columns("bar").values(SQLBind([Bar]())).run()
                let rows = try await connection.query("SELECT bar FROM foo", logger: connection.logger).collect()
                #expect(rows.count == 1)
                #expect(rows.first?.count == 1)
                #expect(rows.first?.first?.dataType == Bar.psqlArrayType)
                #expect(try rows.first?.first?.decode([Bar].self) == [Bar]())
            }
        }
        try await connection.close()
    }
    
    /// Tests dealing with encoding of values whose `encode(to:)` implementation calls one of the `superEncoder()`
    /// methods (most notably the implementation of `Codable` for Fluent's `Fields`, which we can't directly test
    /// at this layer).
    @Test
    func valuesThatUseSuperEncoder() throws {
        struct UnusualType: Codable {
            var prop1: String, prop2: [Bool], prop3: [[Bool]]
            
            // This is intentionally contrived - Fluent's implementation does Codable this roundabout way as a
            // workaround for the interaction of property wrappers with optional properties; it serves no purpose
            // here other than to demonstrate that the encoder supports it.
            private enum CodingKeys: String, CodingKey { case prop1, prop2, prop3 }
            init(prop1: String, prop2: [Bool], prop3: [[Bool]]) { (self.prop1, self.prop2, self.prop3) = (prop1, prop2, prop3) }
            init(from decoder: any Decoder) throws {
                let container = try decoder.container(keyedBy: CodingKeys.self)
                self.prop1 = try .init(from: container.superDecoder(forKey: .prop1))
                var acontainer = try container.nestedUnkeyedContainer(forKey: .prop2), ongoing: [Bool] = []
                while !acontainer.isAtEnd { ongoing.append(try Bool.init(from: acontainer.superDecoder())) }
                self.prop2 = ongoing
                var bcontainer = try container.nestedUnkeyedContainer(forKey: .prop3), bongoing: [[Bool]] = []
                while !bcontainer.isAtEnd {
                    var ccontainer = try bcontainer.nestedUnkeyedContainer(), congoing: [Bool] = []
                    while !ccontainer.isAtEnd { congoing.append(try Bool.init(from: ccontainer.superDecoder())) }
                    bongoing.append(congoing)
                }
                self.prop3 = bongoing
            }
            func encode(to encoder: any Encoder) throws {
                var container = encoder.container(keyedBy: CodingKeys.self)
                try self.prop1.encode(to: container.superEncoder(forKey: .prop1))
                var acontainer = container.nestedUnkeyedContainer(forKey: .prop2)
                for val in self.prop2 { try val.encode(to: acontainer.superEncoder()) }
                var bcontainer = container.nestedUnkeyedContainer(forKey: .prop3)
                for arr in self.prop3 {
                    var ccontainer = bcontainer.nestedUnkeyedContainer()
                    for val in arr { try val.encode(to: ccontainer.superEncoder()) }
                }
            }
        }
        
        let instance = UnusualType(prop1: "hello", prop2: [true, false, false, true], prop3: [[true, true], [false], [true], []])
        let encoded1 = try PostgresDataTranslation.encode(codingPath: [], userInfo: [:], value: instance, in: .default, file: #fileID, line: #line)
        let encoded2 = try PostgresDataTranslation.encode(codingPath: [], userInfo: [:], value: [instance, instance], in: .default, file: #fileID, line: #line)
        
        #expect(encoded1.type == .jsonb)
        #expect(encoded2.type == .jsonbArray)

        let decoded1 = try PostgresDataTranslation.decode(UnusualType.self, from: .init(bytes: encoded1.value, dataType: encoded1.type, format: encoded1.formatCode, columnName: "", columnIndex: -1), in: .default)
        let decoded2 = try PostgresDataTranslation.decode([UnusualType].self, from: .init(bytes: encoded2.value, dataType: encoded2.type, format: encoded2.formatCode, columnName: "", columnIndex: -1), in: .default)
        
        #expect(decoded1.prop3 == instance.prop3)
        #expect(decoded2.count == 2)
    }

    @Test
    func fluentWorkaroundsDecoding() throws {
        // SQLKit benchmarks already test enum handling
        
        // Text encoding for Decimal
        let decimalBuffer = ByteBuffer(string: Decimal(12345.6789).description)
        var decimalValue: Decimal?
        #expect(throws: Never.self) { decimalValue = try PostgresDataTranslation.decode(Decimal.self, from: .init(bytes: decimalBuffer, dataType: .numeric, format: .text, columnName: "", columnIndex: -1), in: .default) }
        #expect(decimalValue == Decimal(12345.6789))

        // Decoding Double from NUMERIC
        let numericBuffer = PostgresData(numeric: .init(decimal: 12345.6789)).value
        var numericValue: Double?
        #expect(throws: Never.self) { numericValue = try PostgresDataTranslation.decode(Double.self, from: .init(bytes: numericBuffer, dataType: .numeric, format: .binary, columnName: "", columnIndex: -1), in: .default) }
        #expect(numericValue == Double(Decimal(12345.6789).description))
    }

    @Test
    func urlWorkaroundDecoding() throws {
        let url = URL(string: "https://user:pass@www.example.com:8080/path/to/endpoint?query=value#fragment")!
        
        let encodedNormal = try PostgresDataTranslation.encode(codingPath: [], userInfo: [:], value: url, in: .default, file: #fileID, line: #line)
        #expect(encodedNormal.value?.getString(at: 0, length: encodedNormal.value?.readableBytes ?? 0) == url.absoluteString)

        let encodedBroken = try PostgresDataTranslation.encode(codingPath: [], userInfo: [:], value: "\"\(url.absoluteString)\"", in: .default, file: #fileID, line: #line)
        
        #expect(try PostgresDataTranslation.decode(URL.self, from: .init(with: encodedNormal), in: .default) == url)
        #expect(try PostgresDataTranslation.decode(URL.self, from: .init(with: encodedBroken), in: .default) == url)
    }

    /// This test is painful to write before Swift 6.1 due to #expect(throws:) not returning the thrown error.
    ///
    /// This test cares that:
    ///
    /// 1. The Swift type (i.e. `Foo`) is metnioned in the error's debug description.
    /// 2. The underlying error is included.
    #if swift(>=6.1)
    @Test
    func errorHandlingWhenDecodingNestedDictionary() throws {
        struct Foo: Codable {
            struct Bar: Codable { let id: Int }
            let bar: Bar
        }

        let error = try #require(throws: DecodingError.self) {
            _ = try PostgresDataTranslation.decode(Foo.self, from: .init(bytes: .init(integer: 0), dataType: .int8, format: .binary, columnName: "", columnIndex: 0), in: .default)
        }

        let context = try #require({ if case .dataCorrupted(let context) = error { context } else { nil } }())
        #expect(context.debugDescription == "Unable to interpret value of PSQL type BIGINT as Swift type Foo: [0000000000000000](8 bytes)")

        let underContext = try #require({ if case .dataCorrupted(let context2) = context.underlyingError as? DecodingError { context2 } else { nil } }())
        #expect(underContext.debugDescription == "Dictionary containers must be JSON-encoded")
    }
    #endif

    var eventLoop: any EventLoop {
        MultiThreadedEventLoopGroup.singleton.any()
    }

    init() {
        #expect(isLoggingConfigured)
    }
}

}

extension PostgresCell {
    fileprivate init(with data: PostgresData) {
        self.init(bytes: data.value, dataType: data.type, format: data.formatCode, columnName: "", columnIndex: -1)
    }
}

enum Bar: Int, Codable {
    case one, two
}

extension Bar: PostgresNonThrowingEncodable, PostgresArrayEncodable, PostgresDecodable, PostgresArrayDecodable {
    func encode(into byteBuffer: inout ByteBuffer, context: PostgresEncodingContext<some PostgresJSONEncoder>) {
        self.rawValue.encode(into: &byteBuffer, context: context)
    }
    
    init(from byteBuffer: inout ByteBuffer, type: PostgresDataType, format: PostgresFormat, context: PostgresDecodingContext<some PostgresJSONDecoder>) throws {
        guard let value = try Self.init(rawValue: Self.RawValue.init(from: &byteBuffer, type: type, format: format, context: context)) else {
            throw PostgresDecodingError.Code.failure
        }
        self = value
    }
    
    static var psqlType: PostgresDataType { .int8 }
    static var psqlFormat: PostgresFormat { .binary }
    static var psqlArrayType: PostgresDataType { .int8Array }
}


================================================
FILE: Tests/PostgresKitTests/SQLPostgresConfigurationTests.swift
================================================
import PostgresKit
import Testing

extension AllSuites {
@Suite
struct SQLPostgresConfigurationTests {
    @Test
    func urlHandling() throws {
        let config1 = try SQLPostgresConfiguration(url: "postgres+tcp://test_username:test_password@test_hostname:9999/test_database?tlsmode=disable")
        #expect(config1.coreConfiguration.database == "test_database")
        #expect(config1.coreConfiguration.password == "test_password")
        #expect(config1.coreConfiguration.username == "test_username")
        #expect(config1.coreConfiguration.host == "test_hostname")
        #expect(config1.coreConfiguration.port == 9999)
        #expect(config1.coreConfiguration.unixSocketPath == nil)
        #expect(!config1.coreConfiguration.tls.isAllowed)
        #expect(!config1.coreConfiguration.tls.isEnforced)

        let config2 = try SQLPostgresConfiguration(url: "postgres+tcp://test_username@test_hostname")
        #expect(config2.coreConfiguration.database == nil)
        #expect(config2.coreConfiguration.password == nil)
        #expect(config2.coreConfiguration.username == "test_username")
        #expect(config2.coreConfiguration.host == "test_hostname")
        #expect(config2.coreConfiguration.port == SQLPostgresConfiguration.ianaPortNumber)
        #expect(config2.coreConfiguration.unixSocketPath == nil)
        #expect(config2.coreConfiguration.tls.isAllowed)
        #expect(!config2.coreConfiguration.tls.isEnforced)

        let config3 = try SQLPostgresConfiguration(url: "postgres+uds://test_username:test_password@localhost/tmp/postgres.sock?tlsmode=require#test_database")
        #expect(config3.coreConfiguration.database == "test_database")
        #expect(config3.coreConfiguration.password == "test_password")
        #expect(config3.coreConfiguration.username == "test_username")
        #expect(config3.coreConfiguration.host == nil)
        #expect(config3.coreConfiguration.port == nil)
        #expect(config3.coreConfiguration.unixSocketPath == "/tmp/postgres.sock")
        #expect(config3.coreConfiguration.tls.isAllowed)
        #expect(config3.coreConfiguration.tls.isEnforced)

        let config4 = try SQLPostgresConfiguration(url: "postgres+uds://test_username@/tmp/postgres.sock")
        #expect(config4.coreConfiguration.database == nil)
        #expect(config4.coreConfiguration.password == nil)
        #expect(config4.coreConfiguration.username == "test_username")
        #expect(config4.coreConfiguration.host == nil)
        #expect(config4.coreConfiguration.port == nil)
        #expect(config4.coreConfiguration.unixSocketPath == "/tmp/postgres.sock")
        #expect(!config4.coreConfiguration.tls.isAllowed)
        #expect(!config4.coreConfiguration.tls.isEnforced)

        for modestr in ["tlsmode=false", "tlsmode=verify-full&tlsmode=disable"] {
            let config = try SQLPostgresConfiguration(url: "postgres://u@h?\(modestr)")
            #expect(!config.coreConfiguration.tls.isAllowed)
            #expect(!config.coreConfiguration.tls.isEnforced)
        }

        for modestr in ["tlsmode=prefer", "tlsmode=allow", "tlsmode=true"] {
            let config = try SQLPostgresConfiguration(url: "postgres://u@h?\(modestr)")
            #expect(config.coreConfiguration.tls.isAllowed)
            #expect(!config.coreConfiguration.tls.isEnforced)
        }

        for modestr in ["tlsmode=require", "tlsmode=verify-ca", "tlsmode=verify-full", "tls=verify-full", "ssl=verify-full", "tlsmode=prefer&sslmode=verify-full"] {
            let config = try SQLPostgresConfiguration(url: "postgres://u@h?\(modestr)")
            #expect(config.coreConfiguration.tls.isAllowed)
            #expect(config.coreConfiguration.tls.isEnforced)
        }
        
        #expect(throws: Never.self) { try SQLPostgresConfiguration(url: "postgresql://test_username@test_hostname") }
        #expect(throws: Never.self) { try SQLPostgresConfiguration(url: "postgresql+tcp://test_username@test_hostname") }
        #expect(throws: Never.self) { try SQLPostgresConfiguration(url: "postgresql+uds://test_username@/tmp/postgres.sock") }

        #expect(throws: (any Error).self, "should fail when username missing") { try SQLPostgresConfiguration(url: "postgres+tcp://test_hostname") }
        #expect(throws: (any Error).self, "should fail when TLS mode invalid") { try SQLPostgresConfiguration(url: "postgres+tcp://test_username@test_hostname?tlsmode=absurd") }
        #expect(throws: (any Error).self, "should fail when username missing") { try SQLPostgresConfiguration(url: "postgres+uds://localhost/tmp/postgres.sock?tlsmode=require") }
        #expect(throws: (any Error).self, "should fail when authority missing") { try SQLPostgresConfiguration(url: "postgres+uds:///tmp/postgres.sock") }
        #expect(throws: (any Error).self, "should fail when path missing") { try SQLPostgresConfiguration(url: "postgres+uds://username@localhost/") }
        #expect(throws: (any Error).self, "should fail when authority not localhost or empty") { try SQLPostgresConfiguration(url: "postgres+uds://username@remotehost/tmp") }
    }

    init() {
        #expect(isLoggingConfigured)
    }
}
}


================================================
FILE: Tests/PostgresKitTests/Utilities.swift
================================================
import Foundation
import Logging
import NIOCore
import PostgresKit
import PostgresNIO
import Testing

extension PostgresConnection {
    static func test(on eventLoop: any EventLoop) async throws -> PostgresConnection {
        try await PostgresConnectionSource(sqlConfiguration: .test).makeConnection(
            logger: .init(label: "vapor.codes.postgres-kit.test"),
            on: eventLoop
        ).get()
    }
}

extension SQLPostgresConfiguration {
    static var test: Self {
        .init(
            hostname: env("POSTGRES_HOSTNAME") ?? "localhost",
            port: env("POSTGRES_PORT").flatMap(Int.init) ?? Self.ianaPortNumber,
            username: env("POSTGRES_USER") ?? "test_username",
            password: env("POSTGRES_PASSWORD") ?? "test_password",
            database: env("POSTGRES_DB") ?? "test_database",
            tls: .disable
        )
    }
}

func env(_ name: String) -> String? {
    ProcessInfo.processInfo.environment[name]
}

let isLoggingConfigured: Bool = {
    LoggingSystem.bootstrap { QuickLogHandler(label: $0, level: env("LOG_LEVEL").flatMap { .init(rawValue: $0) } ?? .info) }
    return true
}()

struct QuickLogHandler: LogHandler {
    private let label: String
    var logLevel = Logger.Level.info, metadataProvider = LoggingSystem.metadataProvider, metadata = Logger.Metadata()
    subscript(metadataKey key: String) -> Logger.Metadata.Value? { get { self.metadata[key] } set { self.metadata[key] = newValue } }
    init(label: String, level: Logger.Level) { (self.label, self.logLevel) = (label, level) }
    func log(level: Logger.Level, message: Logger.Message, metadata: Logger.Metadata?, source: String, file: String, function: String, line: UInt) {
        print("\(self.timestamp()) \(level) \(self.label):\(self.prettify(metadata ?? [:]).map { " \($0)" } ?? "") [\(source)] \(message)")
    }
    private func prettify(_ metadata: Logger.Metadata) -> String? {
        self.metadata.merging(self.metadataProvider?.get() ?? [:]) { $1 }.merging(metadata) { $1 }.sorted { $0.0 < $1.0 }.map { "\($0)=\($1.mvDesc)" }.joined(separator: " ")
    }
    private func timestamp() -> String { .init(unsafeUninitializedCapacity: 255) { buffer in
        var timestamp = time(nil)
        return localtime(&timestamp).map { strftime(buffer.baseAddress!, buffer.count, "%Y-%m-%dT%H:%M:%S%z", $0) } ?? buffer.initialize(fromContentsOf: "<unknown>".utf8)
    } }
}
extension Logger.MetadataValue {
    var mvDesc: String { switch self {
        case .dictionary(let dict): "[\(dict.mapValues(\.mvDesc).lazy.sorted { $0.0 < $1.0 }.map { "\($0): \($1)" }.joined(separator: ", "))]"
        case .array(let list): "[\(list.map(\.mvDesc).joined(separator: ", "))]"
        case .string(let str): #""\#(str)""#
        case .stringConvertible(let repr): switch repr {
            case let repr as Bool: "\(repr)"
            case let repr as any FixedWidthInteger: "\(repr)"
            case let repr as any BinaryFloatingPoint: "\(repr)"
            default: #""\#(String(describing: repr))""#
        }
    } }
}

@Suite(.serialized)
struct AllSuites {}
Download .txt
gitextract_j417607q/

├── .github/
│   ├── CODEOWNERS
│   ├── dependabot.yml
│   └── workflows/
│       ├── api-docs.yml
│       └── test.yml
├── .gitignore
├── .spi.yml
├── LICENSE
├── Package.swift
├── README.md
├── Sources/
│   └── PostgresKit/
│       ├── ConnectionPool+Postgres.swift
│       ├── Deprecations/
│       │   ├── PostgresColumnType.swift
│       │   ├── PostgresConfiguration.swift
│       │   ├── PostgresConnectionSource+PostgresConfiguration.swift
│       │   ├── PostgresDataDecoder.swift
│       │   ├── PostgresDataEncoder.swift
│       │   └── PostgresDatabase+SQL+Deprecated.swift
│       ├── Docs.docc/
│       │   ├── PostgresKit.md
│       │   └── theme-settings.json
│       ├── Exports.swift
│       ├── PostgresConnectionSource.swift
│       ├── PostgresDataTranslation.swift
│       ├── PostgresDatabase+SQL.swift
│       ├── PostgresDialect.swift
│       ├── PostgresRow+SQL.swift
│       └── SQLPostgresConfiguration.swift
└── Tests/
    └── PostgresKitTests/
        ├── PostgresKitTests.swift
        ├── SQLPostgresConfigurationTests.swift
        └── Utilities.swift
Condensed preview — 28 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (130K chars).
[
  {
    "path": ".github/CODEOWNERS",
    "chars": 338,
    "preview": "*                            @gwynne\n/.github/CONTRIBUTING.md     @gwynne @0xTim\n/.github/workflows/*.yml     @gwynne @0"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 183,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n   "
  },
  {
    "path": ".github/workflows/api-docs.yml",
    "chars": 356,
    "preview": "name: deploy-api-docs\non:\n  push:\n    branches:\n      - main\npermissions:\n  contents: read\n  id-token: write\n\njobs:\n  bu"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 5944,
    "preview": "name: test\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\non:\n  pull_request:"
  },
  {
    "path": ".gitignore",
    "chars": 101,
    "preview": ".DS_Store\n/.build\n/Packages\n/*.xcodeproj\nPackage.resolved\nDerivedData\n.swiftpm\nTests/LinuxMain.swift\n"
  },
  {
    "path": ".spi.yml",
    "chars": 223,
    "preview": "version: 1\nmetadata:\n  authors: \"Maintained by the Vapor Core Team with hundreds of contributions from the Vapor Communi"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2018 Qutheory, LLC\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "Package.swift",
    "chars": 1589,
    "preview": "// swift-tools-version:6.0\nimport PackageDescription\n\nlet package = Package(\n    name: \"postgres-kit\",\n    platforms: [\n"
  },
  {
    "path": "README.md",
    "chars": 7887,
    "preview": "<p align=\"center\">\n<img src=\"https://design.vapor.codes/images/vapor-postgreskit.svg\" height=\"96\" alt=\"PostgresKit\">\n<br"
  },
  {
    "path": "Sources/PostgresKit/ConnectionPool+Postgres.swift",
    "chars": 1780,
    "preview": "@preconcurrency import AsyncKit\nimport Logging\nimport NIOCore\nimport PostgresNIO\n\nextension EventLoopGroupConnectionPool"
  },
  {
    "path": "Sources/PostgresKit/Deprecations/PostgresColumnType.swift",
    "chars": 12582,
    "preview": "import SQLKit\n\n/// Postgres-specific column types.\n@available(*, deprecated, message: \"Use `PostgresDataType` instead.\")"
  },
  {
    "path": "Sources/PostgresKit/Deprecations/PostgresConfiguration.swift",
    "chars": 2868,
    "preview": "import Foundation\nimport NIOCore\nimport NIOSSL\n\n@available(*, deprecated, message: \"Use `SQLPostgresConfiguration` inste"
  },
  {
    "path": "Sources/PostgresKit/Deprecations/PostgresConnectionSource+PostgresConfiguration.swift",
    "chars": 3787,
    "preview": "import Atomics\nimport Logging\nimport NIOCore\nimport NIOSSL\nimport PostgresNIO\n\nextension PostgresConnectionSource {\n    "
  },
  {
    "path": "Sources/PostgresKit/Deprecations/PostgresDataDecoder.swift",
    "chars": 5797,
    "preview": "import Foundation\nimport PostgresNIO\n\n@available(*, deprecated, message: \"Use `PostgresDecodingContext` instead.\")\npubli"
  },
  {
    "path": "Sources/PostgresKit/Deprecations/PostgresDataEncoder.swift",
    "chars": 7657,
    "preview": "import Foundation\nimport PostgresNIO\n\n@available(*, deprecated, message: \"Use `PostgresJSONEncoder` and `PostgresEncodab"
  },
  {
    "path": "Sources/PostgresKit/Deprecations/PostgresDatabase+SQL+Deprecated.swift",
    "chars": 1986,
    "preview": "import Foundation\nimport PostgresNIO\nimport SQLKit\n\n@available(*, deprecated, message: \"Use `.sql(jsonEncoder:jsonDecode"
  },
  {
    "path": "Sources/PostgresKit/Docs.docc/PostgresKit.md",
    "chars": 6942,
    "preview": "# ``PostgresKit``\n\n@Metadata {\n    @TitleHeading(Package)\n}\n\nPostgresKit is an [SQLKit] driver for PostgreSQL clients.\n\n"
  },
  {
    "path": "Sources/PostgresKit/Docs.docc/theme-settings.json",
    "chars": 997,
    "preview": "{\n  \"theme\": {\n    \"aside\": { \"border-radius\": \"16px\", \"border-width\": \"3px\", \"border-style\": \"double\" },\n    \"border-ra"
  },
  {
    "path": "Sources/PostgresKit/Exports.swift",
    "chars": 274,
    "preview": "@_documentation(visibility: internal) @_exported import AsyncKit\n@_documentation(visibility: internal) @_exported import"
  },
  {
    "path": "Sources/PostgresKit/PostgresConnectionSource.swift",
    "chars": 1345,
    "preview": "import AsyncKit\nimport Logging\nimport NIOConcurrencyHelpers\nimport NIOCore\nimport NIOSSL\nimport PostgresNIO\nimport SQLKi"
  },
  {
    "path": "Sources/PostgresKit/PostgresDataTranslation.swift",
    "chars": 22415,
    "preview": "import Foundation\nimport PostgresNIO\n\n/// Quick and dirty `CodingKey`, borrowed from FluentKit. If `CodingKeyRepresentab"
  },
  {
    "path": "Sources/PostgresKit/PostgresDatabase+SQL.swift",
    "chars": 4091,
    "preview": "import Logging\nimport PostgresNIO\nimport SQLKit\n\nextension PostgresDatabase {\n    @inlinable\n    public func sql(queryLo"
  },
  {
    "path": "Sources/PostgresKit/PostgresDialect.swift",
    "chars": 2974,
    "preview": "import SQLKit\n\npublic struct PostgresDialect: SQLDialect {\n    public init() {}\n\n    public var name: String {\n        \""
  },
  {
    "path": "Sources/PostgresKit/PostgresRow+SQL.swift",
    "chars": 1326,
    "preview": "import Foundation\nimport PostgresNIO\nimport SQLKit\n\nextension PostgresRow {\n    @inlinable\n    public func sql() -> some"
  },
  {
    "path": "Sources/PostgresKit/SQLPostgresConfiguration.swift",
    "chars": 8428,
    "preview": "import Foundation\nimport NIOCore\nimport NIOSSL\nimport PostgresNIO\n\n/// Provides configuration paramters for establishing"
  },
  {
    "path": "Tests/PostgresKitTests/PostgresKitTests.swift",
    "chars": 13280,
    "preview": "import Foundation\nimport Logging\nimport NIOCore\nimport PostgresNIO\nimport SQLKitBenchmark\nimport Testing\n@testable impor"
  },
  {
    "path": "Tests/PostgresKitTests/SQLPostgresConfigurationTests.swift",
    "chars": 5150,
    "preview": "import PostgresKit\nimport Testing\n\nextension AllSuites {\n@Suite\nstruct SQLPostgresConfigurationTests {\n    @Test\n    fun"
  },
  {
    "path": "Tests/PostgresKitTests/Utilities.swift",
    "chars": 3099,
    "preview": "import Foundation\nimport Logging\nimport NIOCore\nimport PostgresKit\nimport PostgresNIO\nimport Testing\n\nextension Postgres"
  }
]

About this extraction

This page contains the full source code of the vapor/postgres-kit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 28 files (121.6 KB), approximately 29.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!