@@ -3,6 +3,7 @@ import Logging
33
44struct QueryResult {
55 enum Value : Equatable {
6+ case emptyResponse
67 case noRows( String )
78 case rowDescription( [ RowDescription . Column ] )
89 }
@@ -19,6 +20,7 @@ final class PSQLRowStream: @unchecked Sendable {
1920 enum Source {
2021 case stream( [ RowDescription . Column ] , PSQLRowsDataSource )
2122 case noRows( Result < String , Error > )
23+ case emptyResponse
2224 }
2325
2426 let eventLoop : EventLoop
@@ -27,14 +29,20 @@ final class PSQLRowStream: @unchecked Sendable {
2729 private enum BufferState {
2830 case streaming( buffer: CircularBuffer < DataRow > , dataSource: PSQLRowsDataSource )
2931 case finished( buffer: CircularBuffer < DataRow > , commandTag: String )
32+ case empty
3033 case failure( Error )
3134 }
32-
35+
36+ private enum Consumed {
37+ case tag( String )
38+ case emptyResponse
39+ }
40+
3341 private enum DownstreamState {
3442 case waitingForConsumer( BufferState )
3543 case iteratingRows( onRow: ( PostgresRow ) throws -> ( ) , EventLoopPromise < Void > , PSQLRowsDataSource )
3644 case waitingForAll( [ PostgresRow ] , EventLoopPromise < [ PostgresRow ] > , PSQLRowsDataSource )
37- case consumed( Result < String , Error > )
45+ case consumed( Result < Consumed , Error > )
3846 case asyncSequence( AsyncSequenceSource , PSQLRowsDataSource , onFinish: @Sendable ( ) -> ( ) )
3947 }
4048
@@ -58,6 +66,9 @@ final class PSQLRowStream: @unchecked Sendable {
5866 case . noRows( . failure( let error) ) :
5967 self . rowDescription = [ ]
6068 bufferState = . failure( error)
69+ case . emptyResponse:
70+ self . rowDescription = [ ]
71+ bufferState = . empty
6172 }
6273
6374 self . downstreamState = . waitingForConsumer( bufferState)
@@ -98,11 +109,16 @@ final class PSQLRowStream: @unchecked Sendable {
98109 self . downstreamState = . asyncSequence( source, dataSource, onFinish: onFinish)
99110 self . executeActionBasedOnYieldResult ( yieldResult, source: dataSource)
100111
112+ case . empty:
113+ source. finish ( )
114+ onFinish ( )
115+ self . downstreamState = . consumed( . success( . emptyResponse) )
116+
101117 case . finished( let buffer, let commandTag) :
102118 _ = source. yield ( contentsOf: buffer)
103119 source. finish ( )
104120 onFinish ( )
105- self . downstreamState = . consumed( . success( commandTag) )
121+ self . downstreamState = . consumed( . success( . tag ( commandTag) ) )
106122
107123 case . failure( let error) :
108124 source. finish ( error)
@@ -195,12 +211,16 @@ final class PSQLRowStream: @unchecked Sendable {
195211 PostgresRow ( data: $0, lookupTable: self . lookupTable, columns: self . rowDescription)
196212 }
197213
198- self . downstreamState = . consumed( . success( commandTag) )
214+ self . downstreamState = . consumed( . success( . tag ( commandTag) ) )
199215 return self . eventLoop. makeSucceededFuture ( rows)
200216
201217 case . failure( let error) :
202218 self . downstreamState = . consumed( . failure( error) )
203219 return self . eventLoop. makeFailedFuture ( error)
220+
221+ case . empty:
222+ self . downstreamState = . consumed( . success( . emptyResponse) )
223+ return self . eventLoop. makeSucceededFuture ( [ ] )
204224 }
205225 }
206226
@@ -247,7 +267,11 @@ final class PSQLRowStream: @unchecked Sendable {
247267 }
248268
249269 return promise. futureResult
250-
270+
271+ case . empty:
272+ self . downstreamState = . consumed( . success( . emptyResponse) )
273+ return self . eventLoop. makeSucceededVoidFuture ( )
274+
251275 case . finished( let buffer, let commandTag) :
252276 do {
253277 for data in buffer {
@@ -259,7 +283,7 @@ final class PSQLRowStream: @unchecked Sendable {
259283 try onRow ( row)
260284 }
261285
262- self . downstreamState = . consumed( . success( commandTag) )
286+ self . downstreamState = . consumed( . success( . tag ( commandTag) ) )
263287 return self . eventLoop. makeSucceededVoidFuture ( )
264288 } catch {
265289 self . downstreamState = . consumed( . failure( error) )
@@ -290,9 +314,9 @@ final class PSQLRowStream: @unchecked Sendable {
290314 buffer. append ( contentsOf: newRows)
291315 self . downstreamState = . waitingForConsumer( . streaming( buffer: buffer, dataSource: dataSource) )
292316
293- case . waitingForConsumer( . finished) , . waitingForConsumer( . failure) :
317+ case . waitingForConsumer( . finished) , . waitingForConsumer( . failure) , . waitingForConsumer ( . empty ) :
294318 preconditionFailure ( " How can new rows be received, if an end was already signalled? " )
295-
319+
296320 case . iteratingRows( let onRow, let promise, let dataSource) :
297321 do {
298322 for data in newRows {
@@ -353,20 +377,23 @@ final class PSQLRowStream: @unchecked Sendable {
353377 preconditionFailure ( " How can we get another end, if an end was already signalled? " )
354378
355379 case . iteratingRows( _, let promise, _) :
356- self . downstreamState = . consumed( . success( commandTag) )
380+ self . downstreamState = . consumed( . success( . tag ( commandTag) ) )
357381 promise. succeed ( ( ) )
358382
359383 case . waitingForAll( let rows, let promise, _) :
360- self . downstreamState = . consumed( . success( commandTag) )
384+ self . downstreamState = . consumed( . success( . tag ( commandTag) ) )
361385 promise. succeed ( rows)
362386
363387 case . asyncSequence( let source, _, let onFinish) :
364- self . downstreamState = . consumed( . success( commandTag) )
388+ self . downstreamState = . consumed( . success( . tag ( commandTag) ) )
365389 source. finish ( )
366390 onFinish ( )
367391
368- case . consumed:
392+ case . consumed( . success ( . tag ) ) , . consumed ( . failure ) :
369393 break
394+
395+ case . consumed( . success( . emptyResponse) ) , . waitingForConsumer( . empty) :
396+ preconditionFailure ( " How can we get an end for empty query response? " )
370397 }
371398 }
372399
@@ -375,7 +402,7 @@ final class PSQLRowStream: @unchecked Sendable {
375402 case . waitingForConsumer( . streaming) :
376403 self . downstreamState = . waitingForConsumer( . failure( error) )
377404
378- case . waitingForConsumer( . finished) , . waitingForConsumer( . failure) :
405+ case . waitingForConsumer( . finished) , . waitingForConsumer( . failure) , . waitingForConsumer ( . empty ) :
379406 preconditionFailure ( " How can we get another end, if an end was already signalled? " )
380407
381408 case . iteratingRows( _, let promise, _) :
@@ -391,8 +418,11 @@ final class PSQLRowStream: @unchecked Sendable {
391418 consumer. finish ( error)
392419 onFinish ( )
393420
394- case . consumed:
421+ case . consumed( . success ( . tag ) ) , . consumed ( . failure ) :
395422 break
423+
424+ case . consumed( . success( . emptyResponse) ) :
425+ preconditionFailure ( " How can we get an error for empty query response? " )
396426 }
397427 }
398428
@@ -413,10 +443,15 @@ final class PSQLRowStream: @unchecked Sendable {
413443 }
414444
415445 var commandTag : String {
416- guard case . consumed( . success( let commandTag ) ) = self . downstreamState else {
446+ guard case . consumed( . success( let consumed ) ) = self . downstreamState else {
417447 preconditionFailure ( " commandTag may only be called if all rows have been consumed " )
418448 }
419- return commandTag
449+ switch consumed {
450+ case . tag( let tag) :
451+ return tag
452+ case . emptyResponse:
453+ return " "
454+ }
420455 }
421456}
422457
0 commit comments