MCPcopy Create free account
hub / github.com/PostHog/duckgres / CopyFromStdin

Method CopyFromStdin

server/flightclient/copyfromstdin.go:43–117  ·  view source on GitHub ↗

1 MiB CopyFromStdin streams CSV bytes from r to a remote worker, then runs copySQL on the worker against a worker-local spool file. copySQL must contain CopyFromStdinPathPlaceholder where the file path should appear. Returns the number of rows the worker reports COPY-affected. Wire layout: frame

(ctx context.Context, copySQL string, r io.Reader)

Source from the content-addressed store, hash-verified

41// from the control plane to the worker during a COPY upload. Large
42// enough to amortise per-frame overhead, small enough to keep memory
43// bounded if the worker is slow to drain.
44const CopyFromStdinChunkSize = 1 << 20 // 1 MiB
45
46// CopyFromStdin streams COPY input bytes from r to a remote worker, then runs
47// request.SQLTemplate against a worker-local spool file. The SQL template must
48// contain CopyFromStdinPathPlaceholder where the file path should appear. It
49// returns the number of rows the worker reports COPY-affected.
50//
51// Wire layout:
52//
53// frame 0: FlightDescriptor{Type=PATH, Path=[CopyFromStdinDescriptorPath, optional version], Cmd=SQL or structured request}
54// frame 1..N: DataBody=<chunk of COPY input bytes>
55// (client closes send)
56// server: PutResult{AppMetadata=DoPutUpdateResult{RecordCount=N}}
57func (e *FlightExecutor) CopyFromStdin(ctx context.Context, request sqlcore.CopyFromStdinRequest, r io.Reader) (int64, error) {
58 if e.dead.Load() {
59 return 0, ErrWorkerDead
60 }
61
62 reqCtx, cancel := e.mergedContext(ctx)
63 defer cancel()
64 reqCtx = e.withSession(reqCtx)
65
66 stream, err := e.client.Client.DoPut(reqCtx)
67 if err != nil {
68 return 0, fmt.Errorf("flight doput: %w", err)
69 }
70
71 // Frame 0: descriptor + COPY SQL.
72 path := []string{CopyFromStdinDescriptorPath}
73 cmd := []byte(request.SQLTemplate)
74 if len(request.PostgresBinaryDatabaseTypeNames) > 0 {
75 path = append(path, CopyFromStdinPostgresBinaryPathVersion)
76 cmd, err = json.Marshal(request)
77 if err != nil {
78 return 0, fmt.Errorf("marshal binary COPY request: %w", err)
79 }
80 }
81 desc := &flight.FlightDescriptor{
82 Type: flight.DescriptorPATH,
83 Path: path,
84 Cmd: cmd,
85 }
86 if err := stream.Send(&flight.FlightData{FlightDescriptor: desc}); err != nil {
87 return 0, fmt.Errorf("flight doput send descriptor: %w", err)
88 }
89
90 // Frames 1..N: COPY input byte chunks. We re-use one buffer; gRPC marshals the
91 // proto synchronously inside Send, so reusing is safe across iterations.
92 //
93 // On a non-EOF read error we return immediately WITHOUT calling
94 // CloseSend. The deferred cancel() then aborts the gRPC stream, so the
95 // worker's Recv fails with Canceled and the worker bails before
96 // running COPY on a partial spool file. This is what makes wire-level
97 // COPY cancellation correct end-to-end.
98 buf := make([]byte, CopyFromStdinChunkSize)
99 for {
100 n, readErr := r.Read(buf)

Callers

nothing calls this directly

Calls 7

mergedContextMethod · 0.95
withSessionMethod · 0.95
DoPutMethod · 0.45
SendMethod · 0.45
ReadMethod · 0.45
CloseSendMethod · 0.45
RecvMethod · 0.45

Tested by

no test coverage detected