diff --git a/pkg/dal/driver.go b/pkg/dal/driver.go index fcd5f02f1..5ef66b2b5 100644 --- a/pkg/dal/driver.go +++ b/pkg/dal/driver.go @@ -90,23 +90,6 @@ type ( TransformationFunction func(*Model, Attribute, expr.TypedValue) (expr.TypedValue, bool, error) - // Iterator provides an interface for loading data from the underlying store - Iterator interface { - Next(ctx context.Context) bool - More(uint, ValueGetter) error - Err() error - Scan(ValueSetter) error - Close() error - - BackCursor(ValueGetter) (*filter.PagingCursor, error) - ForwardCursor(ValueGetter) (*filter.PagingCursor, error) - - // // -1 means unknown - // Total() int - // Cursor() any - // // ... do we need anything else here? - } - // Store provides an interface which CRS uses to interact with the underlying database ValueGetter interface { diff --git a/pkg/dal/iterator.go b/pkg/dal/iterator.go new file mode 100644 index 000000000..72ae5957b --- /dev/null +++ b/pkg/dal/iterator.go @@ -0,0 +1,65 @@ +package dal + +import ( + "context" + "encoding/json" + "github.com/cortezaproject/corteza-server/pkg/filter" + "io" +) + +type ( + // Iterator provides an interface for loading data from the underlying store + Iterator interface { + Next(ctx context.Context) bool + More(uint, ValueGetter) error + Err() error + Scan(ValueSetter) error + Close() error + + BackCursor(ValueGetter) (*filter.PagingCursor, error) + ForwardCursor(ValueGetter) (*filter.PagingCursor, error) + + // // -1 means unknown + // Total() int + // Cursor() any + // // ... do we need anything else here? + } +) + +// IteratorEncodeJSON helper function that encodes each item from the iterator as JSON +// and writes it to th given io.Writer. +// +// target initialization function is intentionally used to avoid use of reflection +func IteratorEncodeJSON(ctx context.Context, w io.Writer, iter Iterator, initTarget func() ValueSetter) (err error) { + var ( + target ValueSetter + firstOut = false + ) + + for iter.Next(ctx) { + if err = iter.Err(); err != nil { + return + } + + if firstOut { + if _, err = w.Write([]byte(`,`)); err != nil { + return + } + } + + firstOut = true + + target = initTarget() + + if err = iter.Scan(target); err != nil { + return + } + + err = json.NewEncoder(w).Encode(target) + if err != nil { + return + } + } + + return +}