From 80ceec0025308645d6792a3a711754d174b137f6 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:05:32 +0100 Subject: [PATCH 01/17] Remove `PostgresDatabase` --- .../Connection/PostgresConnection.swift | 138 - .../PostgresDatabase+PreparedQuery.swift | 79 - Sources/PostgresNIO/Pool/PostgresClient.swift | 2 +- .../PostgresNIO/PostgresDatabase+Query.swift | 109 - .../PostgresDatabase+SimpleQuery.swift | 19 - Sources/PostgresNIO/PostgresDatabase.swift | 39 - .../PostgresNIO/PostgresQueryMetadata.swift | 45 + .../PSQLIntegrationTests.swift | 625 ++-- Tests/IntegrationTests/PerformanceTests.swift | 310 -- Tests/IntegrationTests/PostgresNIOTests.swift | 2570 ++++++++--------- 10 files changed, 1643 insertions(+), 2293 deletions(-) delete mode 100644 Sources/PostgresNIO/Connection/PostgresDatabase+PreparedQuery.swift delete mode 100644 Sources/PostgresNIO/PostgresDatabase+Query.swift delete mode 100644 Sources/PostgresNIO/PostgresDatabase+SimpleQuery.swift delete mode 100644 Sources/PostgresNIO/PostgresDatabase.swift create mode 100644 Sources/PostgresNIO/PostgresQueryMetadata.swift delete mode 100644 Tests/IntegrationTests/PerformanceTests.swift diff --git a/Sources/PostgresNIO/Connection/PostgresConnection.swift b/Sources/PostgresNIO/Connection/PostgresConnection.swift index f79a5555..eaf3b9f6 100644 --- a/Sources/PostgresNIO/Connection/PostgresConnection.swift +++ b/Sources/PostgresNIO/Connection/PostgresConnection.swift @@ -529,144 +529,6 @@ extension PostgresConnection { } } -// MARK: EventLoopFuture interface - -extension PostgresConnection { - - /// Run a query on the Postgres server the connection is connected to and collect all rows. - /// - /// - Parameters: - /// - query: The ``PostgresQuery`` to run - /// - logger: The `Logger` to log into for the query - /// - file: The file, the query was started in. Used for better error reporting. - /// - line: The line, the query was started in. Used for better error reporting. - /// - Returns: An EventLoopFuture, that allows access to the future ``PostgresQueryResult``. - public func query( - _ query: PostgresQuery, - logger: Logger, - file: String = #fileID, - line: Int = #line - ) -> EventLoopFuture { - self.queryStream(query, logger: logger).flatMap { rowStream in - rowStream.all().flatMapThrowing { rows -> PostgresQueryResult in - guard let metadata = PostgresQueryMetadata(string: rowStream.commandTag) else { - throw PSQLError.invalidCommandTag(rowStream.commandTag) - } - return PostgresQueryResult(metadata: metadata, rows: rows) - } - }.enrichPSQLError(query: query, file: file, line: line) - } - - /// Run a query on the Postgres server the connection is connected to and iterate the rows in a callback. - /// - /// - Note: This API does not support back-pressure. If you need back-pressure please use the query - /// API, that supports structured concurrency. - /// - Parameters: - /// - query: The ``PostgresQuery`` to run - /// - logger: The `Logger` to log into for the query - /// - file: The file, the query was started in. Used for better error reporting. - /// - line: The line, the query was started in. Used for better error reporting. - /// - onRow: A closure that is invoked for every row. - /// - Returns: An EventLoopFuture, that allows access to the future ``PostgresQueryMetadata``. - @preconcurrency - public func query( - _ query: PostgresQuery, - logger: Logger, - file: String = #fileID, - line: Int = #line, - _ onRow: @escaping @Sendable (PostgresRow) throws -> () - ) -> EventLoopFuture { - self.queryStream(query, logger: logger).flatMap { rowStream in - rowStream.onRow(onRow).flatMapThrowing { () -> PostgresQueryMetadata in - guard let metadata = PostgresQueryMetadata(string: rowStream.commandTag) else { - throw PSQLError.invalidCommandTag(rowStream.commandTag) - } - return metadata - } - }.enrichPSQLError(query: query, file: file, line: line) - } -} - -// MARK: PostgresDatabase conformance - -extension PostgresConnection: PostgresDatabase { - public func send( - _ request: PostgresRequest, - logger: Logger - ) -> EventLoopFuture { - guard let command = request as? PostgresCommands else { - preconditionFailure("\(#function) requires an instance of PostgresCommands. This will be a compile-time error in the future.") - } - - let resultFuture: EventLoopFuture - - switch command { - case .query(let query, let onMetadata, let onRow): - resultFuture = self.queryStream(query, logger: logger).flatMap { stream in - return stream.onRow(onRow).map { _ in - onMetadata(PostgresQueryMetadata(string: stream.commandTag)!) - } - } - - case .queryAll(let query, let onResult): - resultFuture = self.queryStream(query, logger: logger).flatMap { rows in - return rows.all().map { allrows in - onResult(.init(metadata: PostgresQueryMetadata(string: rows.commandTag)!, rows: allrows)) - } - } - - case .prepareQuery(let request): - resultFuture = self.prepareStatement(request.query, with: request.name, logger: logger).map { - request.prepared = PreparedQuery(underlying: $0, database: self) - } - - case .executePreparedStatement(let preparedQuery, let binds, let onRow): - var bindings = PostgresBindings(capacity: binds.count) - binds.forEach { bindings.append($0) } - - let statement = PSQLExecuteStatement( - name: preparedQuery.underlying.name, - binds: bindings, - rowDescription: preparedQuery.underlying.rowDescription - ) - - resultFuture = self.execute(statement, logger: logger).flatMap { rows in - return rows.onRow(onRow) - } - } - - return resultFuture.flatMapErrorThrowing { error in - throw error.asAppropriatePostgresError - } - } - - @preconcurrency - public func withConnection(_ closure: (PostgresConnection) -> EventLoopFuture) -> EventLoopFuture { - closure(self) - } -} - -internal enum PostgresCommands: PostgresRequest { - case query(PostgresQuery, - onMetadata: @Sendable (PostgresQueryMetadata) -> () = { _ in }, - onRow: @Sendable (PostgresRow) throws -> ()) - case queryAll(PostgresQuery, onResult: @Sendable (PostgresQueryResult) -> ()) - case prepareQuery(request: PrepareQueryRequest) - case executePreparedStatement(query: PreparedQuery, binds: [PostgresData], onRow: @Sendable (PostgresRow) throws -> ()) - - func respond(to message: PostgresMessage) throws -> [PostgresMessage]? { - fatalError("This function must not be called") - } - - func start() throws -> [PostgresMessage] { - fatalError("This function must not be called") - } - - func log(to logger: Logger) { - fatalError("This function must not be called") - } -} - // MARK: Notifications /// Context for receiving NotificationResponse messages on a connection, used for PostgreSQL's `LISTEN`/`NOTIFY` support. diff --git a/Sources/PostgresNIO/Connection/PostgresDatabase+PreparedQuery.swift b/Sources/PostgresNIO/Connection/PostgresDatabase+PreparedQuery.swift deleted file mode 100644 index 56496172..00000000 --- a/Sources/PostgresNIO/Connection/PostgresDatabase+PreparedQuery.swift +++ /dev/null @@ -1,79 +0,0 @@ -import NIOCore -import NIOConcurrencyHelpers -import struct Foundation.UUID - -extension PostgresDatabase { - public func prepare(query: String) -> EventLoopFuture { - let name = "nio-postgres-\(UUID().uuidString)" - let request = PrepareQueryRequest(query, as: name) - return self.send(PostgresCommands.prepareQuery(request: request), logger: self.logger).map { _ in - // we can force unwrap the prepared here, since in a success case it must be set - // in the send method of `PostgresDatabase`. We do this dirty trick to work around - // the fact that the send method only returns an `EventLoopFuture`. - // Eventually we should move away from the `PostgresDatabase.send` API. - request.prepared! - } - } - - @preconcurrency - public func prepare(query: String, handler: @Sendable @escaping (PreparedQuery) -> EventLoopFuture<[[PostgresRow]]>) -> EventLoopFuture<[[PostgresRow]]> { - prepare(query: query) - .flatMap { preparedQuery in - handler(preparedQuery) - .flatMap { results in - preparedQuery.deallocate().map { results } - } - } - } -} - - -public struct PreparedQuery: Sendable { - let underlying: PSQLPreparedStatement - let database: PostgresDatabase - - init(underlying: PSQLPreparedStatement, database: PostgresDatabase) { - self.underlying = underlying - self.database = database - } - - public func execute(_ binds: [PostgresData] = []) -> EventLoopFuture<[PostgresRow]> { - let rowsBoxed = NIOLockedValueBox([PostgresRow]()) - return self.execute(binds) { row in - rowsBoxed.withLockedValue { - $0.append(row) - } - }.map { rowsBoxed.withLockedValue { $0 } } - } - - @preconcurrency - public func execute(_ binds: [PostgresData] = [], _ onRow: @Sendable @escaping (PostgresRow) throws -> ()) -> EventLoopFuture { - let command = PostgresCommands.executePreparedStatement(query: self, binds: binds, onRow: onRow) - return self.database.send(command, logger: self.database.logger) - } - - public func deallocate() -> EventLoopFuture { - self.underlying.connection.close(.preparedStatement(self.underlying.name), logger: self.database.logger) - } -} - -final class PrepareQueryRequest: Sendable { - let query: String - let name: String - var prepared: PreparedQuery? { - get { - self._prepared.withLockedValue { $0 } - } - set { - self._prepared.withLockedValue { - $0 = newValue - } - } - } - let _prepared: NIOLockedValueBox = .init(nil) - - init(_ query: String, as name: String) { - self.query = query - self.name = name - } -} diff --git a/Sources/PostgresNIO/Pool/PostgresClient.swift b/Sources/PostgresNIO/Pool/PostgresClient.swift index fc5a5b00..ad252ee7 100644 --- a/Sources/PostgresNIO/Pool/PostgresClient.swift +++ b/Sources/PostgresNIO/Pool/PostgresClient.swift @@ -332,7 +332,7 @@ struct PostgresKeepAliveBehavor: ConnectionKeepAliveBehavior { } func runKeepAlive(for connection: PostgresConnection) async throws { - try await connection.query(self.behavior!.query, logger: self.logger).map { _ in }.get() + try await connection.query(self.behavior!.query, logger: self.logger) } } diff --git a/Sources/PostgresNIO/PostgresDatabase+Query.swift b/Sources/PostgresNIO/PostgresDatabase+Query.swift deleted file mode 100644 index 01a7e61f..00000000 --- a/Sources/PostgresNIO/PostgresDatabase+Query.swift +++ /dev/null @@ -1,109 +0,0 @@ -import NIOCore -import Logging -import NIOConcurrencyHelpers - -extension PostgresDatabase { - public func query( - _ string: String, - _ binds: [PostgresData] = [] - ) -> EventLoopFuture { - let box = NIOLockedValueBox((metadata: PostgresQueryMetadata?.none, rows: [PostgresRow]())) - - return self.query(string, binds, onMetadata: { metadata in - box.withLockedValue { - $0.metadata = metadata - } - }) { row in - box.withLockedValue { - $0.rows.append(row) - } - }.map { - box.withLockedValue { - PostgresQueryResult(metadata: $0.metadata!, rows: $0.rows) - } - } - } - - @preconcurrency - public func query( - _ string: String, - _ binds: [PostgresData] = [], - onMetadata: @Sendable @escaping (PostgresQueryMetadata) -> () = { _ in }, - onRow: @Sendable @escaping (PostgresRow) throws -> () - ) -> EventLoopFuture { - var bindings = PostgresBindings(capacity: binds.count) - binds.forEach { bindings.append($0) } - let query = PostgresQuery(unsafeSQL: string, binds: bindings) - let request = PostgresCommands.query(query, onMetadata: onMetadata, onRow: onRow) - - return self.send(request, logger: logger) - } -} - -public struct PostgresQueryResult { - public let metadata: PostgresQueryMetadata - public let rows: [PostgresRow] -} - -extension PostgresQueryResult: Collection { - public typealias Index = Int - public typealias Element = PostgresRow - - public var startIndex: Int { - self.rows.startIndex - } - - public var endIndex: Int { - self.rows.endIndex - } - - public subscript(position: Int) -> PostgresRow { - self.rows[position] - } - - public func index(after i: Int) -> Int { - self.rows.index(after: i) - } -} - -public struct PostgresQueryMetadata: Sendable { - public let command: String - public var oid: Int? - public var rows: Int? - - init?(string: String) { - let parts = string.split(separator: " ") - guard parts.count >= 1 else { - return nil - } - switch parts[0] { - case "INSERT": - // INSERT oid rows - guard parts.count == 3 else { - return nil - } - self.command = .init(parts[0]) - self.oid = Int(parts[1]) - self.rows = Int(parts[2]) - case "SELECT" where parts.count == 1: - // AWS Redshift does not return the actual row count as defined in the postgres wire spec for SELECT: - // https://www.postgresql.org/docs/13/protocol-message-formats.html in section `CommandComplete` - self.command = "SELECT" - self.oid = nil - self.rows = nil - case "SELECT", "DELETE", "UPDATE", "MOVE", "FETCH", "COPY": - // rows - guard parts.count == 2 else { - return nil - } - self.command = .init(parts[0]) - self.oid = nil - self.rows = Int(parts[1]) - default: - // - self.command = string - self.oid = nil - self.rows = nil - } - } -} diff --git a/Sources/PostgresNIO/PostgresDatabase+SimpleQuery.swift b/Sources/PostgresNIO/PostgresDatabase+SimpleQuery.swift deleted file mode 100644 index 5cf2d7a4..00000000 --- a/Sources/PostgresNIO/PostgresDatabase+SimpleQuery.swift +++ /dev/null @@ -1,19 +0,0 @@ -import NIOCore -import NIOConcurrencyHelpers -import Logging - -extension PostgresDatabase { - public func simpleQuery(_ string: String) -> EventLoopFuture<[PostgresRow]> { - let rowsBoxed = NIOLockedValueBox([PostgresRow]()) - return self.simpleQuery(string) { row in - rowsBoxed.withLockedValue { - $0.append(row) - } - }.map { rowsBoxed.withLockedValue { $0 } } - } - - @preconcurrency - public func simpleQuery(_ string: String, _ onRow: @Sendable @escaping (PostgresRow) throws -> ()) -> EventLoopFuture { - self.query(string, onRow: onRow) - } -} diff --git a/Sources/PostgresNIO/PostgresDatabase.swift b/Sources/PostgresNIO/PostgresDatabase.swift deleted file mode 100644 index fcd1afc7..00000000 --- a/Sources/PostgresNIO/PostgresDatabase.swift +++ /dev/null @@ -1,39 +0,0 @@ -import NIOCore -import Logging - -@preconcurrency -public protocol PostgresDatabase: Sendable { - var logger: Logger { get } - var eventLoop: EventLoop { get } - func send( - _ request: PostgresRequest, - logger: Logger - ) -> EventLoopFuture - - func withConnection(_ closure: @escaping (PostgresConnection) -> EventLoopFuture) -> EventLoopFuture -} - -extension PostgresDatabase { - public func logging(to logger: Logger) -> PostgresDatabase { - _PostgresDatabaseCustomLogger(database: self, logger: logger) - } -} - -private struct _PostgresDatabaseCustomLogger { - let database: PostgresDatabase - let logger: Logger -} - -extension _PostgresDatabaseCustomLogger: PostgresDatabase { - var eventLoop: EventLoop { - self.database.eventLoop - } - - func send(_ request: PostgresRequest, logger: Logger) -> EventLoopFuture { - self.database.send(request, logger: logger) - } - - func withConnection(_ closure: @escaping (PostgresConnection) -> EventLoopFuture) -> EventLoopFuture { - self.database.withConnection(closure) - } -} diff --git a/Sources/PostgresNIO/PostgresQueryMetadata.swift b/Sources/PostgresNIO/PostgresQueryMetadata.swift new file mode 100644 index 00000000..28a8d977 --- /dev/null +++ b/Sources/PostgresNIO/PostgresQueryMetadata.swift @@ -0,0 +1,45 @@ +import NIOCore +import Logging +import NIOConcurrencyHelpers + +public struct PostgresQueryMetadata: Sendable { + public let command: String + public var oid: Int? + public var rows: Int? + + init?(string: String) { + let parts = string.split(separator: " ") + guard parts.count >= 1 else { + return nil + } + switch parts[0] { + case "INSERT": + // INSERT oid rows + guard parts.count == 3 else { + return nil + } + self.command = .init(parts[0]) + self.oid = Int(parts[1]) + self.rows = Int(parts[2]) + case "SELECT" where parts.count == 1: + // AWS Redshift does not return the actual row count as defined in the postgres wire spec for SELECT: + // https://www.postgresql.org/docs/13/protocol-message-formats.html in section `CommandComplete` + self.command = "SELECT" + self.oid = nil + self.rows = nil + case "SELECT", "DELETE", "UPDATE", "MOVE", "FETCH", "COPY": + // rows + guard parts.count == 2 else { + return nil + } + self.command = .init(parts[0]) + self.oid = nil + self.rows = Int(parts[1]) + default: + // + self.command = string + self.oid = nil + self.rows = nil + } + } +} diff --git a/Tests/IntegrationTests/PSQLIntegrationTests.swift b/Tests/IntegrationTests/PSQLIntegrationTests.swift index 57939c06..4fe8faea 100644 --- a/Tests/IntegrationTests/PSQLIntegrationTests.swift +++ b/Tests/IntegrationTests/PSQLIntegrationTests.swift @@ -47,317 +47,316 @@ final class IntegrationTests: XCTestCase { XCTAssertNoThrow(try connection?.close().wait()) } - func testQueryVersion() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query("SELECT version()", logger: .psqlTest).wait()) - let rows = result?.rows - var version: String? - XCTAssertNoThrow(version = try rows?.first?.decode(String.self, context: .default)) - XCTAssertEqual(version?.contains("PostgreSQL"), true) - } - - func testQuery10kItems() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var metadata: PostgresQueryMetadata? - let received = ManagedAtomic(0) - XCTAssertNoThrow(metadata = try conn?.query("SELECT generate_series(1, 10000);", logger: .psqlTest) { row in - func workaround() { - let expected = received.wrappingIncrementThenLoad(ordering: .relaxed) - XCTAssertEqual(expected, try row.decode(Int64.self, context: .default)) - } - - workaround() - }.wait()) - - XCTAssertEqual(received.load(ordering: .relaxed), 10000) - XCTAssertEqual(metadata?.command, "SELECT") - XCTAssertEqual(metadata?.rows, 10000) - } - - func test1kRoundTrips() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - for _ in 0..<1_000 { - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query("SELECT version()", logger: .psqlTest).wait()) - var version: String? - XCTAssertNoThrow(version = try result?.rows.first?.decode(String.self, context: .default)) - XCTAssertEqual(version?.contains("PostgreSQL"), true) - } - } - - func testQuerySelectParameter() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query("SELECT \("hello")::TEXT as foo", logger: .psqlTest).wait()) - var foo: String? - XCTAssertNoThrow(foo = try result?.rows.first?.decode(String.self, context: .default)) - XCTAssertEqual(foo, "hello") - } - - func testDecodeIntegers() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - SELECT - 1::SMALLINT as smallint, - -32767::SMALLINT as smallint_min, - 32767::SMALLINT as smallint_max, - 1::INT as int, - -2147483647::INT as int_min, - 2147483647::INT as int_max, - 1::BIGINT as bigint, - -9223372036854775807::BIGINT as bigint_min, - 9223372036854775807::BIGINT as bigint_max - """, logger: .psqlTest).wait()) - - XCTAssertEqual(result?.rows.count, 1) - let row = result?.rows.first - - var cells: (Int16, Int16, Int16, Int32, Int32, Int32, Int64, Int64, Int64)? - XCTAssertNoThrow(cells = try row?.decode((Int16, Int16, Int16, Int32, Int32, Int32, Int64, Int64, Int64).self, context: .default)) - - XCTAssertEqual(cells?.0, 1) - XCTAssertEqual(cells?.1, -32_767) - XCTAssertEqual(cells?.2, 32_767) - XCTAssertEqual(cells?.3, 1) - XCTAssertEqual(cells?.4, -2_147_483_647) - XCTAssertEqual(cells?.5, 2_147_483_647) - XCTAssertEqual(cells?.6, 1) - XCTAssertEqual(cells?.7, -9_223_372_036_854_775_807) - XCTAssertEqual(cells?.8, 9_223_372_036_854_775_807) - } - - func testEncodeAndDecodeIntArray() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - let array: [Int64] = [1, 2, 3] - XCTAssertNoThrow(result = try conn?.query("SELECT \(array)::int8[] as array", logger: .psqlTest).wait()) - XCTAssertEqual(result?.rows.count, 1) - XCTAssertEqual(try result?.rows.first?.decode([Int64].self, context: .default), array) - } - - func testDecodeEmptyIntegerArray() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query("SELECT '{}'::int[] as array", logger: .psqlTest).wait()) - - XCTAssertEqual(result?.rows.count, 1) - XCTAssertEqual(try result?.rows.first?.decode([Int64].self, context: .default), []) - } - - func testDoubleArraySerialization() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - let doubles: [Double] = [3.14, 42] - XCTAssertNoThrow(result = try conn?.query("SELECT \(doubles)::double precision[] as doubles", logger: .psqlTest).wait()) - XCTAssertEqual(result?.rows.count, 1) - XCTAssertEqual(try result?.rows.first?.decode([Double].self, context: .default), doubles) - } - - func testDecodeDates() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - SELECT - '2016-01-18 01:02:03 +0042'::DATE as date, - '2016-01-18 01:02:03 +0042'::TIMESTAMP as timestamp, - '2016-01-18 01:02:03 +0042'::TIMESTAMPTZ as timestamptz - """, logger: .psqlTest).wait()) - - XCTAssertEqual(result?.rows.count, 1) - - var cells: (Date, Date, Date)? - XCTAssertNoThrow(cells = try result?.rows.first?.decode((Date, Date, Date).self, context: .default)) - - XCTAssertEqual(cells?.0.description, "2016-01-18 00:00:00 +0000") - XCTAssertEqual(cells?.1.description, "2016-01-18 01:02:03 +0000") - XCTAssertEqual(cells?.2.description, "2016-01-18 00:20:03 +0000") - } - - func testDecodeDecimals() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - SELECT - \(Decimal(string: "123456.789123")!)::numeric as numeric, - \(Decimal(string: "-123456.789123")!)::numeric as numeric_negative - """, logger: .psqlTest).wait()) - XCTAssertEqual(result?.rows.count, 1) - - var cells: (Decimal, Decimal)? - XCTAssertNoThrow(cells = try result?.rows.first?.decode((Decimal, Decimal).self, context: .default)) - - XCTAssertEqual(cells?.0, Decimal(string: "123456.789123")) - XCTAssertEqual(cells?.1, Decimal(string: "-123456.789123")) - } - - func testDecodeRawRepresentables() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - enum StringRR: String, PostgresDecodable { - case a - } - - enum IntRR: Int, PostgresDecodable { - case b - } - - let stringValue = StringRR.a - let intValue = IntRR.b - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - SELECT - \(stringValue.rawValue)::varchar as string, - \(intValue.rawValue)::int8 as int - """, logger: .psqlTest).wait()) - XCTAssertEqual(result?.rows.count, 1) - - var cells: (StringRR, IntRR)? - XCTAssertNoThrow(cells = try result?.rows.first?.decode((StringRR, IntRR).self, context: .default)) - - XCTAssertEqual(cells?.0, stringValue) - XCTAssertEqual(cells?.1, intValue) - } - - func testRoundTripUUID() { - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - let uuidString = "2c68f645-9ca6-468b-b193-ee97f241c2f8" - - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - SELECT \(uuidString)::UUID as uuid - """, - logger: .psqlTest - ).wait()) - - XCTAssertEqual(result?.rows.count, 1) - XCTAssertEqual(try result?.rows.first?.decode(UUID.self, context: .default), UUID(uuidString: uuidString)) - } - - func testRoundTripJSONB() { - struct Object: Codable, PostgresCodable { - let foo: Int - let bar: Int - } - - let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) - defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } - let eventLoop = eventLoopGroup.next() - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow(try conn?.close().wait()) } - - do { - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - select \(Object(foo: 1, bar: 2))::jsonb as jsonb - """, logger: .psqlTest).wait()) - - XCTAssertEqual(result?.rows.count, 1) - var obj: Object? - XCTAssertNoThrow(obj = try result?.rows.first?.decode(Object.self, context: .default)) - XCTAssertEqual(obj?.foo, 1) - XCTAssertEqual(obj?.bar, 2) - } - - do { - var result: PostgresQueryResult? - XCTAssertNoThrow(result = try conn?.query(""" - select \(Object(foo: 1, bar: 2))::json as json - """, logger: .psqlTest).wait()) - - XCTAssertEqual(result?.rows.count, 1) - var obj: Object? - XCTAssertNoThrow(obj = try result?.rows.first?.decode(Object.self, context: .default)) - XCTAssertEqual(obj?.foo, 1) - XCTAssertEqual(obj?.bar, 2) - } - } - +// func testQueryVersion() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query("SELECT version()", logger: .psqlTest).wait()) +// let rows = result?.rows +// var version: String? +// XCTAssertNoThrow(version = try rows?.first?.decode(String.self, context: .default)) +// XCTAssertEqual(version?.contains("PostgreSQL"), true) +// } +// +// func testQuery10kItems() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var metadata: PostgresQueryMetadata? +// let received = ManagedAtomic(0) +// XCTAssertNoThrow(metadata = try conn?.query("SELECT generate_series(1, 10000);", logger: .psqlTest) { row in +// func workaround() { +// let expected = received.wrappingIncrementThenLoad(ordering: .relaxed) +// XCTAssertEqual(expected, try row.decode(Int64.self, context: .default)) +// } +// +// workaround() +// }.wait()) +// +// XCTAssertEqual(received.load(ordering: .relaxed), 10000) +// XCTAssertEqual(metadata?.command, "SELECT") +// XCTAssertEqual(metadata?.rows, 10000) +// } +// +// func test1kRoundTrips() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// for _ in 0..<1_000 { +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query("SELECT version()", logger: .psqlTest).wait()) +// var version: String? +// XCTAssertNoThrow(version = try result?.rows.first?.decode(String.self, context: .default)) +// XCTAssertEqual(version?.contains("PostgreSQL"), true) +// } +// } +// +// func testQuerySelectParameter() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query("SELECT \("hello")::TEXT as foo", logger: .psqlTest).wait()) +// var foo: String? +// XCTAssertNoThrow(foo = try result?.rows.first?.decode(String.self, context: .default)) +// XCTAssertEqual(foo, "hello") +// } +// +// func testDecodeIntegers() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// SELECT +// 1::SMALLINT as smallint, +// -32767::SMALLINT as smallint_min, +// 32767::SMALLINT as smallint_max, +// 1::INT as int, +// -2147483647::INT as int_min, +// 2147483647::INT as int_max, +// 1::BIGINT as bigint, +// -9223372036854775807::BIGINT as bigint_min, +// 9223372036854775807::BIGINT as bigint_max +// """, logger: .psqlTest).wait()) +// +// XCTAssertEqual(result?.rows.count, 1) +// let row = result?.rows.first +// +// var cells: (Int16, Int16, Int16, Int32, Int32, Int32, Int64, Int64, Int64)? +// XCTAssertNoThrow(cells = try row?.decode((Int16, Int16, Int16, Int32, Int32, Int32, Int64, Int64, Int64).self, context: .default)) +// +// XCTAssertEqual(cells?.0, 1) +// XCTAssertEqual(cells?.1, -32_767) +// XCTAssertEqual(cells?.2, 32_767) +// XCTAssertEqual(cells?.3, 1) +// XCTAssertEqual(cells?.4, -2_147_483_647) +// XCTAssertEqual(cells?.5, 2_147_483_647) +// XCTAssertEqual(cells?.6, 1) +// XCTAssertEqual(cells?.7, -9_223_372_036_854_775_807) +// XCTAssertEqual(cells?.8, 9_223_372_036_854_775_807) +// } +// +// func testEncodeAndDecodeIntArray() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// let array: [Int64] = [1, 2, 3] +// XCTAssertNoThrow(result = try conn?.query("SELECT \(array)::int8[] as array", logger: .psqlTest).wait()) +// XCTAssertEqual(result?.rows.count, 1) +// XCTAssertEqual(try result?.rows.first?.decode([Int64].self, context: .default), array) +// } +// +// func testDecodeEmptyIntegerArray() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query("SELECT '{}'::int[] as array", logger: .psqlTest).wait()) +// +// XCTAssertEqual(result?.rows.count, 1) +// XCTAssertEqual(try result?.rows.first?.decode([Int64].self, context: .default), []) +// } +// +// func testDoubleArraySerialization() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// let doubles: [Double] = [3.14, 42] +// XCTAssertNoThrow(result = try conn?.query("SELECT \(doubles)::double precision[] as doubles", logger: .psqlTest).wait()) +// XCTAssertEqual(result?.rows.count, 1) +// XCTAssertEqual(try result?.rows.first?.decode([Double].self, context: .default), doubles) +// } +// +// func testDecodeDates() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// SELECT +// '2016-01-18 01:02:03 +0042'::DATE as date, +// '2016-01-18 01:02:03 +0042'::TIMESTAMP as timestamp, +// '2016-01-18 01:02:03 +0042'::TIMESTAMPTZ as timestamptz +// """, logger: .psqlTest).wait()) +// +// XCTAssertEqual(result?.rows.count, 1) +// +// var cells: (Date, Date, Date)? +// XCTAssertNoThrow(cells = try result?.rows.first?.decode((Date, Date, Date).self, context: .default)) +// +// XCTAssertEqual(cells?.0.description, "2016-01-18 00:00:00 +0000") +// XCTAssertEqual(cells?.1.description, "2016-01-18 01:02:03 +0000") +// XCTAssertEqual(cells?.2.description, "2016-01-18 00:20:03 +0000") +// } +// +// func testDecodeDecimals() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// SELECT +// \(Decimal(string: "123456.789123")!)::numeric as numeric, +// \(Decimal(string: "-123456.789123")!)::numeric as numeric_negative +// """, logger: .psqlTest).wait()) +// XCTAssertEqual(result?.rows.count, 1) +// +// var cells: (Decimal, Decimal)? +// XCTAssertNoThrow(cells = try result?.rows.first?.decode((Decimal, Decimal).self, context: .default)) +// +// XCTAssertEqual(cells?.0, Decimal(string: "123456.789123")) +// XCTAssertEqual(cells?.1, Decimal(string: "-123456.789123")) +// } +// +// func testDecodeRawRepresentables() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// enum StringRR: String, PostgresDecodable { +// case a +// } +// +// enum IntRR: Int, PostgresDecodable { +// case b +// } +// +// let stringValue = StringRR.a +// let intValue = IntRR.b +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// SELECT +// \(stringValue.rawValue)::varchar as string, +// \(intValue.rawValue)::int8 as int +// """, logger: .psqlTest).wait()) +// XCTAssertEqual(result?.rows.count, 1) +// +// var cells: (StringRR, IntRR)? +// XCTAssertNoThrow(cells = try result?.rows.first?.decode((StringRR, IntRR).self, context: .default)) +// +// XCTAssertEqual(cells?.0, stringValue) +// XCTAssertEqual(cells?.1, intValue) +// } +// +// func testRoundTripUUID() { +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// let uuidString = "2c68f645-9ca6-468b-b193-ee97f241c2f8" +// +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// SELECT \(uuidString)::UUID as uuid +// """, +// logger: .psqlTest +// ).wait()) +// +// XCTAssertEqual(result?.rows.count, 1) +// XCTAssertEqual(try result?.rows.first?.decode(UUID.self, context: .default), UUID(uuidString: uuidString)) +// } +// +// func testRoundTripJSONB() { +// struct Object: Codable, PostgresCodable { +// let foo: Int +// let bar: Int +// } +// +// let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1) +// defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) } +// let eventLoop = eventLoopGroup.next() +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow(try conn?.close().wait()) } +// +// do { +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// select \(Object(foo: 1, bar: 2))::jsonb as jsonb +// """, logger: .psqlTest).wait()) +// +// XCTAssertEqual(result?.rows.count, 1) +// var obj: Object? +// XCTAssertNoThrow(obj = try result?.rows.first?.decode(Object.self, context: .default)) +// XCTAssertEqual(obj?.foo, 1) +// XCTAssertEqual(obj?.bar, 2) +// } +// +// do { +// var result: PostgresQueryResult? +// XCTAssertNoThrow(result = try conn?.query(""" +// select \(Object(foo: 1, bar: 2))::json as json +// """, logger: .psqlTest).wait()) +// +// XCTAssertEqual(result?.rows.count, 1) +// var obj: Object? +// XCTAssertNoThrow(obj = try result?.rows.first?.decode(Object.self, context: .default)) +// XCTAssertEqual(obj?.foo, 1) +// XCTAssertEqual(obj?.bar, 2) +// } +// } } diff --git a/Tests/IntegrationTests/PerformanceTests.swift b/Tests/IntegrationTests/PerformanceTests.swift deleted file mode 100644 index 6f730560..00000000 --- a/Tests/IntegrationTests/PerformanceTests.swift +++ /dev/null @@ -1,310 +0,0 @@ -import XCTest -import Logging -import NIOCore -import NIOPosix -@testable import PostgresNIO -import NIOTestUtils - -final class PerformanceTests: XCTestCase { - private var group: EventLoopGroup! - - private var eventLoop: EventLoop { self.group.next() } - - override func setUpWithError() throws { - try super.setUpWithError() - try XCTSkipUnless(Self.shouldRunPerformanceTests) - - XCTAssertTrue(isLoggingConfigured) - self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1) - } - - override func tearDownWithError() throws { - try self.group?.syncShutdownGracefully() - self.group = nil - try super.tearDownWithError() - } - - - // MARK: Performance - - func testPerformanceRangeSelectDecodePerformance() throws { - struct Series: Decodable { - var num: Int - } - - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - measure { - do { - for _ in 0..<5 { - try conn.query("SELECT * FROM generate_series(1, 10000) num") { row in - _ = try row.decode(Int.self, context: .default) - }.wait() - } - } catch { - XCTFail("\(error)") - } - } - } - - func testPerformanceSelectTinyModel() throws { - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - - try prepareTableToMeasureSelectPerformance( - rowCount: 300_000, batchSize: 5_000, - schema: - """ - "int" int8, - """, - fixtureData: [PostgresData(int: 1234)], - on: self.eventLoop - ) - defer { _ = try! conn.simpleQuery("DROP TABLE \"measureSelectPerformance\"").wait() } - - measure { - do { - try conn.query("SELECT * FROM \"measureSelectPerformance\"") { row in - _ = try row.decode(Int.self, context: .default) - }.wait() - } catch { - XCTFail("\(error)") - } - } - } - - @available(*, deprecated, message: "Testing deprecated functionality") - func testPerformanceSelectMediumModel() throws { - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - - let now = Date() - let uuid = UUID() - try prepareTableToMeasureSelectPerformance( - rowCount: 300_000, - schema: - // TODO: Also add a `Double` and a `Data` field to this performance test. - """ - "string" text, - "int" int8, - "date" timestamptz, - "uuid" uuid, - """, - fixtureData: [ - PostgresData(string: "foo"), - PostgresData(int: 0), - now.postgresData!, - PostgresData(uuid: uuid) - ], - on: self.eventLoop - ) - defer { _ = try! conn.simpleQuery("DROP TABLE \"measureSelectPerformance\"").wait() } - - measure { - do { - try conn.query("SELECT * FROM \"measureSelectPerformance\"") { - let row = $0.makeRandomAccess() - _ = row[data: "id"].int - _ = row[data: "string"].string - _ = row[data: "int"].int - _ = row[data: "date"].date - _ = row[data: "uuid"].uuid - }.wait() - } catch { - XCTFail("\(error)") - } - } - } - - @available(*, deprecated, message: "Testing deprecated functionality") - func testPerformanceSelectLargeModel() throws { - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - - let now = Date() - let uuid = UUID() - try prepareTableToMeasureSelectPerformance( - rowCount: 100_000, - schema: - // TODO: Also add `Double` and `Data` fields to this performance test. - """ - "string1" text, - "string2" text, - "string3" text, - "string4" text, - "string5" text, - "int1" int8, - "int2" int8, - "int3" int8, - "int4" int8, - "int5" int8, - "date1" timestamptz, - "date2" timestamptz, - "date3" timestamptz, - "date4" timestamptz, - "date5" timestamptz, - "uuid1" uuid, - "uuid2" uuid, - "uuid3" uuid, - "uuid4" uuid, - "uuid5" uuid, - """, - fixtureData: [ - PostgresData(string: "string1"), - PostgresData(string: "string2"), - PostgresData(string: "string3"), - PostgresData(string: "string4"), - PostgresData(string: "string5"), - PostgresData(int: 1), - PostgresData(int: 2), - PostgresData(int: 3), - PostgresData(int: 4), - PostgresData(int: 5), - now.postgresData!, - now.postgresData!, - now.postgresData!, - now.postgresData!, - now.postgresData!, - PostgresData(uuid: uuid), - PostgresData(uuid: uuid), - PostgresData(uuid: uuid), - PostgresData(uuid: uuid), - PostgresData(uuid: uuid) - ], - on: self.eventLoop - ) - defer { _ = try! conn.simpleQuery("DROP TABLE \"measureSelectPerformance\"").wait() } - - measure { - do { - try conn.query("SELECT * FROM \"measureSelectPerformance\"") { - let row = $0.makeRandomAccess() - _ = row[data: "id"].int - _ = row[data: "string1"].string - _ = row[data: "string2"].string - _ = row[data: "string3"].string - _ = row[data: "string4"].string - _ = row[data: "string5"].string - _ = row[data: "int1"].int - _ = row[data: "int2"].int - _ = row[data: "int3"].int - _ = row[data: "int4"].int - _ = row[data: "int5"].int - _ = row[data: "date1"].date - _ = row[data: "date2"].date - _ = row[data: "date3"].date - _ = row[data: "date4"].date - _ = row[data: "date5"].date - _ = row[data: "uuid1"].uuid - _ = row[data: "uuid2"].uuid - _ = row[data: "uuid3"].uuid - _ = row[data: "uuid4"].uuid - _ = row[data: "uuid5"].uuid - }.wait() - } catch { - XCTFail("\(error)") - } - } - } - - func testPerformanceSelectLargeModelWithLongFieldNames() throws { - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - - let fieldIndices = Array(1...20) - let fieldNames = fieldIndices.map { "veryLongFieldNameVeryLongFieldName\($0)" } - try prepareTableToMeasureSelectPerformance( - rowCount: 50_000, batchSize: 200, - schema: fieldNames.map { "\"\($0)\" int8" }.joined(separator: ", ") + ",", - fixtureData: fieldIndices.map { PostgresData(int: $0) }, - on: self.eventLoop - ) - defer { _ = try! conn.simpleQuery("DROP TABLE \"measureSelectPerformance\"").wait() } - - measure { - do { - try conn.query("SELECT * FROM \"measureSelectPerformance\"") { - let row = $0.makeRandomAccess() - _ = row[data: "id"].int - for fieldName in fieldNames { - _ = row[data: fieldName].int - } - }.wait() - } catch { - XCTFail("\(error)") - } - } - } - - func testPerformanceSelectHugeModel() throws { - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - - let fieldIndices = Array(1...100) - let fieldNames = fieldIndices.map { "int\($0)" } - try prepareTableToMeasureSelectPerformance( - rowCount: 10_000, batchSize: 200, - schema: fieldNames.map { "\"\($0)\" int8" }.joined(separator: ", ") + ",", - fixtureData: fieldIndices.map { PostgresData(int: $0) }, - on: self.eventLoop - ) - defer { _ = try! conn.simpleQuery("DROP TABLE \"measureSelectPerformance\"").wait() } - - measure { - do { - try conn.query("SELECT * FROM \"measureSelectPerformance\"") { - let row = $0.makeRandomAccess() - _ = row[data: "id"].int - for fieldName in fieldNames { - _ = row[data: fieldName].int - } - }.wait() - } catch { - XCTFail("\(error)") - } - } - } - -} - -private func prepareTableToMeasureSelectPerformance( - rowCount: Int, - batchSize: Int = 1_000, - schema: String, - fixtureData: [PostgresData], - on eventLoop: EventLoop, - file: StaticString = #filePath, - line: UInt = #line -) throws { - XCTAssertEqual(rowCount % batchSize, 0, "`rowCount` must be a multiple of `batchSize`", file: (file), line: line) - let conn = try PostgresConnection.test(on: eventLoop).wait() - defer { try! conn.close().wait() } - - _ = try conn.simpleQuery("DROP TABLE IF EXISTS \"measureSelectPerformance\"").wait() - _ = try conn.simpleQuery(""" - CREATE TABLE "measureSelectPerformance" ( - "id" int8 NOT NULL, - \(schema) - PRIMARY KEY ("id") - ); - """).wait() - - // Batch `batchSize` inserts into one for better insert performance. - let totalArgumentsPerRow = fixtureData.count + 1 - let insertArgumentsPlaceholder = (0.. 350, "Results count not large enough") - } - - func testSelectType() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - var results: [PostgresRow]? - XCTAssertNoThrow(results = try conn?.simpleQuery("SELECT * FROM pg_type WHERE typname = 'float8'").wait()) - // [ - // "typreceive": "float8recv", - // "typelem": "0", - // "typarray": "1022", - // "typalign": "d", - // "typanalyze": "-", - // "typtypmod": "-1", - // "typname": "float8", - // "typnamespace": "11", - // "typdefault": "", - // "typdefaultbin": "", - // "typcollation": "0", - // "typispreferred": "t", - // "typrelid": "0", - // "typbyval": "t", - // "typnotnull": "f", - // "typinput": "float8in", - // "typlen": "8", - // "typcategory": "N", - // "typowner": "10", - // "typtype": "b", - // "typdelim": ",", - // "typndims": "0", - // "typbasetype": "0", - // "typacl": "", - // "typisdefined": "t", - // "typmodout": "-", - // "typmodin": "-", - // "typsend": "float8send", - // "typstorage": "p", - // "typoutput": "float8out" - // ] - XCTAssertEqual(results?.count, 1) - let row = results?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "typname"].string, "float8") - XCTAssertEqual(row?[data: "typnamespace"].int, 11) - XCTAssertEqual(row?[data: "typowner"].int, 10) - XCTAssertEqual(row?[data: "typlen"].int, 8) - } - - func testIntegers() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - struct Integers: Decodable { - let smallint: Int16 - let smallint_min: Int16 - let smallint_max: Int16 - let int: Int32 - let int_min: Int32 - let int_max: Int32 - let bigint: Int64 - let bigint_min: Int64 - let bigint_max: Int64 - } - var results: PostgresQueryResult? - XCTAssertNoThrow(results = try conn?.query(""" - SELECT - 1::SMALLINT as smallint, - -32767::SMALLINT as smallint_min, - 32767::SMALLINT as smallint_max, - 1::INT as int, - -2147483647::INT as int_min, - 2147483647::INT as int_max, - 1::BIGINT as bigint, - -9223372036854775807::BIGINT as bigint_min, - 9223372036854775807::BIGINT as bigint_max - """).wait()) - XCTAssertEqual(results?.count, 1) - - let row = results?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "smallint"].int16, 1) - XCTAssertEqual(row?[data: "smallint_min"].int16, -32_767) - XCTAssertEqual(row?[data: "smallint_max"].int16, 32_767) - XCTAssertEqual(row?[data: "int"].int32, 1) - XCTAssertEqual(row?[data: "int_min"].int32, -2_147_483_647) - XCTAssertEqual(row?[data: "int_max"].int32, 2_147_483_647) - XCTAssertEqual(row?[data: "bigint"].int64, 1) - XCTAssertEqual(row?[data: "bigint_min"].int64, -9_223_372_036_854_775_807) - XCTAssertEqual(row?[data: "bigint_max"].int64, 9_223_372_036_854_775_807) - } - - func testPi() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - - struct Pi: Decodable { - let text: String - let numeric_string: String - let numeric_decimal: Decimal - let double: Double - let float: Float - } - var results: PostgresQueryResult? - XCTAssertNoThrow(results = try conn?.query(""" - SELECT - pi()::TEXT as text, - pi()::NUMERIC as numeric_string, - pi()::NUMERIC as numeric_decimal, - pi()::FLOAT8 as double, - pi()::FLOAT4 as float - """).wait()) - XCTAssertEqual(results?.count, 1) - let row = results?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "text"].string?.hasPrefix("3.14159265"), true) - XCTAssertEqual(row?[data: "numeric_string"].string?.hasPrefix("3.14159265"), true) - XCTAssertTrue(row?[data: "numeric_decimal"].decimal?.isLess(than: 3.14159265358980) ?? false) - XCTAssertFalse(row?[data: "numeric_decimal"].decimal?.isLess(than: 3.14159265358978) ?? true) - XCTAssertTrue(row?[data: "double"].double?.description.hasPrefix("3.141592") ?? false) - XCTAssertTrue(row?[data: "float"].float?.description.hasPrefix("3.141592") ?? false) - } - - func testUUID() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - struct Model: Decodable { - let id: UUID - let string: String - } - var results: PostgresQueryResult? - XCTAssertNoThrow(results = try conn?.query(""" - SELECT - '123e4567-e89b-12d3-a456-426655440000'::UUID as id, - '123e4567-e89b-12d3-a456-426655440000'::UUID as string - """).wait()) - XCTAssertEqual(results?.count, 1) - let row = results?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "id"].uuid, UUID(uuidString: "123E4567-E89B-12D3-A456-426655440000")) - XCTAssertEqual(UUID(uuidString: row?[data: "id"].string ?? ""), UUID(uuidString: "123E4567-E89B-12D3-A456-426655440000")) - } - - func testInt4Range() async throws { - let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() - self.addTeardownBlock { - try await conn.close() - } - struct Model: Decodable { - let range: Range - } - let results1: PostgresQueryResult = try await conn.query(""" - SELECT - '[\(Int32.min), \(Int32.max))'::int4range AS range - """).get() - XCTAssertEqual(results1.count, 1) - var row = results1.first?.makeRandomAccess() - let expectedRange: Range = Int32.min...self, context: .default) - XCTAssertEqual(decodedRange, expectedRange) - - let results2 = try await conn.query(""" - SELECT - ARRAY[ - '[0, 1)'::int4range, - '[10, 11)'::int4range - ] AS ranges - """).get() - XCTAssertEqual(results2.count, 1) - row = results2.first?.makeRandomAccess() - let decodedRangeArray = try row?.decode(column: "ranges", as: [Range].self, context: .default) - let decodedClosedRangeArray = try row?.decode(column: "ranges", as: [ClosedRange].self, context: .default) - XCTAssertEqual(decodedRangeArray, [0..<1, 10..<11]) - XCTAssertEqual(decodedClosedRangeArray, [0...0, 10...10]) - } - - func testEmptyInt4Range() async throws { - let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() - self.addTeardownBlock { - try await conn.close() - } - struct Model: Decodable { - let range: Range - } - let randomValue = Int32.random(in: Int32.min...Int32.max) - let results: PostgresQueryResult = try await conn.query(""" - SELECT - '[\(randomValue),\(randomValue))'::int4range AS range - """).get() - XCTAssertEqual(results.count, 1) - let row = results.first?.makeRandomAccess() - let expectedRange: Range = Int32.valueForEmptyRange...self, context: .default) - XCTAssertEqual(decodedRange, expectedRange) - - XCTAssertThrowsError( - try row?.decode(column: "range", as: ClosedRange.self, context: .default) - ) - } - - func testInt8Range() async throws { - let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() - self.addTeardownBlock { - try await conn.close() - } - struct Model: Decodable { - let range: Range - } - let results1: PostgresQueryResult = try await conn.query(""" - SELECT - '[\(Int64.min), \(Int64.max))'::int8range AS range - """).get() - XCTAssertEqual(results1.count, 1) - var row = results1.first?.makeRandomAccess() - let expectedRange: Range = Int64.min...self, context: .default) - XCTAssertEqual(decodedRange, expectedRange) - - let results2: PostgresQueryResult = try await conn.query(""" - SELECT - ARRAY[ - '[0, 1)'::int8range, - '[10, 11)'::int8range - ] AS ranges - """).get() - XCTAssertEqual(results2.count, 1) - row = results2.first?.makeRandomAccess() - let decodedRangeArray = try row?.decode(column: "ranges", as: [Range].self, context: .default) - let decodedClosedRangeArray = try row?.decode(column: "ranges", as: [ClosedRange].self, context: .default) - XCTAssertEqual(decodedRangeArray, [0..<1, 10..<11]) - XCTAssertEqual(decodedClosedRangeArray, [0...0, 10...10]) - } - - func testEmptyInt8Range() async throws { - let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() - self.addTeardownBlock { - try await conn.close() - } - struct Model: Decodable { - let range: Range - } - let randomValue = Int64.random(in: Int64.min...Int64.max) - let results: PostgresQueryResult = try await conn.query(""" - SELECT - '[\(randomValue),\(randomValue))'::int8range AS range - """).get() - XCTAssertEqual(results.count, 1) - let row = results.first?.makeRandomAccess() - let expectedRange: Range = Int64.valueForEmptyRange...self, context: .default) - XCTAssertEqual(decodedRange, expectedRange) - - XCTAssertThrowsError( - try row?.decode(column: "range", as: ClosedRange.self, context: .default) - ) - } - - func testDates() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - struct Dates: Decodable { - var date: Date - var timestamp: Date - var timestamptz: Date - } - var results: PostgresQueryResult? - XCTAssertNoThrow(results = try conn?.query(""" - SELECT - '2016-01-18 01:02:03 +0042'::DATE as date, - '2016-01-18 01:02:03 +0042'::TIMESTAMP as timestamp, - '2016-01-18 01:02:03 +0042'::TIMESTAMPTZ as timestamptz - """).wait()) - XCTAssertEqual(results?.count, 1) - let row = results?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "date"].date?.description, "2016-01-18 00:00:00 +0000") - XCTAssertEqual(row?[data: "timestamp"].date?.description, "2016-01-18 01:02:03 +0000") - XCTAssertEqual(row?[data: "timestamptz"].date?.description, "2016-01-18 00:20:03 +0000") - } - - /// https://github.com/vapor/nio-postgres/issues/20 - func testBindInteger() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - XCTAssertNoThrow(_ = try conn?.simpleQuery("drop table if exists person;").wait()) - XCTAssertNoThrow(_ = try conn?.simpleQuery("create table person(id serial primary key, first_name text, last_name text);").wait()) - defer { XCTAssertNoThrow(_ = try conn?.simpleQuery("drop table person;").wait()) } - let id = PostgresData(int32: 5) - XCTAssertNoThrow(_ = try conn?.query("SELECT id, first_name, last_name FROM person WHERE id = $1", [id]).wait()) - } - - // https://github.com/vapor/nio-postgres/issues/21 - func testAverageLengthNumeric() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - var results: PostgresQueryResult? - XCTAssertNoThrow(results = try conn?.query("select avg(length('foo')) as average_length").wait()) - let row = results?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: 0].double, 3.0) - } - - func testNumericParsing() { - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - var rows: PostgresQueryResult? - XCTAssertNoThrow(rows = try conn?.query(""" - select - '1234.5678'::numeric as a, - '-123.456'::numeric as b, - '123456.789123'::numeric as c, - '3.14159265358979'::numeric as d, - '10000'::numeric as e, - '0.00001'::numeric as f, - '100000000'::numeric as g, - '0.000000001'::numeric as h, - '100000000000'::numeric as i, - '0.000000000001'::numeric as j, - '123000000000'::numeric as k, - '0.000000000123'::numeric as l, - '0.5'::numeric as m - """).wait()) - XCTAssertEqual(rows?.count, 1) - let row = rows?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "a"].string, "1234.5678") - XCTAssertEqual(row?[data: "b"].string, "-123.456") - XCTAssertEqual(row?[data: "c"].string, "123456.789123") - XCTAssertEqual(row?[data: "d"].string, "3.14159265358979") - XCTAssertEqual(row?[data: "e"].string, "10000") - XCTAssertEqual(row?[data: "f"].string, "0.00001") - XCTAssertEqual(row?[data: "g"].string, "100000000") - XCTAssertEqual(row?[data: "h"].string, "0.000000001") - XCTAssertEqual(row?[data: "k"].string, "123000000000") - XCTAssertEqual(row?[data: "l"].string, "0.000000000123") - XCTAssertEqual(row?[data: "m"].string, "0.5") - } - - func testSingleNumericParsing() { - // this seemingly duped test is useful for debugging numeric parsing - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - let numeric = "790226039477542363.6032384900176272473" - var rows: PostgresQueryResult? - XCTAssertNoThrow(rows = try conn?.query(""" - select - '\(numeric)'::numeric as n - """).wait()) - let row = rows?.first?.makeRandomAccess() - XCTAssertEqual(row?[data: "n"].string, numeric) - } - - func testRandomlyGeneratedNumericParsing() throws { - // this test takes a long time to run - try XCTSkipUnless(Self.shouldRunLongRunningTests) - - var conn: PostgresConnection? - XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) - defer { XCTAssertNoThrow( try conn?.close().wait() ) } - - for _ in 0..<1_000_000 { - let integer = UInt.random(in: UInt.min.. 350, "Results count not large enough") +// } +// +// func testSelectType() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// var results: [PostgresRow]? +// XCTAssertNoThrow(results = try conn?.simpleQuery("SELECT * FROM pg_type WHERE typname = 'float8'").wait()) +// // [ +// // "typreceive": "float8recv", +// // "typelem": "0", +// // "typarray": "1022", +// // "typalign": "d", +// // "typanalyze": "-", +// // "typtypmod": "-1", +// // "typname": "float8", +// // "typnamespace": "11", +// // "typdefault": "", +// // "typdefaultbin": "", +// // "typcollation": "0", +// // "typispreferred": "t", +// // "typrelid": "0", +// // "typbyval": "t", +// // "typnotnull": "f", +// // "typinput": "float8in", +// // "typlen": "8", +// // "typcategory": "N", +// // "typowner": "10", +// // "typtype": "b", +// // "typdelim": ",", +// // "typndims": "0", +// // "typbasetype": "0", +// // "typacl": "", +// // "typisdefined": "t", +// // "typmodout": "-", +// // "typmodin": "-", +// // "typsend": "float8send", +// // "typstorage": "p", +// // "typoutput": "float8out" +// // ] +// XCTAssertEqual(results?.count, 1) +// let row = results?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "typname"].string, "float8") +// XCTAssertEqual(row?[data: "typnamespace"].int, 11) +// XCTAssertEqual(row?[data: "typowner"].int, 10) +// XCTAssertEqual(row?[data: "typlen"].int, 8) +// } +// +// func testIntegers() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// struct Integers: Decodable { +// let smallint: Int16 +// let smallint_min: Int16 +// let smallint_max: Int16 +// let int: Int32 +// let int_min: Int32 +// let int_max: Int32 +// let bigint: Int64 +// let bigint_min: Int64 +// let bigint_max: Int64 +// } +// var results: PostgresQueryResult? +// XCTAssertNoThrow(results = try conn?.query(""" +// SELECT +// 1::SMALLINT as smallint, +// -32767::SMALLINT as smallint_min, +// 32767::SMALLINT as smallint_max, +// 1::INT as int, +// -2147483647::INT as int_min, +// 2147483647::INT as int_max, +// 1::BIGINT as bigint, +// -9223372036854775807::BIGINT as bigint_min, +// 9223372036854775807::BIGINT as bigint_max +// """).wait()) +// XCTAssertEqual(results?.count, 1) +// +// let row = results?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "smallint"].int16, 1) +// XCTAssertEqual(row?[data: "smallint_min"].int16, -32_767) +// XCTAssertEqual(row?[data: "smallint_max"].int16, 32_767) +// XCTAssertEqual(row?[data: "int"].int32, 1) +// XCTAssertEqual(row?[data: "int_min"].int32, -2_147_483_647) +// XCTAssertEqual(row?[data: "int_max"].int32, 2_147_483_647) +// XCTAssertEqual(row?[data: "bigint"].int64, 1) +// XCTAssertEqual(row?[data: "bigint_min"].int64, -9_223_372_036_854_775_807) +// XCTAssertEqual(row?[data: "bigint_max"].int64, 9_223_372_036_854_775_807) +// } +// +// func testPi() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// +// struct Pi: Decodable { +// let text: String +// let numeric_string: String +// let numeric_decimal: Decimal +// let double: Double +// let float: Float +// } +// var results: PostgresQueryResult? +// XCTAssertNoThrow(results = try conn?.query(""" +// SELECT +// pi()::TEXT as text, +// pi()::NUMERIC as numeric_string, +// pi()::NUMERIC as numeric_decimal, +// pi()::FLOAT8 as double, +// pi()::FLOAT4 as float +// """).wait()) +// XCTAssertEqual(results?.count, 1) +// let row = results?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "text"].string?.hasPrefix("3.14159265"), true) +// XCTAssertEqual(row?[data: "numeric_string"].string?.hasPrefix("3.14159265"), true) +// XCTAssertTrue(row?[data: "numeric_decimal"].decimal?.isLess(than: 3.14159265358980) ?? false) +// XCTAssertFalse(row?[data: "numeric_decimal"].decimal?.isLess(than: 3.14159265358978) ?? true) +// XCTAssertTrue(row?[data: "double"].double?.description.hasPrefix("3.141592") ?? false) +// XCTAssertTrue(row?[data: "float"].float?.description.hasPrefix("3.141592") ?? false) +// } +// +// func testUUID() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// struct Model: Decodable { +// let id: UUID +// let string: String +// } +// var results: PostgresQueryResult? +// XCTAssertNoThrow(results = try conn?.query(""" +// SELECT +// '123e4567-e89b-12d3-a456-426655440000'::UUID as id, +// '123e4567-e89b-12d3-a456-426655440000'::UUID as string +// """).wait()) +// XCTAssertEqual(results?.count, 1) +// let row = results?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "id"].uuid, UUID(uuidString: "123E4567-E89B-12D3-A456-426655440000")) +// XCTAssertEqual(UUID(uuidString: row?[data: "id"].string ?? ""), UUID(uuidString: "123E4567-E89B-12D3-A456-426655440000")) +// } +// +// func testInt4Range() async throws { +// let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() +// self.addTeardownBlock { +// try await conn.close() +// } +// struct Model: Decodable { +// let range: Range +// } +// let results1: PostgresQueryResult = try await conn.query(""" +// SELECT +// '[\(Int32.min), \(Int32.max))'::int4range AS range +// """).get() +// XCTAssertEqual(results1.count, 1) +// var row = results1.first?.makeRandomAccess() +// let expectedRange: Range = Int32.min...self, context: .default) +// XCTAssertEqual(decodedRange, expectedRange) +// +// let results2 = try await conn.query(""" +// SELECT +// ARRAY[ +// '[0, 1)'::int4range, +// '[10, 11)'::int4range +// ] AS ranges +// """).get() +// XCTAssertEqual(results2.count, 1) +// row = results2.first?.makeRandomAccess() +// let decodedRangeArray = try row?.decode(column: "ranges", as: [Range].self, context: .default) +// let decodedClosedRangeArray = try row?.decode(column: "ranges", as: [ClosedRange].self, context: .default) +// XCTAssertEqual(decodedRangeArray, [0..<1, 10..<11]) +// XCTAssertEqual(decodedClosedRangeArray, [0...0, 10...10]) +// } +// +// func testEmptyInt4Range() async throws { +// let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() +// self.addTeardownBlock { +// try await conn.close() +// } +// struct Model: Decodable { +// let range: Range +// } +// let randomValue = Int32.random(in: Int32.min...Int32.max) +// let results: PostgresQueryResult = try await conn.query(""" +// SELECT +// '[\(randomValue),\(randomValue))'::int4range AS range +// """).get() +// XCTAssertEqual(results.count, 1) +// let row = results.first?.makeRandomAccess() +// let expectedRange: Range = Int32.valueForEmptyRange...self, context: .default) +// XCTAssertEqual(decodedRange, expectedRange) +// +// XCTAssertThrowsError( +// try row?.decode(column: "range", as: ClosedRange.self, context: .default) +// ) +// } +// +// func testInt8Range() async throws { +// let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() +// self.addTeardownBlock { +// try await conn.close() +// } +// struct Model: Decodable { +// let range: Range +// } +// let results1: PostgresQueryResult = try await conn.query(""" +// SELECT +// '[\(Int64.min), \(Int64.max))'::int8range AS range +// """).get() +// XCTAssertEqual(results1.count, 1) +// var row = results1.first?.makeRandomAccess() +// let expectedRange: Range = Int64.min...self, context: .default) +// XCTAssertEqual(decodedRange, expectedRange) +// +// let results2: PostgresQueryResult = try await conn.query(""" +// SELECT +// ARRAY[ +// '[0, 1)'::int8range, +// '[10, 11)'::int8range +// ] AS ranges +// """).get() +// XCTAssertEqual(results2.count, 1) +// row = results2.first?.makeRandomAccess() +// let decodedRangeArray = try row?.decode(column: "ranges", as: [Range].self, context: .default) +// let decodedClosedRangeArray = try row?.decode(column: "ranges", as: [ClosedRange].self, context: .default) +// XCTAssertEqual(decodedRangeArray, [0..<1, 10..<11]) +// XCTAssertEqual(decodedClosedRangeArray, [0...0, 10...10]) +// } +// +// func testEmptyInt8Range() async throws { +// let conn: PostgresConnection = try await PostgresConnection.test(on: eventLoop).get() +// self.addTeardownBlock { +// try await conn.close() +// } +// struct Model: Decodable { +// let range: Range +// } +// let randomValue = Int64.random(in: Int64.min...Int64.max) +// let results: PostgresQueryResult = try await conn.query(""" +// SELECT +// '[\(randomValue),\(randomValue))'::int8range AS range +// """).get() +// XCTAssertEqual(results.count, 1) +// let row = results.first?.makeRandomAccess() +// let expectedRange: Range = Int64.valueForEmptyRange...self, context: .default) +// XCTAssertEqual(decodedRange, expectedRange) +// +// XCTAssertThrowsError( +// try row?.decode(column: "range", as: ClosedRange.self, context: .default) +// ) +// } +// +// func testDates() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// struct Dates: Decodable { +// var date: Date +// var timestamp: Date +// var timestamptz: Date +// } +// var results: PostgresQueryResult? +// XCTAssertNoThrow(results = try conn?.query(""" +// SELECT +// '2016-01-18 01:02:03 +0042'::DATE as date, +// '2016-01-18 01:02:03 +0042'::TIMESTAMP as timestamp, +// '2016-01-18 01:02:03 +0042'::TIMESTAMPTZ as timestamptz +// """).wait()) +// XCTAssertEqual(results?.count, 1) +// let row = results?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "date"].date?.description, "2016-01-18 00:00:00 +0000") +// XCTAssertEqual(row?[data: "timestamp"].date?.description, "2016-01-18 01:02:03 +0000") +// XCTAssertEqual(row?[data: "timestamptz"].date?.description, "2016-01-18 00:20:03 +0000") +// } +// +// /// https://github.com/vapor/nio-postgres/issues/20 +// func testBindInteger() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// XCTAssertNoThrow(_ = try conn?.simpleQuery("drop table if exists person;").wait()) +// XCTAssertNoThrow(_ = try conn?.simpleQuery("create table person(id serial primary key, first_name text, last_name text);").wait()) +// defer { XCTAssertNoThrow(_ = try conn?.simpleQuery("drop table person;").wait()) } +// let id = PostgresData(int32: 5) +// XCTAssertNoThrow(_ = try conn?.query("SELECT id, first_name, last_name FROM person WHERE id = $1", [id]).wait()) +// } +// +// // https://github.com/vapor/nio-postgres/issues/21 +// func testAverageLengthNumeric() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// var results: PostgresQueryResult? +// XCTAssertNoThrow(results = try conn?.query("select avg(length('foo')) as average_length").wait()) +// let row = results?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: 0].double, 3.0) +// } +// +// func testNumericParsing() { +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// var rows: PostgresQueryResult? +// XCTAssertNoThrow(rows = try conn?.query(""" +// select +// '1234.5678'::numeric as a, +// '-123.456'::numeric as b, +// '123456.789123'::numeric as c, +// '3.14159265358979'::numeric as d, +// '10000'::numeric as e, +// '0.00001'::numeric as f, +// '100000000'::numeric as g, +// '0.000000001'::numeric as h, +// '100000000000'::numeric as i, +// '0.000000000001'::numeric as j, +// '123000000000'::numeric as k, +// '0.000000000123'::numeric as l, +// '0.5'::numeric as m +// """).wait()) +// XCTAssertEqual(rows?.count, 1) +// let row = rows?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "a"].string, "1234.5678") +// XCTAssertEqual(row?[data: "b"].string, "-123.456") +// XCTAssertEqual(row?[data: "c"].string, "123456.789123") +// XCTAssertEqual(row?[data: "d"].string, "3.14159265358979") +// XCTAssertEqual(row?[data: "e"].string, "10000") +// XCTAssertEqual(row?[data: "f"].string, "0.00001") +// XCTAssertEqual(row?[data: "g"].string, "100000000") +// XCTAssertEqual(row?[data: "h"].string, "0.000000001") +// XCTAssertEqual(row?[data: "k"].string, "123000000000") +// XCTAssertEqual(row?[data: "l"].string, "0.000000000123") +// XCTAssertEqual(row?[data: "m"].string, "0.5") +// } +// +// func testSingleNumericParsing() { +// // this seemingly duped test is useful for debugging numeric parsing +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// let numeric = "790226039477542363.6032384900176272473" +// var rows: PostgresQueryResult? +// XCTAssertNoThrow(rows = try conn?.query(""" +// select +// '\(numeric)'::numeric as n +// """).wait()) +// let row = rows?.first?.makeRandomAccess() +// XCTAssertEqual(row?[data: "n"].string, numeric) +// } +// +// func testRandomlyGeneratedNumericParsing() throws { +// // this test takes a long time to run +// try XCTSkipUnless(Self.shouldRunLongRunningTests) +// +// var conn: PostgresConnection? +// XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) +// defer { XCTAssertNoThrow( try conn?.close().wait() ) } +// +// for _ in 0..<1_000_000 { +// let integer = UInt.random(in: UInt.min.. Date: Wed, 13 Dec 2023 15:09:38 +0100 Subject: [PATCH 02/17] Remove deprecated listen API --- .../Connection/PostgresConnection.swift | 55 ------------------- .../New/NotificationListener.swift | 33 ----------- 2 files changed, 88 deletions(-) diff --git a/Sources/PostgresNIO/Connection/PostgresConnection.swift b/Sources/PostgresNIO/Connection/PostgresConnection.swift index eaf3b9f6..9762677b 100644 --- a/Sources/PostgresNIO/Connection/PostgresConnection.swift +++ b/Sources/PostgresNIO/Connection/PostgresConnection.swift @@ -529,61 +529,6 @@ extension PostgresConnection { } } -// MARK: Notifications - -/// Context for receiving NotificationResponse messages on a connection, used for PostgreSQL's `LISTEN`/`NOTIFY` support. -public final class PostgresListenContext: Sendable { - private let promise: EventLoopPromise - - var future: EventLoopFuture { - self.promise.futureResult - } - - init(promise: EventLoopPromise) { - self.promise = promise - } - - func cancel() { - self.promise.succeed() - } - - /// Detach this listener so it no longer receives notifications. Other listeners, including those for the same channel, are unaffected. `UNLISTEN` is not sent; you are responsible for issuing an `UNLISTEN` query yourself if it is appropriate for your application. - public func stop() { - self.promise.succeed() - } -} - -extension PostgresConnection { - /// Add a handler for NotificationResponse messages on a certain channel. This is used in conjunction with PostgreSQL's `LISTEN`/`NOTIFY` support: to listen on a channel, you add a listener using this method to handle the NotificationResponse messages, then issue a `LISTEN` query to instruct PostgreSQL to begin sending NotificationResponse messages. - @discardableResult - @preconcurrency - public func addListener( - channel: String, - handler notificationHandler: @Sendable @escaping (PostgresListenContext, PostgresMessage.NotificationResponse) -> Void - ) -> PostgresListenContext { - let listenContext = PostgresListenContext(promise: self.eventLoop.makePromise(of: Void.self)) - let id = self.internalListenID.loadThenWrappingIncrement(ordering: .relaxed) - - let listener = NotificationListener( - channel: channel, - id: id, - eventLoop: self.eventLoop, - context: listenContext, - closure: notificationHandler - ) - - let task = HandlerTask.startListening(listener) - self.channel.write(task, promise: nil) - - listenContext.future.whenComplete { _ in - let task = HandlerTask.cancelListening(channel, id) - self.channel.write(task, promise: nil) - } - - return listenContext - } -} - enum CloseTarget { case preparedStatement(String) case portal(String) diff --git a/Sources/PostgresNIO/New/NotificationListener.swift b/Sources/PostgresNIO/New/NotificationListener.swift index 9e47ff34..01951106 100644 --- a/Sources/PostgresNIO/New/NotificationListener.swift +++ b/Sources/PostgresNIO/New/NotificationListener.swift @@ -13,7 +13,6 @@ final class NotificationListener: @unchecked Sendable { case streamInitialized(CheckedContinuation) case streamListening(AsyncThrowingStream.Continuation) - case closure(PostgresListenContext, (PostgresListenContext, PostgresMessage.NotificationResponse) -> Void) case done } @@ -29,19 +28,6 @@ final class NotificationListener: @unchecked Sendable { self.state = .streamInitialized(checkedContinuation) } - init( - channel: String, - id: Int, - eventLoop: EventLoop, - context: PostgresListenContext, - closure: @Sendable @escaping (PostgresListenContext, PostgresMessage.NotificationResponse) -> Void - ) { - self.channel = channel - self.id = id - self.eventLoop = eventLoop - self.state = .closure(context, closure) - } - func startListeningSucceeded(handler: PostgresChannelHandler) { self.eventLoop.preconditionInEventLoop() let handlerLoopBound = NIOLoopBound(handler, eventLoop: self.eventLoop) @@ -73,9 +59,6 @@ final class NotificationListener: @unchecked Sendable { case .streamListening, .done: fatalError("Invalid state: \(self.state)") - - case .closure: - break // ignore } } @@ -87,14 +70,6 @@ final class NotificationListener: @unchecked Sendable { fatalError("Invalid state: \(self.state)") case .streamListening(let continuation): continuation.yield(.init(payload: backendMessage.payload)) - - case .closure(let postgresListenContext, let closure): - let message = PostgresMessage.NotificationResponse( - backendPID: backendMessage.backendPID, - channel: backendMessage.channel, - payload: backendMessage.payload - ) - closure(postgresListenContext, message) } } @@ -110,10 +85,6 @@ final class NotificationListener: @unchecked Sendable { self.state = .done continuation.finish(throwing: error) - case .closure(let postgresListenContext, _): - self.state = .done - postgresListenContext.cancel() - case .done: break // ignore } @@ -131,10 +102,6 @@ final class NotificationListener: @unchecked Sendable { self.state = .done continuation.finish() - case .closure(let postgresListenContext, _): - self.state = .done - postgresListenContext.cancel() - case .done: break // ignore } From 05d51ef32c1b4a6f40d02d98eb4e70bdc75e10cc Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:10:55 +0100 Subject: [PATCH 03/17] Remove `PostgresRequest` --- Sources/PostgresNIO/Docs.docc/index.md | 1 - Sources/PostgresNIO/PostgresRequest.swift | 11 ----------- 2 files changed, 12 deletions(-) delete mode 100644 Sources/PostgresNIO/PostgresRequest.swift diff --git a/Sources/PostgresNIO/Docs.docc/index.md b/Sources/PostgresNIO/Docs.docc/index.md index ebe27cd0..84b6b117 100644 --- a/Sources/PostgresNIO/Docs.docc/index.md +++ b/Sources/PostgresNIO/Docs.docc/index.md @@ -74,7 +74,6 @@ removed from the public API with the next major release. - ``PostgresJSONBCodable`` - ``PostgresMessageEncoder`` - ``PostgresMessageDecoder`` -- ``PostgresRequest`` - ``PostgresMessage`` - ``PostgresMessageType`` - ``PostgresFormatCode`` diff --git a/Sources/PostgresNIO/PostgresRequest.swift b/Sources/PostgresNIO/PostgresRequest.swift deleted file mode 100644 index 71bb6cd1..00000000 --- a/Sources/PostgresNIO/PostgresRequest.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Logging - -/// Protocol to encapsulate a function call on the Postgres server -/// -/// This protocol is deprecated going forward. -public protocol PostgresRequest { - // return nil to end request - func respond(to message: PostgresMessage) throws -> [PostgresMessage]? - func start() throws -> [PostgresMessage] - func log(to logger: Logger) -} From 2fcff6fae691b1b4b478a9b5c8a87a2e7234dbcd Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:12:34 +0100 Subject: [PATCH 04/17] Remove `PostgresMessageEncoder` --- .../Deprecated/PostgresMessageEncoder.swift | 42 ------------------- Sources/PostgresNIO/Docs.docc/index.md | 1 - 2 files changed, 43 deletions(-) delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessageEncoder.swift diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessageEncoder.swift b/Sources/PostgresNIO/Deprecated/PostgresMessageEncoder.swift deleted file mode 100644 index 8dd4c38d..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessageEncoder.swift +++ /dev/null @@ -1,42 +0,0 @@ -import NIOCore -import Logging - -@available(*, deprecated, message: "Will be removed from public API") -public final class PostgresMessageEncoder: MessageToByteEncoder { - /// See `MessageToByteEncoder`. - public typealias OutboundIn = PostgresMessage - - /// Logger to send debug messages to. - let logger: Logger? - - /// Creates a new `PostgresMessageEncoder`. - public init(logger: Logger? = nil) { - self.logger = logger - } - - /// See `MessageToByteEncoder`. - public func encode(data message: PostgresMessage, out: inout ByteBuffer) throws { - // serialize identifier - var message = message - switch message.identifier { - case .none: break - default: - out.write(identifier: message.identifier) - } - - // leave room for identifier and size - let messageSizeIndex = out.writerIndex - out.moveWriterIndex(forwardBy: 4) - - // serialize the message data - out.writeBuffer(&message.data) - - // set message size - out.setInteger(Int32(out.writerIndex - messageSizeIndex), at: messageSizeIndex) - self.logger?.trace("Encoded: PostgresMessage (\(message.identifier))") - } -} - -protocol ByteBufferSerializable { - func serialize(into buffer: inout ByteBuffer) -} diff --git a/Sources/PostgresNIO/Docs.docc/index.md b/Sources/PostgresNIO/Docs.docc/index.md index 84b6b117..f30a592f 100644 --- a/Sources/PostgresNIO/Docs.docc/index.md +++ b/Sources/PostgresNIO/Docs.docc/index.md @@ -72,7 +72,6 @@ removed from the public API with the next major release. - ``PostgresQueryResult`` - ``PostgresJSONCodable`` - ``PostgresJSONBCodable`` -- ``PostgresMessageEncoder`` - ``PostgresMessageDecoder`` - ``PostgresMessage`` - ``PostgresMessageType`` From f42ffdb8fa2b10f69f85172cd36a2ba059816b3a Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:13:27 +0100 Subject: [PATCH 05/17] Remove `PostgresMessageDecoder` --- .../Deprecated/PostgresMessageDecoder.swift | 66 ------------------- .../Message/PostgresMessageDecoderTests.swift | 39 ----------- 2 files changed, 105 deletions(-) delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessageDecoder.swift delete mode 100644 Tests/PostgresNIOTests/Message/PostgresMessageDecoderTests.swift diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessageDecoder.swift b/Sources/PostgresNIO/Deprecated/PostgresMessageDecoder.swift deleted file mode 100644 index e092c234..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessageDecoder.swift +++ /dev/null @@ -1,66 +0,0 @@ -import NIOCore -import Logging - -@available(*, deprecated, message: "Will be removed from public API") -public final class PostgresMessageDecoder: ByteToMessageDecoder { - /// See `ByteToMessageDecoder`. - public typealias InboundOut = PostgresMessage - - /// See `ByteToMessageDecoder`. - public var cumulationBuffer: ByteBuffer? - - /// If `true`, the server has asked for authentication. - public var hasSeenFirstMessage: Bool - - /// Logger to send debug messages to. - let logger: Logger? - - /// Creates a new `PostgresMessageDecoder`. - public init(logger: Logger? = nil) { - self.hasSeenFirstMessage = false - self.logger = logger - } - - /// See `ByteToMessageDecoder`. - public func decode(context: ChannelHandlerContext, buffer: inout ByteBuffer) throws -> DecodingState { - var peekBuffer = buffer - - // peek at the message identifier - // the message identifier is always the first byte of a message - guard let identifier = peekBuffer.readInteger(as: UInt8.self).map(PostgresMessage.Identifier.init) else { - return .needMoreData - } - - let message: PostgresMessage - - // special ssl case, no body - if !self.hasSeenFirstMessage && (identifier == .sslSupported || identifier == .sslUnsupported) { - message = PostgresMessage(identifier: identifier, data: context.channel.allocator.buffer(capacity: 0)) - } else { - // peek at the message size - // the message size is always a 4 byte integer appearing immediately after the message identifier - guard let messageSize = peekBuffer.readInteger(as: Int32.self).flatMap(Int.init) else { - return .needMoreData - } - - // ensure message is large enough (skipping message type) or reject - guard let data = peekBuffer.readSlice(length: messageSize - 4) else { - return .needMoreData - } - - message = PostgresMessage(identifier: identifier, data: data) - } - self.hasSeenFirstMessage = true - - // there is sufficient data, use this buffer - buffer = peekBuffer - self.logger?.trace("Decoded: PostgresMessage (\(message.identifier))") - context.fireChannelRead(wrapInboundOut(message)) - return .continue - } - - public func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState { - // ignore - return .needMoreData - } -} diff --git a/Tests/PostgresNIOTests/Message/PostgresMessageDecoderTests.swift b/Tests/PostgresNIOTests/Message/PostgresMessageDecoderTests.swift deleted file mode 100644 index bbd022db..00000000 --- a/Tests/PostgresNIOTests/Message/PostgresMessageDecoderTests.swift +++ /dev/null @@ -1,39 +0,0 @@ -import PostgresNIO -import XCTest -import NIOTestUtils -import NIOCore - -class PostgresMessageDecoderTests: XCTestCase { - @available(*, deprecated, message: "Tests deprecated API") - func testMessageDecoder() { - let sample: [UInt8] = [ - 0x52, // R - authentication - 0x00, 0x00, 0x00, 0x0C, // length = 12 - 0x00, 0x00, 0x00, 0x05, // md5 - 0x01, 0x02, 0x03, 0x04, // salt - 0x4B, // B - backend key data - 0x00, 0x00, 0x00, 0x0C, // length = 12 - 0x05, 0x05, 0x05, 0x05, // process id - 0x01, 0x01, 0x01, 0x01, // secret key - ] - var input = ByteBufferAllocator().buffer(capacity: 0) - input.writeBytes(sample) - - let output: [PostgresMessage] = [ - PostgresMessage(identifier: .authentication, bytes: [ - 0x00, 0x00, 0x00, 0x05, - 0x01, 0x02, 0x03, 0x04, - ]), - PostgresMessage(identifier: .backendKeyData, bytes: [ - 0x05, 0x05, 0x05, 0x05, - 0x01, 0x01, 0x01, 0x01, - ]) - ] - XCTAssertNoThrow(try XCTUnwrap(ByteToMessageDecoderVerifier.verifyDecoder( - inputOutputPairs: [(input, output)], - decoderFactory: { - PostgresMessageDecoder() - } - ))) - } -} From aecd71a49d0d17f530ebf123ec2bb9f0f4622e50 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:17:25 +0100 Subject: [PATCH 06/17] Remove `PostgresMessageType` --- .../PostgresMessage+Authentication.swift | 2 +- .../Deprecated/PostgresMessage+Bind.swift | 2 +- .../Deprecated/PostgresMessage+Close.swift | 2 +- .../PostgresMessage+CommandComplete.swift | 2 +- .../Deprecated/PostgresMessage+Describe.swift | 2 +- .../Deprecated/PostgresMessage+Execute.swift | 2 +- ...PostgresMessage+ParameterDescription.swift | 2 +- .../PostgresMessage+ParameterStatus.swift | 2 +- .../Deprecated/PostgresMessage+Parse.swift | 2 +- .../Deprecated/PostgresMessage+Password.swift | 2 +- .../PostgresMessage+SASLResponse.swift | 4 +-- .../PostgresMessage+SSLRequest.swift | 2 +- .../PostgresMessage+SimpleQuery.swift | 2 +- .../Deprecated/PostgresMessage+Startup.swift | 2 +- .../Deprecated/PostgresMessage+Sync.swift | 2 +- .../PostgresMessage+Terminate.swift | 2 +- Sources/PostgresNIO/Docs.docc/index.md | 2 -- .../PostgresMessage+BackendKeyData.swift | 2 +- .../Message/PostgresMessage+DataRow.swift | 2 +- .../Message/PostgresMessage+Error.swift | 2 +- ...PostgresMessage+NotificationResponse.swift | 2 +- .../PostgresMessage+RowDescription.swift | 2 +- .../Message/PostgresMessageType.swift | 36 ------------------- 23 files changed, 22 insertions(+), 60 deletions(-) delete mode 100644 Sources/PostgresNIO/Message/PostgresMessageType.swift diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift index da7c25d5..3eb0875c 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Authentication request returned by the server. @available(*, deprecated, message: "Will be removed from public API") - public enum Authentication: PostgresMessageType { + public enum Authentication { public static var identifier: PostgresMessage.Identifier { return .authentication } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift index 5ff4bbf0..077b05c7 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a Bind command. @available(*, deprecated, message: "Will be removed from public API") - public struct Bind: PostgresMessageType { + public struct Bind { public static var identifier: PostgresMessage.Identifier { return .bind } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift index 9bcc8aa1..f26340af 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a Close Command @available(*, deprecated, message: "Will be removed from public API") - public struct Close: PostgresMessageType { + public struct Close { public static var identifier: PostgresMessage.Identifier { return .close } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift index c9370402..746ce190 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a Close command. @available(*, deprecated, message: "Will be removed from public API") - public struct CommandComplete: PostgresMessageType { + public struct CommandComplete { /// Parses an instance of this message type from a byte buffer. public static func parse(from buffer: inout ByteBuffer) throws -> CommandComplete { guard let string = buffer.readNullTerminatedString() else { diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift index 787355db..e4545cf0 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a Describe command. @available(*, deprecated, message: "Will be removed from public API") - public struct Describe: PostgresMessageType { + public struct Describe { public static var identifier: PostgresMessage.Identifier { return .describe } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift index 39b447a4..33232920 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as an Execute command. @available(*, deprecated, message: "Will be removed from public API") - public struct Execute: PostgresMessageType { + public struct Execute { public static var identifier: PostgresMessage.Identifier { return .execute } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift index 89e67682..672c2ee2 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a parameter description. @available(*, deprecated, message: "Will be removed from public API") - public struct ParameterDescription: PostgresMessageType { + public struct ParameterDescription { /// Parses an instance of this message type from a byte buffer. public static func parse(from buffer: inout ByteBuffer) throws -> ParameterDescription { guard let dataTypes = try buffer.read(array: PostgresDataType.self, { buffer in diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift index 5ad6f95e..bffad6e6 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift @@ -2,7 +2,7 @@ import NIOCore extension PostgresMessage { @available(*, deprecated, message: "Will be removed from public API") - public struct ParameterStatus: PostgresMessageType, CustomStringConvertible { + public struct ParameterStatus: CustomStringConvertible { /// Parses an instance of this message type from a byte buffer. public static func parse(from buffer: inout ByteBuffer) throws -> ParameterStatus { guard let parameter = buffer.readNullTerminatedString() else { diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift index 8fb5a1ff..ad53a012 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a Parse command. @available(*, deprecated, message: "Will be removed from public API") - public struct Parse: PostgresMessageType { + public struct Parse { public static var identifier: PostgresMessage.Identifier { return .parse } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift index cafe9cda..bb1f0c41 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift @@ -5,7 +5,7 @@ extension PostgresMessage { /// GSSAPI and SSPI response messages (which is really a design error, since the contained /// data is not a null-terminated string in that case, but can be arbitrary binary data). @available(*, deprecated, message: "Will be removed from public API") - public struct Password: PostgresMessageType { + public struct Password { public static var identifier: PostgresMessage.Identifier { return .passwordMessage } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift index dc3b1772..a7f19a61 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// SASL ongoing challenge response message sent by the client. @available(*, deprecated, message: "Will be removed from public API") - public struct SASLResponse: PostgresMessageType { + public struct SASLResponse { public static var identifier: PostgresMessage.Identifier { return .saslResponse } @@ -52,7 +52,7 @@ extension PostgresMessage { } @available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.SASLInitialResponse: PostgresMessageType { +extension PostgresMessage.SASLInitialResponse { public static var identifier: PostgresMessage.Identifier { return .saslInitialResponse } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift index ee504932..ab3d5373 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift @@ -4,7 +4,7 @@ extension PostgresMessage { /// A message asking the PostgreSQL server if SSL is supported /// For more info, see https://www.postgresql.org/docs/10/static/protocol-flow.html#id-1.10.5.7.11 @available(*, deprecated, message: "Will be removed from public API") - public struct SSLRequest: PostgresMessageType { + public struct SSLRequest { /// The SSL request code. The value is chosen to contain 1234 in the most significant 16 bits, /// and 5679 in the least significant 16 bits. public let code: Int32 diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift index a0a6cfcf..a447120d 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a simple query. @available(*, deprecated, message: "Will be removed from public API") - public struct SimpleQuery: PostgresMessageType { + public struct SimpleQuery { public static var identifier: PostgresMessage.Identifier { return .query } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift index e9762439..62f7dc55 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// First message sent from the frontend during startup. @available(*, deprecated, message: "Will be removed from public API") - public struct Startup: PostgresMessageType { + public struct Startup { public static var identifier: PostgresMessage.Identifier { return .none } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift index 0560ef7a..4ec1aae1 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift @@ -3,7 +3,7 @@ import NIOCore extension PostgresMessage { /// Identifies the message as a Bind command. @available(*, deprecated, message: "Will be removed from public API") - public struct Sync: PostgresMessageType { + public struct Sync { public static var identifier: PostgresMessage.Identifier { return .sync } diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift index afeae5bf..8f08e2be 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift @@ -2,7 +2,7 @@ import NIOCore extension PostgresMessage { @available(*, deprecated, message: "Will be removed from public API") - public struct Terminate: PostgresMessageType { + public struct Terminate { public static var identifier: PostgresMessage.Identifier { .terminate } diff --git a/Sources/PostgresNIO/Docs.docc/index.md b/Sources/PostgresNIO/Docs.docc/index.md index f30a592f..0f833b68 100644 --- a/Sources/PostgresNIO/Docs.docc/index.md +++ b/Sources/PostgresNIO/Docs.docc/index.md @@ -72,9 +72,7 @@ removed from the public API with the next major release. - ``PostgresQueryResult`` - ``PostgresJSONCodable`` - ``PostgresJSONBCodable`` -- ``PostgresMessageDecoder`` - ``PostgresMessage`` -- ``PostgresMessageType`` - ``PostgresFormatCode`` - ``SASLAuthenticationManager`` - ``SASLAuthenticationMechanism`` diff --git a/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift b/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift index 63a6af7d..875be913 100644 --- a/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift +++ b/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift @@ -13,7 +13,7 @@ extension PostgresMessage { } @available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.BackendKeyData: PostgresMessageType { +extension PostgresMessage.BackendKeyData { public static var identifier: PostgresMessage.Identifier { .backendKeyData } diff --git a/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift b/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift index 655bfb1e..e15c8cb6 100644 --- a/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift +++ b/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift @@ -31,7 +31,7 @@ extension PostgresMessage { } @available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.DataRow: PostgresMessageType { +extension PostgresMessage.DataRow { public static var identifier: PostgresMessage.Identifier { return .dataRow } diff --git a/Sources/PostgresNIO/Message/PostgresMessage+Error.swift b/Sources/PostgresNIO/Message/PostgresMessage+Error.swift index 45cda21f..7296d554 100644 --- a/Sources/PostgresNIO/Message/PostgresMessage+Error.swift +++ b/Sources/PostgresNIO/Message/PostgresMessage+Error.swift @@ -94,7 +94,7 @@ extension PostgresMessage { } @available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.Error: PostgresMessageType { +extension PostgresMessage.Error { public static var identifier: PostgresMessage.Identifier { return .error } diff --git a/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift b/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift index 1a3b596d..8b37a2e6 100644 --- a/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift +++ b/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift @@ -10,7 +10,7 @@ extension PostgresMessage { } @available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.NotificationResponse: PostgresMessageType { +extension PostgresMessage.NotificationResponse { public static let identifier = PostgresMessage.Identifier.notificationResponse /// Parses an instance of this message type from a byte buffer. diff --git a/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift b/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift index 5713cc99..66cc318c 100644 --- a/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift +++ b/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift @@ -81,7 +81,7 @@ extension PostgresMessage { } @available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.RowDescription: PostgresMessageType { +extension PostgresMessage.RowDescription { /// See `PostgresMessageType`. public static var identifier: PostgresMessage.Identifier { return .rowDescription diff --git a/Sources/PostgresNIO/Message/PostgresMessageType.swift b/Sources/PostgresNIO/Message/PostgresMessageType.swift deleted file mode 100644 index 170c4aec..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessageType.swift +++ /dev/null @@ -1,36 +0,0 @@ -import NIOCore - -@available(*, deprecated, message: "Will be removed from public API. Internally we now use `PostgresBackendMessage` and `PostgresFrontendMessage`") -public protocol PostgresMessageType { - static var identifier: PostgresMessage.Identifier { get } - static func parse(from buffer: inout ByteBuffer) throws -> Self - func serialize(into buffer: inout ByteBuffer) throws -} - -@available(*, deprecated, message: "`PostgresMessageType` protocol is deprecated.") -extension PostgresMessageType { - @available(*, deprecated, message: "Will be removed from public API.") - func message() throws -> PostgresMessage { - var buffer = ByteBufferAllocator().buffer(capacity: 0) - try self.serialize(into: &buffer) - return .init(identifier: Self.identifier, data: buffer) - } - - public init(message: PostgresMessage) throws { - var message = message - self = try Self.parse(from: &message.data) - } - - @available(*, deprecated, message: "Will be removed from public API.") - public static var identifier: PostgresMessage.Identifier { - return .none - } - - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - fatalError("\(Self.self) does not support parsing.") - } - - public func serialize(into buffer: inout ByteBuffer) throws { - fatalError("\(Self.self) does not support serializing.") - } -} From 2685e57e64fdfa8942a73e1e361de2c618962b7f Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:21:53 +0100 Subject: [PATCH 07/17] Remove `PostgresMessage` --- Sources/PostgresNIO/Data/PostgresRow.swift | 24 --- .../PostgresMessage+Authentication.swift | 119 -------------- .../Deprecated/PostgresMessage+Bind.swift | 61 ------- .../Deprecated/PostgresMessage+Close.swift | 40 ----- .../PostgresMessage+CommandComplete.swift | 18 --- .../Deprecated/PostgresMessage+Describe.swift | 38 ----- .../Deprecated/PostgresMessage+Execute.swift | 28 ---- ...PostgresMessage+ParameterDescription.swift | 23 --- .../PostgresMessage+ParameterStatus.swift | 28 ---- .../Deprecated/PostgresMessage+Parse.swift | 31 ---- .../Deprecated/PostgresMessage+Password.swift | 29 ---- .../PostgresMessage+ReadyForQuery.swift | 27 ---- .../PostgresMessage+SASLResponse.swift | 78 --------- .../PostgresMessage+SSLRequest.swift | 27 ---- .../PostgresMessage+SimpleQuery.swift | 19 --- .../Deprecated/PostgresMessage+Startup.swift | 48 ------ .../Deprecated/PostgresMessage+Sync.swift | 19 --- .../PostgresMessage+Terminate.swift | 12 -- .../Message/PostgresMessage+0.swift | 23 --- .../PostgresMessage+BackendKeyData.swift | 31 ---- .../Message/PostgresMessage+DataRow.swift | 54 ------- .../Message/PostgresMessage+Error.swift | 113 ------------- .../Message/PostgresMessage+Identifier.swift | 151 ------------------ ...PostgresMessage+NotificationResponse.swift | 29 ---- .../PostgresMessage+RowDescription.swift | 99 ------------ Sources/PostgresNIO/Postgres+PSQLCompat.swift | 11 +- .../Utilities/PostgresError+Code.swift | 5 - .../PostgresNIO/Utilities/PostgresError.swift | 3 - 28 files changed, 1 insertion(+), 1187 deletions(-) delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+ReadyForQuery.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+0.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+Error.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+Identifier.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift delete mode 100644 Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift diff --git a/Sources/PostgresNIO/Data/PostgresRow.swift b/Sources/PostgresNIO/Data/PostgresRow.swift index e3aea692..cc7b7611 100644 --- a/Sources/PostgresNIO/Data/PostgresRow.swift +++ b/Sources/PostgresNIO/Data/PostgresRow.swift @@ -265,30 +265,6 @@ extension PostgresRandomAccessRow { // MARK: Deprecated API extension PostgresRow { - @available(*, deprecated, message: "Will be removed from public API.") - public var rowDescription: PostgresMessage.RowDescription { - let fields = self.columns.map { column in - PostgresMessage.RowDescription.Field( - name: column.name, - tableOID: UInt32(column.tableOID), - columnAttributeNumber: column.columnAttributeNumber, - dataType: PostgresDataType(UInt32(column.dataType.rawValue)), - dataTypeSize: column.dataTypeSize, - dataTypeModifier: column.dataTypeModifier, - formatCode: .init(psqlFormatCode: column.format) - ) - } - return PostgresMessage.RowDescription(fields: fields) - } - - @available(*, deprecated, message: "Iterate the cells on `PostgresRow` instead.") - public var dataRow: PostgresMessage.DataRow { - let columns = self.data.map { - PostgresMessage.DataRow.Column(value: $0) - } - return PostgresMessage.DataRow(columns: columns) - } - @available(*, deprecated, message: """ This call is O(n) where n is the number of cells in the row. For random access to cells in a row create a PostgresRandomAccessRow from the row first and use its subscript diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift deleted file mode 100644 index 3eb0875c..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Authentication.swift +++ /dev/null @@ -1,119 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Authentication request returned by the server. - @available(*, deprecated, message: "Will be removed from public API") - public enum Authentication { - public static var identifier: PostgresMessage.Identifier { - return .authentication - } - - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> Authentication { - guard let type = buffer.readInteger(as: Int32.self) else { - throw PostgresError.protocol("Could not read authentication message type") - } - switch type { - case 0: return .ok - case 3: return .plaintext - case 5: - guard let salt = buffer.readBytes(length: 4) else { - throw PostgresError.protocol("Could not parse MD5 salt from authentication message") - } - return .md5(salt) - case 10: - var mechanisms: [String] = [] - while buffer.readableBytes > 0 { - guard let nextString = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not parse SASL mechanisms from authentication message") - } - if nextString.isEmpty { - break - } - mechanisms.append(nextString) - } - guard buffer.readableBytes == 0 else { - throw PostgresError.protocol("Trailing data at end of SASL mechanisms authentication message") - } - return .saslMechanisms(mechanisms) - case 11: - guard let challengeData = buffer.readBytes(length: buffer.readableBytes) else { - throw PostgresError.protocol("Could not parse SASL challenge from authentication message") - } - return .saslContinue(challengeData) - case 12: - guard let finalData = buffer.readBytes(length: buffer.readableBytes) else { - throw PostgresError.protocol("Could not parse SASL final data from authentication message") - } - return .saslFinal(finalData) - - case 2, 7...9: - throw PostgresError.protocol("Support for KRBv5, GSSAPI, and SSPI authentication are not implemented") - case 6: - throw PostgresError.protocol("Support for SCM credential authentication is obsolete") - - default: - throw PostgresError.protocol("Unknown authentication request type: \(type)") - } - } - - public func serialize(into buffer: inout ByteBuffer) throws { - switch self { - case .ok: - buffer.writeInteger(0, as: Int32.self) - case .plaintext: - buffer.writeInteger(3, as: Int32.self) - case .md5(let salt): - buffer.writeInteger(5, as: Int32.self) - buffer.writeBytes(salt) - case .saslMechanisms(let mechanisms): - buffer.writeInteger(10, as: Int32.self) - mechanisms.forEach { - buffer.writeNullTerminatedString($0) - } - case .saslContinue(let challenge): - buffer.writeInteger(11, as: Int32.self) - buffer.writeBytes(challenge) - case .saslFinal(let data): - buffer.writeInteger(12, as: Int32.self) - buffer.writeBytes(data) - } - } - - /// AuthenticationOk - /// Specifies that the authentication was successful. - case ok - - /// AuthenticationCleartextPassword - /// Specifies that a clear-text password is required. - case plaintext - - /// AuthenticationMD5Password - /// Specifies that an MD5-encrypted password is required. - case md5([UInt8]) - - /// AuthenticationSASL - /// Specifies the start of SASL mechanism negotiation. - case saslMechanisms([String]) - - /// AuthenticationSASLContinue - /// Specifies SASL mechanism-specific challenge data. - case saslContinue([UInt8]) - - /// AuthenticationSASLFinal - /// Specifies mechanism-specific post-authentication client data. - case saslFinal([UInt8]) - - /// See `CustomStringConvertible`. - public var description: String { - switch self { - case .ok: return "Ok" - case .plaintext: return "CleartextPassword" - case .md5(let salt): return "MD5Password(salt: 0x\(salt.hexdigest()))" - case .saslMechanisms(let mech): return "SASLMechanisms(\(mech))" - case .saslContinue(let data): return "SASLChallenge(\(data))" - case .saslFinal(let data): return "SASLFinal(\(data))" - } - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift deleted file mode 100644 index 077b05c7..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Bind.swift +++ /dev/null @@ -1,61 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a Bind command. - @available(*, deprecated, message: "Will be removed from public API") - public struct Bind { - public static var identifier: PostgresMessage.Identifier { - return .bind - } - - public var description: String { - return "Bind(\(self.parameters.count))" - } - - public struct Parameter { - /// The value of the parameter, in the format indicated by the associated format code. n is the above length. - var value: ByteBuffer? - } - - /// The name of the destination portal (an empty string selects the unnamed portal). - public var portalName: String - - /// The name of the source prepared statement (an empty string selects the unnamed prepared statement). - public var statementName: String - - /// The number of parameter format codes that follow (denoted C below). - /// This can be zero to indicate that there are no parameters or that the parameters all use the default format (text); - /// or one, in which case the specified format code is applied to all parameters; or it can equal the actual number of parameters. - /// The parameter format codes. Each must presently be zero (text) or one (binary). - public var parameterFormatCodes: [PostgresFormat] - - /// The number of parameter values that follow (possibly zero). This must match the number of parameters needed by the query. - public var parameters: [Parameter] - - /// The number of result-column format codes that follow (denoted R below). - /// This can be zero to indicate that there are no result columns or that the result columns should all use the default format (text); - /// or one, in which case the specified format code is applied to all result columns (if any); - /// or it can equal the actual number of result columns of the query. - public var resultFormatCodes: [PostgresFormat] - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeNullTerminatedString(self.portalName) - buffer.writeNullTerminatedString(self.statementName) - - buffer.write(array: self.parameterFormatCodes) - buffer.write(array: self.parameters) { - if var data = $1.value { - // The length of the parameter value, in bytes (this count does not include itself). Can be zero. - $0.writeInteger(numericCast(data.readableBytes), as: Int32.self) - // The value of the parameter, in the format indicated by the associated format code. n is the above length. - $0.writeBuffer(&data) - } else { - // As a special case, -1 indicates a NULL parameter value. No value bytes follow in the NULL case. - $0.writeInteger(-1, as: Int32.self) - } - } - buffer.write(array: self.resultFormatCodes) - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift deleted file mode 100644 index f26340af..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Close.swift +++ /dev/null @@ -1,40 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a Close Command - @available(*, deprecated, message: "Will be removed from public API") - public struct Close { - public static var identifier: PostgresMessage.Identifier { - return .close - } - - /// Close Target. Determines if the Close command should close a prepared statement - /// or portal. - public enum Target: Int8 { - case preparedStatement = 0x53 // 'S' - prepared statement - case portal = 0x50 // 'P' - portal - } - - /// Determines if the `name` identifes a portal or a prepared statement - public var target: Target - - /// The name of the prepared statement or portal to describe - /// (an empty string selects the unnamed prepared statement or portal). - public var name: String - - - /// See `CustomStringConvertible`. - public var description: String { - switch target { - case .preparedStatement: return "Statement(\(name))" - case .portal: return "Portal(\(name))" - } - } - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) throws { - buffer.writeInteger(target.rawValue) - buffer.writeNullTerminatedString(name) - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift deleted file mode 100644 index 746ce190..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+CommandComplete.swift +++ /dev/null @@ -1,18 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a Close command. - @available(*, deprecated, message: "Will be removed from public API") - public struct CommandComplete { - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> CommandComplete { - guard let string = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not parse close response message") - } - return .init(tag: string) - } - - /// The command tag. This is usually a single word that identifies which SQL command was completed. - public var tag: String - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift deleted file mode 100644 index e4545cf0..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Describe.swift +++ /dev/null @@ -1,38 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a Describe command. - @available(*, deprecated, message: "Will be removed from public API") - public struct Describe { - public static var identifier: PostgresMessage.Identifier { - return .describe - } - - /// Command type. - public enum Command: UInt8 { - case statement = 0x53 // S - case portal = 0x50 // P - } - - /// 'S' to describe a prepared statement; or 'P' to describe a portal. - public let command: Command - - /// The name of the prepared statement or portal to describe - /// (an empty string selects the unnamed prepared statement or portal). - public var name: String - - /// See `CustomStringConvertible`. - public var description: String { - switch command { - case .statement: return "Statement(" + name + ")" - case .portal: return "Portal(" + name + ")" - } - } - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeInteger(command.rawValue) - buffer.writeNullTerminatedString(name) - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift deleted file mode 100644 index 33232920..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Execute.swift +++ /dev/null @@ -1,28 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as an Execute command. - @available(*, deprecated, message: "Will be removed from public API") - public struct Execute { - public static var identifier: PostgresMessage.Identifier { - return .execute - } - - public var description: String { - return "Execute()" - } - - /// The name of the destination portal (an empty string selects the unnamed portal). - public var portalName: String - - /// Maximum number of rows to return, if portal contains a query that - /// returns rows (ignored otherwise). Zero denotes “no limit”. - public var maxRows: Int32 - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeNullTerminatedString(portalName) - buffer.writeInteger(self.maxRows) - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift deleted file mode 100644 index 672c2ee2..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterDescription.swift +++ /dev/null @@ -1,23 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a parameter description. - @available(*, deprecated, message: "Will be removed from public API") - public struct ParameterDescription { - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> ParameterDescription { - guard let dataTypes = try buffer.read(array: PostgresDataType.self, { buffer in - guard let dataType = buffer.readInteger(as: PostgresDataType.self) else { - throw PostgresError.protocol("Could not parse data type integer in parameter description message.") - } - return dataType - }) else { - throw PostgresError.protocol("Could not parse data types in parameter description message.") - } - return .init(dataTypes: dataTypes) - } - - /// Specifies the object ID of the parameter data type. - public var dataTypes: [PostgresDataType] - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift deleted file mode 100644 index bffad6e6..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+ParameterStatus.swift +++ /dev/null @@ -1,28 +0,0 @@ -import NIOCore - -extension PostgresMessage { - @available(*, deprecated, message: "Will be removed from public API") - public struct ParameterStatus: CustomStringConvertible { - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> ParameterStatus { - guard let parameter = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not read parameter from parameter status message") - } - guard let value = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not read value from parameter status message") - } - return .init(parameter: parameter, value: value) - } - - /// The name of the run-time parameter being reported. - public var parameter: String - - /// The current value of the parameter. - public var value: String - - /// See `CustomStringConvertible`. - public var description: String { - return "\(parameter): \(value)" - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift deleted file mode 100644 index ad53a012..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Parse.swift +++ /dev/null @@ -1,31 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a Parse command. - @available(*, deprecated, message: "Will be removed from public API") - public struct Parse { - public static var identifier: PostgresMessage.Identifier { - return .parse - } - - /// The name of the destination prepared statement (an empty string selects the unnamed prepared statement). - public var statementName: String - - /// The query string to be parsed. - public var query: String - - /// The number of parameter data types specified (can be zero). - /// Note that this is not an indication of the number of parameters that might appear in the - /// query string, only the number that the frontend wants to prespecify types for. - /// Specifies the object ID of the parameter data type. Placing a zero here is equivalent to leaving the type unspecified. - public var parameterTypes: [PostgresDataType] - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeString(statementName + "\0") - buffer.writeString(query + "\0") - buffer.writeInteger(numericCast(self.parameterTypes.count), as: Int16.self) - self.parameterTypes.forEach { buffer.writeInteger($0.rawValue) } - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift deleted file mode 100644 index bb1f0c41..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Password.swift +++ /dev/null @@ -1,29 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a password response. Note that this is also used for - /// GSSAPI and SSPI response messages (which is really a design error, since the contained - /// data is not a null-terminated string in that case, but can be arbitrary binary data). - @available(*, deprecated, message: "Will be removed from public API") - public struct Password { - public static var identifier: PostgresMessage.Identifier { - return .passwordMessage - } - - public init(string: String) { - self.string = string - } - - /// The password (encrypted, if requested). - public var string: String - - public var description: String { - return "Password(\(string))" - } - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeString(self.string + "\0") - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+ReadyForQuery.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+ReadyForQuery.swift deleted file mode 100644 index 5afc0910..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+ReadyForQuery.swift +++ /dev/null @@ -1,27 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message type. ReadyForQuery is sent whenever the backend is ready for a new query cycle. - @available(*, deprecated, message: "Will be removed from public API") - public struct ReadyForQuery: CustomStringConvertible { - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> ReadyForQuery { - guard let status = buffer.readInteger(as: UInt8.self) else { - throw PostgresError.protocol("Could not read transaction status from ready for query message") - } - return .init(transactionStatus: status) - } - - /// Current backend transaction status indicator. - /// Possible values are 'I' if idle (not in a transaction block); - /// 'T' if in a transaction block; or 'E' if in a failed transaction block - /// (queries will be rejected until block is ended). - public var transactionStatus: UInt8 - - /// See `CustomStringConvertible`. - public var description: String { - let char = String(bytes: [transactionStatus], encoding: .ascii) ?? "n/a" - return "transactionStatus: \(char)" - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift deleted file mode 100644 index a7f19a61..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+SASLResponse.swift +++ /dev/null @@ -1,78 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// SASL ongoing challenge response message sent by the client. - @available(*, deprecated, message: "Will be removed from public API") - public struct SASLResponse { - public static var identifier: PostgresMessage.Identifier { - return .saslResponse - } - - public let responseData: [UInt8] - - public static func parse(from buffer: inout ByteBuffer) throws -> SASLResponse { - guard let data = buffer.readBytes(length: buffer.readableBytes) else { - throw PostgresError.protocol("Could not parse SASL response from response message") - } - - return SASLResponse(responseData: data) - } - - public func serialize(into buffer: inout ByteBuffer) throws { - buffer.writeBytes(responseData) - } - - public var description: String { - return "SASLResponse(\(responseData))" - } - } -} - -extension PostgresMessage { - /// SASL initial challenge response message sent by the client. - @available(*, deprecated, message: "Will be removed from public API") - public struct SASLInitialResponse { - public let mechanism: String - public let initialData: [UInt8] - - public func serialize(into buffer: inout ByteBuffer) throws { - buffer.writeNullTerminatedString(self.mechanism) - if initialData.count > 0 { - buffer.writeInteger(Int32(initialData.count), as: Int32.self) // write(array:) writes Int16, which is incorrect here - buffer.writeBytes(initialData) - } else { - buffer.writeInteger(-1, as: Int32.self) - } - } - - public var description: String { - return "SASLInitialResponse(\(mechanism), data: \(initialData))" - } - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.SASLInitialResponse { - public static var identifier: PostgresMessage.Identifier { - return .saslInitialResponse - } - - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - guard let mechanism = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not parse SASL mechanism from initial response message") - } - guard let dataLength = buffer.readInteger(as: Int32.self) else { - throw PostgresError.protocol("Could not parse SASL initial data length from initial response message") - } - - var actualData: [UInt8] = [] - - if dataLength != -1 { - guard let data = buffer.readBytes(length: Int(dataLength)) else { - throw PostgresError.protocol("Could not parse SASL initial data from initial response message") - } - actualData = data - } - return .init(mechanism: mechanism, initialData: actualData) - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift deleted file mode 100644 index ab3d5373..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+SSLRequest.swift +++ /dev/null @@ -1,27 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// A message asking the PostgreSQL server if SSL is supported - /// For more info, see https://www.postgresql.org/docs/10/static/protocol-flow.html#id-1.10.5.7.11 - @available(*, deprecated, message: "Will be removed from public API") - public struct SSLRequest { - /// The SSL request code. The value is chosen to contain 1234 in the most significant 16 bits, - /// and 5679 in the least significant 16 bits. - public let code: Int32 - - /// See `CustomStringConvertible`. - public var description: String { - return "SSLRequest" - } - - /// Creates a new `SSLRequest`. - public init() { - self.code = 80877103 - } - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeInteger(self.code) - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift deleted file mode 100644 index a447120d..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+SimpleQuery.swift +++ /dev/null @@ -1,19 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a simple query. - @available(*, deprecated, message: "Will be removed from public API") - public struct SimpleQuery { - public static var identifier: PostgresMessage.Identifier { - return .query - } - - /// The query string itself. - public var string: String - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeString(self.string + "\0") - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift deleted file mode 100644 index 62f7dc55..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Startup.swift +++ /dev/null @@ -1,48 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// First message sent from the frontend during startup. - @available(*, deprecated, message: "Will be removed from public API") - public struct Startup { - public static var identifier: PostgresMessage.Identifier { - return .none - } - - public var description: String { - return "Startup()" - } - - /// Creates a `Startup` with "3.0" as the protocol version. - public static func versionThree(parameters: [String: String]) -> Startup { - return .init(protocolVersion: 0x00_03_00_00, parameters: parameters) - } - - /// The protocol version number. The most significant 16 bits are the major - /// version number (3 for the protocol described here). The least significant - /// 16 bits are the minor version number (0 for the protocol described here). - public var protocolVersion: Int32 - - /// The protocol version number is followed by one or more pairs of parameter - /// name and value strings. A zero byte is required as a terminator after - /// the last name/value pair. Parameters can appear in any order. user is required, - /// others are optional. Each parameter is specified as: - public var parameters: [String: String] - - /// Creates a new `PostgreSQLStartupMessage`. - public init(protocolVersion: Int32, parameters: [String: String]) { - self.protocolVersion = protocolVersion - self.parameters = parameters - } - - /// Serializes this message into a byte buffer. - public func serialize(into buffer: inout ByteBuffer) { - buffer.writeInteger(self.protocolVersion) - for (key, val) in parameters { - buffer.writeString(key + "\0") - buffer.writeString(val + "\0") - } - // terminator - buffer.writeString("\0") - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift deleted file mode 100644 index 4ec1aae1..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Sync.swift +++ /dev/null @@ -1,19 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a Bind command. - @available(*, deprecated, message: "Will be removed from public API") - public struct Sync { - public static var identifier: PostgresMessage.Identifier { - return .sync - } - - public var description: String { - return "Sync" - } - - public func serialize(into buffer: inout ByteBuffer) { - - } - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift b/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift deleted file mode 100644 index 8f08e2be..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresMessage+Terminate.swift +++ /dev/null @@ -1,12 +0,0 @@ -import NIOCore - -extension PostgresMessage { - @available(*, deprecated, message: "Will be removed from public API") - public struct Terminate { - public static var identifier: PostgresMessage.Identifier { - .terminate - } - - public func serialize(into buffer: inout ByteBuffer) { } - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+0.swift b/Sources/PostgresNIO/Message/PostgresMessage+0.swift deleted file mode 100644 index 386ffd34..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+0.swift +++ /dev/null @@ -1,23 +0,0 @@ -import NIOCore - -/// A frontend or backend Postgres message. -public struct PostgresMessage: Equatable { - @available(*, deprecated, message: "Will be removed from public API.") - public var identifier: Identifier - public var data: ByteBuffer - - @available(*, deprecated, message: "Will be removed from public API.") - public init(identifier: Identifier, bytes: Data) - where Data: Sequence, Data.Element == UInt8 - { - var buffer = ByteBufferAllocator().buffer(capacity: 0) - buffer.writeBytes(bytes) - self.init(identifier: identifier, data: buffer) - } - - @available(*, deprecated, message: "Will be removed from public API.") - public init(identifier: Identifier, data: ByteBuffer) { - self.identifier = identifier - self.data = data - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift b/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift deleted file mode 100644 index 875be913..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+BackendKeyData.swift +++ /dev/null @@ -1,31 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as cancellation key data. - /// The frontend must save these values if it wishes to be able to issue CancelRequest messages later. - public struct BackendKeyData { - /// The process ID of this backend. - public var processID: Int32 - - /// The secret key of this backend. - public var secretKey: Int32 - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.BackendKeyData { - public static var identifier: PostgresMessage.Identifier { - .backendKeyData - } - - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - guard let processID = buffer.readInteger(as: Int32.self) else { - throw PostgresError.protocol("Could not parse process id from backend key data") - } - guard let secretKey = buffer.readInteger(as: Int32.self) else { - throw PostgresError.protocol("Could not parse secret key from backend key data") - } - return .init(processID: processID, secretKey: secretKey) - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift b/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift deleted file mode 100644 index e15c8cb6..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+DataRow.swift +++ /dev/null @@ -1,54 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a data row. - public struct DataRow { - public struct Column: CustomStringConvertible { - /// The length of the column value, in bytes (this count does not include itself). - /// Can be zero. As a special case, -1 indicates a NULL column value. No value bytes follow in the NULL case. - - /// The value of the column, in the format indicated by the associated format code. n is the above length. - public var value: ByteBuffer? - - /// See `CustomStringConvertible`. - public var description: String { - if let value = value { - return "0x" + value.readableBytesView.hexdigest() - } else { - return "" - } - } - } - - /// The data row's columns - public var columns: [Column] - - /// See `CustomStringConvertible`. - public var description: String { - return "Columns(" + columns.map { $0.description }.joined(separator: ", ") + ")" - } - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.DataRow { - public static var identifier: PostgresMessage.Identifier { - return .dataRow - } - - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - guard let columns = buffer.read(array: Column.self, { buffer in - if var slice = buffer.readNullableBytes() { - var copy = ByteBufferAllocator().buffer(capacity: slice.readableBytes) - copy.writeBuffer(&slice) - return .init(value: copy) - } else { - return .init(value: nil) - } - }) else { - throw PostgresError.protocol("Could not parse data row columns") - } - return .init(columns: columns) - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+Error.swift b/Sources/PostgresNIO/Message/PostgresMessage+Error.swift deleted file mode 100644 index 7296d554..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+Error.swift +++ /dev/null @@ -1,113 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// First message sent from the frontend during startup. - public struct Error: CustomStringConvertible, Sendable { - public enum Field: UInt8, Hashable, Sendable { - /// Severity: the field contents are ERROR, FATAL, or PANIC (in an error message), - /// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a - //// localized translation of one of these. Always present. - case localizedSeverity = 0x53 /// S - - /// Severity: the field contents are ERROR, FATAL, or PANIC (in an error message), - /// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message). - /// This is identical to the S field except that the contents are never localized. - /// This is present only in messages generated by PostgreSQL versions 9.6 and later. - case severity = 0x56 /// V - - /// Code: the SQLSTATE code for the error (see Appendix A). Not localizable. Always present. - case sqlState = 0x43 /// C - - /// Message: the primary human-readable error message. This should be accurate but terse (typically one line). - /// Always present. - case message = 0x4D /// M - - /// Detail: an optional secondary error message carrying more detail about the problem. - /// Might run to multiple lines. - case detail = 0x44 /// D - - /// Hint: an optional suggestion what to do about the problem. - /// This is intended to differ from Detail in that it offers advice (potentially inappropriate) - /// rather than hard facts. Might run to multiple lines. - case hint = 0x48 /// H - - /// Position: the field value is a decimal ASCII integer, indicating an error cursor - /// position as an index into the original query string. The first character has index 1, - /// and positions are measured in characters not bytes. - case position = 0x50 /// P - - /// Internal position: this is defined the same as the P field, but it is used when the - /// cursor position refers to an internally generated command rather than the one submitted by the client. - /// The q field will always appear when this field appears. - case internalPosition = 0x70 /// p - - /// Internal query: the text of a failed internally-generated command. - /// This could be, for example, a SQL query issued by a PL/pgSQL function. - case internalQuery = 0x71 /// q - - /// Where: an indication of the context in which the error occurred. - /// Presently this includes a call stack traceback of active procedural language functions and - /// internally-generated queries. The trace is one entry per line, most recent first. - case locationContext = 0x57 /// W - - /// Schema name: if the error was associated with a specific database object, the name of - /// the schema containing that object, if any. - case schemaName = 0x73 /// s - - /// Table name: if the error was associated with a specific table, the name of the table. - /// (Refer to the schema name field for the name of the table's schema.) - case tableName = 0x74 /// t - - /// Column name: if the error was associated with a specific table column, the name of the column. - /// (Refer to the schema and table name fields to identify the table.) - case columnName = 0x63 /// c - - /// Data type name: if the error was associated with a specific data type, the name of the data type. - /// (Refer to the schema name field for the name of the data type's schema.) - case dataTypeName = 0x64 /// d - - /// Constraint name: if the error was associated with a specific constraint, the name of the constraint. - /// Refer to fields listed above for the associated table or domain. (For this purpose, indexes are - /// treated as constraints, even if they weren't created with constraint syntax.) - case constraintName = 0x6E /// n - - /// File: the file name of the source-code location where the error was reported. - case file = 0x46 /// F - - /// Line: the line number of the source-code location where the error was reported. - case line = 0x4C /// L - - /// Routine: the name of the source-code routine reporting the error. - case routine = 0x52 /// R - } - - /// The diagnostic messages. - public var fields: [Field: String] - - /// See `CustomStringConvertible`. - public var description: String { - let unique = self.fields[.routine] ?? self.fields[.sqlState] ?? "unknown" - let message = self.fields[.message] ?? "Unknown" - return "\(message) (\(unique))" - } - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.Error { - public static var identifier: PostgresMessage.Identifier { - return .error - } - - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - var fields: [Field: String] = [:] - while let field = buffer.readInteger(as: Field.self) { - guard let string = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not read error response string.") - } - fields[field] = string - } - return .init(fields: fields) - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+Identifier.swift b/Sources/PostgresNIO/Message/PostgresMessage+Identifier.swift deleted file mode 100644 index 786b91ef..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+Identifier.swift +++ /dev/null @@ -1,151 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies an incoming or outgoing postgres message. Sent as the first byte, before the message size. - /// Values are not unique across all identifiers, meaning some messages will require keeping state to identify. - @available(*, deprecated, message: "Will be removed from public API.") - public struct Identifier: ExpressibleByIntegerLiteral, Equatable, CustomStringConvertible { - // special - public static let none: Identifier = 0x00 - // special - public static let sslSupported: Identifier = 0x53 // 'S' - // special - public static let sslUnsupported: Identifier = 0x4E // 'N' - - /// Authentication (B) - public static let authentication: Identifier = 0x52 // 'R' - - /// BackendKeyData (B) - public static let backendKeyData: Identifier = 0x4B // 'K' - - /// Bind (F) - public static let bind: Identifier = 0x42 // 'B' - - /// BindComplete (B) - public static let bindComplete: Identifier = 0x32 // '2' - - /// Close (F) - public static let close: Identifier = 0x43 // 'C' - - /// CloseComplete (B) - public static let closeComplete: Identifier = 0x33 // '3' - - /// CommandComplete (B) - public static let commandComplete: Identifier = 0x43 // 'C' - - /// CopyData (F & B) - public static let copyData: Identifier = 0x64 // 'd' - - /// CopyDone (F & B) - public static let copyDone: Identifier = 0x63 // 'c' - - /// CopyFail (F) - public static let copyFail: Identifier = 0x66 // 'f' - - /// CopyInResponse (B) - public static let copyInResponse: Identifier = 0x47 // 'G' - - /// CopyOutResponse (B) - public static let copyOutResponse: Identifier = 0x48 // 'H' - - // CopyBothResponse (B) - public static let copyBothResponse: Identifier = 0x57 // 'W' - - /// DataRow (B) - public static let dataRow: Identifier = 0x44 // 'D' - - /// Describe (F) - public static let describe: Identifier = 0x44 // 'D' - - /// EmptyQueryResponse (B) - public static let emptyQueryResponse: Identifier = 0x49 // 'I' - - /// ErrorResponse (B) - public static let error: Identifier = 0x45 // 'E' - - /// Execute (F) - public static let execute: Identifier = 0x45 // 'E' - - /// Flush (F) - public static let flush: Identifier = 0x48 // 'H' - - /// FunctionCall (F) - public static let functionCall: Identifier = 0x46 // 'F' - - /// FunctionCallResponse (B) - public static let functionCallResponse: Identifier = 0x56 // 'V' - - /// GSSResponse (F) - public static let gssResponse: Identifier = 0x70 // 'p' - - /// NegotiateProtocolVersion (B) - public static let negotiateProtocolVersion: Identifier = 0x76 // 'v' - - /// NoData (B) - public static let noData: Identifier = 0x6E // 'n' - - /// NoticeResponse (B) - public static let notice: Identifier = 0x4E // 'N' - - /// NotificationResponse (B) - public static let notificationResponse: Identifier = 0x41 // 'A' - - /// ParameterDescription (B) - public static let parameterDescription: Identifier = 0x74 // 't' - - /// ParameterStatus (B) - public static let parameterStatus: Identifier = 0x53 // 'S' - - /// Parse (F) - public static let parse: Identifier = 0x50 // 'P' - - /// ParseComplete (B) - public static let parseComplete: Identifier = 0x31 // '1' - - /// PasswordMessage (F) - public static let passwordMessage: Identifier = 0x70 // 'p' - - /// PortalSuspended (B) - public static let portalSuspended: Identifier = 0x73 // 's' - - /// Query (F) - public static let query: Identifier = 0x51 // 'Q' - - /// ReadyForQuery (B) - public static let readyForQuery: Identifier = 0x5A // 'Z' - - /// RowDescription (B) - public static let rowDescription: Identifier = 0x54 // 'T' - - /// SASLInitialResponse (F) - public static let saslInitialResponse: Identifier = 0x70 // 'p' - - /// SASLResponse (F) - public static let saslResponse: Identifier = 0x70 // 'p' - - /// Sync (F) - public static let sync: Identifier = 0x53 // 'S' - - /// Terminate (F) - public static let terminate: Identifier = 0x58 // 'X' - - public let value: UInt8 - - /// See `CustomStringConvertible`. - public var description: String { - return String(Unicode.Scalar(self.value)) - } - - /// See `ExpressibleByIntegerLiteral`. - public init(integerLiteral value: UInt8) { - self.value = value - } - } -} - -extension ByteBuffer { - @available(*, deprecated, message: "Will be removed from public API") - mutating func write(identifier: PostgresMessage.Identifier) { - self.writeInteger(identifier.value) - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift b/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift deleted file mode 100644 index 8b37a2e6..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+NotificationResponse.swift +++ /dev/null @@ -1,29 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a notification response. - public struct NotificationResponse { - public var backendPID: Int32 - public var channel: String - public var payload: String - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.NotificationResponse { - public static let identifier = PostgresMessage.Identifier.notificationResponse - - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - guard let backendPID: Int32 = buffer.readInteger() else { - throw PostgresError.protocol("Invalid NotificationResponse message: unable to read backend PID") - } - guard let channel = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Invalid NotificationResponse message: unable to read channel") - } - guard let payload = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Invalid NotificationResponse message: unable to read payload") - } - return .init(backendPID: backendPID, channel: channel, payload: payload) - } -} diff --git a/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift b/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift deleted file mode 100644 index 66cc318c..00000000 --- a/Sources/PostgresNIO/Message/PostgresMessage+RowDescription.swift +++ /dev/null @@ -1,99 +0,0 @@ -import NIOCore - -extension PostgresMessage { - /// Identifies the message as a row description. - public struct RowDescription { - /// Describes a single field returns in a `RowDescription` message. - public struct Field: CustomStringConvertible { - static func parse(from buffer: inout ByteBuffer) throws -> Field { - guard let name = buffer.readNullTerminatedString() else { - throw PostgresError.protocol("Could not read row description field name") - } - guard let tableOID = buffer.readInteger(as: UInt32.self) else { - throw PostgresError.protocol("Could not read row description field table OID") - } - guard let columnAttributeNumber = buffer.readInteger(as: Int16.self) else { - throw PostgresError.protocol("Could not read row description field column attribute number") - } - guard let dataType = buffer.readInteger(as: PostgresDataType.self) else { - throw PostgresError.protocol("Could not read row description field data type") - } - guard let dataTypeSize = buffer.readInteger(as: Int16.self) else { - throw PostgresError.protocol("Could not read row description field data type size") - } - guard let dataTypeModifier = buffer.readInteger(as: Int32.self) else { - throw PostgresError.protocol("Could not read row description field data type modifier") - } - guard let formatCode = buffer.readInteger(as: PostgresFormat.self) else { - throw PostgresError.protocol("Could not read row description field format code") - } - return .init( - name: name, - tableOID: tableOID, - columnAttributeNumber: columnAttributeNumber, - dataType: dataType, - dataTypeSize: dataTypeSize, - dataTypeModifier: dataTypeModifier, - formatCode: formatCode - ) - } - - /// The field name. - public var name: String - - /// If the field can be identified as a column of a specific table, the object ID of the table; otherwise zero. - public var tableOID: UInt32 - - /// If the field can be identified as a column of a specific table, the attribute number of the column; otherwise zero. - public var columnAttributeNumber: Int16 - - /// The object ID of the field's data type. - public var dataType: PostgresDataType - - /// The data type size (see pg_type.typlen). Note that negative values denote variable-width types. - public var dataTypeSize: Int16 - - /// The type modifier (see pg_attribute.atttypmod). The meaning of the modifier is type-specific. - public var dataTypeModifier: Int32 - - /// The format code being used for the field. - /// Currently will be zero (text) or one (binary). - /// In a RowDescription returned from the statement variant of Describe, - /// the format code is not yet known and will always be zero. - public var formatCode: PostgresFormat - - /// See `CustomStringConvertible`. - public var description: String { - return self.name.description + "(\(tableOID))" - } - } - - - - /// The fields supplied in the row description. - public var fields: [Field] - - /// See `CustomStringConverible`. - public var description: String { - return "Row(\(self.fields)" - } - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresMessageType` since it is deprecated.") -extension PostgresMessage.RowDescription { - /// See `PostgresMessageType`. - public static var identifier: PostgresMessage.Identifier { - return .rowDescription - } - - /// Parses an instance of this message type from a byte buffer. - public static func parse(from buffer: inout ByteBuffer) throws -> Self { - guard let fields = try buffer.read(array: Field.self, { buffer in - return try.parse(from: &buffer) - }) else { - throw PostgresError.protocol("Could not read row description fields") - } - return .init(fields: fields) - } -} diff --git a/Sources/PostgresNIO/Postgres+PSQLCompat.swift b/Sources/PostgresNIO/Postgres+PSQLCompat.swift index 7d464c2b..e5e9b5d0 100644 --- a/Sources/PostgresNIO/Postgres+PSQLCompat.swift +++ b/Sources/PostgresNIO/Postgres+PSQLCompat.swift @@ -6,16 +6,7 @@ extension PSQLError { case .queryCancelled: return self case .server, .listenFailed: - guard let serverInfo = self.serverInfo else { - return self - } - - var fields = [PostgresMessage.Error.Field: String]() - fields.reserveCapacity(serverInfo.underlying.fields.count) - serverInfo.underlying.fields.forEach { (key, value) in - fields[PostgresMessage.Error.Field(rawValue: key.rawValue)!] = value - } - return PostgresError.server(PostgresMessage.Error(fields: fields)) + return self case .sslUnsupported: return PostgresError.protocol("Server does not support TLS") case .failedToAddSSLHandler: diff --git a/Sources/PostgresNIO/Utilities/PostgresError+Code.swift b/Sources/PostgresNIO/Utilities/PostgresError+Code.swift index 11224f4b..19dfd6f0 100644 --- a/Sources/PostgresNIO/Utilities/PostgresError+Code.swift +++ b/Sources/PostgresNIO/Utilities/PostgresError+Code.swift @@ -338,11 +338,6 @@ extension PostgresError { public var code: Code { switch self { case .protocol: return .internalError - case .server(let server): - guard let code = server.fields[.sqlState] else { - return .internalError - } - return Code(raw: code) case .connectionClosed: return .internalError } } diff --git a/Sources/PostgresNIO/Utilities/PostgresError.swift b/Sources/PostgresNIO/Utilities/PostgresError.swift index b9524275..b7eb5e02 100644 --- a/Sources/PostgresNIO/Utilities/PostgresError.swift +++ b/Sources/PostgresNIO/Utilities/PostgresError.swift @@ -2,7 +2,6 @@ import Foundation public enum PostgresError: Error, LocalizedError, CustomStringConvertible { case `protocol`(String) - case server(PostgresMessage.Error) case connectionClosed /// See `LocalizedError`. @@ -16,8 +15,6 @@ public enum PostgresError: Error, LocalizedError, CustomStringConvertible { switch self { case .protocol(let message): description = "protocol error: \(message)" - case .server(let error): - return "server: \(error.description)" case .connectionClosed: description = "connection closed" } From 2946a5a424c5363eef1807016d943115c4caeaed Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:29:12 +0100 Subject: [PATCH 08/17] Remove `PostgresDataConvertible` --- .../PostgresNIO/Data/PostgresData+Array.swift | 45 ----------- .../PostgresNIO/Data/PostgresData+Bool.swift | 18 ----- .../PostgresNIO/Data/PostgresData+Bytes.swift | 18 ----- .../PostgresNIO/Data/PostgresData+Date.swift | 18 ----- .../Data/PostgresData+Decimal.swift | 18 ----- .../Data/PostgresData+Double.swift | 18 ----- .../PostgresNIO/Data/PostgresData+Float.swift | 18 ----- .../PostgresNIO/Data/PostgresData+Int.swift | 80 ------------------- .../PostgresNIO/Data/PostgresData+JSON.swift | 21 ----- .../PostgresNIO/Data/PostgresData+JSONB.swift | 21 ----- .../Data/PostgresData+Optional.swift | 19 ----- .../Data/PostgresData+RawRepresentable.swift | 17 ---- .../PostgresNIO/Data/PostgresData+Set.swift | 17 ---- .../Data/PostgresData+String.swift | 18 ----- .../PostgresNIO/Data/PostgresData+UUID.swift | 18 ----- Sources/PostgresNIO/Data/PostgresData.swift | 25 ------ .../Data/PostgresDataConvertible.swift | 8 -- .../Deprecated/PostgresData+UInt.swift | 80 ------------------- Sources/PostgresNIO/Docs.docc/index.md | 1 - .../Data/PostgresData+JSONTests.swift | 21 ----- 20 files changed, 499 deletions(-) delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Optional.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+RawRepresentable.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Set.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresDataConvertible.swift delete mode 100644 Tests/PostgresNIOTests/Data/PostgresData+JSONTests.swift diff --git a/Sources/PostgresNIO/Data/PostgresData+Array.swift b/Sources/PostgresNIO/Data/PostgresData+Array.swift index 5d648db6..d7da4a7a 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Array.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Array.swift @@ -1,14 +1,6 @@ import NIOCore extension PostgresData { - @available(*, deprecated, message: "Use ``PostgresQuery`` and ``PostgresBindings`` instead.") - public init(array: [T]) where T: PostgresDataConvertible { - self.init( - array: array.map { $0.postgresData }, - elementType: T.postgresDataType - ) - } - public init(array: [PostgresData?], elementType: PostgresDataType) { var buffer = ByteBufferAllocator().buffer(capacity: 0) // 0 if empty, 1 if not @@ -46,22 +38,6 @@ extension PostgresData { ) } - @available(*, deprecated, message: "Use ``PostgresRow`` and ``PostgresDecodable`` instead.") - public func array(of type: T.Type = T.self) -> [T]? where T: PostgresDataConvertible { - guard let array = self.array else { - return nil - } - var items: [T] = [] - for data in array { - guard let item = T(postgresData: data) else { - // if we fail to convert any data, fail the entire array - return nil - } - items.append(item) - } - return items - } - public var array: [PostgresData]? { guard case .binary = self.formatCode else { return nil @@ -112,24 +88,3 @@ extension PostgresData { return array } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Array: PostgresDataConvertible where Element: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - guard let arrayType = Element.postgresDataType.arrayType else { - fatalError("No array type for \(Element.postgresDataType)") - } - return arrayType - } - - public init?(postgresData: PostgresData) { - guard let array = postgresData.array(of: Element.self) else { - return nil - } - self = array - } - - public var postgresData: PostgresData? { - return PostgresData(array: self) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Bool.swift b/Sources/PostgresNIO/Data/PostgresData+Bool.swift index 0b9f2738..23e1eb42 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Bool.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Bool.swift @@ -46,21 +46,3 @@ extension PostgresData: ExpressibleByBooleanLiteral { self.init(bool: value) } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Bool: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .bool - } - - public var postgresData: PostgresData? { - return .init(bool: self) - } - - public init?(postgresData: PostgresData) { - guard let bool = postgresData.bool else { - return nil - } - self = bool - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Bytes.swift b/Sources/PostgresNIO/Data/PostgresData+Bytes.swift index 5ec507cd..1a5942f0 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Bytes.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Bytes.swift @@ -20,21 +20,3 @@ extension PostgresData { return bytes } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Data: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .bytea - } - - public var postgresData: PostgresData? { - return .init(bytes: self) - } - - public init?(postgresData: PostgresData) { - guard let bytes = postgresData.bytes else { - return nil - } - self.init(bytes) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Date.swift b/Sources/PostgresNIO/Data/PostgresData+Date.swift index 6d730f25..1fe75d22 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Date.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Date.swift @@ -36,24 +36,6 @@ extension PostgresData { } } -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Date: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .timestamptz - } - - public init?(postgresData: PostgresData) { - guard let date = postgresData.date else { - return nil - } - self = date - } - - public var postgresData: PostgresData? { - return .init(date: self) - } -} - // MARK: Private private let _microsecondsPerSecond: Int64 = 1_000_000 private let _secondsInDay: Int64 = 24 * 60 * 60 diff --git a/Sources/PostgresNIO/Data/PostgresData+Decimal.swift b/Sources/PostgresNIO/Data/PostgresData+Decimal.swift index 3af709e5..6f9e6fca 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Decimal.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Decimal.swift @@ -15,21 +15,3 @@ extension PostgresData { self.init(string: decimal.description) } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Decimal: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .numeric - } - - public init?(postgresData: PostgresData) { - guard let decimal = postgresData.decimal else { - return nil - } - self = decimal - } - - public var postgresData: PostgresData? { - return .init(numeric: PostgresNumeric(decimal: self)) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Double.swift b/Sources/PostgresNIO/Data/PostgresData+Double.swift index 2d7735ef..76f8e49a 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Double.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Double.swift @@ -33,21 +33,3 @@ extension PostgresData { } } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Double: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .float8 - } - - public init?(postgresData: PostgresData) { - guard let double = postgresData.double else { - return nil - } - self = double - } - - public var postgresData: PostgresData? { - return .init(double: self) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Float.swift b/Sources/PostgresNIO/Data/PostgresData+Float.swift index 45430934..723f42d4 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Float.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Float.swift @@ -27,21 +27,3 @@ extension PostgresData { } } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Float: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .float4 - } - - public init?(postgresData: PostgresData) { - guard let float = postgresData.float else { - return nil - } - self = float - } - - public var postgresData: PostgresData? { - return .init(float: self) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Int.swift b/Sources/PostgresNIO/Data/PostgresData+Int.swift index 5a97b3fb..ec275a12 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Int.swift +++ b/Sources/PostgresNIO/Data/PostgresData+Int.swift @@ -182,83 +182,3 @@ extension PostgresData { } } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Int: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int8 } - - public init?(postgresData: PostgresData) { - guard let int = postgresData.int else { - return nil - } - self = int - } - - public var postgresData: PostgresData? { - .init(int: self) - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension UInt8: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .char } - - public init?(postgresData: PostgresData) { - guard let uint8 = postgresData.uint8 else { - return nil - } - self = uint8 - } - - public var postgresData: PostgresData? { - .init(uint8: self) - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Int16: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int2 } - - public init?(postgresData: PostgresData) { - guard let int16 = postgresData.int16 else { - return nil - } - self = int16 - } - - public var postgresData: PostgresData? { - .init(int16: self) - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Int32: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int4 } - - public init?(postgresData: PostgresData) { - guard let int32 = postgresData.int32 else { - return nil - } - self = int32 - } - - public var postgresData: PostgresData? { - .init(int32: self) - } -} - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Int64: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int8 } - - public init?(postgresData: PostgresData) { - guard let int64 = postgresData.int64 else { - return nil - } - self = int64 - } - - public var postgresData: PostgresData? { - .init(int64: self) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+JSON.swift b/Sources/PostgresNIO/Data/PostgresData+JSON.swift index 53a2d84c..6eadb9af 100644 --- a/Sources/PostgresNIO/Data/PostgresData+JSON.swift +++ b/Sources/PostgresNIO/Data/PostgresData+JSON.swift @@ -36,24 +36,3 @@ extension PostgresData { return try PostgresNIO._defaultJSONDecoder.decode(T.self, from: data) } } - -@available(*, deprecated, message: "This protocol is going to be replaced with ``PostgresEncodable`` and ``PostgresDecodable`` and conforming to ``Codable`` at the same time") -public protocol PostgresJSONCodable: Codable, PostgresDataConvertible { } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension PostgresJSONCodable { - public static var postgresDataType: PostgresDataType { - return .json - } - - public var postgresData: PostgresData? { - return try? .init(json: self) - } - - public init?(postgresData: PostgresData) { - guard let value = try? postgresData.json(as: Self.self) else { - return nil - } - self = value - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+JSONB.swift b/Sources/PostgresNIO/Data/PostgresData+JSONB.swift index 0d5befa3..6252d245 100644 --- a/Sources/PostgresNIO/Data/PostgresData+JSONB.swift +++ b/Sources/PostgresNIO/Data/PostgresData+JSONB.swift @@ -47,24 +47,3 @@ extension PostgresData { return try PostgresNIO._defaultJSONDecoder.decode(T.self, from: data) } } - -@available(*, deprecated, message: "This protocol is going to be replaced with ``PostgresEncodable`` and ``PostgresDecodable`` and conforming to ``Codable`` at the same time") -public protocol PostgresJSONBCodable: Codable, PostgresDataConvertible { } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension PostgresJSONBCodable { - public static var postgresDataType: PostgresDataType { - return .jsonb - } - - public var postgresData: PostgresData? { - return try? .init(jsonb: self) - } - - public init?(postgresData: PostgresData) { - guard let value = try? postgresData.jsonb(as: Self.self) else { - return nil - } - self = value - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Optional.swift b/Sources/PostgresNIO/Data/PostgresData+Optional.swift deleted file mode 100644 index 9468478a..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Optional.swift +++ /dev/null @@ -1,19 +0,0 @@ -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Optional: PostgresDataConvertible where Wrapped: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return Wrapped.postgresDataType - } - - public init?(postgresData: PostgresData) { - self = Wrapped.init(postgresData: postgresData) - } - - public var postgresData: PostgresData? { - switch self { - case .some(let wrapped): - return wrapped.postgresData - case .none: - return .init(type: Wrapped.postgresDataType, value: nil) - } - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+RawRepresentable.swift b/Sources/PostgresNIO/Data/PostgresData+RawRepresentable.swift deleted file mode 100644 index 6cc8316a..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+RawRepresentable.swift +++ /dev/null @@ -1,17 +0,0 @@ -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension RawRepresentable where Self.RawValue: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - RawValue.postgresDataType - } - - public init?(postgresData: PostgresData) { - guard let rawValue = RawValue.init(postgresData: postgresData) else { - return nil - } - self.init(rawValue: rawValue) - } - - public var postgresData: PostgresData? { - self.rawValue.postgresData - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Set.swift b/Sources/PostgresNIO/Data/PostgresData+Set.swift deleted file mode 100644 index ade48db1..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Set.swift +++ /dev/null @@ -1,17 +0,0 @@ -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension Set: PostgresDataConvertible where Element: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - [Element].postgresDataType - } - - public init?(postgresData: PostgresData) { - guard let array = [Element](postgresData: postgresData) else { - return nil - } - self = Set(array) - } - - public var postgresData: PostgresData? { - [Element](self).postgresData - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+String.swift b/Sources/PostgresNIO/Data/PostgresData+String.swift index f38e2ab8..643a9243 100644 --- a/Sources/PostgresNIO/Data/PostgresData+String.swift +++ b/Sources/PostgresNIO/Data/PostgresData+String.swift @@ -93,21 +93,3 @@ extension PostgresData: ExpressibleByStringLiteral { self.init(string: value) } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension String: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .text - } - - public var postgresData: PostgresData? { - return .init(string: self) - } - - public init?(postgresData: PostgresData) { - guard let string = postgresData.string else { - return nil - } - self = string - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+UUID.swift b/Sources/PostgresNIO/Data/PostgresData+UUID.swift index 7c2da080..322a898d 100644 --- a/Sources/PostgresNIO/Data/PostgresData+UUID.swift +++ b/Sources/PostgresNIO/Data/PostgresData+UUID.swift @@ -28,21 +28,3 @@ extension PostgresData { } } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension UUID: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - return .uuid - } - - public init?(postgresData: PostgresData) { - guard let uuid = postgresData.uuid else { - return nil - } - self = uuid - } - - public var postgresData: PostgresData? { - return .init(uuid: self) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData.swift b/Sources/PostgresNIO/Data/PostgresData.swift index d0be48eb..a1079976 100644 --- a/Sources/PostgresNIO/Data/PostgresData.swift +++ b/Sources/PostgresNIO/Data/PostgresData.swift @@ -61,16 +61,6 @@ extension PostgresData: CustomStringConvertible { var value = value value.moveReaderIndex(forwardBy: 1) description = String(decoding: value.readableBytesView, as: UTF8.self) - case .uuidArray: - description = self.array(of: UUID.self)?.description - case .int8Array: - description = self.array(of: Int.self)?.description - case .float8Array: - description = self.array(of: Double.self)?.description - case .float4Array: - description = self.array(of: Float.self)?.description - case .textArray: - description = self.array(of: String.self)?.description case .jsonbArray: description = self.array?.description default: @@ -104,18 +94,3 @@ extension PostgresData: CustomDebugStringConvertible { return self.description } } - -@available(*, deprecated, message: "Deprecating conformance to `PostgresDataConvertible`, since it is deprecated.") -extension PostgresData: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { - fatalError("PostgresData cannot be statically represented as a single data type") - } - - public init?(postgresData: PostgresData) { - self = postgresData - } - - public var postgresData: PostgresData? { - return self - } -} diff --git a/Sources/PostgresNIO/Data/PostgresDataConvertible.swift b/Sources/PostgresNIO/Data/PostgresDataConvertible.swift deleted file mode 100644 index 675ed6fe..00000000 --- a/Sources/PostgresNIO/Data/PostgresDataConvertible.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -@available(*, deprecated, message: "This protocol is going to be replaced with ``PostgresEncodable`` and ``PostgresDecodable``") -public protocol PostgresDataConvertible { - static var postgresDataType: PostgresDataType { get } - init?(postgresData: PostgresData) - var postgresData: PostgresData? { get } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift b/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift index ab3e493f..51579c7b 100644 --- a/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift +++ b/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift @@ -80,83 +80,3 @@ extension PostgresData { return self.int64.flatMap { .init(bitPattern: $0) } } } - -@available(*, deprecated, message: "Use 'Int' instead.") -extension UInt: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int8 } - - public init?(postgresData: PostgresData) { - guard let uint = postgresData.uint else { - return nil - } - self = uint - } - - public var postgresData: PostgresData? { - .init(uint: self) - } -} - -@available(*, deprecated, message: "Use 'UInt8' instead.") -extension Int8: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .char } - - public init?(postgresData: PostgresData) { - guard let int8 = postgresData.int8 else { - return nil - } - self = int8 - } - - public var postgresData: PostgresData? { - .init(int8: self) - } -} - -@available(*, deprecated, message: "Use 'Int16' instead.") -extension UInt16: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int2 } - - public init?(postgresData: PostgresData) { - guard let uint16 = postgresData.uint16 else { - return nil - } - self = uint16 - } - - public var postgresData: PostgresData? { - .init(uint16: self) - } -} - -@available(*, deprecated, message: "Use 'Int32' instead.") -extension UInt32: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int4 } - - public init?(postgresData: PostgresData) { - guard let uint32 = postgresData.uint32 else { - return nil - } - self = uint32 - } - - public var postgresData: PostgresData? { - .init(uint32: self) - } -} - -@available(*, deprecated, message: "Use 'Int64' instead.") -extension UInt64: PostgresDataConvertible { - public static var postgresDataType: PostgresDataType { .int8 } - - public init?(postgresData: PostgresData) { - guard let uint64 = postgresData.uint64 else { - return nil - } - self = uint64 - } - - public var postgresData: PostgresData? { - .init(uint64: self) - } -} diff --git a/Sources/PostgresNIO/Docs.docc/index.md b/Sources/PostgresNIO/Docs.docc/index.md index 0f833b68..324c3da1 100644 --- a/Sources/PostgresNIO/Docs.docc/index.md +++ b/Sources/PostgresNIO/Docs.docc/index.md @@ -68,7 +68,6 @@ removed from the public API with the next major release. - ``PostgresDatabase`` - ``PostgresData`` -- ``PostgresDataConvertible`` - ``PostgresQueryResult`` - ``PostgresJSONCodable`` - ``PostgresJSONBCodable`` diff --git a/Tests/PostgresNIOTests/Data/PostgresData+JSONTests.swift b/Tests/PostgresNIOTests/Data/PostgresData+JSONTests.swift deleted file mode 100644 index 47dd89a1..00000000 --- a/Tests/PostgresNIOTests/Data/PostgresData+JSONTests.swift +++ /dev/null @@ -1,21 +0,0 @@ -import PostgresNIO -import XCTest - -class PostgresData_JSONTests: XCTestCase { - @available(*, deprecated, message: "Testing deprecated functionality") - func testJSONBConvertible() { - struct Object: PostgresJSONBCodable { - let foo: Int - let bar: Int - } - - XCTAssertEqual(Object.postgresDataType, .jsonb) - - let postgresData = Object(foo: 1, bar: 2).postgresData - XCTAssertEqual(postgresData?.type, .jsonb) - - let object = Object(postgresData: postgresData!) - XCTAssertEqual(object?.foo, 1) - XCTAssertEqual(object?.bar, 2) - } -} From dd56a8bacc604d3157f3da84133ed9cf76e6d928 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:35:47 +0100 Subject: [PATCH 09/17] Remove `PostgresData` --- .../PostgresNIO/Data/PostgresData+Array.swift | 90 --------- .../PostgresNIO/Data/PostgresData+Bool.swift | 48 ----- .../PostgresNIO/Data/PostgresData+Bytes.swift | 22 --- .../PostgresNIO/Data/PostgresData+Date.swift | 42 ---- .../Data/PostgresData+Decimal.swift | 17 -- .../Data/PostgresData+Double.swift | 35 ---- .../PostgresNIO/Data/PostgresData+Float.swift | 29 --- .../PostgresNIO/Data/PostgresData+Int.swift | 184 ------------------ .../PostgresNIO/Data/PostgresData+JSON.swift | 38 ---- .../PostgresNIO/Data/PostgresData+JSONB.swift | 49 ----- .../Data/PostgresData+String.swift | 95 --------- .../PostgresNIO/Data/PostgresData+UUID.swift | 30 --- Sources/PostgresNIO/Data/PostgresData.swift | 96 --------- ...ta+Numeric.swift => PostgresNumeric.swift} | 27 --- Sources/PostgresNIO/Data/PostgresRow.swift | 59 ------ .../Deprecated/PostgresData+UInt.swift | 82 -------- Sources/PostgresNIO/New/PostgresQuery.swift | 11 -- .../New/PostgresConnectionTests.swift | 2 +- .../Utilities/PostgresJSONCodingTests.swift | 66 ------- 19 files changed, 1 insertion(+), 1021 deletions(-) delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Array.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Bool.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Bytes.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Date.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Decimal.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Double.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Float.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+Int.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+JSON.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+JSONB.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+String.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData+UUID.swift delete mode 100644 Sources/PostgresNIO/Data/PostgresData.swift rename Sources/PostgresNIO/Data/{PostgresData+Numeric.swift => PostgresNumeric.swift} (90%) delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift delete mode 100644 Tests/PostgresNIOTests/Utilities/PostgresJSONCodingTests.swift diff --git a/Sources/PostgresNIO/Data/PostgresData+Array.swift b/Sources/PostgresNIO/Data/PostgresData+Array.swift deleted file mode 100644 index d7da4a7a..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Array.swift +++ /dev/null @@ -1,90 +0,0 @@ -import NIOCore - -extension PostgresData { - public init(array: [PostgresData?], elementType: PostgresDataType) { - var buffer = ByteBufferAllocator().buffer(capacity: 0) - // 0 if empty, 1 if not - buffer.writeInteger(array.isEmpty ? 0 : 1, as: UInt32.self) - // b - this gets ignored by psql - buffer.writeInteger(0, as: UInt32.self) - // array element type - buffer.writeInteger(elementType.rawValue) - - // continue if the array is not empty - if !array.isEmpty { - // length of array - buffer.writeInteger(numericCast(array.count), as: UInt32.self) - // dimensions - buffer.writeInteger(1, as: UInt32.self) - - for item in array { - if let item = item, var value = item.value { - buffer.writeInteger(numericCast(value.readableBytes), as: UInt32.self) - buffer.writeBuffer(&value) - } else { - buffer.writeInteger(-1, as: Int32.self) - } - } - } - - guard let arrayType = elementType.arrayType else { - fatalError("No array type for \(elementType)") - } - self.init( - type: arrayType, - typeModifier: nil, - formatCode: .binary, - value: buffer - ) - } - - public var array: [PostgresData]? { - guard case .binary = self.formatCode else { - return nil - } - guard var value = self.value else { - return nil - } - // ensures the data type is actually an array - guard self.type.elementType != nil else { - return nil - } - guard let isNotEmpty = value.readInteger(as: UInt32.self) else { - return nil - } - // b - guard let _ = value.readInteger(as: UInt32.self) else { - return nil - } - guard let type = value.readInteger(as: PostgresDataType.self) else { - return nil - } - guard isNotEmpty == 1 else { - return [] - } - guard let length = value.readInteger(as: UInt32.self) else { - return nil - } - assert(length >= 0, "Invalid length") - - guard let dimensions = value.readInteger(as: UInt32.self) else { - return nil - } - assert(dimensions == 1, "Multi-dimensional arrays not yet supported") - - var array: [PostgresData] = [] - while - let itemLength = value.readInteger(as: Int32.self) - { - let itemValue = itemLength == -1 ? nil : value.readSlice(length: numericCast(itemLength)) - let data = PostgresData( - type: type, - typeModifier: nil, - formatCode: self.formatCode, - value: itemValue - ) - array.append(data) - } - return array - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Bool.swift b/Sources/PostgresNIO/Data/PostgresData+Bool.swift deleted file mode 100644 index 23e1eb42..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Bool.swift +++ /dev/null @@ -1,48 +0,0 @@ -import NIOCore - -extension PostgresData { - public init(bool: Bool) { - var buffer = ByteBufferAllocator().buffer(capacity: 1) - buffer.writeInteger(bool ? 1 : 0, as: UInt8.self) - self.init(type: .bool, formatCode: .binary, value: buffer) - } - - public var bool: Bool? { - guard var value = self.value else { - return nil - } - guard value.readableBytes == 1 else { - return nil - } - guard let byte = value.readInteger(as: UInt8.self) else { - return nil - } - - switch self.formatCode { - case .text: - switch byte { - case Character("t").asciiValue!: - return true - case Character("f").asciiValue!: - return false - default: - return nil - } - case .binary: - switch byte { - case 1: - return true - case 0: - return false - default: - return nil - } - } - } -} - -extension PostgresData: ExpressibleByBooleanLiteral { - public init(booleanLiteral value: Bool) { - self.init(bool: value) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Bytes.swift b/Sources/PostgresNIO/Data/PostgresData+Bytes.swift deleted file mode 100644 index 1a5942f0..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Bytes.swift +++ /dev/null @@ -1,22 +0,0 @@ -import struct Foundation.Data -import NIOCore - -extension PostgresData { - public init(bytes: Bytes) - where Bytes: Sequence, Bytes.Element == UInt8 - { - var buffer = ByteBufferAllocator().buffer(capacity: 1) - buffer.writeBytes(bytes) - self.init(type: .bytea, formatCode: .binary, value: buffer) - } - - public var bytes: [UInt8]? { - guard var value = self.value else { - return nil - } - guard let bytes = value.readBytes(length: value.readableBytes) else { - return nil - } - return bytes - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Date.swift b/Sources/PostgresNIO/Data/PostgresData+Date.swift deleted file mode 100644 index 1fe75d22..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Date.swift +++ /dev/null @@ -1,42 +0,0 @@ -import struct Foundation.Date -import NIOCore - -extension PostgresData { - public init(date: Date) { - var buffer = ByteBufferAllocator().buffer(capacity: 0) - let seconds = date.timeIntervalSince(_psqlDateStart) * Double(_microsecondsPerSecond) - buffer.writeInteger(Int64(seconds)) - self.init(type: .timestamptz, value: buffer) - } - - public var date: Date? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .text: - return nil - case .binary: - switch self.type { - case .timestamp, .timestamptz: - let microseconds = value.readInteger(as: Int64.self)! - let seconds = Double(microseconds) / Double(_microsecondsPerSecond) - return Date(timeInterval: seconds, since: _psqlDateStart) - case .time, .timetz: - return nil - case .date: - let days = value.readInteger(as: Int32.self)! - let seconds = Int64(days) * _secondsInDay - return Date(timeInterval: Double(seconds), since: _psqlDateStart) - default: - return nil - } - } - } -} - -// MARK: Private -private let _microsecondsPerSecond: Int64 = 1_000_000 -private let _secondsInDay: Int64 = 24 * 60 * 60 -private let _psqlDateStart = Date(timeIntervalSince1970: 946_684_800) // values are stored as seconds before or after midnight 2000-01-01 diff --git a/Sources/PostgresNIO/Data/PostgresData+Decimal.swift b/Sources/PostgresNIO/Data/PostgresData+Decimal.swift deleted file mode 100644 index 6f9e6fca..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Decimal.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Foundation - -extension PostgresData { - public var decimal: Decimal? { - guard let string = self.string else { - return nil - } - guard let decimal = Decimal(string: string) else { - return nil - } - return decimal - } - - public init(decimal: Decimal) { - self.init(string: decimal.description) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Double.swift b/Sources/PostgresNIO/Data/PostgresData+Double.swift deleted file mode 100644 index 76f8e49a..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Double.swift +++ /dev/null @@ -1,35 +0,0 @@ -import NIOCore - -extension PostgresData { - public init(double: Double) { - var buffer = ByteBufferAllocator().buffer(capacity: 0) - buffer.psqlWriteDouble(double) - self.init(type: .float8, formatCode: .binary, value: buffer) - } - - public var double: Double? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .float4: - return value.psqlReadFloat() - .flatMap { Double($0) } - case .float8: - return value.psqlReadDouble() - case .numeric: - return self.numeric?.double - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return Double(string) - } - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Float.swift b/Sources/PostgresNIO/Data/PostgresData+Float.swift deleted file mode 100644 index 723f42d4..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Float.swift +++ /dev/null @@ -1,29 +0,0 @@ -extension PostgresData { - public init(float: Float) { - self.init(double: Double(float)) - } - - public var float: Float? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .float4: - return value.psqlReadFloat() - case .float8: - return value.psqlReadDouble() - .flatMap { Float($0) } - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return Float(string) - } - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Int.swift b/Sources/PostgresNIO/Data/PostgresData+Int.swift deleted file mode 100644 index ec275a12..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+Int.swift +++ /dev/null @@ -1,184 +0,0 @@ -extension PostgresData { - public init(int value: Int) { - self.init(type: .int8, value: .init(integer: Int64(value))) - } - - public init(uint8 value: UInt8) { - self.init(type: .char, value: .init(integer: value)) - } - - public init(int16 value: Int16) { - self.init(type: .int2, value: .init(integer: value)) - } - - public init(int32 value: Int32) { - self.init(type: .int4, value: .init(integer: value)) - } - - public init(int64 value: Int64) { - self.init(type: .int8, value: .init(integer: value)) - } - - public var int: Int? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .char, .bpchar: - guard value.readableBytes == 1 else { - return nil - } - return value.readInteger(as: UInt8.self).flatMap(Int.init) - case .int2: - assert(value.readableBytes == 2) - return value.readInteger(as: Int16.self).flatMap(Int.init) - case .int4, .regproc: - assert(value.readableBytes == 4) - return value.readInteger(as: Int32.self).flatMap(Int.init) - case .oid: - assert(value.readableBytes == 4) - return value.readInteger(as: UInt32.self).flatMap { Int(exactly: $0) } - case .int8: - assert(value.readableBytes == 8) - return value.readInteger(as: Int64.self).flatMap { Int(exactly: $0) } - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return Int(string) - } - } - - public var uint8: UInt8? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .char, .bpchar: - guard value.readableBytes == 1 else { - return nil - } - return value.readInteger(as: UInt8.self) - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return UInt8(string) - } - } - - public var int16: Int16? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .char, .bpchar: - guard value.readableBytes == 1 else { - return nil - } - return value.readInteger(as: UInt8.self) - .flatMap(Int16.init) - case .int2: - assert(value.readableBytes == 2) - return value.readInteger(as: Int16.self) - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return Int16(string) - } - } - - public var int32: Int32? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .char, .bpchar: - guard value.readableBytes == 1 else { - return nil - } - return value.readInteger(as: UInt8.self) - .flatMap(Int32.init) - case .int2: - assert(value.readableBytes == 2) - return value.readInteger(as: Int16.self) - .flatMap(Int32.init) - case .int4, .regproc: - assert(value.readableBytes == 4) - return value.readInteger(as: Int32.self) - .flatMap(Int32.init) - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return Int32(string) - } - } - - public var int64: Int64? { - guard var value = self.value else { - return nil - } - - switch self.formatCode { - case .binary: - switch self.type { - case .char, .bpchar: - guard value.readableBytes == 1 else { - return nil - } - return value.readInteger(as: UInt8.self) - .flatMap(Int64.init) - case .int2: - assert(value.readableBytes == 2) - return value.readInteger(as: Int16.self) - .flatMap(Int64.init) - case .int4, .regproc: - assert(value.readableBytes == 4) - return value.readInteger(as: Int32.self) - .flatMap(Int64.init) - case .oid: - assert(value.readableBytes == 4) - assert(Int.bitWidth == 64) // or else overflow is possible - return value.readInteger(as: UInt32.self) - .flatMap(Int64.init) - case .int8: - assert(value.readableBytes == 8) - assert(Int.bitWidth == 64) - return value.readInteger(as: Int64.self) - default: - return nil - } - case .text: - guard let string = self.string else { - return nil - } - return Int64(string) - } - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+JSON.swift b/Sources/PostgresNIO/Data/PostgresData+JSON.swift deleted file mode 100644 index 6eadb9af..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+JSON.swift +++ /dev/null @@ -1,38 +0,0 @@ -import struct Foundation.Data -import NIOCore - -extension PostgresData { - public init(json jsonData: Data) { - let jsonData = [UInt8](jsonData) - - var buffer = ByteBufferAllocator() - .buffer(capacity: jsonData.count) - buffer.writeBytes(jsonData) - self.init(type: .json, formatCode: .binary, value: buffer) - } - - public init(json value: T) throws where T: Encodable { - let jsonData = try PostgresNIO._defaultJSONEncoder.encode(value) - self.init(json: jsonData) - } - - public var json: Data? { - guard var value = self.value else { - return nil - } - guard case .json = self.type else { - return nil - } - guard let data = value.readBytes(length: value.readableBytes) else { - return nil - } - return Data(data) - } - - public func json(as type: T.Type) throws -> T? where T: Decodable { - guard let data = self.json else { - return nil - } - return try PostgresNIO._defaultJSONDecoder.decode(T.self, from: data) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+JSONB.swift b/Sources/PostgresNIO/Data/PostgresData+JSONB.swift deleted file mode 100644 index 6252d245..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+JSONB.swift +++ /dev/null @@ -1,49 +0,0 @@ -import NIOCore -import struct Foundation.Data - -fileprivate let jsonBVersionBytes: [UInt8] = [0x01] - -extension PostgresData { - public init(jsonb jsonData: Data) { - let jsonBData = [UInt8](jsonData) - - var buffer = ByteBufferAllocator() - .buffer(capacity: jsonBVersionBytes.count + jsonBData.count) - buffer.writeBytes(jsonBVersionBytes) - buffer.writeBytes(jsonBData) - - self.init(type: .jsonb, formatCode: .binary, value: buffer) - } - - public init(jsonb value: T) throws where T: Encodable { - let jsonData = try PostgresNIO._defaultJSONEncoder.encode(value) - self.init(jsonb: jsonData) - } - - public var jsonb: Data? { - guard var value = self.value else { - return nil - } - guard case .jsonb = self.type else { - return nil - } - - guard let versionBytes = value.readBytes(length: jsonBVersionBytes.count), [UInt8](versionBytes) == jsonBVersionBytes else { - return nil - } - - guard let data = value.readBytes(length: value.readableBytes) else { - return nil - } - - return Data(data) - } - - public func jsonb(as type: T.Type) throws -> T? where T: Decodable { - guard let data = jsonb else { - return nil - } - - return try PostgresNIO._defaultJSONDecoder.decode(T.self, from: data) - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+String.swift b/Sources/PostgresNIO/Data/PostgresData+String.swift deleted file mode 100644 index 643a9243..00000000 --- a/Sources/PostgresNIO/Data/PostgresData+String.swift +++ /dev/null @@ -1,95 +0,0 @@ -import NIOCore - -extension PostgresData { - public init(string: String) { - var buffer = ByteBufferAllocator().buffer(capacity: string.utf8.count) - buffer.writeString(string) - self.init(type: .text, formatCode: .binary, value: buffer) - } - - public var string: String? { - guard var value = self.value else { - return nil - } - switch self.formatCode { - case .binary: - switch self.type { - case .varchar, .text, .name: - guard let string = value.readString(length: value.readableBytes) else { - return nil - } - return string - case .numeric: - return self.numeric?.string - case .uuid: - return value.readUUIDBytes()!.uuidString - case .timestamp, .timestamptz, .date: - return self.date?.description - case .money: - assert(value.readableBytes == 8) - guard let int64 = value.getInteger(at: value.readerIndex, as: Int64.self) else { - return nil - } - let description = int64.description - switch description.count { - case 0: - return "0.00" - case 1: - return "0.0" + description - case 2: - return "0." + description - default: - let decimalIndex = description.index(description.endIndex, offsetBy: -2) - return description[description.startIndex.." - } - let description: String? - - switch self.type { - case .bool: - description = self.bool?.description - case .float4: - description = self.float?.description - case .float8, .numeric: - description = self.double?.description - case .int2: - description = self.int16?.description - case .int4, .regproc, .oid: - description = self.int32?.description - case .int8: - description = self.int64?.description - case .timestamp, .timestamptz, .date, .time, .timetz: - description = self.date?.description - case .text: - description = self.string?.debugDescription - case .uuid: - description = self.uuid?.description - case .json: - description = String(decoding: value.readableBytesView, as: UTF8.self) - case .jsonb: - var value = value - value.moveReaderIndex(forwardBy: 1) - description = String(decoding: value.readableBytesView, as: UTF8.self) - case .jsonbArray: - description = self.array?.description - default: - if self.type.isUserDefined { - // custom type - description = value.readString(length: value.readableBytes) - } else { - description = nil - } - } - - if let description = description { - return description - } else { - let raw: String - switch self.formatCode { - case .text: - raw = (value.readString(length: value.readableBytes) ?? "") - .debugDescription - case .binary: - raw = "0x" + value.readableBytesView.hexdigest() - } - return "\(raw) (\(self.type))" - } - } -} - -@available(*, deprecated, message: "Deprecating conformance to `CustomDebugStringConvertible` as a first step of deprecating `PostgresData`. Please use `PostgresBindings` or `PostgresCell` instead.") -extension PostgresData: CustomDebugStringConvertible { - public var debugDescription: String { - return self.description - } -} diff --git a/Sources/PostgresNIO/Data/PostgresData+Numeric.swift b/Sources/PostgresNIO/Data/PostgresNumeric.swift similarity index 90% rename from Sources/PostgresNIO/Data/PostgresData+Numeric.swift rename to Sources/PostgresNIO/Data/PostgresNumeric.swift index 5e564d6d..039b7b72 100644 --- a/Sources/PostgresNIO/Data/PostgresData+Numeric.swift +++ b/Sources/PostgresNIO/Data/PostgresNumeric.swift @@ -223,33 +223,6 @@ public struct PostgresNumeric: CustomStringConvertible, CustomDebugStringConvert } } -extension PostgresData { - public init(numeric: PostgresNumeric) { - var buffer = ByteBufferAllocator().buffer(capacity: 0) - buffer.writeInteger(numeric.ndigits, endianness: .big) - buffer.writeInteger(numeric.weight, endianness: .big) - buffer.writeInteger(numeric.sign, endianness: .big) - buffer.writeInteger(numeric.dscale, endianness: .big) - var value = numeric.value - buffer.writeBuffer(&value) - self.init(type: .numeric, value: buffer) - } - - public var numeric: PostgresNumeric? { - /// create mutable value since we will be using `.extract` which advances the buffer's view - guard var value = self.value else { - return nil - } - - /// grab the numeric metadata from the beginning of the array - guard let metadata = PostgresNumeric(buffer: &value) else { - return nil - } - - return metadata - } -} - private extension Collection { // splits the collection into chunks of the supplied size // if the collection is not evenly divisible, the last chunk will be smaller diff --git a/Sources/PostgresNIO/Data/PostgresRow.swift b/Sources/PostgresNIO/Data/PostgresRow.swift index cc7b7611..401be2c6 100644 --- a/Sources/PostgresNIO/Data/PostgresRow.swift +++ b/Sources/PostgresNIO/Data/PostgresRow.swift @@ -183,28 +183,6 @@ extension PostgresRandomAccessRow: Sendable, RandomAccessCollection { } } -extension PostgresRandomAccessRow { - public subscript(data index: Int) -> PostgresData { - guard index < self.endIndex else { - preconditionFailure("index out of bounds") - } - let column = self.columns[index] - return PostgresData( - type: column.dataType, - typeModifier: column.dataTypeModifier, - formatCode: .binary, - value: self.cells[index] - ) - } - - public subscript(data column: String) -> PostgresData { - guard let index = self.lookupTable[column] else { - fatalError(#"A column "\#(column)" does not exist."#) - } - return self[data: index] - } -} - extension PostgresRandomAccessRow { /// Access the data in the provided column and decode it into the target type. /// @@ -261,40 +239,3 @@ extension PostgresRandomAccessRow { } } } - -// MARK: Deprecated API - -extension PostgresRow { - @available(*, deprecated, message: """ - This call is O(n) where n is the number of cells in the row. For random access to cells - in a row create a PostgresRandomAccessRow from the row first and use its subscript - methods. (see `makeRandomAccess()`) - """) - public func column(_ column: String) -> PostgresData? { - guard let index = self.lookupTable[column] else { - return nil - } - - return PostgresData( - type: self.columns[index].dataType, - typeModifier: self.columns[index].dataTypeModifier, - formatCode: .binary, - value: self.data[column: index] - ) - } -} - -extension PostgresRow: CustomStringConvertible { - public var description: String { - var row: [String: PostgresData] = [:] - for cell in self { - row[cell.columnName] = PostgresData( - type: cell.dataType, - typeModifier: 0, - formatCode: cell.format, - value: cell.bytes - ) - } - return row.description - } -} diff --git a/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift b/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift deleted file mode 100644 index 51579c7b..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresData+UInt.swift +++ /dev/null @@ -1,82 +0,0 @@ -private func warn( - _ old: Any.Type, mustBeConvertedTo new: Any.Type, - file: StaticString = #file, line: UInt = #line -) { - assertionFailure(""" - Integer conversion unsafe. - Postgres does not support storing \(old) natively. - - To bypass this assertion, compile in release mode. - - swift build -c release - - Unsigned integers were previously allowed by PostgresNIO - but may cause overflow. To avoid overflow errors, update - your code to use \(new) instead. - - See https://github.com/vapor/postgres-nio/pull/120 - - """, file: file, line: line) -} - -extension PostgresData { - @available(*, deprecated, renamed: "init(int:)") - public init(uint value: UInt) { - warn(UInt.self, mustBeConvertedTo: Int.self) - self.init(int: .init(bitPattern: value)) - } - - @available(*, deprecated, renamed: "init(uint8:)") - public init(int8 value: Int8) { - warn(Int8.self, mustBeConvertedTo: UInt8.self) - self.init(uint8: .init(bitPattern: value)) - } - - @available(*, deprecated, renamed: "init(int16:)") - public init(uint16 value: UInt16) { - warn(UInt16.self, mustBeConvertedTo: Int16.self) - self.init(int16: .init(bitPattern: value)) - } - - @available(*, deprecated, renamed: "init(int32:)") - public init(uint32 value: UInt32) { - warn(UInt32.self, mustBeConvertedTo: Int32.self) - self.init(int32: .init(bitPattern: value)) - } - - @available(*, deprecated, renamed: "init(int64:)") - public init(uint64 value: UInt64) { - warn(UInt64.self, mustBeConvertedTo: Int64.self) - self.init(int64: .init(bitPattern: value)) - } - - @available(*, deprecated, renamed: "int") - public var uint: UInt? { - warn(UInt.self, mustBeConvertedTo: Int.self) - return self.int.flatMap { .init(bitPattern: $0) } - } - - @available(*, deprecated, renamed: "uint8") - public var int8: Int8? { - warn(Int8.self, mustBeConvertedTo: UInt8.self) - return self.uint8.flatMap { .init(bitPattern: $0) } - } - - @available(*, deprecated, renamed: "int16") - public var uint16: UInt16? { - warn(UInt16.self, mustBeConvertedTo: Int16.self) - return self.int16.flatMap { .init(bitPattern: $0) } - } - - @available(*, deprecated, renamed: "int32") - public var uint32: UInt32? { - warn(UInt32.self, mustBeConvertedTo: Int32.self) - return self.int32.flatMap { .init(bitPattern: $0) } - } - - @available(*, deprecated, renamed: "int64") - public var uint64: UInt64? { - warn(UInt64.self, mustBeConvertedTo: Int64.self) - return self.int64.flatMap { .init(bitPattern: $0) } - } -} diff --git a/Sources/PostgresNIO/New/PostgresQuery.swift b/Sources/PostgresNIO/New/PostgresQuery.swift index 1cfcf2dc..4e31e241 100644 --- a/Sources/PostgresNIO/New/PostgresQuery.swift +++ b/Sources/PostgresNIO/New/PostgresQuery.swift @@ -212,17 +212,6 @@ public struct PostgresBindings: Sendable, Hashable { value.encodeRaw(into: &self.bytes, context: context) self.metadata.append(.init(value: value, protected: false)) } - - public mutating func append(_ postgresData: PostgresData) { - switch postgresData.value { - case .none: - self.bytes.writeInteger(-1, as: Int32.self) - case .some(var input): - self.bytes.writeInteger(Int32(input.readableBytes)) - self.bytes.writeBuffer(&input) - } - self.metadata.append(.init(dataType: postgresData.type, format: .binary, protected: true)) - } } extension PostgresBindings: CustomStringConvertible, CustomDebugStringConvertible { diff --git a/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift b/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift index 82baf914..ee567dc9 100644 --- a/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift +++ b/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift @@ -311,7 +311,7 @@ class PostgresConnectionTests: XCTestCase { func makeBindings() -> PostgresBindings { var bindings = PostgresBindings() - bindings.append(.init(string: self.state)) + bindings.append(self.state) return bindings } diff --git a/Tests/PostgresNIOTests/Utilities/PostgresJSONCodingTests.swift b/Tests/PostgresNIOTests/Utilities/PostgresJSONCodingTests.swift deleted file mode 100644 index c6f876f2..00000000 --- a/Tests/PostgresNIOTests/Utilities/PostgresJSONCodingTests.swift +++ /dev/null @@ -1,66 +0,0 @@ -import Atomics -import NIOCore -import XCTest -import PostgresNIO - -class PostgresJSONCodingTests: XCTestCase { - // https://github.com/vapor/postgres-nio/issues/126 - func testCustomJSONEncoder() { - let previousDefaultJSONEncoder = PostgresNIO._defaultJSONEncoder - defer { - PostgresNIO._defaultJSONEncoder = previousDefaultJSONEncoder - } - final class CustomJSONEncoder: PostgresJSONEncoder { - let counter = ManagedAtomic(0) - func encode(_ value: T) throws -> Data where T : Encodable { - self.counter.wrappingIncrement(ordering: .relaxed) - return try JSONEncoder().encode(value) - } - } - struct Object: Codable { - var foo: Int - var bar: Int - } - let customJSONEncoder = CustomJSONEncoder() - XCTAssertEqual(customJSONEncoder.counter.load(ordering: .relaxed), 0) - PostgresNIO._defaultJSONEncoder = customJSONEncoder - XCTAssertNoThrow(try PostgresData(json: Object(foo: 1, bar: 2))) - XCTAssertEqual(customJSONEncoder.counter.load(ordering: .relaxed), 1) - - let customJSONBEncoder = CustomJSONEncoder() - XCTAssertEqual(customJSONBEncoder.counter.load(ordering: .relaxed), 0) - PostgresNIO._defaultJSONEncoder = customJSONBEncoder - XCTAssertNoThrow(try PostgresData(json: Object(foo: 1, bar: 2))) - XCTAssertEqual(customJSONBEncoder.counter.load(ordering: .relaxed), 1) - } - - // https://github.com/vapor/postgres-nio/issues/126 - func testCustomJSONDecoder() { - let previousDefaultJSONDecoder = PostgresNIO._defaultJSONDecoder - defer { - PostgresNIO._defaultJSONDecoder = previousDefaultJSONDecoder - } - final class CustomJSONDecoder: PostgresJSONDecoder { - let counter = ManagedAtomic(0) - func decode(_ type: T.Type, from data: Data) throws -> T where T : Decodable { - self.counter.wrappingIncrement(ordering: .relaxed) - return try JSONDecoder().decode(type, from: data) - } - } - struct Object: Codable { - var foo: Int - var bar: Int - } - let customJSONDecoder = CustomJSONDecoder() - XCTAssertEqual(customJSONDecoder.counter.load(ordering: .relaxed), 0) - PostgresNIO._defaultJSONDecoder = customJSONDecoder - XCTAssertNoThrow(try PostgresData(json: Object(foo: 1, bar: 2)).json(as: Object.self)) - XCTAssertEqual(customJSONDecoder.counter.load(ordering: .relaxed), 1) - - let customJSONBDecoder = CustomJSONDecoder() - XCTAssertEqual(customJSONBDecoder.counter.load(ordering: .relaxed), 0) - PostgresNIO._defaultJSONDecoder = customJSONBDecoder - XCTAssertNoThrow(try PostgresData(json: Object(foo: 1, bar: 2)).json(as: Object.self)) - XCTAssertEqual(customJSONBDecoder.counter.load(ordering: .relaxed), 1) - } -} From 5954c93e12cb6357ff3fbb1286822d0f02e49a43 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:39:05 +0100 Subject: [PATCH 10/17] Remove deprecated Connection Configs --- ...sConnection+Configuration+Deprecated.swift | 95 ------------------- 1 file changed, 95 deletions(-) delete mode 100644 Sources/PostgresNIO/Deprecated/PostgresConnection+Configuration+Deprecated.swift diff --git a/Sources/PostgresNIO/Deprecated/PostgresConnection+Configuration+Deprecated.swift b/Sources/PostgresNIO/Deprecated/PostgresConnection+Configuration+Deprecated.swift deleted file mode 100644 index 9619c182..00000000 --- a/Sources/PostgresNIO/Deprecated/PostgresConnection+Configuration+Deprecated.swift +++ /dev/null @@ -1,95 +0,0 @@ -import NIOCore - -extension PostgresConnection.Configuration { - /// Legacy connection parameters structure. Replaced by ``PostgresConnection/Configuration/host`` etc. - @available(*, deprecated, message: "Use `Configuration.host` etc. instead.") - public struct Connection { - /// See ``PostgresConnection/Configuration/host``. - public var host: String - - /// See ``PostgresConnection/Configuration/port``. - public var port: Int - - /// See ``PostgresConnection/Configuration/Options-swift.struct/requireBackendKeyData``. - public var requireBackendKeyData: Bool = true - - /// See ``PostgresConnection/Configuration/Options-swift.struct/connectTimeout``. - public var connectTimeout: TimeAmount = .seconds(10) - - /// Create a configuration for connecting to a server. - /// - /// - Parameters: - /// - host: The hostname to connect to. - /// - port: The TCP port to connect to (defaults to 5432). - public init(host: String, port: Int = 5432) { - self.host = host - self.port = port - } - } - - /// Legacy authentication parameters structure. Replaced by ``PostgresConnection/Configuration/username`` etc. - @available(*, deprecated, message: "Use `Configuration.username` etc. instead.") - public struct Authentication { - /// See ``PostgresConnection/Configuration/username``. - public var username: String - - /// See ``PostgresConnection/Configuration/password``. - public var password: String? - - /// See ``PostgresConnection/Configuration/database``. - public var database: String? - - public init(username: String, database: String?, password: String?) { - self.username = username - self.database = database - self.password = password - } - } - - /// Accessor for legacy connection parameters. Replaced by ``PostgresConnection/Configuration/host`` etc. - @available(*, deprecated, message: "Use `Configuration.host` etc. instead.") - public var connection: Connection { - get { - var conn: Connection - switch self.endpointInfo { - case .connectTCP(let host, let port): - conn = .init(host: host, port: port) - case .bindUnixDomainSocket(_), .configureChannel(_): - conn = .init(host: "!invalid!", port: 0) // best we can do, really - } - conn.requireBackendKeyData = self.options.requireBackendKeyData - conn.connectTimeout = self.options.connectTimeout - return conn - } - set { - self.endpointInfo = .connectTCP(host: newValue.host, port: newValue.port) - self.options.connectTimeout = newValue.connectTimeout - self.options.requireBackendKeyData = newValue.requireBackendKeyData - } - } - - @available(*, deprecated, message: "Use `Configuration.username` etc. instead.") - public var authentication: Authentication { - get { - .init(username: self.username, database: self.database, password: self.password) - } - set { - self.username = newValue.username - self.password = newValue.password - self.database = newValue.database - } - } - - /// Legacy initializer. - /// Replaced by ``PostgresConnection/Configuration/init(host:port:username:password:database:tls:)`` etc. - @available(*, deprecated, message: "Use `init(host:port:username:password:database:tls:)` instead.") - public init(connection: Connection, authentication: Authentication, tls: TLS) { - self.init( - host: connection.host, port: connection.port, - username: authentication.username, password: authentication.password, database: authentication.database, - tls: tls - ) - self.options.connectTimeout = connection.connectTimeout - self.options.requireBackendKeyData = connection.requireBackendKeyData - } -} From 0bfadd1fa70a942667d4ae73a0dba6eb76d33e95 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:40:55 +0100 Subject: [PATCH 11/17] Make SASLAuth internal --- .../Utilities/SASLAuthenticationManager.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/PostgresNIO/Utilities/SASLAuthenticationManager.swift b/Sources/PostgresNIO/Utilities/SASLAuthenticationManager.swift index f6c7ee75..1ae314e6 100644 --- a/Sources/PostgresNIO/Utilities/SASLAuthenticationManager.swift +++ b/Sources/PostgresNIO/Utilities/SASLAuthenticationManager.swift @@ -1,6 +1,6 @@ import Crypto -public final class SASLAuthenticationManager { +final class SASLAuthenticationManager { private enum Role { case client, server @@ -24,12 +24,12 @@ public final class SASLAuthenticationManager { private let role: Role private var state: State = .waitingForInitial - public init(asClientSpeaking mechanism: M) { + init(asClientSpeaking mechanism: M) { self.mechanism = mechanism self.role = .client } - public init(asServerAccepting mechanism: M) { + init(asServerAccepting mechanism: M) { self.mechanism = mechanism self.role = .server } @@ -46,7 +46,7 @@ public final class SASLAuthenticationManager { /// /// Pass a `nil` message to start the initial request from a client. It is /// invalid to do this for a server. - public func handle(message: [UInt8]?, sender: ([UInt8]) throws -> Void) throws -> Bool { + func handle(message: [UInt8]?, sender: ([UInt8]) throws -> Void) throws -> Bool { guard self.state != .done else { // Already did whatever we were gonna do. throw SASLAuthenticationError.resultAlreadyDelivered @@ -99,7 +99,7 @@ public final class SASLAuthenticationManager { /// Various errors that can occur during SASL negotiation that are not specific /// to the particular SASL mechanism in use. -public enum SASLAuthenticationError: Error { +enum SASLAuthenticationError: Error { /// A server can not handle a nonexistent message. Only an initial-state /// client can do that, and even then it's really just a proxy for the API /// having difficulty expressing "this must be done once and then never @@ -128,7 +128,7 @@ public enum SASLAuthenticationError: Error { /// Signifies an action to be taken as the result of a single step of a SASL /// mechanism. -public enum SASLAuthenticationStepResult { +enum SASLAuthenticationStepResult { /// More steps are needed. Assume neither success nor failure. If data is /// provided, send it. A value of `nil` signifies sending no response at @@ -155,7 +155,7 @@ public enum SASLAuthenticationStepResult { /// the responsibility of each individual implementation to provide an API for /// creating instances of itself which are able to retrieve information from the /// caller (such as usernames and passwords) by some mechanism. -public protocol SASLAuthenticationMechanism { +protocol SASLAuthenticationMechanism { /// The IANA-registered SASL mechanism name. This may be a family prefix or /// a specific mechanism name. It is explicitly suitable for use in From 499ef7e751d4e8fea71be211571b812d4f4ab549 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:50:38 +0100 Subject: [PATCH 12/17] Update supported platforms --- Package.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 814335bd..ba61370c 100644 --- a/Package.swift +++ b/Package.swift @@ -4,10 +4,10 @@ import PackageDescription let package = Package( name: "postgres-nio", platforms: [ - .macOS(.v10_15), - .iOS(.v13), - .watchOS(.v6), - .tvOS(.v13), + .macOS(.v13), + .iOS(.v16), + .watchOS(.v9), + .tvOS(.v16), ], products: [ .library(name: "PostgresNIO", targets: ["PostgresNIO"]), From ad061c0858f295fc10e8283b40acfcb6e70028d6 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:56:12 +0100 Subject: [PATCH 13/17] Remove `@_exported` --- Sources/PostgresNIO/Utilities/Exports.swift | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 Sources/PostgresNIO/Utilities/Exports.swift diff --git a/Sources/PostgresNIO/Utilities/Exports.swift b/Sources/PostgresNIO/Utilities/Exports.swift deleted file mode 100644 index 58e12891..00000000 --- a/Sources/PostgresNIO/Utilities/Exports.swift +++ /dev/null @@ -1,14 +0,0 @@ -#if swift(>=5.8) - -@_documentation(visibility: internal) @_exported import NIO -@_documentation(visibility: internal) @_exported import NIOSSL -@_documentation(visibility: internal) @_exported import struct Logging.Logger - -#else - -// TODO: Remove this with the next major release! -@_exported import NIO -@_exported import NIOSSL -@_exported import struct Logging.Logger - -#endif From 3f59fa1342ef69a74263fbc14a0a2c8b5cb747ab Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 15:56:31 +0100 Subject: [PATCH 14/17] Cleanup PostgresFormat and PostgresDataType --- Sources/PostgresNIO/Data/PostgresDataType.swift | 17 ----------------- Sources/PostgresNIO/Docs.docc/index.md | 17 ----------------- 2 files changed, 34 deletions(-) diff --git a/Sources/PostgresNIO/Data/PostgresDataType.swift b/Sources/PostgresNIO/Data/PostgresDataType.swift index f3ab4dca..5b45046b 100644 --- a/Sources/PostgresNIO/Data/PostgresDataType.swift +++ b/Sources/PostgresNIO/Data/PostgresDataType.swift @@ -17,13 +17,6 @@ extension PostgresFormat: CustomStringConvertible { } } -// TODO: The Codable conformance does not make any sense. Let's remove this with next major break. -extension PostgresFormat: Codable {} - -// TODO: Renamed during 1.x. Remove this with next major break. -@available(*, deprecated, renamed: "PostgresFormat") -public typealias PostgresFormatCode = PostgresFormat - /// Data types and their raw OIDs. /// /// Use `select * from pg_type where oid = ` to look up more information for a given type. @@ -768,13 +761,3 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri return self.knownSQLName ?? "UNKNOWN \(self.rawValue)" } } - -// TODO: The Codable conformance does not make any sense. Let's remove this with next major break. -extension PostgresDataType: Codable {} - -// TODO: The ExpressibleByIntegerLiteral conformance does not make any sense and is not used anywhere. Remove with next major break. -extension PostgresDataType: ExpressibleByIntegerLiteral { - public init(integerLiteral value: UInt32) { - self.init(value) - } -} diff --git a/Sources/PostgresNIO/Docs.docc/index.md b/Sources/PostgresNIO/Docs.docc/index.md index 324c3da1..995a0c04 100644 --- a/Sources/PostgresNIO/Docs.docc/index.md +++ b/Sources/PostgresNIO/Docs.docc/index.md @@ -61,22 +61,5 @@ Features: - ``PostgresError`` - ``PostgresDecodingError`` -### Deprecated - -These types are already deprecated or will be deprecated in the near future. All of them will be -removed from the public API with the next major release. - -- ``PostgresDatabase`` -- ``PostgresData`` -- ``PostgresQueryResult`` -- ``PostgresJSONCodable`` -- ``PostgresJSONBCodable`` -- ``PostgresMessage`` -- ``PostgresFormatCode`` -- ``SASLAuthenticationManager`` -- ``SASLAuthenticationMechanism`` -- ``SASLAuthenticationError`` -- ``SASLAuthenticationStepResult`` - [SwiftNIO]: https://github.com/apple/swift-nio [SwiftLog]: https://github.com/apple/swift-log From 87cee04edcfcbd60e68f5e9be975f2d5e13cdfb1 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 13 Dec 2023 16:00:23 +0100 Subject: [PATCH 15/17] Remove unused function `hexdigest` --- Sources/PostgresNIO/Utilities/NIOUtils.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Sources/PostgresNIO/Utilities/NIOUtils.swift b/Sources/PostgresNIO/Utilities/NIOUtils.swift index 75ab8c20..44172bf1 100644 --- a/Sources/PostgresNIO/Utilities/NIOUtils.swift +++ b/Sources/PostgresNIO/Utilities/NIOUtils.swift @@ -52,9 +52,3 @@ internal extension ByteBuffer { return array } } - -internal extension Sequence where Element == UInt8 { - func hexdigest() -> String { - return reduce("") { $0 + String(format: "%02x", $1) } - } -} From 7926cb3ca89c51335b5b9e0b1aef2eb5d917e53c Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Fri, 15 Dec 2023 15:06:33 +0100 Subject: [PATCH 16/17] Remove separate connect and auth methods --- .../PostgresConnection+Configuration.swift | 2 +- .../Connection/PostgresConnection.swift | 77 +------------------ .../PostgresNIO/Data/PostgresDataType.swift | 2 - .../PostgresNIO/New/PSQLEventsHandler.swift | 5 -- .../New/PostgresChannelHandler.swift | 20 ++--- Tests/IntegrationTests/Utilities.swift | 11 --- .../New/PostgresChannelHandlerTests.swift | 14 ++-- 7 files changed, 15 insertions(+), 116 deletions(-) diff --git a/Sources/PostgresNIO/Connection/PostgresConnection+Configuration.swift b/Sources/PostgresNIO/Connection/PostgresConnection+Configuration.swift index dd0f5404..1da41dc1 100644 --- a/Sources/PostgresNIO/Connection/PostgresConnection+Configuration.swift +++ b/Sources/PostgresNIO/Connection/PostgresConnection+Configuration.swift @@ -233,7 +233,7 @@ extension PostgresConnection { } let connection: InternalConfiguration.Connection - let username: String? + let username: String let password: String? let database: String? var tls: Configuration.TLS diff --git a/Sources/PostgresNIO/Connection/PostgresConnection.swift b/Sources/PostgresNIO/Connection/PostgresConnection.swift index 9762677b..de900aea 100644 --- a/Sources/PostgresNIO/Connection/PostgresConnection.swift +++ b/Sources/PostgresNIO/Connection/PostgresConnection.swift @@ -95,16 +95,9 @@ public final class PostgresConnection: @unchecked Sendable { return self.eventLoop.makeFailedFuture(error) } - let startupFuture: EventLoopFuture - if configuration.username == nil { - startupFuture = eventHandler.readyForStartupFuture - } else { - startupFuture = eventHandler.authenticateFuture - } - // 3. wait for startup future to succeed. - return startupFuture.flatMapError { error in + return eventHandler.authenticateFuture.flatMapError { error in // in case of an startup error, the connection must be closed and after that // the originating error should be surfaced @@ -284,74 +277,6 @@ public final class PostgresConnection: @unchecked Sendable { extension PostgresConnection { static let idGenerator = ManagedAtomic(0) - - @available(*, deprecated, - message: "Use the new connect method that allows you to connect and authenticate in a single step", - renamed: "connect(on:configuration:id:logger:)" - ) - public static func connect( - to socketAddress: SocketAddress, - tlsConfiguration: TLSConfiguration? = nil, - serverHostname: String? = nil, - logger: Logger = .init(label: "codes.vapor.postgres"), - on eventLoop: EventLoop - ) -> EventLoopFuture { - var tlsFuture: EventLoopFuture - - if let tlsConfiguration = tlsConfiguration { - tlsFuture = eventLoop.makeSucceededVoidFuture().flatMapBlocking(onto: .global(qos: .default)) { - try .require(.init(configuration: tlsConfiguration)) - } - } else { - tlsFuture = eventLoop.makeSucceededFuture(.disable) - } - - return tlsFuture.flatMap { tls in - var options = PostgresConnection.Configuration.Options() - options.tlsServerName = serverHostname - let configuration = PostgresConnection.InternalConfiguration( - connection: .resolved(address: socketAddress), - username: nil, - password: nil, - database: nil, - tls: tls, - options: options - ) - - return PostgresConnection.connect( - connectionID: self.idGenerator.wrappingIncrementThenLoad(ordering: .relaxed), - configuration: configuration, - logger: logger, - on: eventLoop - ) - }.flatMapErrorThrowing { error in - throw error.asAppropriatePostgresError - } - } - - @available(*, deprecated, - message: "Use the new connect method that allows you to connect and authenticate in a single step", - renamed: "connect(on:configuration:id:logger:)" - ) - public func authenticate( - username: String, - database: String? = nil, - password: String? = nil, - logger: Logger = .init(label: "codes.vapor.postgres") - ) -> EventLoopFuture { - let authContext = AuthContext( - username: username, - password: password, - database: database) - let outgoing = PSQLOutgoingEvent.authenticate(authContext) - self.channel.triggerUserOutboundEvent(outgoing, promise: nil) - - return self.channel.pipeline.handler(type: PSQLEventsHandler.self).flatMap { handler in - handler.authenticateFuture - }.flatMapErrorThrowing { error in - throw error.asAppropriatePostgresError - } - } } // MARK: Async/Await Interface diff --git a/Sources/PostgresNIO/Data/PostgresDataType.swift b/Sources/PostgresNIO/Data/PostgresDataType.swift index 5b45046b..35dbca3f 100644 --- a/Sources/PostgresNIO/Data/PostgresDataType.swift +++ b/Sources/PostgresNIO/Data/PostgresDataType.swift @@ -110,8 +110,6 @@ public struct PostgresDataType: RawRepresentable, Sendable, Hashable, CustomStri /// `790` public static let money = PostgresDataType(790) /// `791` - @available(*, deprecated, renamed: "moneyArray") - public static let _money = PostgresDataType(791) public static let moneyArray = PostgresDataType(791) /// `829` public static let macaddr = PostgresDataType(829) diff --git a/Sources/PostgresNIO/New/PSQLEventsHandler.swift b/Sources/PostgresNIO/New/PSQLEventsHandler.swift index 2bf0d6d8..ef963569 100644 --- a/Sources/PostgresNIO/New/PSQLEventsHandler.swift +++ b/Sources/PostgresNIO/New/PSQLEventsHandler.swift @@ -3,11 +3,6 @@ import NIOTLS import Logging enum PSQLOutgoingEvent { - /// the event we send down the channel to inform the ``PostgresChannelHandler`` to authenticate - /// - /// this shall be removed with the next breaking change and always supplied with `PSQLConnection.Configuration` - case authenticate(AuthContext) - case gracefulShutdown } diff --git a/Sources/PostgresNIO/New/PostgresChannelHandler.swift b/Sources/PostgresNIO/New/PostgresChannelHandler.swift index 54ae0fc9..36730766 100644 --- a/Sources/PostgresNIO/New/PostgresChannelHandler.swift +++ b/Sources/PostgresNIO/New/PostgresChannelHandler.swift @@ -277,10 +277,6 @@ final class PostgresChannelHandler: ChannelDuplexHandler { self.logger.trace("User outbound event received", metadata: [.userEvent: "\(event)"]) switch event { - case PSQLOutgoingEvent.authenticate(let authContext): - let action = self.state.provideAuthenticationContext(authContext) - self.run(action, with: context) - case PSQLOutgoingEvent.gracefulShutdown: let action = self.state.gracefulClose(promise) self.run(action, with: context) @@ -386,15 +382,13 @@ final class PostgresChannelHandler: ChannelDuplexHandler { case .provideAuthenticationContext: context.fireUserInboundEventTriggered(PSQLEvent.readyForStartup) - if let username = self.configuration.username { - let authContext = AuthContext( - username: username, - password: self.configuration.password, - database: self.configuration.database - ) - let action = self.state.provideAuthenticationContext(authContext) - return self.run(action, with: context) - } + let authContext = AuthContext( + username: self.configuration.username, + password: self.configuration.password, + database: self.configuration.database + ) + let action = self.state.provideAuthenticationContext(authContext) + return self.run(action, with: context) case .fireEventReadyForQuery: context.fireUserInboundEventTriggered(PSQLEvent.readyForQuery) case .closeConnection(let promise): diff --git a/Tests/IntegrationTests/Utilities.swift b/Tests/IntegrationTests/Utilities.swift index b1788110..245134c4 100644 --- a/Tests/IntegrationTests/Utilities.swift +++ b/Tests/IntegrationTests/Utilities.swift @@ -12,17 +12,6 @@ extension PostgresConnection { static func address() throws -> SocketAddress { try .makeAddressResolvingHost(env("POSTGRES_HOSTNAME") ?? "localhost", port: env("POSTGRES_PORT").flatMap(Int.init(_:)) ?? 5432) } - - @available(*, deprecated, message: "Test deprecated functionality") - static func testUnauthenticated(on eventLoop: EventLoop, logLevel: Logger.Level = .info) -> EventLoopFuture { - var logger = Logger(label: "postgres.connection.test") - logger.logLevel = logLevel - do { - return connect(to: try address(), logger: logger, on: eventLoop) - } catch { - return eventLoop.makeFailedFuture(error) - } - } static func test(on eventLoop: EventLoop, logLevel: Logger.Level = .info) -> EventLoopFuture { var logger = Logger(label: "postgres.connection.test") diff --git a/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift b/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift index dfdcc53e..f86f979f 100644 --- a/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift +++ b/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift @@ -145,18 +145,17 @@ class PostgresChannelHandlerTests: XCTestCase { func testRunAuthenticateMD5Password() { let config = self.testConnectionConfiguration() let authContext = AuthContext( - username: config.username ?? "something wrong", + username: config.username, password: config.password, database: config.database ) - let state = ConnectionStateMachine(.waitingToStartAuthentication) - let handler = PostgresChannelHandler(configuration: config, eventLoop: self.eventLoop, state: state, configureSSLCallback: nil) + let handler = PostgresChannelHandler(configuration: config, eventLoop: self.eventLoop, configureSSLCallback: nil) let embedded = EmbeddedChannel(handlers: [ ReverseByteToMessageHandler(PSQLFrontendMessageDecoder()), handler ], loop: self.eventLoop) - embedded.triggerUserOutboundEvent(PSQLOutgoingEvent.authenticate(authContext), promise: nil) + XCTAssertNoThrow(try embedded.connect(to: .init(ipAddress: "127.0.0.1", port: 5432))) XCTAssertEqual(try embedded.readOutbound(as: PostgresFrontendMessage.self), .startup(.versionThree(parameters: authContext.toStartupParameters()))) let salt: UInt32 = 0x00_01_02_03 @@ -172,19 +171,18 @@ class PostgresChannelHandlerTests: XCTestCase { let password = "postgres" let config = self.testConnectionConfiguration(password: password) let authContext = AuthContext( - username: config.username ?? "something wrong", + username: config.username, password: config.password, database: config.database ) - let state = ConnectionStateMachine(.waitingToStartAuthentication) - let handler = PostgresChannelHandler(configuration: config, eventLoop: self.eventLoop, state: state, configureSSLCallback: nil) + let handler = PostgresChannelHandler(configuration: config, eventLoop: self.eventLoop, configureSSLCallback: nil) let embedded = EmbeddedChannel(handlers: [ ReverseByteToMessageHandler(PSQLFrontendMessageDecoder()), ReverseMessageToByteHandler(PSQLBackendMessageEncoder()), handler ], loop: self.eventLoop) - embedded.triggerUserOutboundEvent(PSQLOutgoingEvent.authenticate(authContext), promise: nil) + XCTAssertNoThrow(try embedded.connect(to: .init(ipAddress: "127.0.0.1", port: 5432))) XCTAssertEqual(try embedded.readOutbound(as: PostgresFrontendMessage.self), .startup(.versionThree(parameters: authContext.toStartupParameters()))) XCTAssertNoThrow(try embedded.writeInbound(PostgresBackendMessage.authentication(.plaintext))) From ce3fee6060efe67478938d9cb82d017fb18711b5 Mon Sep 17 00:00:00 2001 From: Fabian Fett Date: Wed, 31 Jan 2024 17:14:14 +0100 Subject: [PATCH 17/17] Remove old PostgresError; Rename PSQLError -> PostgresError --- .../Connection/PostgresConnection.swift | 20 +++--- .../AuthenticationStateMachine.swift | 10 +-- .../CloseStateMachine.swift | 10 +-- .../ConnectionStateMachine.swift | 34 +++++----- .../ExtendedQueryStateMachine.swift | 16 ++--- .../PreparedStatementStateMachine.swift | 8 +-- .../New/NotificationListener.swift | 2 +- Sources/PostgresNIO/New/PSQLTask.swift | 2 +- .../New/PostgresChannelHandler.swift | 12 ++-- .../{PSQLError.swift => PostgresError.swift} | 58 ++++++++--------- Sources/PostgresNIO/Pool/PostgresClient.swift | 6 +- Sources/PostgresNIO/Postgres+PSQLCompat.swift | 65 ------------------- .../Utilities/PostgresError+Code.swift | 9 +-- .../PostgresNIO/Utilities/PostgresError.swift | 23 ------- Tests/IntegrationTests/AsyncTests.swift | 4 +- .../PSQLIntegrationTests.swift | 2 +- .../AuthenticationStateMachineTests.swift | 2 +- .../ConnectionStateMachineTests.swift | 10 +-- .../ExtendedQueryStateMachineTests.swift | 18 ++--- .../PrepareStatementStateMachineTests.swift | 6 +- .../PreparedStatementStateMachineTests.swift | 2 +- .../ConnectionAction+TestUtils.swift | 4 +- .../New/PSQLRowStreamTests.swift | 4 +- .../New/PostgresChannelHandlerTests.swift | 6 +- .../New/PostgresConnectionTests.swift | 12 ++-- .../New/PostgresErrorTests.swift | 2 +- .../New/PostgresRowSequenceTests.swift | 8 +-- 27 files changed, 130 insertions(+), 225 deletions(-) rename Sources/PostgresNIO/New/{PSQLError.swift => PostgresError.swift} (92%) delete mode 100644 Sources/PostgresNIO/Postgres+PSQLCompat.swift delete mode 100644 Sources/PostgresNIO/Utilities/PostgresError.swift diff --git a/Sources/PostgresNIO/Connection/PostgresConnection.swift b/Sources/PostgresNIO/Connection/PostgresConnection.swift index de900aea..b5d1313b 100644 --- a/Sources/PostgresNIO/Connection/PostgresConnection.swift +++ b/Sources/PostgresNIO/Connection/PostgresConnection.swift @@ -163,7 +163,7 @@ public final class PostgresConnection: @unchecked Sendable { connectFuture = bootstrap.connect(unixDomainSocketPath: path) case .bootstrapped(let channel): guard channel.isActive else { - return eventLoop.makeFailedFuture(PSQLError.connectionError(underlying: ChannelError.alreadyClosed)) + return eventLoop.makeFailedFuture(PostgresError.connectionError(underlying: ChannelError.alreadyClosed)) } connectFuture = eventLoop.makeSucceededFuture(channel) } @@ -173,10 +173,10 @@ public final class PostgresConnection: @unchecked Sendable { return connection.start(configuration: configuration).map { _ in connection } }.flatMapErrorThrowing { error -> PostgresConnection in switch error { - case is PSQLError: + case is PostgresError: throw error default: - throw PSQLError.connectionError(underlying: error) + throw PostgresError.connectionError(underlying: error) } } } @@ -205,7 +205,7 @@ public final class PostgresConnection: @unchecked Sendable { var logger = logger logger[postgresMetadataKey: .connectionID] = "\(self.id)" guard query.binds.count <= Int(UInt16.max) else { - return self.channel.eventLoop.makeFailedFuture(PSQLError(code: .tooManyParameters, query: query)) + return self.channel.eventLoop.makeFailedFuture(PostgresError(code: .tooManyParameters, query: query)) } let promise = self.channel.eventLoop.makePromise(of: PSQLRowStream.self) @@ -239,7 +239,7 @@ public final class PostgresConnection: @unchecked Sendable { func execute(_ executeStatement: PSQLExecuteStatement, logger: Logger) -> EventLoopFuture { guard executeStatement.binds.count <= Int(UInt16.max) else { - return self.channel.eventLoop.makeFailedFuture(PSQLError(code: .tooManyParameters)) + return self.channel.eventLoop.makeFailedFuture(PostgresError(code: .tooManyParameters)) } let promise = self.channel.eventLoop.makePromise(of: PSQLRowStream.self) let context = ExtendedQueryContext( @@ -341,7 +341,7 @@ extension PostgresConnection { logger[postgresMetadataKey: .connectionID] = "\(self.id)" guard query.binds.count <= Int(UInt16.max) else { - throw PSQLError(code: .tooManyParameters, query: query, file: file, line: line) + throw PostgresError(code: .tooManyParameters, query: query, file: file, line: line) } let promise = self.channel.eventLoop.makePromise(of: PSQLRowStream.self) let context = ExtendedQueryContext( @@ -354,7 +354,7 @@ extension PostgresConnection { do { return try await promise.futureResult.map({ $0.asyncSequence() }).get() - } catch var error as PSQLError { + } catch var error as PostgresError { error.file = file error.line = line error.query = query @@ -409,7 +409,7 @@ extension PostgresConnection { .map { $0.asyncSequence() } .get() .map { try preparedStatement.decodeRow($0) } - } catch var error as PSQLError { + } catch var error as PostgresError { error.file = file error.line = line error.query = .init( @@ -442,7 +442,7 @@ extension PostgresConnection { return try await promise.futureResult .map { $0.commandTag } .get() - } catch var error as PSQLError { + } catch var error as PostgresError { error.file = file error.line = line error.query = .init( @@ -462,7 +462,7 @@ enum CloseTarget { extension EventLoopFuture { func enrichPSQLError(query: PostgresQuery, file: String, line: Int) -> EventLoopFuture { return self.flatMapErrorThrowing { error in - if var error = error as? PSQLError { + if var error = error as? PostgresError { error.file = file error.line = line error.query = query diff --git a/Sources/PostgresNIO/New/Connection State Machine/AuthenticationStateMachine.swift b/Sources/PostgresNIO/New/Connection State Machine/AuthenticationStateMachine.swift index 245e5efd..d4d605ec 100644 --- a/Sources/PostgresNIO/New/Connection State Machine/AuthenticationStateMachine.swift +++ b/Sources/PostgresNIO/New/Connection State Machine/AuthenticationStateMachine.swift @@ -11,7 +11,7 @@ struct AuthenticationStateMachine { case saslChallengeResponseSent(SASLAuthenticationManager) case saslFinalReceived - case error(PSQLError) + case error(PostgresError) case authenticated } @@ -23,7 +23,7 @@ struct AuthenticationStateMachine { case wait case authenticated - case reportAuthenticationError(PSQLError) + case reportAuthenticationError(PostgresError) } let authContext: AuthContext @@ -51,7 +51,7 @@ struct AuthenticationStateMachine { return .authenticated case .md5(let salt): guard self.authContext.password != nil else { - return self.setAndFireError(PSQLError(code: .authMechanismRequiresPassword)) + return self.setAndFireError(PostgresError(code: .authMechanismRequiresPassword)) } self.state = .passwordAuthenticationSent return .sendPassword(.md5(salt: salt), self.authContext) @@ -160,11 +160,11 @@ struct AuthenticationStateMachine { return self.setAndFireError(.server(message)) } - mutating func errorHappened(_ error: PSQLError) -> Action { + mutating func errorHappened(_ error: PostgresError) -> Action { return self.setAndFireError(error) } - private mutating func setAndFireError(_ error: PSQLError) -> Action { + private mutating func setAndFireError(_ error: PostgresError) -> Action { switch self.state { case .initialized: preconditionFailure(""" diff --git a/Sources/PostgresNIO/New/Connection State Machine/CloseStateMachine.swift b/Sources/PostgresNIO/New/Connection State Machine/CloseStateMachine.swift index 791cebdd..299f04df 100644 --- a/Sources/PostgresNIO/New/Connection State Machine/CloseStateMachine.swift +++ b/Sources/PostgresNIO/New/Connection State Machine/CloseStateMachine.swift @@ -6,13 +6,13 @@ struct CloseStateMachine { case closeSyncSent(CloseCommandContext) case closeCompleteReceived - case error(PSQLError) + case error(PostgresError) } enum Action { case sendCloseSync(CloseTarget) case succeedClose(CloseCommandContext) - case failClose(CloseCommandContext, with: PSQLError) + case failClose(CloseCommandContext, with: PostgresError) case read case wait @@ -44,7 +44,7 @@ struct CloseStateMachine { } mutating func errorReceived(_ errorMessage: PostgresBackendMessage.ErrorResponse) -> Action { - let error = PSQLError.server(errorMessage) + let error = PostgresError.server(errorMessage) switch self.state { case .initialized: return self.setAndFireError(.unexpectedBackendMessage(.error(errorMessage))) @@ -63,7 +63,7 @@ struct CloseStateMachine { } } - mutating func errorHappened(_ error: PSQLError) -> Action { + mutating func errorHappened(_ error: PostgresError) -> Action { return self.setAndFireError(error) } @@ -84,7 +84,7 @@ struct CloseStateMachine { // MARK: Private Methods - private mutating func setAndFireError(_ error: PSQLError) -> Action { + private mutating func setAndFireError(_ error: PostgresError) -> Action { switch self.state { case .closeSyncSent(let closeContext): self.state = .error(error) diff --git a/Sources/PostgresNIO/New/Connection State Machine/ConnectionStateMachine.swift b/Sources/PostgresNIO/New/Connection State Machine/ConnectionStateMachine.swift index 8c3252de..1d988af1 100644 --- a/Sources/PostgresNIO/New/Connection State Machine/ConnectionStateMachine.swift +++ b/Sources/PostgresNIO/New/Connection State Machine/ConnectionStateMachine.swift @@ -33,8 +33,8 @@ struct ConnectionStateMachine { case extendedQuery(ExtendedQueryStateMachine, ConnectionContext) case closeCommand(CloseStateMachine, ConnectionContext) - case closing(PSQLError?) - case closed(clientInitiated: Bool, error: PSQLError?) + case closing(PostgresError?) + case closed(clientInitiated: Bool, error: PostgresError?) case modifying } @@ -57,7 +57,7 @@ struct ConnectionStateMachine { /// Tasks to fail with the error let tasks: [PSQLTask] - let error: PSQLError + let error: PostgresError let closePromise: EventLoopPromise? } @@ -87,24 +87,24 @@ struct ConnectionStateMachine { // --- general actions case sendParseDescribeBindExecuteSync(PostgresQuery) case sendBindExecuteSync(PSQLExecuteStatement) - case failQuery(EventLoopPromise, with: PSQLError, cleanupContext: CleanUpContext?) + case failQuery(EventLoopPromise, with: PostgresError, cleanupContext: CleanUpContext?) case succeedQuery(EventLoopPromise, with: QueryResult) // --- streaming actions // actions if query has requested next row but we are waiting for backend case forwardRows([DataRow]) case forwardStreamComplete([DataRow], commandTag: String) - case forwardStreamError(PSQLError, read: Bool, cleanupContext: CleanUpContext?) + case forwardStreamError(PostgresError, read: Bool, cleanupContext: CleanUpContext?) // Prepare statement actions case sendParseDescribeSync(name: String, query: String) case succeedPreparedStatementCreation(EventLoopPromise, with: RowDescription?) - case failPreparedStatementCreation(EventLoopPromise, with: PSQLError, cleanupContext: CleanUpContext?) + case failPreparedStatementCreation(EventLoopPromise, with: PostgresError, cleanupContext: CleanUpContext?) // Close actions case sendCloseSync(CloseTarget) case succeedClose(CloseCommandContext) - case failClose(CloseCommandContext, with: PSQLError, cleanupContext: CleanUpContext?) + case failClose(CloseCommandContext, with: PostgresError, cleanupContext: CleanUpContext?) } private var state: State @@ -443,7 +443,7 @@ struct ConnectionStateMachine { } } - mutating func errorHappened(_ error: PSQLError) -> ConnectionAction { + mutating func errorHappened(_ error: PostgresError) -> ConnectionAction { switch self.state { case .initialized, .sslRequestSent, @@ -544,12 +544,12 @@ struct ConnectionStateMachine { } mutating func enqueue(task: PSQLTask) -> ConnectionAction { - let psqlErrror: PSQLError + let psqlErrror: PostgresError // check if we are quiescing. if so fail task immidiatly switch self.quiescingState { case .quiescing: - psqlErrror = PSQLError.clientClosedConnection(underlying: nil) + psqlErrror = PostgresError.clientClosedConnection(underlying: nil) case .notQuiescing: switch self.state { @@ -569,13 +569,13 @@ struct ConnectionStateMachine { return self.executeTask(task) case .closing(let error): - psqlErrror = PSQLError.clientClosedConnection(underlying: error) + psqlErrror = PostgresError.clientClosedConnection(underlying: error) case .closed(clientInitiated: true, error: let error): - psqlErrror = PSQLError.clientClosedConnection(underlying: error) + psqlErrror = PostgresError.clientClosedConnection(underlying: error) case .closed(clientInitiated: false, error: let error): - psqlErrror = PSQLError.serverClosedConnection(underlying: error) + psqlErrror = PostgresError.serverClosedConnection(underlying: error) case .modifying: preconditionFailure("Invalid state: \(self.state)") @@ -812,7 +812,7 @@ struct ConnectionStateMachine { return self.modify(with: action) } - private mutating func closeConnectionAndCleanup(_ error: PSQLError, closePromise: EventLoopPromise? = nil) -> ConnectionAction { + private mutating func closeConnectionAndCleanup(_ error: PostgresError, closePromise: EventLoopPromise? = nil) -> ConnectionAction { switch self.state { case .initialized, .sslRequestSent, @@ -956,7 +956,7 @@ struct ConnectionStateMachine { } extension ConnectionStateMachine { - func shouldCloseConnection(reason error: PSQLError) -> Bool { + func shouldCloseConnection(reason error: PostgresError) -> Bool { switch error.code.base { case .failedToAddSSLHandler, .receivedUnencryptedDataAfterSSLRequest, @@ -993,7 +993,7 @@ extension ConnectionStateMachine { } } - mutating func setErrorAndCreateCleanupContextIfNeeded(_ error: PSQLError) -> ConnectionAction.CleanUpContext? { + mutating func setErrorAndCreateCleanupContextIfNeeded(_ error: PostgresError) -> ConnectionAction.CleanUpContext? { if self.shouldCloseConnection(reason: error) { return self.setErrorAndCreateCleanupContext(error) } @@ -1001,7 +1001,7 @@ extension ConnectionStateMachine { return nil } - mutating func setErrorAndCreateCleanupContext(_ error: PSQLError, closePromise: EventLoopPromise? = nil) -> ConnectionAction.CleanUpContext { + mutating func setErrorAndCreateCleanupContext(_ error: PostgresError, closePromise: EventLoopPromise? = nil) -> ConnectionAction.CleanUpContext { let tasks = Array(self.taskQueue) self.taskQueue.removeAll() diff --git a/Sources/PostgresNIO/New/Connection State Machine/ExtendedQueryStateMachine.swift b/Sources/PostgresNIO/New/Connection State Machine/ExtendedQueryStateMachine.swift index 3a84031b..85c4ab1d 100644 --- a/Sources/PostgresNIO/New/Connection State Machine/ExtendedQueryStateMachine.swift +++ b/Sources/PostgresNIO/New/Connection State Machine/ExtendedQueryStateMachine.swift @@ -19,7 +19,7 @@ struct ExtendedQueryStateMachine { case drain([RowDescription.Column]) case commandComplete(commandTag: String) - case error(PSQLError) + case error(PostgresError) case modifying } @@ -30,19 +30,19 @@ struct ExtendedQueryStateMachine { case sendBindExecuteSync(PSQLExecuteStatement) // --- general actions - case failQuery(EventLoopPromise, with: PSQLError) + case failQuery(EventLoopPromise, with: PostgresError) case succeedQuery(EventLoopPromise, with: QueryResult) - case evaluateErrorAtConnectionLevel(PSQLError) + case evaluateErrorAtConnectionLevel(PostgresError) case succeedPreparedStatementCreation(EventLoopPromise, with: RowDescription?) - case failPreparedStatementCreation(EventLoopPromise, with: PSQLError) + case failPreparedStatementCreation(EventLoopPromise, with: PostgresError) // --- streaming actions // actions if query has requested next row but we are waiting for backend case forwardRows([DataRow]) case forwardStreamComplete([DataRow], commandTag: String) - case forwardStreamError(PSQLError, read: Bool) + case forwardStreamError(PostgresError, read: Bool) case read case wait @@ -323,7 +323,7 @@ struct ExtendedQueryStateMachine { } mutating func errorReceived(_ errorMessage: PostgresBackendMessage.ErrorResponse) -> Action { - let error = PSQLError.server(errorMessage) + let error = PostgresError.server(errorMessage) switch self.state { case .initialized: return self.setAndFireError(.unexpectedBackendMessage(.error(errorMessage))) @@ -354,7 +354,7 @@ struct ExtendedQueryStateMachine { return .wait } - mutating func errorHappened(_ error: PSQLError) -> Action { + mutating func errorHappened(_ error: PostgresError) -> Action { return self.setAndFireError(error) } @@ -461,7 +461,7 @@ struct ExtendedQueryStateMachine { // MARK: Private Methods - private mutating func setAndFireError(_ error: PSQLError) -> Action { + private mutating func setAndFireError(_ error: PostgresError) -> Action { switch self.state { case .initialized(let context), .messagesSent(let context), diff --git a/Sources/PostgresNIO/New/Connection State Machine/PreparedStatementStateMachine.swift b/Sources/PostgresNIO/New/Connection State Machine/PreparedStatementStateMachine.swift index 5afa4d0b..6c24f437 100644 --- a/Sources/PostgresNIO/New/Connection State Machine/PreparedStatementStateMachine.swift +++ b/Sources/PostgresNIO/New/Connection State Machine/PreparedStatementStateMachine.swift @@ -4,7 +4,7 @@ struct PreparedStatementStateMachine { enum State { case preparing([PreparedStatementContext]) case prepared(RowDescription?) - case error(PSQLError) + case error(PostgresError) } var preparedStatements: [String: State] = [:] @@ -13,7 +13,7 @@ struct PreparedStatementStateMachine { case prepareStatement case waitForAlreadyInFlightPreparation case executeStatement(RowDescription?) - case returnError(PSQLError) + case returnError(PostgresError) } mutating func lookup(preparedStatement: PreparedStatementContext) -> LookupAction { @@ -72,10 +72,10 @@ struct PreparedStatementStateMachine { struct ErrorHappenedAction { var statements: [PreparedStatementContext] - var error: PSQLError + var error: PostgresError } - mutating func errorHappened(name: String, error: PSQLError) -> ErrorHappenedAction { + mutating func errorHappened(name: String, error: PostgresError) -> ErrorHappenedAction { guard let state = self.preparedStatements[name] else { fatalError("Unknown prepared statement \(name)") } diff --git a/Sources/PostgresNIO/New/NotificationListener.swift b/Sources/PostgresNIO/New/NotificationListener.swift index 01951106..523bd836 100644 --- a/Sources/PostgresNIO/New/NotificationListener.swift +++ b/Sources/PostgresNIO/New/NotificationListener.swift @@ -96,7 +96,7 @@ final class NotificationListener: @unchecked Sendable { switch self.state { case .streamInitialized(let checkedContinuation): self.state = .done - checkedContinuation.resume(throwing: PSQLError(code: .queryCancelled)) + checkedContinuation.resume(throwing: PostgresError(code: .queryCancelled)) case .streamListening(let continuation): self.state = .done diff --git a/Sources/PostgresNIO/New/PSQLTask.swift b/Sources/PostgresNIO/New/PSQLTask.swift index 6308a5b3..009e76d1 100644 --- a/Sources/PostgresNIO/New/PSQLTask.swift +++ b/Sources/PostgresNIO/New/PSQLTask.swift @@ -13,7 +13,7 @@ enum PSQLTask { case extendedQuery(ExtendedQueryContext) case closeCommand(CloseCommandContext) - func failWithError(_ error: PSQLError) { + func failWithError(_ error: PostgresError) { switch self { case .extendedQuery(let extendedQueryContext): switch extendedQueryContext.query { diff --git a/Sources/PostgresNIO/New/PostgresChannelHandler.swift b/Sources/PostgresNIO/New/PostgresChannelHandler.swift index 36730766..96603ce0 100644 --- a/Sources/PostgresNIO/New/PostgresChannelHandler.swift +++ b/Sources/PostgresNIO/New/PostgresChannelHandler.swift @@ -616,12 +616,12 @@ final class PostgresChannelHandler: ChannelDuplexHandler { } case .failure(let error): - let finalError: PSQLError - if var psqlError = error as? PSQLError { + let finalError: PostgresError + if var psqlError = error as? PostgresError { psqlError.code = .listenFailed finalError = psqlError } else { - var psqlError = PSQLError(code: .listenFailed) + var psqlError = PostgresError(code: .listenFailed) psqlError.underlying = error finalError = psqlError } @@ -702,8 +702,8 @@ final class PostgresChannelHandler: ChannelDuplexHandler { context: context ) case .failure(let error): - let psqlError: PSQLError - if let error = error as? PSQLError { + let psqlError: PostgresError + if let error = error as? PostgresError { psqlError = error } else { psqlError = .connectionError(underlying: error) @@ -764,7 +764,7 @@ final class PostgresChannelHandler: ChannelDuplexHandler { private func prepareStatementFailed( name: String, - error: PSQLError, + error: PostgresError, context: ChannelHandlerContext ) { let action = self.preparedStatementState.errorHappened( diff --git a/Sources/PostgresNIO/New/PSQLError.swift b/Sources/PostgresNIO/New/PostgresError.swift similarity index 92% rename from Sources/PostgresNIO/New/PSQLError.swift rename to Sources/PostgresNIO/New/PostgresError.swift index 4a9f9216..7baaf6f8 100644 --- a/Sources/PostgresNIO/New/PSQLError.swift +++ b/Sources/PostgresNIO/New/PostgresError.swift @@ -2,7 +2,7 @@ import NIOCore /// An error that is thrown from the PostgresClient. /// Sendability enforced through Copy on Write semantics -public struct PSQLError: Error, @unchecked Sendable { +public struct PostgresError: Error, @unchecked Sendable { public struct Code: Sendable, Hashable, CustomStringConvertible { enum Base: Sendable, Hashable { @@ -115,7 +115,7 @@ public struct PSQLError: Error, @unchecked Sendable { } } - /// The ``PSQLError/Code-swift.struct`` code + /// The ``PostgresError/Code-swift.struct`` code public internal(set) var code: Code { get { self.backing.code } set { @@ -390,66 +390,66 @@ public struct PSQLError: Error, @unchecked Sendable { return new } - static func clientClosedConnection(underlying: Error?) -> PSQLError { - var error = PSQLError(code: .clientClosedConnection) + static func clientClosedConnection(underlying: Error?) -> PostgresError { + var error = PostgresError(code: .clientClosedConnection) error.underlying = underlying return error } - static func serverClosedConnection(underlying: Error?) -> PSQLError { - var error = PSQLError(code: .serverClosedConnection) + static func serverClosedConnection(underlying: Error?) -> PostgresError { + var error = PostgresError(code: .serverClosedConnection) error.underlying = underlying return error } - static let authMechanismRequiresPassword = PSQLError(code: .authMechanismRequiresPassword) + static let authMechanismRequiresPassword = PostgresError(code: .authMechanismRequiresPassword) - static let sslUnsupported = PSQLError(code: .sslUnsupported) + static let sslUnsupported = PostgresError(code: .sslUnsupported) - static let queryCancelled = PSQLError(code: .queryCancelled) + static let queryCancelled = PostgresError(code: .queryCancelled) - static let uncleanShutdown = PSQLError(code: .uncleanShutdown) + static let uncleanShutdown = PostgresError(code: .uncleanShutdown) - static let receivedUnencryptedDataAfterSSLRequest = PSQLError(code: .receivedUnencryptedDataAfterSSLRequest) + static let receivedUnencryptedDataAfterSSLRequest = PostgresError(code: .receivedUnencryptedDataAfterSSLRequest) - static func server(_ response: PostgresBackendMessage.ErrorResponse) -> PSQLError { - var error = PSQLError(code: .server) + static func server(_ response: PostgresBackendMessage.ErrorResponse) -> PostgresError { + var error = PostgresError(code: .server) error.serverInfo = .init(response) return error } - static func sasl(underlying: Error) -> PSQLError { - var error = PSQLError(code: .saslError) + static func sasl(underlying: Error) -> PostgresError { + var error = PostgresError(code: .saslError) error.underlying = underlying return error } - static func failedToAddSSLHandler(underlying: Error) -> PSQLError { - var error = PSQLError(code: .failedToAddSSLHandler) + static func failedToAddSSLHandler(underlying: Error) -> PostgresError { + var error = PostgresError(code: .failedToAddSSLHandler) error.underlying = underlying return error } - static func connectionError(underlying: Error) -> PSQLError { - var error = PSQLError(code: .connectionError) + static func connectionError(underlying: Error) -> PostgresError { + var error = PostgresError(code: .connectionError) error.underlying = underlying return error } - static func unsupportedAuthMechanism(_ authScheme: UnsupportedAuthScheme) -> PSQLError { - var error = PSQLError(code: .unsupportedAuthMechanism) + static func unsupportedAuthMechanism(_ authScheme: UnsupportedAuthScheme) -> PostgresError { + var error = PostgresError(code: .unsupportedAuthMechanism) error.unsupportedAuthScheme = authScheme return error } - static func invalidCommandTag(_ value: String) -> PSQLError { - var error = PSQLError(code: .invalidCommandTag) + static func invalidCommandTag(_ value: String) -> PostgresError { + var error = PostgresError(code: .invalidCommandTag) error.invalidCommandTag = value return error } - static func unlistenError(underlying: Error) -> PSQLError { - var error = PSQLError(code: .unlistenFailed) + static func unlistenError(underlying: Error) -> PostgresError { + var error = PostgresError(code: .unlistenFailed) error.underlying = underlying return error } @@ -465,12 +465,12 @@ public struct PSQLError: Error, @unchecked Sendable { case sasl(mechanisms: [String]) } - static var poolClosed: PSQLError { + static var poolClosed: PostgresError { Self.init(code: .poolClosed) } } -extension PSQLError: CustomStringConvertible { +extension PostgresError: CustomStringConvertible { public var description: String { // This may seem very odd... But we are afraid that users might accidentally send the // unfiltered errors out to end-users. This may leak security relevant information. For this @@ -481,7 +481,7 @@ extension PSQLError: CustomStringConvertible { } } -extension PSQLError: CustomDebugStringConvertible { +extension PostgresError: CustomDebugStringConvertible { public var debugDescription: String { var result = #"PSQLError(code: \#(self.code)"# @@ -490,7 +490,7 @@ extension PSQLError: CustomDebugStringConvertible { result.append( serverInfo.fields .sorted(by: { $0.key.rawValue < $1.key.rawValue }) - .map { "\(PSQLError.ServerInfo.Field($0.0)): \($0.1)" } + .map { "\(PostgresError.ServerInfo.Field($0.0)): \($0.1)" } .joined(separator: ", ") ) result.append("]") diff --git a/Sources/PostgresNIO/Pool/PostgresClient.swift b/Sources/PostgresNIO/Pool/PostgresClient.swift index ad252ee7..7949a8a5 100644 --- a/Sources/PostgresNIO/Pool/PostgresClient.swift +++ b/Sources/PostgresNIO/Pool/PostgresClient.swift @@ -360,14 +360,14 @@ extension PostgresConnection: PooledConnection { extension ConnectionPoolError { func mapToPSQLError(lastConnectError: Error?) -> Error { - var psqlError: PSQLError + var psqlError: PostgresError switch self { case .poolShutdown: - psqlError = PSQLError.poolClosed + psqlError = PostgresError.poolClosed psqlError.underlying = self case .requestCancelled: - psqlError = PSQLError.queryCancelled + psqlError = PostgresError.queryCancelled psqlError.underlying = self default: diff --git a/Sources/PostgresNIO/Postgres+PSQLCompat.swift b/Sources/PostgresNIO/Postgres+PSQLCompat.swift deleted file mode 100644 index e5e9b5d0..00000000 --- a/Sources/PostgresNIO/Postgres+PSQLCompat.swift +++ /dev/null @@ -1,65 +0,0 @@ -import NIOCore - -extension PSQLError { - func toPostgresError() -> Error { - switch self.code.base { - case .queryCancelled: - return self - case .server, .listenFailed: - return self - case .sslUnsupported: - return PostgresError.protocol("Server does not support TLS") - case .failedToAddSSLHandler: - return self.underlying ?? self - case .messageDecodingFailure: - let message = self.underlying != nil ? String(describing: self.underlying!) : "no message" - return PostgresError.protocol("Error decoding message: \(message)") - case .unexpectedBackendMessage: - let message = self.backendMessage != nil ? String(describing: self.backendMessage!) : "no message" - return PostgresError.protocol("Unexpected message: \(message)") - case .unsupportedAuthMechanism: - let message = self.unsupportedAuthScheme != nil ? String(describing: self.unsupportedAuthScheme!) : "no scheme" - return PostgresError.protocol("Unsupported auth scheme: \(message)") - case .authMechanismRequiresPassword: - return PostgresError.protocol("Unable to authenticate without password") - case .receivedUnencryptedDataAfterSSLRequest: - return PostgresError.protocol("Received unencrypted data after SSL request") - case .saslError: - return self.underlying ?? self - case .tooManyParameters, .invalidCommandTag: - return self - case .clientClosedConnection, - .serverClosedConnection: - return PostgresError.connectionClosed - case .connectionError: - return self.underlying ?? self - case .unlistenFailed: - return self.underlying ?? self - case .uncleanShutdown: - return PostgresError.protocol("Unexpected connection close") - case .poolClosed: - return self - } - } -} - -extension PostgresFormat { - init(psqlFormatCode: PostgresFormat) { - switch psqlFormatCode { - case .binary: - self = .binary - case .text: - self = .text - } - } -} - -extension Error { - internal var asAppropriatePostgresError: Error { - if let psqlError = self as? PSQLError { - return psqlError.toPostgresError() - } else { - return self - } - } -} diff --git a/Sources/PostgresNIO/Utilities/PostgresError+Code.swift b/Sources/PostgresNIO/Utilities/PostgresError+Code.swift index 19dfd6f0..eb4a5c6a 100644 --- a/Sources/PostgresNIO/Utilities/PostgresError+Code.swift +++ b/Sources/PostgresNIO/Utilities/PostgresError+Code.swift @@ -1,4 +1,4 @@ -extension PostgresError { +extension PostgresError.ServerInfo { public struct Code: ExpressibleByStringLiteral, Equatable { // Class 00 — Successful Completion public static let successfulCompletion: Code = "00000" @@ -334,11 +334,4 @@ extension PostgresError { self.raw = raw } } - - public var code: Code { - switch self { - case .protocol: return .internalError - case .connectionClosed: return .internalError - } - } } diff --git a/Sources/PostgresNIO/Utilities/PostgresError.swift b/Sources/PostgresNIO/Utilities/PostgresError.swift deleted file mode 100644 index b7eb5e02..00000000 --- a/Sources/PostgresNIO/Utilities/PostgresError.swift +++ /dev/null @@ -1,23 +0,0 @@ -import Foundation - -public enum PostgresError: Error, LocalizedError, CustomStringConvertible { - case `protocol`(String) - case connectionClosed - - /// See `LocalizedError`. - public var errorDescription: String? { - return self.description - } - - /// See `CustomStringConvertible`. - public var description: String { - let description: String - switch self { - case .protocol(let message): - description = "protocol error: \(message)" - case .connectionClosed: - description = "connection closed" - } - return "NIOPostgres error: \(description)" - } -} diff --git a/Tests/IntegrationTests/AsyncTests.swift b/Tests/IntegrationTests/AsyncTests.swift index 91b5656c..d60d576a 100644 --- a/Tests/IntegrationTests/AsyncTests.swift +++ b/Tests/IntegrationTests/AsyncTests.swift @@ -104,7 +104,7 @@ final class AsyncPostgresConnectionTests: XCTestCase { } XCTFail("Expected to get cancelled while reading the query") } catch { - guard let error = error as? PSQLError else { return XCTFail("Unexpected error type") } + guard let error = error as? PostgresError else { return XCTFail("Unexpected error type") } XCTAssertEqual(error.code, .server) XCTAssertEqual(error.serverInfo?[.severity], "ERROR") @@ -134,7 +134,7 @@ final class AsyncPostgresConnectionTests: XCTestCase { try await connection.query("SELECT generte_series(\(start), \(end));", logger: .psqlTest) XCTFail("Expected to throw from the request") } catch { - guard let error = error as? PSQLError else { return XCTFail("Unexpected error type: \(error)") } + guard let error = error as? PostgresError else { return XCTFail("Unexpected error type: \(error)") } XCTAssertEqual(error.code, .server) XCTAssertEqual(error.serverInfo?[.severity], "ERROR") diff --git a/Tests/IntegrationTests/PSQLIntegrationTests.swift b/Tests/IntegrationTests/PSQLIntegrationTests.swift index 4fe8faea..4fe1b492 100644 --- a/Tests/IntegrationTests/PSQLIntegrationTests.swift +++ b/Tests/IntegrationTests/PSQLIntegrationTests.swift @@ -40,7 +40,7 @@ final class IntegrationTests: XCTestCase { var connection: PostgresConnection? XCTAssertThrowsError(connection = try PostgresConnection.connect(on: eventLoopGroup.next(), configuration: config, id: 1, logger: logger).wait()) { - XCTAssertTrue($0 is PSQLError) + XCTAssertTrue($0 is PostgresError) } // In case of a test failure the created connection must be closed. diff --git a/Tests/PostgresNIOTests/New/Connection State Machine/AuthenticationStateMachineTests.swift b/Tests/PostgresNIOTests/New/Connection State Machine/AuthenticationStateMachineTests.swift index df881f90..92a03206 100644 --- a/Tests/PostgresNIOTests/New/Connection State Machine/AuthenticationStateMachineTests.swift +++ b/Tests/PostgresNIOTests/New/Connection State Machine/AuthenticationStateMachineTests.swift @@ -93,7 +93,7 @@ class AuthenticationStateMachineTests: XCTestCase { // MARK: Test unsupported messages func testUnsupportedAuthMechanism() { - let unsupported: [(PostgresBackendMessage.Authentication, PSQLError.UnsupportedAuthScheme)] = [ + let unsupported: [(PostgresBackendMessage.Authentication, PostgresError.UnsupportedAuthScheme)] = [ (.kerberosV5, .kerberosV5), (.scmCredential, .scmCredential), (.gss, .gss), diff --git a/Tests/PostgresNIOTests/New/Connection State Machine/ConnectionStateMachineTests.swift b/Tests/PostgresNIOTests/New/Connection State Machine/ConnectionStateMachineTests.swift index f3d72a5e..0d3bff4f 100644 --- a/Tests/PostgresNIOTests/New/Connection State Machine/ConnectionStateMachineTests.swift +++ b/Tests/PostgresNIOTests/New/Connection State Machine/ConnectionStateMachineTests.swift @@ -30,7 +30,7 @@ class ConnectionStateMachineTests: XCTestCase { func testSSLStartupFailureTooManyBytesRemaining() { var state = ConnectionStateMachine(requireBackendKeyData: true) XCTAssertEqual(state.connected(tls: .require), .sendSSLRequest) - let failError = PSQLError.receivedUnencryptedDataAfterSSLRequest + let failError = PostgresError.receivedUnencryptedDataAfterSSLRequest XCTAssertEqual(state.sslSupportedReceived(unprocessedBytes: 1), .closeConnectionAndCleanup(.init(action: .close, tasks: [], error: failError, closePromise: nil))) } @@ -40,7 +40,7 @@ class ConnectionStateMachineTests: XCTestCase { var state = ConnectionStateMachine(requireBackendKeyData: true) XCTAssertEqual(state.connected(tls: .require), .sendSSLRequest) XCTAssertEqual(state.sslSupportedReceived(unprocessedBytes: 0), .establishSSLConnection) - let failError = PSQLError.failedToAddSSLHandler(underlying: SSLHandlerAddError()) + let failError = PostgresError.failedToAddSSLHandler(underlying: SSLHandlerAddError()) XCTAssertEqual(state.errorHappened(failError), .closeConnectionAndCleanup(.init(action: .close, tasks: [], error: failError, closePromise: nil))) } @@ -49,7 +49,7 @@ class ConnectionStateMachineTests: XCTestCase { XCTAssertEqual(state.connected(tls: .require), .sendSSLRequest) XCTAssertEqual(state.sslUnsupportedReceived(), - .closeConnectionAndCleanup(.init(action: .close, tasks: [], error: PSQLError.sslUnsupported, closePromise: nil))) + .closeConnectionAndCleanup(.init(action: .close, tasks: [], error: PostgresError.sslUnsupported, closePromise: nil))) } func testTLSPreferredStartupSSLUnsupported() { @@ -114,7 +114,7 @@ class ConnectionStateMachineTests: XCTestCase { XCTAssertEqual(state.parameterStatusReceived(.init(parameter: "standard_conforming_strings", value: "on")), .wait) XCTAssertEqual(state.readyForQueryReceived(.idle), - .closeConnectionAndCleanup(.init(action: .close, tasks: [], error: PSQLError.unexpectedBackendMessage(.readyForQuery(.idle)), closePromise: nil))) + .closeConnectionAndCleanup(.init(action: .close, tasks: [], error: PostgresError.unexpectedBackendMessage(.readyForQuery(.idle)), closePromise: nil))) } func testReadyForQueryReceivedWithoutUnneededBackendKeyAfterAuthenticated() { @@ -183,6 +183,6 @@ class ConnectionStateMachineTests: XCTestCase { XCTAssertNil(queryPromise.futureResult._value) // make sure we don't crash - queryPromise.fail(PSQLError.server(.init(fields: fields))) + queryPromise.fail(PostgresError.server(.init(fields: fields))) } } diff --git a/Tests/PostgresNIOTests/New/Connection State Machine/ExtendedQueryStateMachineTests.swift b/Tests/PostgresNIOTests/New/Connection State Machine/ExtendedQueryStateMachineTests.swift index 40e32468..6eee5653 100644 --- a/Tests/PostgresNIOTests/New/Connection State Machine/ExtendedQueryStateMachineTests.swift +++ b/Tests/PostgresNIOTests/New/Connection State Machine/ExtendedQueryStateMachineTests.swift @@ -11,7 +11,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "DELETE FROM table WHERE id=\(1)" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -29,7 +29,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "SELECT version()" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -83,7 +83,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "DELETE FROM table WHERE id=\(1)" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -91,7 +91,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { XCTAssertEqual(state.parseCompleteReceived(), .wait) XCTAssertEqual(state.parameterDescriptionReceived(.init(dataTypes: [.int8])), .wait) - let psqlError = PSQLError.unexpectedBackendMessage(.authentication(.ok)) + let psqlError = PostgresError.unexpectedBackendMessage(.authentication(.ok)) XCTAssertEqual(state.authenticationMessageReceived(.ok), .failQuery(promise, with: psqlError, cleanupContext: .init(action: .close, tasks: [], error: psqlError, closePromise: nil))) } @@ -101,7 +101,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "SELECT version()" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -145,7 +145,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "SELECT version()" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -187,7 +187,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "SELECT version()" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -241,7 +241,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "SELECT version()" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) @@ -262,7 +262,7 @@ class ExtendedQueryStateMachineTests: XCTestCase { let logger = Logger.psqlTest let promise = EmbeddedEventLoop().makePromise(of: PSQLRowStream.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let query: PostgresQuery = "SELECT version()" let queryContext = ExtendedQueryContext(query: query, logger: logger, promise: promise) diff --git a/Tests/PostgresNIOTests/New/Connection State Machine/PrepareStatementStateMachineTests.swift b/Tests/PostgresNIOTests/New/Connection State Machine/PrepareStatementStateMachineTests.swift index 6a08afeb..6c2efa6f 100644 --- a/Tests/PostgresNIOTests/New/Connection State Machine/PrepareStatementStateMachineTests.swift +++ b/Tests/PostgresNIOTests/New/Connection State Machine/PrepareStatementStateMachineTests.swift @@ -7,7 +7,7 @@ class PrepareStatementStateMachineTests: XCTestCase { var state = ConnectionStateMachine.readyForQuery() let promise = EmbeddedEventLoop().makePromise(of: RowDescription?.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let name = "haha" let query = #"SELECT id FROM users WHERE id = $1 "# @@ -33,7 +33,7 @@ class PrepareStatementStateMachineTests: XCTestCase { var state = ConnectionStateMachine.readyForQuery() let promise = EmbeddedEventLoop().makePromise(of: RowDescription?.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let name = "haha" let query = #"DELETE FROM users WHERE id = $1 "# @@ -55,7 +55,7 @@ class PrepareStatementStateMachineTests: XCTestCase { var state = ConnectionStateMachine.readyForQuery() let promise = EmbeddedEventLoop().makePromise(of: RowDescription?.self) - promise.fail(PSQLError.uncleanShutdown) // we don't care about the error at all. + promise.fail(PostgresError.uncleanShutdown) // we don't care about the error at all. let name = "haha" let query = #"DELETE FROM users WHERE id = $1 "# diff --git a/Tests/PostgresNIOTests/New/Connection State Machine/PreparedStatementStateMachineTests.swift b/Tests/PostgresNIOTests/New/Connection State Machine/PreparedStatementStateMachineTests.swift index ab77a57c..fb8c48c3 100644 --- a/Tests/PostgresNIOTests/New/Connection State Machine/PreparedStatementStateMachineTests.swift +++ b/Tests/PostgresNIOTests/New/Connection State Machine/PreparedStatementStateMachineTests.swift @@ -69,7 +69,7 @@ class PreparedStatementStateMachineTests: XCTestCase { } // Simulate an error occurring during preparation - let error = PSQLError(code: .server) + let error = PostgresError(code: .server) let preparationCompleteAction = stateMachine.errorHappened( name: "test", error: error diff --git a/Tests/PostgresNIOTests/New/Extensions/ConnectionAction+TestUtils.swift b/Tests/PostgresNIOTests/New/Extensions/ConnectionAction+TestUtils.swift index febeee37..49f385c3 100644 --- a/Tests/PostgresNIOTests/New/Extensions/ConnectionAction+TestUtils.swift +++ b/Tests/PostgresNIOTests/New/Extensions/ConnectionAction+TestUtils.swift @@ -96,8 +96,8 @@ extension ConnectionStateMachine { } } -extension PSQLError: Equatable { - public static func == (lhs: PSQLError, rhs: PSQLError) -> Bool { +extension PostgresError: Equatable { + public static func == (lhs: PostgresError, rhs: PostgresError) -> Bool { return true } } diff --git a/Tests/PostgresNIOTests/New/PSQLRowStreamTests.swift b/Tests/PostgresNIOTests/New/PSQLRowStreamTests.swift index 9a1e9e41..345aac5c 100644 --- a/Tests/PostgresNIOTests/New/PSQLRowStreamTests.swift +++ b/Tests/PostgresNIOTests/New/PSQLRowStreamTests.swift @@ -23,13 +23,13 @@ final class PSQLRowStreamTests: XCTestCase { func testFailedStream() { let stream = PSQLRowStream( - source: .noRows(.failure(PSQLError.serverClosedConnection(underlying: nil))), + source: .noRows(.failure(PostgresError.serverClosedConnection(underlying: nil))), eventLoop: self.eventLoop, logger: self.logger ) XCTAssertThrowsError(try stream.all().wait()) { - XCTAssertEqual($0 as? PSQLError, .serverClosedConnection(underlying: nil)) + XCTAssertEqual($0 as? PostgresError, .serverClosedConnection(underlying: nil)) } } diff --git a/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift b/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift index f86f979f..0ca78ceb 100644 --- a/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift +++ b/Tests/PostgresNIOTests/New/PostgresChannelHandlerTests.swift @@ -116,7 +116,7 @@ class PostgresChannelHandlerTests: XCTestCase { let handler = PostgresChannelHandler(configuration: config, eventLoop: self.eventLoop) { channel in XCTFail("This callback should never be exectuded") - throw PSQLError.sslUnsupported + throw PostgresError.sslUnsupported } let embedded = EmbeddedChannel(handlers: [ ReverseByteToMessageHandler(PSQLFrontendMessageDecoder()), @@ -256,11 +256,11 @@ class PostgresChannelHandlerTests: XCTestCase { class TestEventHandler: ChannelInboundHandler { typealias InboundIn = Never - var errors = [PSQLError]() + var errors = [PostgresError]() var events = [PSQLEvent]() func errorCaught(context: ChannelHandlerContext, error: Error) { - guard let psqlError = error as? PSQLError else { + guard let psqlError = error as? PostgresError else { return XCTFail("Unexpected error type received: \(error)") } self.errors.append(psqlError) diff --git a/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift b/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift index ee567dc9..90202442 100644 --- a/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift +++ b/Tests/PostgresNIOTests/New/PostgresConnectionTests.swift @@ -34,7 +34,7 @@ class PostgresConnectionTests: XCTestCase { logger.logLevel = .trace XCTAssertThrowsError(try PostgresConnection.connect(on: eventLoopGroup.next(), configuration: config, id: 1, logger: logger).wait()) { - XCTAssertTrue($0 is PSQLError) + XCTAssertTrue($0 is PostgresError) } } @@ -266,7 +266,7 @@ class PostgresConnectionTests: XCTestCase { case .success: XCTFail("Expected queries to fail") case .failure(let failure): - guard let error = failure as? PSQLError else { + guard let error = failure as? PostgresError else { return XCTFail("Unexpected error type: \(failure)") } XCTAssertEqual(error.code, .clientClosedConnection) @@ -290,7 +290,7 @@ class PostgresConnectionTests: XCTestCase { _ = try await response XCTFail("Expected to throw") } catch { - XCTAssertEqual((error as? PSQLError)?.code, .serverClosedConnection) + XCTAssertEqual((error as? PostgresError)?.code, .serverClosedConnection) } // retry on same connection @@ -299,7 +299,7 @@ class PostgresConnectionTests: XCTestCase { _ = try await connection.query("SELECT 1;", logger: self.logger) XCTFail("Expected to throw") } catch { - XCTAssertEqual((error as? PSQLError)?.code, .serverClosedConnection) + XCTAssertEqual((error as? PostgresError)?.code, .serverClosedConnection) } } @@ -549,7 +549,7 @@ class PostgresConnectionTests: XCTestCase { _ = try await connection.execute(preparedStatement, logger: .psqlTest) XCTFail("Was supposed to fail") } catch { - XCTAssert(error is PSQLError) + XCTAssert(error is PostgresError) } } @@ -579,7 +579,7 @@ class PostgresConnectionTests: XCTestCase { _ = try await connection.execute(preparedStatement, logger: .psqlTest) XCTFail("Was supposed to fail") } catch { - XCTAssert(error is PSQLError) + XCTAssert(error is PostgresError) } } } diff --git a/Tests/PostgresNIOTests/New/PostgresErrorTests.swift b/Tests/PostgresNIOTests/New/PostgresErrorTests.swift index 33df5439..c655d053 100644 --- a/Tests/PostgresNIOTests/New/PostgresErrorTests.swift +++ b/Tests/PostgresNIOTests/New/PostgresErrorTests.swift @@ -37,7 +37,7 @@ final class PSQLErrorTests: XCTestCase { } func testPSQLErrorDescription() { - var error1 = PSQLError.server(.init(fields: [.localizedSeverity: "ERROR", .severity: "ERROR", .sqlState: "00000", .message: "Test message", .detail: "More test message", .hint: "It's a test, that's your hint", .position: "1", .schemaName: "testsch", .tableName: "testtab", .columnName: "testcol", .dataTypeName: "testtyp", .constraintName: "testcon", .file: #fileID, .line: "0", .routine: #function])) + var error1 = PostgresError.server(.init(fields: [.localizedSeverity: "ERROR", .severity: "ERROR", .sqlState: "00000", .message: "Test message", .detail: "More test message", .hint: "It's a test, that's your hint", .position: "1", .schemaName: "testsch", .tableName: "testtab", .columnName: "testcol", .dataTypeName: "testtyp", .constraintName: "testcon", .file: #fileID, .line: "0", .routine: #function])) var testBinds = PostgresBindings(capacity: 1) testBinds.append(1, context: .default) error1.query = .init(unsafeSQL: "TEST QUERY", binds: testBinds) diff --git a/Tests/PostgresNIOTests/New/PostgresRowSequenceTests.swift b/Tests/PostgresNIOTests/New/PostgresRowSequenceTests.swift index 816daf04..ef55d978 100644 --- a/Tests/PostgresNIOTests/New/PostgresRowSequenceTests.swift +++ b/Tests/PostgresNIOTests/New/PostgresRowSequenceTests.swift @@ -183,7 +183,7 @@ final class PostgresRowSequenceTests: XCTestCase { logger: self.logger ) - stream.receive(completion: .failure(PSQLError.serverClosedConnection(underlying: nil))) + stream.receive(completion: .failure(PostgresError.serverClosedConnection(underlying: nil))) let rowSequence = stream.asyncSequence() @@ -194,7 +194,7 @@ final class PostgresRowSequenceTests: XCTestCase { } XCTFail("Expected that an error was thrown before.") } catch { - XCTAssertEqual(error as? PSQLError, .serverClosedConnection(underlying: nil)) + XCTAssertEqual(error as? PostgresError, .serverClosedConnection(underlying: nil)) } } @@ -255,14 +255,14 @@ final class PostgresRowSequenceTests: XCTestCase { XCTAssertEqual(try row1?.decode(Int.self), 0) DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { - stream.receive(completion: .failure(PSQLError.serverClosedConnection(underlying: nil))) + stream.receive(completion: .failure(PostgresError.serverClosedConnection(underlying: nil))) } do { _ = try await rowIterator.next() XCTFail("Expected that an error was thrown before.") } catch { - XCTAssertEqual(error as? PSQLError, .serverClosedConnection(underlying: nil)) + XCTAssertEqual(error as? PostgresError, .serverClosedConnection(underlying: nil)) } }