Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve docs #468

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ let client = PostgresClient(configuration: config)
Once you have create your client, you must [`run()`] it:
```swift
await withTaskGroup(of: Void.self) { taskGroup in
taskGroup.addTask {
await client.run() // !important
}
taskGroup.addTask {
await client.run() // !important
}

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

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

Expand Down
9 changes: 9 additions & 0 deletions Snippets/PostgresQuery-unescaped.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import PostgresNIO

// snippet.unescaped
let id = 10000
let tableName = "users"
let query: PostgresQuery = """
SELECT id, username, birthday FROM \(unescaped: tableName) WHERE id < \(id);
"""
// snippet.end
9 changes: 9 additions & 0 deletions Snippets/PostgresQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import PostgresNIO

// snippet.select1
let id = 10000
let query: PostgresQuery = """
SELECT id, username, birthday FROM users WHERE id < \(id);
"""
// snippet.end

2 changes: 1 addition & 1 deletion Sources/PostgresNIO/Docs.docc/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ have changed. The introduction of structured concurrency changed what developers
modern Swift library. Because of this ``PostgresNIO`` added various APIs that embrace the new Swift
patterns. This means however, that PostgresNIO still offers APIs that have fallen out of favor.
Those are documented here. All those APIs will be removed once the maintainers release the next
major version. The maintainers recommend all adopters to move of those APIs sooner rather than
major version. The maintainers recommend all adopters to move off those APIs sooner rather than
later.

## Topics
Expand Down
1 change: 0 additions & 1 deletion Sources/PostgresNIO/Docs.docc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ configure ``PostgresConnection`` to use `Network.framework` as the underlying tr
### Essentials

- ``PostgresClient``
- ``PostgresClient/Configuration``
- ``PostgresConnection``
- <doc:running-queries>

Expand Down
12 changes: 10 additions & 2 deletions Sources/PostgresNIO/Docs.docc/running-queries.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
# Running Queries
# Running Statements

Interact with the PostgreSQL database by running Queries.

## Overview

You run statements on a PostgreSQL database, by:

1. Creating a connection to the Postgres database by creating a ``PostgresClient`` or
``PostgresConnection``

You interact with the Postgres database by running SQL [Queries].

A ``PostgresQuery`` consists out of the ``PostgresQuery/sql`` statement and the
``PostgresQuery/binds``, which are the parameters for the sql statement.

Users should create ``PostgresQuery``s in most cases through String interpolation:

@Snippet(path: "postgres-nio/Snippets/PostgresQuery", slice: "select1")


``PostgresQuery`` conforms to


## Topics
Expand Down
57 changes: 54 additions & 3 deletions Sources/PostgresNIO/New/PostgresQuery.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,62 @@
import NIOCore

/// A Postgres SQL query, that can be executed on a Postgres server. Contains the raw sql string and bindings.
/// A PostgreSQL statement, that can be executed on a database. Contains the raw ``PostgresQuery/sql`` statement
/// and ``PostgresQuery/binds``, that are the parameters for the statement.
///
/// ## Creating a Query
///
/// #### Using string interpolation
///
/// Users should create ``PostgresQuery``s in most cases through string interpolation:
///
/// @Snippet(path: "postgres-nio/Snippets/PostgresQuery", slice: "select1")
///
/// While this looks at first glance like a classic case of [SQL injection](https://en.wikipedia.org/wiki/SQL_injection)
/// 😱, PostgresNIO ensures that this usage is safe.
/// The reason for this is, that ``PostgresQuery`` implements Swift's `ExpressibleByStringInterpolation`
/// protocol. ``PostgresQuery`` uses the literal parts of the provided string as the SQL query and replaces each interpolated
/// value with a parameter binding. Only values which implement the ``PostgresEncodable`` protocol may be interpolated
/// in this way.
///
/// ###### Interpolating non parameter values
///
/// Sometimes you need to interpolate parts of your query that can not be send to the server as an SQL binding. An example could
/// be the table name. In those cases add the `\(unescaped:)` keyword in front of your value.
///
/// @Snippet(path: "postgres-nio/Snippets/PostgresQuery-unescaped", slice: "unescaped")
///
/// > Warning:
/// Always make sure, that values passed via `\(unescaped:)` interpolations are trusted. Passing untrusted values can allow
/// [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
///
/// #### Manually creating a PostgresQuery
///
/// ``PostgresQuery`` can be created manually using the ``PostgresQuery/init(unsafeSQL:binds:)`` initializer.
/// In those cases ``PostgresQuery`` will not perform any validation on the provided SQL statement. Users must make sure
/// that their SQL is safe to execute.
public struct PostgresQuery: Sendable, Hashable {
/// The query string
/// A raw SQL statement
///
/// >Note:
/// Since ``PostgresNIO`` only supports the
/// [Extended Query](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY)
/// flow, only a single sql statement is allowed. In other words: SQL statement batches will lead to server
/// errors at all times.
public var sql: String
/// The query binds

/// The parameters for the ``PostgresQuery/sql`` statement.
public var binds: PostgresBindings

/// Create a ``PostgresQuery`` with a SQL statement string and bindings as ``PostgresBindings``
///
/// > Warning:
/// If you use string interpolation or generate the SQL statement through concatenating strings, it is your
/// responsibility to ensure that you are not prone to [SQL injection](https://en.wikipedia.org/wiki/SQL_injection)
/// attacks.
///
/// - Parameters:
/// - sql: The SQL statement to execute.
/// - binds: The bindings for the SQL statement.
public init(unsafeSQL sql: String, binds: PostgresBindings = PostgresBindings()) {
self.sql = sql
self.binds = binds
Expand Down Expand Up @@ -118,6 +168,7 @@ struct PSQLExecuteStatement {
var rowDescription: RowDescription?
}

/// Parameters/bindings for a ``PostgresQuery/sql`` statement.
public struct PostgresBindings: Sendable, Hashable {
@usableFromInline
struct Metadata: Sendable, Hashable {
Expand Down
2 changes: 1 addition & 1 deletion Tests/IntegrationTests/AsyncTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ final class AsyncPostgresConnectionTests: XCTestCase {
"foo",
"default"
]

let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
let eventLoop = eventLoopGroup.next()
Expand Down