Skip to content
2 changes: 2 additions & 0 deletions Sources/PostgresNIO/New/PostgresRow-multi-decode.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// NOTE: THIS FILE IS AUTO-GENERATED BY dev/generate-postgresrow-multi-decode.sh

#if compiler(<5.9)
extension PostgresRow {
@inlinable
@_alwaysEmitIntoClient
Expand Down Expand Up @@ -1171,3 +1172,4 @@ extension PostgresRow {
try self.decode((T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14).self, context: .default, file: file, line: line)
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// NOTE: THIS FILE IS AUTO-GENERATED BY dev/generate-postgresrowsequence-multi-decode.sh

#if canImport(_Concurrency)
#if compiler(<5.9)
extension AsyncSequence where Element == PostgresRow {
@inlinable
@_alwaysEmitIntoClient
Expand Down
174 changes: 174 additions & 0 deletions Sources/PostgresNIO/New/VariadicGenerics.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#if compiler(>=5.9)
extension PostgresRow {
// --- snip TODO: Remove once bug is fixed, that disallows tuples of one
@inlinable
public func decode<Column: PostgresDecodable>(
_: Column.Type,
file: String = #fileID,
line: Int = #line
) throws -> (Column) {
try self.decode(Column.self, context: .default, file: file, line: line)
}

@inlinable
public func decode<Column: PostgresDecodable>(
_: Column.Type,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String = #fileID,
line: Int = #line
) throws -> (Column) {
precondition(self.columns.count >= 1)
let columnIndex = 0
var cellIterator = self.data.makeIterator()
var cellData = cellIterator.next().unsafelyUnwrapped
var columnIterator = self.columns.makeIterator()
let column = columnIterator.next().unsafelyUnwrapped
let swiftTargetType: Any.Type = Column.self

do {
let r0 = try Column._decodeRaw(from: &cellData, type: column.dataType, format: column.format, context: context)

return (r0)
} catch let code as PostgresDecodingError.Code {
throw PostgresDecodingError(
code: code,
columnName: column.name,
columnIndex: columnIndex,
targetType: swiftTargetType,
postgresType: column.dataType,
postgresFormat: column.format,
postgresData: cellData,
file: file,
line: line
)
}
}
// --- snap TODO: Remove once bug is fixed, that disallows tuples of one

@inlinable
public func decode<each Column: PostgresDecodable>(
_ columnType: (repeat each Column).Type,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String = #fileID,
line: Int = #line
) throws -> (repeat each Column) {
let packCount = ComputeParameterPackLength.count(ofPack: repeat (each Column).self)
precondition(self.columns.count >= packCount)

var columnIndex = 0
var cellIterator = self.data.makeIterator()
var columnIterator = self.columns.makeIterator()

return (
repeat try Self.decodeNextColumn(
(each Column).self,
cellIterator: &cellIterator,
columnIterator: &columnIterator,
columnIndex: &columnIndex,
context: context,
file: file,
line: line
)
)
}

@inlinable
static func decodeNextColumn<Column: PostgresDecodable>(
_ columnType: Column.Type,
cellIterator: inout IndexingIterator<DataRow>,
columnIterator: inout IndexingIterator<[RowDescription.Column]>,
columnIndex: inout Int,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String,
line: Int
) throws -> Column {
defer { columnIndex += 1 }

let column = columnIterator.next().unsafelyUnwrapped
var cellData = cellIterator.next().unsafelyUnwrapped
do {
return try Column._decodeRaw(from: &cellData, type: column.dataType, format: column.format, context: context)
} catch let code as PostgresDecodingError.Code {
throw PostgresDecodingError(
code: code,
columnName: column.name,
columnIndex: columnIndex,
targetType: Column.self,
postgresType: column.dataType,
postgresFormat: column.format,
postgresData: cellData,
file: file,
line: line
)
}
}

@inlinable
public func decode<each Column: PostgresDecodable>(
_ columnType: (repeat each Column).Type,
file: String = #fileID,
line: Int = #line
) throws -> (repeat each Column) {
try self.decode(columnType, context: .default, file: file, line: line)
}
}

extension AsyncSequence where Element == PostgresRow {
// --- snip TODO: Remove once bug is fixed, that disallows tuples of one
@inlinable
public func decode<Column: PostgresDecodable>(
_: Column.Type,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String = #fileID,
line: Int = #line
) -> AsyncThrowingMapSequence<Self, (Column)> {
self.map { row in
try row.decode(Column.self, context: context, file: file, line: line)
}
}

@inlinable
public func decode<Column: PostgresDecodable>(
_: Column.Type,
file: String = #fileID,
line: Int = #line
) -> AsyncThrowingMapSequence<Self, (Column)> {
self.decode(Column.self, context: .default, file: file, line: line)
}
// --- snap TODO: Remove once bug is fixed, that disallows tuples of one

public func decode<each Column: PostgresDecodable>(
_ columnType: (repeat each Column).Type,
context: PostgresDecodingContext<some PostgresJSONDecoder>,
file: String = #fileID,
line: Int = #line
) -> AsyncThrowingMapSequence<Self, (repeat each Column)> {
self.map { row in
try row.decode(columnType, context: context, file: file, line: line)
}
}

public func decode<each Column: PostgresDecodable>(
_ columnType: (repeat each Column).Type,
file: String = #fileID,
line: Int = #line
) -> AsyncThrowingMapSequence<Self, (repeat each Column)> {
self.decode(columnType, context: .default, file: file, line: line)
}
}

@usableFromInline
enum ComputeParameterPackLength {
@usableFromInline
enum BoolConverter<T> {
@usableFromInline
typealias Bool = Swift.Bool
}

@inlinable
static func count<each T>(ofPack t: repeat each T) -> Int {
MemoryLayout<(repeat BoolConverter<each T>.Bool)>.size / MemoryLayout<Bool>.stride
}
}
#endif // compiler(>=5.9)

7 changes: 4 additions & 3 deletions Tests/IntegrationTests/AsyncTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import NIOPosix
import NIOCore

final class AsyncPostgresConnectionTests: XCTestCase {

func test1kRoundTrips() async throws {
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
Expand Down Expand Up @@ -37,7 +36,8 @@ final class AsyncPostgresConnectionTests: XCTestCase {
try await withTestConnection(on: eventLoop) { connection in
let rows = try await connection.query("SELECT generate_series(\(start), \(end));", logger: .psqlTest)
var counter = 0
for try await element in rows.decode(Int.self, context: .default) {
for try await row in rows {
let element = try row.decode(Int.self)
XCTAssertEqual(element, counter + 1)
counter += 1
}
Expand Down Expand Up @@ -259,7 +259,8 @@ final class AsyncPostgresConnectionTests: XCTestCase {
try await withTestConnection(on: eventLoop) { connection in
let rows = try await connection.query("SELECT generate_series(\(start), \(end));", logger: .psqlTest)
var counter = 1
for try await element in rows.decode(Int.self, context: .default) {
for try await row in rows {
let element = try row.decode(Int.self, context: .default)
XCTAssertEqual(element, counter)
counter += 1
}
Expand Down
8 changes: 4 additions & 4 deletions Tests/IntegrationTests/PostgresNIOTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1246,10 +1246,10 @@ final class PostgresNIOTests: XCTestCase {
return EventLoopFuture.whenAllSucceed([a, b, c], on: self.eventLoop)
}).wait())
XCTAssertEqual(queries?.count, 3)
var resutIterator = queries?.makeIterator()
XCTAssertEqual(try resutIterator?.next()?.first?.decode(String.self, context: .default), "a")
XCTAssertEqual(try resutIterator?.next()?.first?.decode(String.self, context: .default), "b")
XCTAssertEqual(try resutIterator?.next()?.first?.decode(String.self, context: .default), "c")
var resultIterator = queries?.makeIterator()
XCTAssertEqual(try resultIterator?.next()?.first?.decode(String.self, context: .default), "a")
XCTAssertEqual(try resultIterator?.next()?.first?.decode(String.self, context: .default), "b")
XCTAssertEqual(try resultIterator?.next()?.first?.decode(String.self, context: .default), "c")
}

// https://github.com/vapor/postgres-nio/issues/122
Expand Down
12 changes: 6 additions & 6 deletions Tests/PostgresNIOTests/New/PostgresRowSequenceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ final class PostgresRowSequenceTests: XCTestCase {

var counter = 0
for try await row in rowSequence {
XCTAssertEqual(try row.decode(Int.self, context: .default), counter)
XCTAssertEqual(try row.decode(Int.self), counter)
counter += 1

if counter == 64 {
Expand Down Expand Up @@ -135,7 +135,7 @@ final class PostgresRowSequenceTests: XCTestCase {

var counter = 0
for try await row in rowSequence {
XCTAssertEqual(try row.decode(Int.self, context: .default), counter)
XCTAssertEqual(try row.decode(Int.self), counter)
counter += 1
}

Expand Down Expand Up @@ -163,7 +163,7 @@ final class PostgresRowSequenceTests: XCTestCase {

var counter = 0
for try await row in rowSequence {
XCTAssertEqual(try row.decode(Int.self, context: .default), counter)
XCTAssertEqual(try row.decode(Int.self), counter)
counter += 1
}

Expand Down Expand Up @@ -220,7 +220,7 @@ final class PostgresRowSequenceTests: XCTestCase {
}

let row1 = try await rowIterator.next()
XCTAssertEqual(try row1?.decode(Int.self, context: .default), 0)
XCTAssertEqual(try row1?.decode(Int.self), 0)

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
stream.receive(completion: .success("SELECT 1"))
Expand Down Expand Up @@ -252,7 +252,7 @@ final class PostgresRowSequenceTests: XCTestCase {
}

let row1 = try await rowIterator.next()
XCTAssertEqual(try row1?.decode(Int.self, context: .default), 0)
XCTAssertEqual(try row1?.decode(Int.self), 0)

DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
stream.receive(completion: .failure(PSQLError.serverClosedConnection(underlying: nil)))
Expand Down Expand Up @@ -415,7 +415,7 @@ final class PostgresRowSequenceTests: XCTestCase {
var counter = 1
for _ in 0..<(2 * messagePerChunk - 1) {
let row = try await rowIterator.next()
XCTAssertEqual(try row?.decode(Int.self, context: .default), counter)
XCTAssertEqual(try row?.decode(Int.self), counter)
counter += 1
}

Expand Down