@@ -283,3 +283,57 @@ func (p *tracedPipeline) Close() { p.inner.Close() }
283
283
func (p * tracedPipeline ) Inputs () []Pipeline { return p .inner .Inputs () }
284
284
285
285
func (p * tracedPipeline ) Transport () Transport { return Local }
286
+
287
+ type lazyPipeline struct {
288
+ ctor func (ctx context.Context , inputs []Pipeline ) Pipeline
289
+
290
+ inputs []Pipeline
291
+ built Pipeline
292
+ }
293
+
294
+ // newLazyPipeline allows for defering construction of a [Pipeline] to query
295
+ // execution time instead of planning time. This is useful for pipelines which
296
+ // are expensive to construct, or have dependencies which are only available
297
+ // during execution.
298
+ //
299
+ // The ctor function will be invoked on the first call to [Pipeline.Read].
300
+ func newLazyPipeline (ctor func (ctx context.Context , inputs []Pipeline ) Pipeline , inputs []Pipeline ) * lazyPipeline {
301
+ return & lazyPipeline {
302
+ ctor : ctor ,
303
+ inputs : inputs ,
304
+ }
305
+ }
306
+
307
+ var _ Pipeline = (* lazyPipeline )(nil )
308
+
309
+ // Read reads the next value from the inner pipeline. If this is the first call
310
+ // to Read, the inner pipeline will be constructed using the provided context.
311
+ func (lp * lazyPipeline ) Read (ctx context.Context ) error {
312
+ if lp .built == nil {
313
+ lp .built = lp .ctor (ctx , lp .inputs )
314
+ }
315
+ return lp .built .Read (ctx )
316
+ }
317
+
318
+ // Value returns the current value from the lazily constructed pipeline. If the
319
+ // pipeline has not been constructed yet, it returns an error.
320
+ func (lp * lazyPipeline ) Value () (arrow.Record , error ) {
321
+ if lp .built == nil {
322
+ return nil , fmt .Errorf ("lazyPipeline not built yet" )
323
+ }
324
+ return lp .built .Value ()
325
+ }
326
+
327
+ // Close closes the lazily constructed pipeline if it has been built.
328
+ func (lp * lazyPipeline ) Close () {
329
+ if lp .built != nil {
330
+ lp .built .Close ()
331
+ }
332
+ lp .built = nil
333
+ }
334
+
335
+ // Inputs implements [Pipeline].
336
+ func (lp * lazyPipeline ) Inputs () []Pipeline { return lp .inputs }
337
+
338
+ // Transport implements [Pipeline].
339
+ func (lp * lazyPipeline ) Transport () Transport { return Local }
0 commit comments