Skip to content

Commit 2e98065

Browse files
committed
Expose query metadata in PostgresRowSequence
1 parent 9f84290 commit 2e98065

File tree

3 files changed

+47
-16
lines changed

3 files changed

+47
-16
lines changed

Sources/PostgresNIO/New/PSQLRowStream.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ final class PSQLRowStream: @unchecked Sendable {
4444
}
4545

4646
internal let rowDescription: [RowDescription.Column]
47-
private let lookupTable: [String: Int]
47+
internal let lookupTable: [String: Int]
4848
private var downstreamState: DownstreamState
4949

5050
init(
@@ -114,7 +114,7 @@ final class PSQLRowStream: @unchecked Sendable {
114114
self.downstreamState = .consumed(.failure(error))
115115
}
116116

117-
return PostgresRowSequence(producer.sequence, lookupTable: self.lookupTable, columns: self.rowDescription)
117+
return PostgresRowSequence(producer.sequence, stream: self)
118118
}
119119

120120
func demand() {

Sources/PostgresNIO/New/PostgresRowSequence.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ public struct PostgresRowSequence: AsyncSequence, Sendable {
99

1010
typealias BackingSequence = NIOThrowingAsyncSequenceProducer<DataRow, Error, AdaptiveRowBuffer, PSQLRowStream>
1111

12-
let backing: BackingSequence
13-
let lookupTable: [String: Int]
14-
let columns: [RowDescription.Column]
12+
private let backing: BackingSequence
13+
private let stream: PSQLRowStream
14+
var lookupTable: [String: Int] {
15+
self.stream.lookupTable
16+
}
17+
var columns: [RowDescription.Column] {
18+
self.stream.rowDescription
19+
}
1520

16-
init(_ backing: BackingSequence, lookupTable: [String: Int], columns: [RowDescription.Column]) {
21+
init(_ backing: BackingSequence, stream: PSQLRowStream) {
1722
self.backing = backing
18-
self.lookupTable = lookupTable
19-
self.columns = columns
23+
self.stream = stream
2024
}
2125

2226
public func makeAsyncIterator() -> AsyncIterator {
@@ -67,6 +71,12 @@ extension PostgresRowSequence {
6771
}
6872
return result
6973
}
74+
75+
public func collectWithMetadata() async throws -> (metadata: PostgresQueryMetadata?, rows: [PostgresRow]) {
76+
let rows = try await self.collect()
77+
let metadata = PostgresQueryMetadata(string: self.stream.commandTag)
78+
return (metadata, rows)
79+
}
7080
}
7181

7282
struct AdaptiveRowBuffer: NIOAsyncSequenceProducerBackPressureStrategy {

Tests/IntegrationTests/AsyncTests.swift

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,31 @@ final class AsyncPostgresConnectionTests: XCTestCase {
4646
}
4747
}
4848

49+
func testSelect10kRowsAndCollect() async throws {
50+
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
51+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
52+
let eventLoop = eventLoopGroup.next()
53+
54+
let start = 1
55+
let end = 10000
56+
57+
try await withTestConnection(on: eventLoop) { connection in
58+
let rows = try await connection.query("SELECT generate_series(\(start), \(end));", logger: .psqlTest)
59+
let (metadata, elements) = try await rows.collectWithMetadata()
60+
var counter = 0
61+
for row in elements {
62+
let element = try row.decode(Int.self)
63+
XCTAssertEqual(element, counter + 1)
64+
counter += 1
65+
}
66+
XCTAssertEqual(metadata?.command, "SELECT")
67+
XCTAssertEqual(metadata?.oid, nil)
68+
XCTAssertEqual(metadata?.rows, 10000)
69+
70+
XCTAssertEqual(counter, end)
71+
}
72+
}
73+
4974
func testSelectActiveConnection() async throws {
5075
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
5176
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
@@ -207,7 +232,7 @@ final class AsyncPostgresConnectionTests: XCTestCase {
207232

208233
try await withTestConnection(on: eventLoop) { connection in
209234
// Max binds limit is UInt16.max which is 65535 which is 3 * 5 * 17 * 257
210-
// Max columns limit is 1664, so we will only make 5 * 257 columns which is less
235+
// Max columns limit appears to be ~1600, so we will only make 5 * 257 columns which is less
211236
// Then we will insert 3 * 17 rows
212237
// In the insertion, there will be a total of 3 * 17 * 5 * 257 == UInt16.max bindings
213238
// If the test is successful, it means Postgres supports UInt16.max bindings
@@ -241,13 +266,9 @@ final class AsyncPostgresConnectionTests: XCTestCase {
241266
unsafeSQL: "INSERT INTO table1 VALUES \(insertionValues)",
242267
binds: binds
243268
)
244-
try await connection.query(insertionQuery, logger: .psqlTest)
245-
246-
let countQuery = PostgresQuery(unsafeSQL: "SELECT COUNT(*) FROM table1")
247-
let countRows = try await connection.query(countQuery, logger: .psqlTest)
248-
var countIterator = countRows.makeAsyncIterator()
249-
let insertedRowsCount = try await countIterator.next()?.decode(Int.self, context: .default)
250-
XCTAssertEqual(rowsCount, insertedRowsCount)
269+
let result = try await connection.query(insertionQuery, logger: .psqlTest)
270+
let metadata = try await result.collectWithMetadata().metadata
271+
XCTAssertEqual(metadata?.rows, rowsCount)
251272

252273
let dropQuery = PostgresQuery(unsafeSQL: "DROP TABLE table1")
253274
try await connection.query(dropQuery, logger: .psqlTest)

0 commit comments

Comments
 (0)