Skip to content

WIP: Implement COPY … FROM STDIN #566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft

Conversation

ahoppen
Copy link

@ahoppen ahoppen commented Jun 24, 2025

This is still WIP. To do items include:

  • Test the various error cases, I have mostly focused on the success case so far
  • Test the backpressure support
  • Change the public API to accept the table + columns to copy into as well as options so that we can build the COPY query instead of letting the user write it
  • Add an API that allows binary transfer of data
  • Check if we should buffer data sent through the PostgresCopyFromWriter to reduce the number of CopyData messages we need to send (and thus the protocol overhead). Alternatively, we can leave that kind of optimization to the client.
  • Generally take performance measurements

Fixes #290

This is still WIP. To do items include:
- [ ] Test the various error cases, I have mostly focused on the success case so far
- [ ] Test the backpressure support
- [ ] Change the public API to accept the table + columns to copy into as well as options so that we can build the `COPY` query instead of letting the user write it
- [ ] Add an API that allows binary transfer of data
/// A handle to send
public struct PostgresCopyFromWriter: Sendable {
private let channelHandler: NIOLoopBound<PostgresChannelHandler>
private let context: NIOLoopBound<ChannelHandlerContext>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the handlerContext: ChannelHandlerContext? with ! in PostgresChannelHandler instead.

Comment on lines +701 to +706
func executeImmediatelyOrSchedule(_ task: @Sendable @escaping () -> Void) {
if inEventLoop {
return task()
}
return execute(task)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to allocate even in the fast path. we don't like that.

Comment on lines +715 to +717
struct NotWritableError: Error, CustomStringConvertible {
var description = "No data must be written to `PostgresCopyFromWriter` after it has sent a CopyDone or CopyFail message, ie. after the closure producing the copy data has finished"
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't used anywhere.

// TODO: Write doc comment
public func copyFrom(
_ query: PostgresQuery,
writeData: @escaping @Sendable (PostgresCopyFromWriter) async throws -> Void,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closure should be last argument.

}
self.avoidingStateMachineCoW { state in
state = .copyingData(.readyToSend)
continuation.resume()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

side effect triggered in state machine. return the continuation out and succeed it in the PostgresChannelHandler.

@@ -88,7 +88,23 @@ struct ConnectionStateMachine {
case sendParseDescribeBindExecuteSync(PostgresQuery)
case sendBindExecuteSync(PSQLExecuteStatement)
case failQuery(EventLoopPromise<PSQLRowStream>, with: PSQLError, cleanupContext: CleanUpContext?)
/// Fail a query's execution by throwing an error on the given continuation.
case failQueryContinuation(any AnyErrorContinuation, with: PSQLError, cleanupContext: CleanUpContext?)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

existential, where Existential isn't necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Copy In Mode
2 participants