@@ -23,6 +23,7 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
23
23
private let configureSSLCallback : ( ( Channel ) throws -> Void ) ?
24
24
25
25
private var listenState : ListenStateMachine
26
+ private var preparedStatementState : PreparedStatementStateMachine
26
27
27
28
init (
28
29
configuration: PostgresConnection . InternalConfiguration ,
@@ -33,6 +34,7 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
33
34
self . state = ConnectionStateMachine ( requireBackendKeyData: configuration. options. requireBackendKeyData)
34
35
self . eventLoop = eventLoop
35
36
self . listenState = ListenStateMachine ( )
37
+ self . preparedStatementState = PreparedStatementStateMachine ( )
36
38
self . configuration = configuration
37
39
self . configureSSLCallback = configureSSLCallback
38
40
self . logger = logger
@@ -51,6 +53,7 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
51
53
self . state = state
52
54
self . eventLoop = eventLoop
53
55
self . listenState = ListenStateMachine ( )
56
+ self . preparedStatementState = PreparedStatementStateMachine ( )
54
57
self . configuration = configuration
55
58
self . configureSSLCallback = configureSSLCallback
56
59
self . logger = logger
@@ -235,6 +238,46 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
235
238
listener. failed ( CancellationError ( ) )
236
239
return
237
240
}
241
+ case . executePreparedStatement( let preparedStatement) :
242
+ switch self . preparedStatementState. lookup (
243
+ name: preparedStatement. name,
244
+ context: preparedStatement
245
+ ) {
246
+ case . none:
247
+ return
248
+ case . prepareStatement:
249
+ let promise = self . eventLoop. makePromise ( of: RowDescription ? . self)
250
+ promise. futureResult. whenSuccess { rowDescription in
251
+ self . prepareStatementComplete (
252
+ name: preparedStatement. name,
253
+ rowDescription: rowDescription,
254
+ context: context
255
+ )
256
+ }
257
+ psqlTask = . preparedStatement( . init(
258
+ name: preparedStatement. name,
259
+ query: preparedStatement. sql,
260
+ logger: preparedStatement. logger,
261
+ promise: promise
262
+ ) )
263
+ case . waitForAlreadyInFlightPreparation:
264
+ // The state machine already keeps track of this
265
+ // and will execute the statement as soon as it's prepared
266
+ return
267
+ case . executePendingStatements( let pendingStatements, let rowDescription) :
268
+ for statement in pendingStatements {
269
+ let action = self . state. enqueue ( task: . extendedQuery( . init(
270
+ executeStatement: . init(
271
+ name: statement. name,
272
+ binds: statement. bindings,
273
+ rowDescription: rowDescription) ,
274
+ logger: statement. logger,
275
+ promise: statement. promise
276
+ ) ) )
277
+ self . run ( action, with: context)
278
+ }
279
+ return
280
+ }
238
281
}
239
282
240
283
let action = self . state. enqueue ( task: psqlTask)
@@ -666,6 +709,32 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
666
709
}
667
710
}
668
711
712
+ private func prepareStatementComplete(
713
+ name: String ,
714
+ rowDescription: RowDescription ? ,
715
+ context: ChannelHandlerContext
716
+ ) {
717
+ let action = self . preparedStatementState. preparationComplete (
718
+ name: name,
719
+ rowDescription: rowDescription
720
+ )
721
+ guard case . executePendingStatements( let statements, let rowDescription) = action else {
722
+ preconditionFailure ( " Expected to have pending statements to execute " )
723
+ }
724
+ for preparedStatement in statements {
725
+ let action = self . state. enqueue ( task: . extendedQuery( . init(
726
+ executeStatement: . init(
727
+ name: preparedStatement. name,
728
+ binds: preparedStatement. bindings,
729
+ rowDescription: rowDescription
730
+ ) ,
731
+ logger: preparedStatement. logger,
732
+ promise: preparedStatement. promise
733
+ ) )
734
+ )
735
+ self . run ( action, with: context)
736
+ }
737
+ }
669
738
}
670
739
671
740
extension PostgresChannelHandler : PSQLRowsDataSource {
0 commit comments